+ memcpy(state->config, attr, blob_pad_len(attr));
+ state->proto.free = proto_shell_free;
+ state->proto.notify = proto_shell_notify;
+ state->proto.cb = proto_shell_handler;
+ state->teardown_timeout.cb = proto_shell_teardown_timeout_cb;
+ state->script_task.cb = proto_shell_script_cb;
+ state->script_task.dir_fd = proto_fd;
+ state->script_task.log_prefix = iface->name;
+ state->proto_task.cb = proto_shell_task_cb;
+ state->proto_task.dir_fd = proto_fd;
+ state->proto_task.log_prefix = iface->name;
+ state->handler = container_of(h, struct proto_shell_handler, proto);
+
+ return &state->proto;
+
+error:
+ free(state);
+ return NULL;
+}
+
+static void
+proto_shell_add_handler(const char *script, const char *name, json_object *obj)
+{
+ struct proto_shell_handler *handler;
+ struct proto_handler *proto;
+ json_object *config, *tmp;
+ char *proto_name, *script_name;
+
+ handler = calloc_a(sizeof(*handler),
+ &proto_name, strlen(name) + 1,
+ &script_name, strlen(script) + 1);
+ if (!handler)
+ return;
+
+ handler->script_name = strcpy(script_name, script);
+
+ proto = &handler->proto;
+ proto->name = strcpy(proto_name, name);
+ proto->config_params = &handler->config;
+ proto->attach = proto_shell_attach;
+
+ tmp = json_get_field(obj, "no-device", json_type_boolean);
+ if (tmp && json_object_get_boolean(tmp))
+ handler->proto.flags |= PROTO_FLAG_NODEV;
+
+ tmp = json_get_field(obj, "available", json_type_boolean);
+ if (tmp && json_object_get_boolean(tmp))
+ handler->proto.flags |= PROTO_FLAG_INIT_AVAILABLE;
+
+ tmp = json_get_field(obj, "renew-handler", json_type_boolean);
+ if (tmp && json_object_get_boolean(tmp))
+ handler->proto.flags |= PROTO_FLAG_RENEW_AVAILABLE;
+
+ config = json_get_field(obj, "config", json_type_array);
+ if (config)
+ handler->config_buf = netifd_handler_parse_config(&handler->config, config);
+
+ DPRINTF("Add handler for script %s: %s\n", script, proto->name);
+ add_proto_handler(proto);
+}
+
+void proto_shell_init(void)
+{
+ proto_fd = netifd_open_subdir("proto");
+ if (proto_fd < 0)
+ return;