struct proto_handler proto;
struct config_param_list config;
char *config_buf;
+ bool init_available;
char script_name[];
};
return;
}
- state->last_error = ret;
+ state->last_error = WEXITSTATUS(ret);
state->proto.proto_event(&state->proto, IFPEV_LINK_LOST);
proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN, false);
}
enum {
NOTIFY_ACTION,
+ NOTIFY_ERROR,
NOTIFY_COMMAND,
NOTIFY_ENV,
NOTIFY_SIGNAL,
+ NOTIFY_AVAILABLE,
NOTIFY_LINK_UP,
NOTIFY_IFNAME,
NOTIFY_ADDR_EXT,
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 },
+ [NOTIFY_AVAILABLE] = { .name = "available", .type = BLOBMSG_TYPE_BOOL },
[NOTIFY_LINK_UP] = { .name = "link-up", .type = BLOBMSG_TYPE_BOOL },
[NOTIFY_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
[NOTIFY_ADDR_EXT] = { .name = "address-external", .type = BLOBMSG_TYPE_BOOL },
}
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_set_available(struct proto_shell_state *state, struct blob_attr **tb)
+{
+ if (!tb[NOTIFY_AVAILABLE])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ interface_set_available(state->proto.iface, blobmsg_get_bool(tb[NOTIFY_AVAILABLE]));
+ return 0;
+}
+
+static int
proto_shell_notify(struct interface_proto_state *proto, struct blob_attr *attr)
{
struct proto_shell_state *state;
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);
+ case 5:
+ return proto_shell_set_available(state, tb);
default:
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_NODEV;
+ tmp = get_field(obj, "available", json_type_boolean);
+ if (tmp && json_object_get_boolean(tmp))
+ handler->proto.flags |= PROTO_FLAG_INIT_AVAILABLE;
+
config = get_field(obj, "config", json_type_array);
if (config)
handler->config_buf = proto_shell_parse_config(&handler->config, config);