X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=proto-shell.c;h=50f1b5b1cc4b638872b37bbdadbab2b292650b9f;hp=7c23caa47c7837946d70f3a0a81f746d73f56dd9;hb=a7e508b71c1cf3ee9d401510d298195067fba8e5;hpb=64ea160818e2dc958fa91f80a3a5a9ac40ccc3ba diff --git a/proto-shell.c b/proto-shell.c index 7c23caa..50f1b5b 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -44,6 +44,7 @@ struct proto_shell_handler { char *config_buf; char *script_name; bool init_available; + bool no_proto_task; struct uci_blob_param_list config; }; @@ -156,10 +157,22 @@ proto_shell_handler(struct interface_proto_state *proto, proc = &state->script_task; if (cmd == PROTO_CMD_SETUP) { - action = "setup"; - state->last_error = -1; - proto_shell_clear_host_dep(state); - state->sm = S_SETUP; + switch (state->sm) { + case S_IDLE: + action = "setup"; + state->last_error = -1; + proto_shell_clear_host_dep(state); + state->sm = S_SETUP; + break; + + case S_SETUP_ABORT: + case S_TEARDOWN: + case S_SETUP: + return 0; + + default: + return -1; + } } else if (cmd == PROTO_CMD_RENEW) { if (!(handler->proto.flags & PROTO_FLAG_RENEW_AVAILABLE)) return 0; @@ -172,28 +185,35 @@ proto_shell_handler(struct interface_proto_state *proto, state->renew_pending = false; action = "renew"; } else { - if (state->sm == S_TEARDOWN) - return 0; - - state->renew_pending = false; - if (state->script_task.uloop.pending) { - if (state->sm != S_SETUP_ABORT) { + switch (state->sm) { + case S_SETUP: + if (state->script_task.uloop.pending) { uloop_timeout_set(&state->teardown_timeout, 1000); kill(state->script_task.uloop.pid, SIGTERM); if (state->proto_task.uloop.pending) kill(state->proto_task.uloop.pid, SIGTERM); + state->renew_pending = false; state->sm = S_SETUP_ABORT; + return 0; } + /* fall through if no script task is running */ + case S_IDLE: + action = "teardown"; + state->renew_pending = false; + state->sm = S_TEARDOWN; + if (state->last_error >= 0) { + snprintf(error_buf, sizeof(error_buf), "ERROR=%d", state->last_error); + envp[j++] = error_buf; + } + uloop_timeout_set(&state->teardown_timeout, 5000); + break; + + case S_TEARDOWN: return 0; - } - action = "teardown"; - state->sm = S_TEARDOWN; - if (state->last_error >= 0) { - snprintf(error_buf, sizeof(error_buf), "ERROR=%d", state->last_error); - envp[j++] = error_buf; + default: + return -1; } - uloop_timeout_set(&state->teardown_timeout, 5000); } D(INTERFACE, "run %s for interface '%s'\n", action, proto->iface->name); @@ -265,9 +285,17 @@ proto_shell_task_finish(struct proto_shell_state *state, if (task == &state->proto_task) proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN, false); - if (task == &state->script_task && state->renew_pending) - proto_shell_handler(&state->proto, PROTO_CMD_RENEW, - false); + else if (task == &state->script_task) { + if (state->renew_pending) + proto_shell_handler(&state->proto, + PROTO_CMD_RENEW, false); + else if (!state->handler->no_proto_task && + !state->proto_task.uloop.pending && + state->sm == S_SETUP) + proto_shell_handler(&state->proto, + PROTO_CMD_TEARDOWN, + false); + } break; case S_SETUP_ABORT: @@ -506,9 +534,11 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr *data, interface_update_complete(state->proto.iface); - if (!keep) - state->proto.proto_event(&state->proto, IFPEV_UP); - state->sm = S_IDLE; + if ((state->sm != S_SETUP_ABORT) && (state->sm != S_TEARDOWN)) { + if (!keep) + state->proto.proto_event(&state->proto, IFPEV_UP); + state->sm = S_IDLE; + } return 0; } @@ -790,6 +820,12 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj) if (tmp && json_object_get_boolean(tmp)) handler->proto.flags |= PROTO_FLAG_NODEV; + tmp = json_get_field(obj, "no-proto-task", json_type_boolean); + if (tmp && json_object_get_boolean(tmp)) + handler->no_proto_task = true; + else + handler->no_proto_task = false; + tmp = json_get_field(obj, "available", json_type_boolean); if (tmp && json_object_get_boolean(tmp)) handler->proto.flags |= PROTO_FLAG_INIT_AVAILABLE; @@ -798,6 +834,10 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj) if (tmp && json_object_get_boolean(tmp)) handler->proto.flags |= PROTO_FLAG_RENEW_AVAILABLE; + tmp = json_get_field(obj, "lasterror", json_type_boolean); + if (tmp && json_object_get_boolean(tmp)) + handler->proto.flags |= PROTO_FLAG_LASTERROR; + config = json_get_field(obj, "config", json_type_array); if (config) handler->config_buf = netifd_handler_parse_config(&handler->config, config);