nl80211: Extend bridge add/del operations for secondary BSSes
Previously, only the main interface was added to a bridge. Extend this to apply to all configured BSSes.
This commit is contained in:
parent
6ca4da6518
commit
e17a2477db
8 changed files with 60 additions and 24 deletions
|
@ -281,7 +281,7 @@ int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
||||||
char force_ifname[IFNAMSIZ];
|
char force_ifname[IFNAMSIZ];
|
||||||
u8 if_addr[ETH_ALEN];
|
u8 if_addr[ETH_ALEN];
|
||||||
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
|
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,
|
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
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)
|
if (hapd->driver == NULL || hapd->driver->if_add == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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_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,
|
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
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,
|
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||||
const char *ifname);
|
const char *ifname);
|
||||||
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
||||||
|
|
|
@ -510,7 +510,9 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
||||||
hapd->interface_added = 1;
|
hapd->interface_added = 1;
|
||||||
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
|
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
|
||||||
hapd->conf->iface, hapd->own_addr, hapd,
|
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="
|
wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
|
||||||
MACSTR ")", MAC2STR(hapd->own_addr));
|
MACSTR ")", MAC2STR(hapd->own_addr));
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1604,11 +1604,13 @@ struct wpa_driver_ops {
|
||||||
* @if_addr: Buffer for returning the allocated interface address
|
* @if_addr: Buffer for returning the allocated interface address
|
||||||
* (this may differ from the requested addr if the driver cannot
|
* (this may differ from the requested addr if the driver cannot
|
||||||
* change interface address)
|
* change interface address)
|
||||||
|
* @bridge: Bridge interface to use or %NULL if no bridge configured
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int (*if_add)(void *priv, enum wpa_driver_if_type type,
|
int (*if_add)(void *priv, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
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
|
* if_remove - Remove a virtual interface
|
||||||
|
|
|
@ -112,7 +112,10 @@ struct i802_bss {
|
||||||
struct i802_bss *next;
|
struct i802_bss *next;
|
||||||
int ifindex;
|
int ifindex;
|
||||||
char ifname[IFNAMSIZ + 1];
|
char ifname[IFNAMSIZ + 1];
|
||||||
|
char brname[IFNAMSIZ];
|
||||||
unsigned int beacon_set:1;
|
unsigned int beacon_set:1;
|
||||||
|
unsigned int added_if_into_bridge:1;
|
||||||
|
unsigned int added_bridge:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wpa_driver_nl80211_data {
|
struct wpa_driver_nl80211_data {
|
||||||
|
@ -123,7 +126,6 @@ struct wpa_driver_nl80211_data {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
struct netlink_data *netlink;
|
struct netlink_data *netlink;
|
||||||
int ioctl_sock; /* socket for ioctl() use */
|
int ioctl_sock; /* socket for ioctl() use */
|
||||||
char brname[IFNAMSIZ];
|
|
||||||
int ifindex;
|
int ifindex;
|
||||||
int if_removed;
|
int if_removed;
|
||||||
int if_disabled;
|
int if_disabled;
|
||||||
|
@ -158,8 +160,6 @@ struct wpa_driver_nl80211_data {
|
||||||
int disable_11b_rates;
|
int disable_11b_rates;
|
||||||
|
|
||||||
unsigned int pending_remain_on_chan:1;
|
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 remain_on_chan_cookie;
|
||||||
u64 send_action_cookie;
|
u64 send_action_cookie;
|
||||||
|
@ -2069,18 +2069,18 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
||||||
|
|
||||||
if (drv->nl_handle_preq)
|
if (drv->nl_handle_preq)
|
||||||
wpa_driver_nl80211_probe_req_report(bss, 0);
|
wpa_driver_nl80211_probe_req_report(bss, 0);
|
||||||
if (drv->added_if_into_bridge) {
|
if (bss->added_if_into_bridge) {
|
||||||
if (linux_br_del_if(drv->ioctl_sock, drv->brname, bss->ifname)
|
if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname)
|
||||||
< 0)
|
< 0)
|
||||||
wpa_printf(MSG_INFO, "nl80211: Failed to remove "
|
wpa_printf(MSG_INFO, "nl80211: Failed to remove "
|
||||||
"interface %s from bridge %s: %s",
|
"interface %s from bridge %s: %s",
|
||||||
bss->ifname, drv->brname, strerror(errno));
|
bss->ifname, bss->brname, strerror(errno));
|
||||||
}
|
}
|
||||||
if (drv->added_bridge) {
|
if (bss->added_bridge) {
|
||||||
if (linux_br_del(drv->ioctl_sock, drv->brname) < 0)
|
if (linux_br_del(drv->ioctl_sock, bss->brname) < 0)
|
||||||
wpa_printf(MSG_INFO, "nl80211: Failed to remove "
|
wpa_printf(MSG_INFO, "nl80211: Failed to remove "
|
||||||
"bridge %s: %s",
|
"bridge %s: %s",
|
||||||
drv->brname, strerror(errno));
|
bss->brname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
nl80211_remove_monitor_interface(drv);
|
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,
|
static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
|
||||||
|
struct i802_bss *bss,
|
||||||
const char *brname, const char *ifname)
|
const char *brname, const char *ifname)
|
||||||
{
|
{
|
||||||
int ifindex;
|
int ifindex;
|
||||||
char in_br[IFNAMSIZ];
|
char in_br[IFNAMSIZ];
|
||||||
|
|
||||||
os_strlcpy(drv->brname, brname, IFNAMSIZ);
|
os_strlcpy(bss->brname, brname, IFNAMSIZ);
|
||||||
ifindex = if_nametoindex(brname);
|
ifindex = if_nametoindex(brname);
|
||||||
if (ifindex == 0) {
|
if (ifindex == 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -5536,7 +5537,7 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
|
||||||
brname, strerror(errno));
|
brname, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
drv->added_bridge = 1;
|
bss->added_bridge = 1;
|
||||||
add_ifidx(drv, if_nametoindex(brname));
|
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));
|
ifname, brname, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
drv->added_if_into_bridge = 1;
|
bss->added_if_into_bridge = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -5628,7 +5629,7 @@ static void *i802_init(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params->num_bridge && params->bridge[0] &&
|
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;
|
goto failed;
|
||||||
|
|
||||||
if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1))
|
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,
|
static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr,
|
const char *ifname, const u8 *addr,
|
||||||
void *bss_ctx, void **drv_priv,
|
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 i802_bss *bss = priv;
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
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 */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
#ifdef HOSTAPD
|
#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 (type == WPA_IF_AP_BSS) {
|
||||||
if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) {
|
if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) {
|
||||||
nl80211_remove_iface(drv, ifidx);
|
nl80211_remove_iface(drv, ifidx);
|
||||||
|
@ -5838,6 +5849,23 @@ static int wpa_driver_nl80211_if_remove(void *priv,
|
||||||
__func__, type, ifname, ifindex);
|
__func__, type, ifname, ifindex);
|
||||||
if (ifindex <= 0)
|
if (ifindex <= 0)
|
||||||
return -1;
|
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);
|
nl80211_remove_iface(drv, ifindex);
|
||||||
|
|
||||||
#ifdef HOSTAPD
|
#ifdef HOSTAPD
|
||||||
|
|
|
@ -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,
|
static int test_driver_if_add(void *priv, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr,
|
const char *ifname, const u8 *addr,
|
||||||
void *bss_ctx, void **drv_priv,
|
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 test_driver_bss *dbss = priv;
|
||||||
struct wpa_driver_test_data *drv = dbss->drv;
|
struct wpa_driver_test_data *drv = dbss->drv;
|
||||||
|
|
|
@ -413,12 +413,12 @@ static inline int wpa_drv_if_add(struct wpa_supplicant *wpa_s,
|
||||||
enum wpa_driver_if_type type,
|
enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr,
|
const char *ifname, const u8 *addr,
|
||||||
void *bss_ctx, char *force_ifname,
|
void *bss_ctx, char *force_ifname,
|
||||||
u8 *if_addr)
|
u8 *if_addr, const char *bridge)
|
||||||
{
|
{
|
||||||
if (wpa_s->driver->if_add)
|
if (wpa_s->driver->if_add)
|
||||||
return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname,
|
return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname,
|
||||||
addr, bss_ctx, NULL, force_ifname,
|
addr, bss_ctx, NULL, force_ifname,
|
||||||
if_addr);
|
if_addr, bridge);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -973,7 +973,7 @@ static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
wpa_s->pending_interface_type = type;
|
wpa_s->pending_interface_type = type;
|
||||||
if (wpa_drv_if_add(wpa_s, type, ifname, NULL, NULL, force_ifname,
|
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 "
|
wpa_printf(MSG_ERROR, "P2P: Failed to create new group "
|
||||||
"interface");
|
"interface");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in a new issue