Add support for virtual interface creation/deletion
authorJithu Jance <jithu@broadcom.com>
Fri, 20 Mar 2015 10:39:50 +0000 (16:09 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 26 Mar 2015 20:20:35 +0000 (22:20 +0200)
Extend interface_add and interface_remove commands via an optional
argument to allow wpa_supplicant to create/delete a new virtual
interface.

Signed-off-by: Jithu Jance <jithu@broadcom.com>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wpa_supplicant_i.h

index 0fb4d99..377b9ed 100644 (file)
@@ -8521,11 +8521,14 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
                                           char *cmd)
 {
        struct wpa_interface iface;
-       char *pos;
+       char *pos, *extra;
+       struct wpa_supplicant *wpa_s;
+       unsigned int create_iface = 0;
+       u8 mac_addr[ETH_ALEN];
 
        /*
         * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
-        * TAB<bridge_ifname>
+        * TAB<bridge_ifname>[TAB<create>]
         */
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
 
@@ -8585,12 +8588,47 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
                        iface.bridge_ifname = NULL;
                if (pos == NULL)
                        break;
+
+               extra = pos;
+               pos = os_strchr(pos, '\t');
+               if (pos)
+                       *pos++ = '\0';
+               if (os_strcmp(extra, "create") == 0)
+                       create_iface = 1;
+               else
+                       return -1;
        } while (0);
 
+       if (create_iface) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
+                          iface.ifname);
+               if (!global->ifaces)
+                       return -1;
+               if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
+                                  NULL, NULL, NULL, mac_addr, NULL) < 0) {
+                       wpa_printf(MSG_ERROR,
+                                  "CTRL_IFACE interface creation failed");
+                       return -1;
+               }
+
+               wpa_printf(MSG_DEBUG,
+                          "CTRL_IFACE interface '%s' created with MAC addr: "
+                          MACSTR, iface.ifname, MAC2STR(mac_addr));
+       }
+
        if (wpa_supplicant_get_iface(global, iface.ifname))
-               return -1;
+               goto fail;
+
+       wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
+       if (!wpa_s)
+               goto fail;
+       wpa_s->added_vif = create_iface;
+       return 0;
 
-       return wpa_supplicant_add_iface(global, &iface, NULL) ? 0 : -1;
+fail:
+       if (create_iface)
+               wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
+       return -1;
 }
 
 
@@ -8598,13 +8636,22 @@ static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
                                              char *cmd)
 {
        struct wpa_supplicant *wpa_s;
+       int ret;
+       unsigned int delete_iface;
 
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
 
        wpa_s = wpa_supplicant_get_iface(global, cmd);
        if (wpa_s == NULL)
                return -1;
-       return wpa_supplicant_remove_iface(global, wpa_s, 0);
+       delete_iface = wpa_s->added_vif;
+       ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
+       if (!ret && delete_iface) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
+                          cmd);
+               ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
+       }
+       return ret;
 }
 
 
index 6e6cdf5..27f10f1 100644 (file)
@@ -1711,20 +1711,20 @@ static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
                printf("Invalid INTERFACE_ADD command: needs at least one "
                       "argument (interface name)\n"
                       "All arguments: ifname confname driver ctrl_interface "
-                      "driver_param bridge_name\n");
+                      "driver_param bridge_name [create]\n");
                return -1;
        }
 
        /*
         * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
-        * <driver_param>TAB<bridge_name>
+        * <driver_param>TAB<bridge_name>[TAB<create>]
         */
        res = os_snprintf(cmd, sizeof(cmd),
-                         "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
+                         "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s",
                          argv[0],
                          argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
                          argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
-                         argc > 5 ? argv[5] : "");
+                         argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "");
        if (os_snprintf_error(sizeof(cmd), res))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
index 0ec102f..2d517f1 100644 (file)
@@ -648,6 +648,7 @@ struct wpa_supplicant {
        unsigned int eap_expected_failure:1;
        unsigned int reattach:1; /* reassociation to the same BSS requested */
        unsigned int mac_addr_changed:1;
+       unsigned int added_vif:1;
 
        struct os_reltime last_mac_addr_change;
        int last_mac_addr_style;