[systemd-devel] [RFC 3/6] proxy-discoveryd: Add PAC support through duktape js engine

Lennart Poettering lennart at poettering.net
Fri Apr 10 08:49:17 PDT 2015


On Fri, 10.04.15 15:17, Tomasz Bursztyka (tomasz.bursztyka at linux.intel.com) wrote:

> +struct PAC {
> +        duk_context *ctx;
> +};
> +
> +static int get_addresses_from_interface(int ifindex, union in_addr_union *address) {
> +        struct ifreq ifr = {};
> +        int sk;
> +
> +        sk = socket(AF_INET, SOCK_DGRAM, 0);
> +        if (sk < 0)
> +                return -1;

No made up errors please! Return -errno or so.

> +
> +        ifr.ifr_ifindex = ifindex;
> +
> +        if (ioctl(sk, SIOCGIFNAME, &ifr) < 0 || ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
> +                close(sk);
> +                return -1;

Same here...

Also, please don't use the old ioctls for querying network
information. Use netlink through sd-rtnl. You can look at the
systemd-resolved sources, they do this already, and this code should
probably do it very similar from that.

> +static int pac_dns_resolve(duk_context *ctx) {
> +        _cleanup_free_ char *address = NULL;
> +        struct addrinfo hints = {};
> +        struct addrinfo *res, *addr;
> +        const char *hostname;
> +        int r;
> +
> +        hostname = duk_require_string(ctx, 0);
> +
> +        hints.ai_family = AF_INET;
> +
> +        r = getaddrinfo(hostname, NULL, &hints, &res);
> +        if (r != 0)
> +                return 0;

Hm, synchronous getaddrinfo() is nasty... Please use sd-resolve for
this, which adds asynchronous getaddrinfo() for cases like this...

> +
> +        for (addr = res; addr; addr = addr->ai_next) {
> +                union in_addr_union a;
> +
> +                if (addr->ai_family != AF_INET ||
> +                                addr->ai_addrlen != sizeof(struct sockaddr_in))
> +                        continue;
> +
> +                a.in = ((struct sockaddr_in *) addr->ai_addr)->sin_addr;
> +                in_addr_to_string(AF_INET, &a, &address);

This can actually fail need to check for OOM...

> +        r = local_gateways(NULL, 0, AF_INET, &gateways);
> +        if (r <= 0)
> +                return 0;
> +
> +        r = get_addresses_from_interface(gateways->ifindex, &addr);
> +        if (r < 0)
> +                return 0;

BTW; local_addresses() can do this for you...

> +        in_addr_to_string(AF_INET, &addr, &address);

Can fail, due to OOM, needs OOM check...

> +static int create_context(struct PAC *pac, char *pac_file, void *user_data) {
> +        duk_context *ctx;
> +
> +        ctx = duk_create_heap(NULL, NULL, NULL, NULL, NULL);
> +        if (!ctx)
> +                return -ENOMEM;
> +
> +        duk_push_global_object(ctx);
> +        duk_push_c_function(ctx, pac_dns_resolve, 1);
> +        duk_put_prop_string(ctx, -2, "dnsResolve");
> +        duk_push_c_function(ctx, pac_my_ip_address, 0);
> +        duk_put_prop_string(ctx, -2, "myIpAddress");
> +
> +        duk_push_pointer(ctx, user_data);
> +        duk_put_prop_string(ctx, -2, "_user_data_");
> +
> +        duk_pop(ctx);
> +
> +        if (duk_peval_file(ctx, pac_file) != 0) {
> +                duk_destroy_heap(ctx);
> +                return -EINVAL;
> +        }

How is error handling done in duktape? The individual functions cannot
fail? And are any errors returned?

> +int pac_execute(struct PAC *pac, const char *url, const char *host, char **ret) {
> +        duk_push_global_object(pac->ctx);
> +        duk_get_prop_string(pac->ctx, -1, "FindProxyForURL");
> +        duk_push_string(pac->ctx, url);
> +        duk_push_string(pac->ctx, host);
> +
> +        if (duk_pcall(pac->ctx, 2) != DUK_EXEC_SUCCESS)
> +                 return -1;
> +
> +        *ret = strdup(duk_to_string(pac->ctx, -1));

Missing OOM check...

Lennart

-- 
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list