wireless: fix reload of active interfaces
[project/netifd.git] / wireless.c
index 7cc832d..fb66e7f 100644 (file)
@@ -167,6 +167,7 @@ wireless_device_free_state(struct wireless_device *wdev)
 {
        struct wireless_interface *vif;
 
+       uloop_timeout_cancel(&wdev->timeout);
        wireless_complete_kill_request(wdev);
        free(wdev->data);
        wdev->data = NULL;
@@ -197,6 +198,7 @@ wireless_device_setup_cancel(struct wireless_device *wdev)
        if (wdev->cancel)
                return;
 
+       D(WIRELESS, "Cancel wireless device '%s' setup\n", wdev->name);
        wdev->cancel = true;
        uloop_timeout_set(&wdev->timeout, 10 * 1000);
 }
@@ -246,6 +248,32 @@ __wireless_device_set_up(struct wireless_device *wdev)
 }
 
 static void
+wireless_device_free(struct wireless_device *wdev)
+{
+    vlist_flush_all(&wdev->interfaces);
+    free(wdev->config);
+    free(wdev);
+}
+
+static void
+wdev_handle_config_change(struct wireless_device *wdev)
+{
+       enum interface_config_state state = wdev->config_state;
+
+       wdev->config_state = IFC_NORMAL;
+       switch(state) {
+       case IFC_NORMAL:
+       case IFC_RELOAD:
+               if (wdev->autostart)
+                       __wireless_device_set_up(wdev);
+               break;
+       case IFC_REMOVE:
+               wireless_device_free(wdev);
+               break;
+       }
+}
+
+static void
 wireless_device_mark_down(struct wireless_device *wdev)
 {
        struct wireless_interface *vif;
@@ -257,11 +285,10 @@ wireless_device_mark_down(struct wireless_device *wdev)
 
        wireless_process_kill_all(wdev, SIGTERM, true);
 
+       wdev->cancel = false;
        wdev->state = IFS_DOWN;
        wireless_device_free_state(wdev);
-
-       if (wdev->autostart)
-               __wireless_device_set_up(wdev);
+       wdev_handle_config_change(wdev);
 }
 
 static void
@@ -342,33 +369,6 @@ wireless_device_set_down(struct wireless_device *wdev)
 }
 
 static void
-wireless_device_free(struct wireless_device *wdev)
-{
-    vlist_flush_all(&wdev->interfaces);
-    free(wdev->config);
-    free(wdev);
-}
-
-static void
-wdev_handle_config_change(struct wireless_device *wdev)
-{
-       enum interface_config_state state = wdev->config_state;
-
-       wdev->config_state = IFC_NORMAL;
-       switch(state) {
-       case IFC_NORMAL:
-               break;
-       case IFC_RELOAD:
-               if (wdev->autostart)
-                       __wireless_device_set_up(wdev);
-               break;
-       case IFC_REMOVE:
-               wireless_device_free(wdev);
-               break;
-       }
-}
-
-static void
 wdev_set_config_state(struct wireless_device *wdev, enum interface_config_state s)
 {
        enum interface_config_state old_state = wdev->config_state;
@@ -709,6 +709,7 @@ wireless_device_add_process(struct wireless_device *wdev, struct blob_attr *data
        struct blob_attr *tb[__PROC_ATTR_MAX];
        struct wireless_process *proc;
        char *name;
+       int pid;
 
        if (!data)
                return UBUS_STATUS_INVALID_ARGUMENT;
@@ -717,10 +718,14 @@ wireless_device_add_process(struct wireless_device *wdev, struct blob_attr *data
        if (!tb[PROC_ATTR_PID] || !tb[PROC_ATTR_EXE])
                return UBUS_STATUS_INVALID_ARGUMENT;
 
+       pid = blobmsg_get_u32(tb[PROC_ATTR_PID]);
+       if (pid < 2)
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
        proc = calloc_a(sizeof(*proc),
                &name, strlen(blobmsg_data(tb[PROC_ATTR_EXE])) + 1);
 
-       proc->pid = blobmsg_get_u32(tb[PROC_ATTR_PID]);
+       proc->pid = pid;
        proc->exe = strcpy(name, blobmsg_data(tb[PROC_ATTR_EXE]));
 
        if (tb[PROC_ATTR_REQUIRED])
@@ -757,7 +762,7 @@ wireless_device_process_kill_all(struct wireless_device *wdev, struct blob_attr
                signal = blobmsg_get_u32(cur);
 
        if ((cur = tb[KILL_ATTR_IMMEDIATE]))
-               immediate = blobmsg_get_u32(cur);
+               immediate = blobmsg_get_bool(cur);
 
        if (wdev->state != IFS_TEARDOWN || wdev->kill_request)
                return UBUS_STATUS_PERMISSION_DENIED;