proto-shell: fix parsing route netmask
[project/netifd.git] / proto-shell.c
index fdb87df..bc74de9 100644 (file)
@@ -55,7 +55,7 @@ kill_process(struct uloop_process *proc)
 }
 
 static int
-start_process(const char **argv, struct uloop_process *proc)
+start_process(const char **argv, char **env, struct uloop_process *proc)
 {
        int pid;
 
@@ -65,6 +65,12 @@ start_process(const char **argv, struct uloop_process *proc)
                return -1;
 
        if (!pid) {
+               if (env) {
+                       while (*env) {
+                               putenv(*env);
+                               env++;
+                       }
+               }
                fchdir(proto_fd);
                execvp(argv[0], (char **) argv);
                exit(127);
@@ -121,7 +127,7 @@ proto_shell_handler(struct interface_proto_state *proto,
                argv[i++] = proto->iface->main_dev.dev->ifname;
        argv[i] = NULL;
 
-       ret = start_process(argv, proc);
+       ret = start_process(argv, NULL, proc);
        free(config);
 
        return ret;
@@ -236,7 +242,7 @@ enum {
 
 static const struct blobmsg_policy route_attr[__ROUTE_LAST] = {
        [ROUTE_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
-       [ROUTE_MASK] = { .name = "mask", .type = BLOBMSG_TYPE_INT32 },
+       [ROUTE_MASK] = { .name = "mask", .type = BLOBMSG_TYPE_STRING },
        [ROUTE_GATEWAY] = { .name = "gateway", .type = BLOBMSG_TYPE_STRING },
        [ROUTE_DEVICE] = { .name = "device", .type = BLOBMSG_TYPE_STRING },
 };
@@ -259,8 +265,8 @@ parse_route(struct interface *iface, struct blob_attr *attr, bool v6)
 
        route->mask = v6 ? 128 : 32;
        if ((cur = tb[ROUTE_MASK]) != NULL) {
-               route->mask = blobmsg_get_u32(cur);
-               if (route->mask > v6 ? 128 : 32)
+               route->mask = parse_netmask_string(blobmsg_data(cur), v6);
+               if (route->mask > (v6 ? 128 : 32))
                        goto error;
        }
 
@@ -305,10 +311,10 @@ proto_shell_parse_route_list(struct interface *iface, struct blob_attr *attr,
        }
 }
 
-
 enum {
        NOTIFY_ACTION,
        NOTIFY_COMMAND,
+       NOTIFY_ENV,
        NOTIFY_SIGNAL,
        NOTIFY_LINK_UP,
        NOTIFY_IFNAME,
@@ -318,12 +324,14 @@ enum {
        NOTIFY_ROUTES,
        NOTIFY_ROUTES6,
        NOTIFY_DNS,
+       NOTIFY_DNS_SEARCH,
        __NOTIFY_LAST
 };
 
 static const struct blobmsg_policy notify_attr[__NOTIFY_LAST] = {
        [NOTIFY_ACTION] = { .name = "action", .type = BLOBMSG_TYPE_INT32 },
        [NOTIFY_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_ARRAY },
+       [NOTIFY_ENV] = { .name = "env", .type = BLOBMSG_TYPE_ARRAY },
        [NOTIFY_SIGNAL] = { .name = "signal", .type = BLOBMSG_TYPE_INT32 },
        [NOTIFY_LINK_UP] = { .name = "link-up", .type = BLOBMSG_TYPE_BOOL },
        [NOTIFY_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
@@ -333,6 +341,7 @@ static const struct blobmsg_policy notify_attr[__NOTIFY_LAST] = {
        [NOTIFY_ROUTES] = { .name = "routes", .type = BLOBMSG_TYPE_ARRAY },
        [NOTIFY_ROUTES6] = { .name = "routes6", .type = BLOBMSG_TYPE_ARRAY },
        [NOTIFY_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },
+       [NOTIFY_DNS_SEARCH] = { .name = "dns_search", .type = BLOBMSG_TYPE_ARRAY },
 };
 
 static int
@@ -351,10 +360,10 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr **tb)
                return 0;
        }
 
-       if (!tb[NOTIFY_IFNAME])
-               return UBUS_STATUS_INVALID_ARGUMENT;
-
-       if (!state->l3_dev.dev) {
+       if (!tb[NOTIFY_IFNAME]) {
+               if (!state->proto.iface->main_dev.dev)
+                       return UBUS_STATUS_INVALID_ARGUMENT;
+       } else if (!state->l3_dev.dev) {
                device_add_user(&state->l3_dev,
                        device_get(blobmsg_data(tb[NOTIFY_IFNAME]), true));
                device_claim(&state->l3_dev);
@@ -381,6 +390,9 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr **tb)
        if ((cur = tb[NOTIFY_DNS]) != NULL)
                interface_add_dns_server_list(state->proto.iface, cur);
 
+       if ((cur = tb[NOTIFY_DNS_SEARCH]) != NULL)
+               interface_add_dns_search_list(state->proto.iface, cur);
+
        interface_ip_update_complete(state->proto.iface);
 
        state->proto.proto_event(&state->proto, IFPEV_UP);
@@ -388,30 +400,49 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr **tb)
        return 0;
 }
 
-static int
-proto_shell_run_command(struct proto_shell_state *state, struct blob_attr **tb)
+static bool
+fill_string_list(struct blob_attr *attr, char **argv, int max)
 {
        struct blob_attr *cur;
-       char *argv[64];
        int argc = 0;
        int rem;
 
-       if (!tb[NOTIFY_COMMAND])
-               goto error;
+       if (!attr)
+               goto out;
 
-       blobmsg_for_each_attr(cur, tb[NOTIFY_COMMAND], rem) {
+       blobmsg_for_each_attr(cur, attr, rem) {
                if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
-                       goto error;
+                       return false;
 
                if (!blobmsg_check_attr(cur, NULL))
-                       goto error;
+                       return false;
 
                argv[argc++] = blobmsg_data(cur);
-               if (argc == ARRAY_SIZE(argv) - 1)
-                       goto error;
+               if (argc == max - 1)
+                       return false;
        }
+
+out:
        argv[argc] = NULL;
-       start_process((const char **) argv, &state->proto_task);
+       return true;
+}
+
+static int
+proto_shell_run_command(struct proto_shell_state *state, struct blob_attr **tb)
+{
+       char *argv[64];
+       char *env[32];
+
+       if (!tb[NOTIFY_COMMAND])
+               goto error;
+
+       if (!fill_string_list(tb[NOTIFY_COMMAND], argv, ARRAY_SIZE(argv)))
+               goto error;
+
+       if (!fill_string_list(tb[NOTIFY_ENV], env, ARRAY_SIZE(env)))
+               goto error;
+
+       start_process((const char **) argv, (char **) env, &state->proto_task);
 
        return 0;