diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 0fb4d99b1..377b9ed16 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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]; /* * TABTABTABTAB - * TAB + * TAB[TAB] */ 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 (wpa_supplicant_get_iface(global, iface.ifname)) - return -1; + 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; + } - return wpa_supplicant_add_iface(global, &iface, NULL) ? 0 : -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)) + goto fail; + + wpa_s = wpa_supplicant_add_iface(global, &iface, NULL); + if (!wpa_s) + goto fail; + wpa_s->added_vif = create_iface; + return 0; + +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; } diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 6e6cdf5e5..27f10f1c6 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -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 TABTABTABTAB - * TAB + * TAB[TAB] */ 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'; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 0ec102f1c..2d517f1a2 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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;