+proto_shell_task_finish(struct proto_shell_state *state,
+ struct netifd_process *task)
+{
+ switch (state->sm) {
+ case S_IDLE:
+ if (task == &state->proto_task)
+ state->proto.proto_event(&state->proto, IFPEV_LINK_LOST);
+ /* fall through */
+ case S_SETUP:
+ if (task == &state->proto_task)
+ proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN,
+ 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);
+
+ /* check up status after setup attempt by this script_task */
+ if (state->sm == S_SETUP && state->checkup_interval > 0) {
+ uloop_timeout_set(&state->checkup_timeout,
+ state->checkup_interval * 1000);
+ }
+ }
+ break;
+
+ case S_SETUP_ABORT:
+ if (state->script_task.uloop.pending ||
+ state->proto_task.uloop.pending)
+ break;
+
+ /* completed aborting all tasks, now idle */
+ uloop_timeout_cancel(&state->teardown_timeout);
+ uloop_timeout_cancel(&state->checkup_timeout);
+ state->sm = S_IDLE;
+ proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN, false);
+ break;
+
+ case S_TEARDOWN:
+ if (state->script_task.uloop.pending)
+ break;
+
+ if (state->proto_task.uloop.pending) {
+ if (!state->proto_task_killed)
+ kill(state->proto_task.uloop.pid, SIGTERM);
+ break;
+ }
+
+ /* completed tearing down all tasks, now idle */
+ uloop_timeout_cancel(&state->teardown_timeout);
+ uloop_timeout_cancel(&state->checkup_timeout);
+ state->sm = S_IDLE;
+ state->proto.proto_event(&state->proto, IFPEV_DOWN);
+ break;
+ }
+}
+
+static void
+proto_shell_teardown_timeout_cb(struct uloop_timeout *timeout)
+{
+ struct proto_shell_state *state;
+
+ state = container_of(timeout, struct proto_shell_state, teardown_timeout);
+
+ netifd_kill_process(&state->script_task);
+ netifd_kill_process(&state->proto_task);
+ proto_shell_task_finish(state, NULL);
+}
+
+static void
+proto_shell_script_cb(struct netifd_process *p, int ret)