diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 22a7b9162..5017cbf2e 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -281,7 +281,7 @@ int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) char force_ifname[IFNAMSIZ]; u8 if_addr[ETH_ALEN]; return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr, - NULL, NULL, force_ifname, if_addr); + NULL, NULL, force_ifname, if_addr, NULL); } @@ -367,12 +367,14 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, void *bss_ctx, - void **drv_priv, char *force_ifname, u8 *if_addr) + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge) { if (hapd->driver == NULL || hapd->driver->if_add == NULL) return -1; return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, - bss_ctx, drv_priv, force_ifname, if_addr); + bss_ctx, drv_priv, force_ifname, if_addr, + bridge); } diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 5bc9d013e..3af9ecaa6 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -43,7 +43,8 @@ int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len); int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len); int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, void *bss_ctx, - void **drv_priv, char *force_ifname, u8 *if_addr); + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge); int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, const char *ifname); int hostapd_set_ieee8021x(struct hostapd_data *hapd, diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index ae960b24b..c7faee6ca 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -510,7 +510,9 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) hapd->interface_added = 1; if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, hapd->conf->iface, hapd->own_addr, hapd, - &hapd->drv_priv, force_ifname, if_addr)) { + &hapd->drv_priv, force_ifname, if_addr, + hapd->conf->bridge[0] ? hapd->conf->bridge : + NULL)) { wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" MACSTR ")", MAC2STR(hapd->own_addr)); return -1; diff --git a/src/drivers/driver.h b/src/drivers/driver.h index df763020c..04b2a108f 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1604,11 +1604,13 @@ struct wpa_driver_ops { * @if_addr: Buffer for returning the allocated interface address * (this may differ from the requested addr if the driver cannot * change interface address) + * @bridge: Bridge interface to use or %NULL if no bridge configured * Returns: 0 on success, -1 on failure */ int (*if_add)(void *priv, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, void *bss_ctx, - void **drv_priv, char *force_ifname, u8 *if_addr); + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge); /** * if_remove - Remove a virtual interface diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index a64b091ab..e50d767ed 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -112,7 +112,10 @@ struct i802_bss { struct i802_bss *next; int ifindex; char ifname[IFNAMSIZ + 1]; + char brname[IFNAMSIZ]; unsigned int beacon_set:1; + unsigned int added_if_into_bridge:1; + unsigned int added_bridge:1; }; struct wpa_driver_nl80211_data { @@ -123,7 +126,6 @@ struct wpa_driver_nl80211_data { void *ctx; struct netlink_data *netlink; int ioctl_sock; /* socket for ioctl() use */ - char brname[IFNAMSIZ]; int ifindex; int if_removed; int if_disabled; @@ -158,8 +160,6 @@ struct wpa_driver_nl80211_data { int disable_11b_rates; unsigned int pending_remain_on_chan:1; - unsigned int added_bridge:1; - unsigned int added_if_into_bridge:1; u64 remain_on_chan_cookie; u64 send_action_cookie; @@ -2069,18 +2069,18 @@ static void wpa_driver_nl80211_deinit(void *priv) if (drv->nl_handle_preq) wpa_driver_nl80211_probe_req_report(bss, 0); - if (drv->added_if_into_bridge) { - if (linux_br_del_if(drv->ioctl_sock, drv->brname, bss->ifname) + if (bss->added_if_into_bridge) { + if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname) < 0) wpa_printf(MSG_INFO, "nl80211: Failed to remove " "interface %s from bridge %s: %s", - bss->ifname, drv->brname, strerror(errno)); + bss->ifname, bss->brname, strerror(errno)); } - if (drv->added_bridge) { - if (linux_br_del(drv->ioctl_sock, drv->brname) < 0) + if (bss->added_bridge) { + if (linux_br_del(drv->ioctl_sock, bss->brname) < 0) wpa_printf(MSG_INFO, "nl80211: Failed to remove " "bridge %s: %s", - drv->brname, strerror(errno)); + bss->brname, strerror(errno)); } nl80211_remove_monitor_interface(drv); @@ -5518,12 +5518,13 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, static int i802_check_bridge(struct wpa_driver_nl80211_data *drv, + struct i802_bss *bss, const char *brname, const char *ifname) { int ifindex; char in_br[IFNAMSIZ]; - os_strlcpy(drv->brname, brname, IFNAMSIZ); + os_strlcpy(bss->brname, brname, IFNAMSIZ); ifindex = if_nametoindex(brname); if (ifindex == 0) { /* @@ -5536,7 +5537,7 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv, brname, strerror(errno)); return -1; } - drv->added_bridge = 1; + bss->added_bridge = 1; add_ifidx(drv, if_nametoindex(brname)); } @@ -5563,7 +5564,7 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv, ifname, brname, strerror(errno)); return -1; } - drv->added_if_into_bridge = 1; + bss->added_if_into_bridge = 1; return 0; } @@ -5628,7 +5629,7 @@ static void *i802_init(struct hostapd_data *hapd, } if (params->num_bridge && params->bridge[0] && - i802_check_bridge(drv, params->bridge[0], params->ifname) < 0) + i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0) goto failed; if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) @@ -5741,7 +5742,8 @@ static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv, static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, void *bss_ctx, void **drv_priv, - char *force_ifname, u8 *if_addr) + char *force_ifname, u8 *if_addr, + const char *bridge) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -5806,6 +5808,15 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, #endif /* CONFIG_P2P */ #ifdef HOSTAPD + if (bridge && + i802_check_bridge(drv, new_bss, bridge, ifname) < 0) { + wpa_printf(MSG_ERROR, "nl80211: Failed to add the new " + "interface %s to a bridge %s", ifname, bridge); + nl80211_remove_iface(drv, ifidx); + os_free(new_bss); + return -1; + } + if (type == WPA_IF_AP_BSS) { if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) { nl80211_remove_iface(drv, ifidx); @@ -5838,6 +5849,23 @@ static int wpa_driver_nl80211_if_remove(void *priv, __func__, type, ifname, ifindex); if (ifindex <= 0) return -1; + +#ifdef HOSTAPD + if (bss->added_if_into_bridge) { + if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname) + < 0) + wpa_printf(MSG_INFO, "nl80211: Failed to remove " + "interface %s from bridge %s: %s", + bss->ifname, bss->brname, strerror(errno)); + } + if (bss->added_bridge) { + if (linux_br_del(drv->ioctl_sock, bss->brname) < 0) + wpa_printf(MSG_INFO, "nl80211: Failed to remove " + "bridge %s: %s", + bss->brname, strerror(errno)); + } +#endif /* HOSTAPD */ + nl80211_remove_iface(drv, ifindex); #ifdef HOSTAPD diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index c335225ec..5f9354ff1 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -1064,7 +1064,8 @@ static int test_driver_bss_remove(void *priv, const char *ifname) static int test_driver_if_add(void *priv, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, void *bss_ctx, void **drv_priv, - char *force_ifname, u8 *if_addr) + char *force_ifname, u8 *if_addr, + const char *bridge) { struct test_driver_bss *dbss = priv; struct wpa_driver_test_data *drv = dbss->drv; diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 682c56cc0..2f57af44a 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -413,12 +413,12 @@ static inline int wpa_drv_if_add(struct wpa_supplicant *wpa_s, enum wpa_driver_if_type type, const char *ifname, const u8 *addr, void *bss_ctx, char *force_ifname, - u8 *if_addr) + u8 *if_addr, const char *bridge) { if (wpa_s->driver->if_add) return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname, addr, bss_ctx, NULL, force_ifname, - if_addr); + if_addr, bridge); return -1; } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 431987a16..b3114932a 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -973,7 +973,7 @@ static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s, wpa_s->pending_interface_type = type; if (wpa_drv_if_add(wpa_s, type, ifname, NULL, NULL, force_ifname, - wpa_s->pending_interface_addr) < 0) { + wpa_s->pending_interface_addr, NULL) < 0) { wpa_printf(MSG_ERROR, "P2P: Failed to create new group " "interface"); return -1;