+ if ((cur = tb[NOTIFY_DNS]) != NULL)
+ interface_add_dns_server_list(state->proto.iface, cur);
+
+ interface_ip_update_complete(state->proto.iface);
+
+ state->proto.proto_event(&state->proto, IFPEV_UP);
+
+ return 0;
+}
+
+static int
+proto_shell_run_command(struct proto_shell_state *state, struct blob_attr **tb)
+{
+ struct blob_attr *cur;
+ char *argv[64];
+ int argc = 0;
+ int rem;
+
+ if (!tb[NOTIFY_COMMAND])
+ goto error;
+
+ blobmsg_for_each_attr(cur, tb[NOTIFY_COMMAND], rem) {
+ if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
+ goto error;
+
+ if (!blobmsg_check_attr(cur, NULL))
+ goto error;
+
+ argv[argc++] = blobmsg_data(cur);
+ if (argc == ARRAY_SIZE(argv) - 1)
+ goto error;
+ }
+ argv[argc] = NULL;
+ start_process((const char **) argv, &state->proto_task);
+
+ return 0;
+
+error:
+ return UBUS_STATUS_INVALID_ARGUMENT;
+}
+
+static int
+proto_shell_kill_command(struct proto_shell_state *state, struct blob_attr **tb)
+{
+ unsigned int signal = ~0;
+
+ if (tb[NOTIFY_SIGNAL])
+ signal = blobmsg_get_u32(tb[NOTIFY_SIGNAL]);
+
+ if (signal > 31)
+ signal = SIGTERM;
+
+ if (state->proto_task.pending) {
+ kill(state->proto_task.pid, signal);
+ state->teardown_wait_task = true;
+ }
+