X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=proto-shell.c;h=fc16f76c6d8a09d4f0924fa82c0cb4264fe24037;hp=3b5311ce17a228f55e4ef90eb415f9e40a823e7e;hb=43c2934a4d3f9a3e9d7fc2a4e9a32a2bef7174ba;hpb=268149290fcd8a52f377b21226990d3bf0e9c226;ds=sidebyside diff --git a/proto-shell.c b/proto-shell.c index 3b5311c..fc16f76 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -42,6 +42,7 @@ struct proto_shell_state { bool teardown_wait_task; struct netifd_process proto_task; + int last_error; }; static int @@ -51,10 +52,12 @@ proto_shell_handler(struct interface_proto_state *proto, struct proto_shell_state *state; struct proto_shell_handler *handler; struct netifd_process *proc; - const char *argv[6]; + static char error_buf[32]; + const char *argv[7]; + char *envp[2]; const char *action; char *config; - int ret, i = 0; + int ret, i = 0, j = 0; state = container_of(proto, struct proto_shell_state, proto); handler = state->handler; @@ -62,6 +65,7 @@ proto_shell_handler(struct interface_proto_state *proto, if (cmd == PROTO_CMD_SETUP) { action = "setup"; proc = &state->setup_task; + state->last_error = -1; } else { action = "teardown"; proc = &state->teardown_task; @@ -71,6 +75,10 @@ proto_shell_handler(struct interface_proto_state *proto, state->teardown_pending = true; return 0; } + if (state->last_error >= 0) { + snprintf(error_buf, sizeof(error_buf), "ERROR=%d", state->last_error); + envp[j++] = error_buf; + } } config = blobmsg_format_json(state->config, true); @@ -85,8 +93,9 @@ proto_shell_handler(struct interface_proto_state *proto, if (proto->iface->main_dev.dev) argv[i++] = proto->iface->main_dev.dev->ifname; argv[i] = NULL; + envp[j] = NULL; - ret = netifd_start_process(argv, NULL, proc); + ret = netifd_start_process(argv, envp, proc); free(config); return ret; @@ -146,6 +155,7 @@ proto_shell_task_cb(struct netifd_process *p, int ret) return; } + state->last_error = ret; state->proto.proto_event(&state->proto, IFPEV_LINK_LOST); proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN, false); } @@ -206,6 +216,7 @@ proto_shell_parse_route_list(struct interface *iface, struct blob_attr *attr, enum { NOTIFY_ACTION, + NOTIFY_ERROR, NOTIFY_COMMAND, NOTIFY_ENV, NOTIFY_SIGNAL, @@ -223,6 +234,7 @@ enum { static const struct blobmsg_policy notify_attr[__NOTIFY_LAST] = { [NOTIFY_ACTION] = { .name = "action", .type = BLOBMSG_TYPE_INT32 }, + [NOTIFY_ERROR] = { .name = "error", .type = BLOBMSG_TYPE_ARRAY }, [NOTIFY_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_ARRAY }, [NOTIFY_ENV] = { .name = "env", .type = BLOBMSG_TYPE_ARRAY }, [NOTIFY_SIGNAL] = { .name = "signal", .type = BLOBMSG_TYPE_INT32 }, @@ -372,6 +384,49 @@ proto_shell_kill_command(struct proto_shell_state *state, struct blob_attr **tb) } static int +proto_shell_notify_error(struct proto_shell_state *state, struct blob_attr **tb) +{ + struct blob_attr *cur; + char *data[16]; + int n_data = 0; + int rem; + + if (!tb[NOTIFY_ERROR]) + return UBUS_STATUS_INVALID_ARGUMENT; + + blobmsg_for_each_attr(cur, tb[NOTIFY_ERROR], rem) { + if (n_data + 1 == ARRAY_SIZE(data)) + goto error; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) + goto error; + + if (!blobmsg_check_attr(cur, NULL)) + goto error; + + data[n_data++] = blobmsg_data(cur); + } + + if (!n_data) + goto error; + + interface_add_error(state->proto.iface, state->handler->proto.name, + data[0], (const char **) &data[1], n_data - 1); + + return 0; + +error: + return UBUS_STATUS_INVALID_ARGUMENT; +} + +static int +proto_shell_block_restart(struct proto_shell_state *state, struct blob_attr **tb) +{ + state->proto.iface->autostart = false; + return 0; +} + +static int proto_shell_notify(struct interface_proto_state *proto, struct blob_attr *attr) { struct proto_shell_state *state; @@ -390,6 +445,10 @@ proto_shell_notify(struct interface_proto_state *proto, struct blob_attr *attr) return proto_shell_run_command(state, tb); case 2: return proto_shell_kill_command(state, tb); + case 3: + return proto_shell_notify_error(state, tb); + case 4: + return proto_shell_block_restart(state, tb); default: return UBUS_STATUS_INVALID_ARGUMENT; }