summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xdummy/netifd-proto.sh18
-rwxr-xr-xdummy/proto/ppp.sh1
-rw-r--r--proto-shell.c88
3 files changed, 98 insertions, 9 deletions
diff --git a/dummy/netifd-proto.sh b/dummy/netifd-proto.sh
index 85e8698..c50d776 100755
--- a/dummy/netifd-proto.sh
+++ b/dummy/netifd-proto.sh
@@ -47,6 +47,7 @@ proto_init_update() {
PROTO_ROUTE=
PROTO_ROUTE6=
json_init
+ json_add_int action 0
json_add_string "ifname" "$ifname"
json_add_boolean "link-up" "$up"
[ -n "$3" ] && json_add_boolean "address-external" "$external"
@@ -113,6 +114,10 @@ _proto_push_array() {
json_close_array
}
+_proto_notify() {
+ ubus call network.interface."$interface" notify_proto "$(json_dump)"
+}
+
proto_send_update() {
local interface="$1"
@@ -120,7 +125,18 @@ proto_send_update() {
_proto_push_array "ip6addr" "$PROTO_IP6ADDR" _proto_push_ip
_proto_push_array "route" "$PROTO_ROUTE" _proto_push_route
_proto_push_array "route6" "$PROTO_ROUTE6" _proto_push_route
- ubus call network.interface."$interface" notify_proto "$(json_dump)" &
+ _proto_notify
+}
+
+proto_run_command() {
+ json_init
+ json_add_int action 1
+ json_add_array command
+ while [ $# -gt 0 ]; do
+ json_add_string "" "$1"
+ shift
+ done
+ _proto_notify
}
init_proto() {
diff --git a/dummy/proto/ppp.sh b/dummy/proto/ppp.sh
index adce2ca..13c4ebb 100755
--- a/dummy/proto/ppp.sh
+++ b/dummy/proto/ppp.sh
@@ -39,6 +39,7 @@ pppoe_setup() {
proto_init_update ppp0 1
proto_add_ipv4_address "192.168.2.1" 32
proto_send_update "$1"
+ proto_run_command sleep 10
}
pppoe_teardown() {
diff --git a/proto-shell.c b/proto-shell.c
index 65ade12..ee2366f 100644
--- a/proto-shell.c
+++ b/proto-shell.c
@@ -39,13 +39,20 @@ struct proto_shell_state {
struct uloop_process setup_task;
struct uloop_process teardown_task;
bool teardown_pending;
+
+ struct uloop_process proto_task;
};
static int
-run_script(const char **argv, struct uloop_process *proc)
+start_process(const char **argv, struct uloop_process *proc)
{
int pid;
+ if (proc->pending) {
+ kill(proc->pid, SIGTERM);
+ uloop_process_delete(proc);
+ }
+
if ((pid = fork()) < 0)
return -1;
@@ -106,7 +113,7 @@ proto_shell_handler(struct interface_proto_state *proto,
argv[i++] = proto->iface->main_dev.dev->ifname;
argv[i] = NULL;
- ret = run_script(argv, proc);
+ ret = start_process(argv, proc);
free(config);
return ret;
@@ -148,6 +155,17 @@ proto_shell_teardown_cb(struct uloop_process *p, int ret)
}
static void
+proto_shell_task_cb(struct uloop_process *p, int ret)
+{
+ struct proto_shell_state *state;
+
+ state = container_of(p, struct proto_shell_state, proto_task);
+
+ state->proto.proto_event(&state->proto, IFPEV_LINK_LOST);
+ proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN, false);
+}
+
+static void
proto_shell_free(struct interface_proto_state *proto)
{
struct proto_shell_state *state;
@@ -265,6 +283,8 @@ proto_shell_parse_route_list(struct interface *iface, struct blob_attr *attr,
enum {
+ NOTIFY_ACTION,
+ NOTIFY_COMMAND,
NOTIFY_LINK_UP,
NOTIFY_IFNAME,
NOTIFY_ADDR_EXT,
@@ -276,6 +296,8 @@ enum {
};
static const struct blobmsg_policy notify_attr[__NOTIFY_LAST] = {
+ [NOTIFY_ACTION] = { .name = "action", .type = BLOBMSG_TYPE_INT32 },
+ [NOTIFY_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_ARRAY },
[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 },
@@ -286,16 +308,12 @@ static const struct blobmsg_policy notify_attr[__NOTIFY_LAST] = {
};
static int
-proto_shell_notify(struct interface_proto_state *proto, struct blob_attr *attr)
+proto_shell_update_link(struct proto_shell_state *state, struct blob_attr **tb)
{
- struct proto_shell_state *state;
- struct blob_attr *tb[__NOTIFY_LAST], *cur;
+ struct blob_attr *cur;
bool addr_ext = false;
bool up;
- state = container_of(proto, struct proto_shell_state, proto);
-
- blobmsg_parse(notify_attr, __NOTIFY_LAST, tb, blob_data(attr), blob_len(attr));
if (!tb[NOTIFY_LINK_UP])
return UBUS_STATUS_INVALID_ARGUMENT;
@@ -333,6 +351,59 @@ proto_shell_notify(struct interface_proto_state *proto, struct blob_attr *attr)
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_notify(struct interface_proto_state *proto, struct blob_attr *attr)
+{
+ struct proto_shell_state *state;
+ struct blob_attr *tb[__NOTIFY_LAST];
+
+ state = container_of(proto, struct proto_shell_state, proto);
+
+ blobmsg_parse(notify_attr, __NOTIFY_LAST, tb, blob_data(attr), blob_len(attr));
+ if (!tb[NOTIFY_ACTION])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ switch(blobmsg_get_u32(tb[NOTIFY_ACTION])) {
+ case 0:
+ return proto_shell_update_link(state, tb);
+ case 1:
+ return proto_shell_run_command(state, tb);
+ default:
+ return UBUS_STATUS_INVALID_ARGUMENT;
+ }
+}
+
struct interface_proto_state *
proto_shell_attach(const struct proto_handler *h, struct interface *iface,
struct blob_attr *attr)
@@ -351,6 +422,7 @@ proto_shell_attach(const struct proto_handler *h, struct interface *iface,
state->setup_timeout.cb = proto_shell_setup_timeout_cb;
state->setup_task.cb = proto_shell_setup_cb;
state->teardown_task.cb = proto_shell_teardown_cb;
+ state->proto_task.cb = proto_shell_task_cb;
state->handler = container_of(h, struct proto_shell_handler, proto);
return &state->proto;