X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=proto-shell.c;h=c2a6d0011f227efe556f596c27deaa1736f3f421;hp=e554d796891e0bb4376e3b0fc1deb6a27ca57d46;hb=4b1a0ddadc70fbce76844bf09af261296ef4fd9f;hpb=b9d470a3f42d0a9e12238711e25653276ab157e6 diff --git a/proto-shell.c b/proto-shell.c index e554d79..c2a6d00 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -18,7 +18,7 @@ #include "interface-ip.h" #include "proto.h" -static int proto_fd; +static struct netifd_fd proto_fd; struct proto_shell_handler { struct list_head list; @@ -36,62 +36,21 @@ struct proto_shell_state { struct device_user l3_dev; struct uloop_timeout setup_timeout; - struct uloop_process setup_task; - struct uloop_process teardown_task; + struct netifd_process setup_task; + struct netifd_process teardown_task; bool teardown_pending; bool teardown_wait_task; - struct uloop_process proto_task; + struct netifd_process proto_task; }; -static void -kill_process(struct uloop_process *proc) -{ - if (!proc->pending) - return; - - kill(proc->pid, SIGTERM); - uloop_process_delete(proc); -} - -static int -start_process(const char **argv, char **env, struct uloop_process *proc) -{ - int pid; - - kill_process(proc); - - if ((pid = fork()) < 0) - return -1; - - if (!pid) { - if (env) { - while (*env) { - putenv(*env); - env++; - } - } - fchdir(proto_fd); - execvp(argv[0], (char **) argv); - exit(127); - } - - if (pid < 0) - return -1; - - proc->pid = pid; - uloop_process_add(proc); - - return 0; -} - static int proto_shell_handler(struct interface_proto_state *proto, enum interface_proto_cmd cmd, bool force) { struct proto_shell_state *state; struct proto_shell_handler *handler; - struct uloop_process *proc; + struct netifd_process *proc; const char *argv[6]; const char *action; char *config; @@ -106,9 +65,9 @@ proto_shell_handler(struct interface_proto_state *proto, } else { action = "teardown"; proc = &state->teardown_task; - if (state->setup_task.pending && !state->teardown_wait_task) { + if (state->setup_task.uloop.pending && !state->teardown_wait_task) { uloop_timeout_set(&state->setup_timeout, 1000); - kill(state->setup_task.pid, SIGTERM); + kill(state->setup_task.uloop.pid, SIGTERM); state->teardown_pending = true; return 0; } @@ -127,7 +86,7 @@ proto_shell_handler(struct interface_proto_state *proto, argv[i++] = proto->iface->main_dev.dev->ifname; argv[i] = NULL; - ret = start_process(argv, NULL, proc); + ret = netifd_start_process(argv, NULL, proc); free(config); return ret; @@ -139,11 +98,11 @@ proto_shell_setup_timeout_cb(struct uloop_timeout *timeout) struct proto_shell_state *state; state = container_of(timeout, struct proto_shell_state, setup_timeout); - kill(state->setup_task.pid, SIGKILL); + kill(state->setup_task.uloop.pid, SIGKILL); } static void -proto_shell_setup_cb(struct uloop_process *p, int ret) +proto_shell_setup_cb(struct netifd_process *p, int ret) { struct proto_shell_state *state; @@ -156,7 +115,7 @@ proto_shell_setup_cb(struct uloop_process *p, int ret) } static void -proto_shell_teardown_cb(struct uloop_process *p, int ret) +proto_shell_teardown_cb(struct netifd_process *p, int ret) { struct proto_shell_state *state; @@ -165,16 +124,12 @@ proto_shell_teardown_cb(struct uloop_process *p, int ret) if (state->teardown_wait_task) return; - kill_process(&state->proto_task); - - if (state->l3_dev.dev) - device_remove_user(&state->l3_dev); - + netifd_kill_process(&state->proto_task); state->proto.proto_event(&state->proto, IFPEV_DOWN); } static void -proto_shell_task_cb(struct uloop_process *p, int ret) +proto_shell_task_cb(struct netifd_process *p, int ret) { struct proto_shell_state *state; bool teardown_wait_task; @@ -183,7 +138,7 @@ proto_shell_task_cb(struct uloop_process *p, int ret) teardown_wait_task = state->teardown_wait_task; state->teardown_wait_task = false; - if (state->teardown_pending || state->teardown_task.pending) + if (state->teardown_pending || state->teardown_task.uloop.pending) return; if (teardown_wait_task) { @@ -206,7 +161,7 @@ proto_shell_free(struct interface_proto_state *proto) } static void -proto_shell_parse_addr_list(struct interface *iface, struct blob_attr *attr, +proto_shell_parse_addr_list(struct interface_ip_settings *ip, struct blob_attr *attr, bool v6, bool external) { struct device_addr *addr; @@ -228,70 +183,8 @@ proto_shell_parse_addr_list(struct interface *iface, struct blob_attr *attr, if (external) addr->flags |= DEVADDR_EXTERNAL; - vlist_add(&iface->proto_addr, &addr->node); - } -} - -enum { - ROUTE_TARGET, - ROUTE_MASK, - ROUTE_GATEWAY, - ROUTE_DEVICE, - __ROUTE_LAST -}; - -static const struct blobmsg_policy route_attr[__ROUTE_LAST] = { - [ROUTE_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING }, - [ROUTE_MASK] = { .name = "mask", .type = BLOBMSG_TYPE_STRING }, - [ROUTE_GATEWAY] = { .name = "gateway", .type = BLOBMSG_TYPE_STRING }, - [ROUTE_DEVICE] = { .name = "device", .type = BLOBMSG_TYPE_STRING }, -}; - -static void -parse_route(struct interface *iface, struct blob_attr *attr, bool v6) -{ - struct blob_attr *tb[__ROUTE_LAST], *cur; - struct device_route *route; - int af = v6 ? AF_INET6 : AF_INET; - - blobmsg_parse(route_attr, __ROUTE_LAST, tb, blobmsg_data(attr), blobmsg_data_len(attr)); - - if (!tb[ROUTE_GATEWAY] && !tb[ROUTE_DEVICE]) - return; - - route = calloc(1, sizeof(*route)); - if (!route) - return; - - route->mask = v6 ? 128 : 32; - if ((cur = tb[ROUTE_MASK]) != NULL) { - route->mask = blobmsg_get_u32(cur); - if (route->mask > v6 ? 128 : 32) - goto error; - } - - if ((cur = tb[ROUTE_TARGET]) != NULL) { - if (!inet_pton(af, blobmsg_data(cur), &route->addr)) { - DPRINTF("Failed to parse route target: %s\n", (char *) blobmsg_data(cur)); - goto error; - } - } - - if ((cur = tb[ROUTE_GATEWAY]) != NULL) { - if (!inet_pton(af, blobmsg_data(cur), &route->nexthop)) { - DPRINTF("Failed to parse route gateway: %s\n", (char *) blobmsg_data(cur)); - goto error; - } + vlist_add(&ip->addr, &addr->node); } - - if ((cur = tb[ROUTE_DEVICE]) != NULL) - route->device = device_get(blobmsg_data(cur), true); - - vlist_add(&iface->proto_route, &route->node); - return; - -error: - free(route); } static void @@ -307,7 +200,7 @@ proto_shell_parse_route_list(struct interface *iface, struct blob_attr *attr, continue; } - parse_route(iface, cur, v6); + interface_ip_add_route(iface, cur, v6); } } @@ -347,7 +240,9 @@ static const struct blobmsg_policy notify_attr[__NOTIFY_LAST] = { static int proto_shell_update_link(struct proto_shell_state *state, struct blob_attr **tb) { + struct interface_ip_settings *ip; struct blob_attr *cur; + int dev_create = 1; bool addr_ext = false; bool up; @@ -360,26 +255,33 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr **tb) return 0; } + if ((cur = tb[NOTIFY_ADDR_EXT]) != NULL) { + addr_ext = blobmsg_get_bool(cur); + if (addr_ext) + dev_create = 2; + } + if (!tb[NOTIFY_IFNAME]) { if (!state->proto.iface->main_dev.dev) return UBUS_STATUS_INVALID_ARGUMENT; - } else if (!state->l3_dev.dev) { + } else { + if (state->l3_dev.dev) + device_remove_user(&state->l3_dev); + device_add_user(&state->l3_dev, - device_get(blobmsg_data(tb[NOTIFY_IFNAME]), true)); - device_claim(&state->l3_dev); + device_get(blobmsg_data(tb[NOTIFY_IFNAME]), dev_create)); state->proto.iface->l3_dev = &state->l3_dev; + device_claim(&state->l3_dev); } - interface_ip_update_start(state->proto.iface); - - if ((cur = tb[NOTIFY_ADDR_EXT]) != NULL) - addr_ext = blobmsg_get_bool(cur); + ip = &state->proto.iface->proto_ip; + interface_update_start(state->proto.iface); if ((cur = tb[NOTIFY_IPADDR]) != NULL) - proto_shell_parse_addr_list(state->proto.iface, cur, false, addr_ext); + proto_shell_parse_addr_list(ip, cur, false, addr_ext); if ((cur = tb[NOTIFY_IP6ADDR]) != NULL) - proto_shell_parse_addr_list(state->proto.iface, cur, true, addr_ext); + proto_shell_parse_addr_list(ip, cur, true, addr_ext); if ((cur = tb[NOTIFY_ROUTES]) != NULL) proto_shell_parse_route_list(state->proto.iface, cur, false); @@ -388,12 +290,12 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr **tb) proto_shell_parse_route_list(state->proto.iface, cur, true); if ((cur = tb[NOTIFY_DNS]) != NULL) - interface_add_dns_server_list(state->proto.iface, cur); + interface_add_dns_server_list(ip, cur); if ((cur = tb[NOTIFY_DNS_SEARCH]) != NULL) - interface_add_dns_search_list(state->proto.iface, cur); + interface_add_dns_search_list(ip, cur); - interface_ip_update_complete(state->proto.iface); + interface_update_complete(state->proto.iface); state->proto.proto_event(&state->proto, IFPEV_UP); @@ -442,7 +344,7 @@ proto_shell_run_command(struct proto_shell_state *state, struct blob_attr **tb) if (!fill_string_list(tb[NOTIFY_ENV], env, ARRAY_SIZE(env))) goto error; - start_process((const char **) argv, (char **) env, &state->proto_task); + netifd_start_process((const char **) argv, (char **) env, &state->proto_task); return 0; @@ -461,8 +363,8 @@ proto_shell_kill_command(struct proto_shell_state *state, struct blob_attr **tb) if (signal > 31) signal = SIGTERM; - if (state->proto_task.pending) { - kill(state->proto_task.pid, signal); + if (state->proto_task.uloop.pending) { + kill(state->proto_task.uloop.pid, signal); state->teardown_wait_task = true; } @@ -493,7 +395,7 @@ proto_shell_notify(struct interface_proto_state *proto, struct blob_attr *attr) } } -struct interface_proto_state * +static struct interface_proto_state * proto_shell_attach(const struct proto_handler *h, struct interface *iface, struct blob_attr *attr) { @@ -510,8 +412,14 @@ proto_shell_attach(const struct proto_handler *h, struct interface *iface, state->proto.cb = proto_shell_handler; state->setup_timeout.cb = proto_shell_setup_timeout_cb; state->setup_task.cb = proto_shell_setup_cb; + state->setup_task.dir_fd = proto_fd.fd; + state->setup_task.log_prefix = iface->name; state->teardown_task.cb = proto_shell_teardown_cb; + state->teardown_task.dir_fd = proto_fd.fd; + state->teardown_task.log_prefix = iface->name; state->proto_task.cb = proto_shell_task_cb; + state->proto_task.dir_fd = proto_fd.fd; + state->proto_task.log_prefix = iface->name; state->handler = container_of(h, struct proto_shell_handler, proto); return &state->proto; @@ -647,9 +555,9 @@ static void proto_shell_add_script(const char *name) struct json_tokener *tok = NULL; json_object *obj; static char buf[512]; - char *start, *end, *cmd; + char *start, *cmd; FILE *f; - int buflen, len; + int len; #define DUMP_SUFFIX " '' dump" @@ -661,33 +569,25 @@ static void proto_shell_add_script(const char *name) return; do { - buflen = fread(buf, 1, sizeof(buf) - 1, f); - if (buflen <= 0) + start = fgets(buf, sizeof(buf), f); + if (!start) continue; - start = buf; - len = buflen; - do { - end = memchr(start, '\n', len); - if (end) - len = end - start; - - if (!tok) - tok = json_tokener_new(); - - obj = json_tokener_parse_ex(tok, start, len); - if (!is_error(obj)) { - proto_shell_add_handler(name, obj); - json_object_put(obj); - json_tokener_free(tok); - tok = NULL; - } - - if (end) { - start = end + 1; - len = buflen - (start - buf); - } - } while (len > 0); + len = strlen(start); + + if (!tok) + tok = json_tokener_new(); + + obj = json_tokener_parse_ex(tok, start, len); + if (!is_error(obj)) { + proto_shell_add_handler(name, obj); + json_object_put(obj); + json_tokener_free(tok); + tok = NULL; + } else if (start[len - 1] == '\n') { + json_tokener_free(tok); + tok = NULL; + } } while (!feof(f) && !ferror(f)); if (tok) @@ -696,7 +596,7 @@ static void proto_shell_add_script(const char *name) pclose(f); } -void __init proto_shell_init(void) +static void __init proto_shell_init(void) { glob_t g; int main_fd; @@ -714,10 +614,11 @@ void __init proto_shell_init(void) if (chdir("./proto")) goto close_cur; - proto_fd = open(".", O_RDONLY | O_DIRECTORY); - if (proto_fd < 0) + proto_fd.fd = open(".", O_RDONLY | O_DIRECTORY); + if (proto_fd.fd < 0) goto close_cur; + netifd_fd_add(&proto_fd); glob("./*.sh", 0, NULL, &g); for (i = 0; i < g.gl_pathc; i++) proto_shell_add_script(g.gl_pathv[i]);