nl80211: Generic Linux master interface support for hostapd

Previously, hostapd only supported the case of EAPOL frames receiving
from interfaces enslaved into bridge. This commit adds support for any
Linux master (teaming, openvswitch, bonding, etc.) to be detected.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Anton Nayshtut 2015-03-04 12:12:36 +02:00 committed by Jouni Malinen
parent dca95e6924
commit cb05808c46
3 changed files with 39 additions and 9 deletions

View file

@ -5675,8 +5675,8 @@ static void *i802_init(struct hostapd_data *hapd,
struct wpa_driver_nl80211_data *drv; struct wpa_driver_nl80211_data *drv;
struct i802_bss *bss; struct i802_bss *bss;
size_t i; size_t i;
char brname[IFNAMSIZ]; char master_ifname[IFNAMSIZ];
int ifindex, br_ifindex; int ifindex, br_ifindex = 0;
int br_added = 0; int br_added = 0;
bss = wpa_driver_nl80211_drv_init(hapd, params->ifname, bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
@ -5687,15 +5687,21 @@ static void *i802_init(struct hostapd_data *hapd,
drv = bss->drv; drv = bss->drv;
if (linux_br_get(brname, params->ifname) == 0) { if (linux_br_get(master_ifname, params->ifname) == 0) {
wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s", wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
params->ifname, brname); params->ifname, master_ifname);
br_ifindex = if_nametoindex(brname); br_ifindex = if_nametoindex(master_ifname);
os_strlcpy(bss->brname, brname, IFNAMSIZ); os_strlcpy(bss->brname, master_ifname, IFNAMSIZ);
} else if ((params->num_bridge == 0 || !params->bridge[0]) &&
linux_master_get(master_ifname, params->ifname) == 0) {
wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in master %s",
params->ifname, master_ifname);
/* start listening for EAPOL on the master interface */
add_ifidx(drv, if_nametoindex(master_ifname));
} else { } else {
brname[0] = '\0'; master_ifname[0] = '\0';
br_ifindex = 0;
} }
bss->br_ifindex = br_ifindex; bss->br_ifindex = br_ifindex;
for (i = 0; i < params->num_bridge; i++) { for (i = 0; i < params->num_bridge; i++) {
@ -5715,7 +5721,7 @@ static void *i802_init(struct hostapd_data *hapd,
if (i802_check_bridge(drv, bss, params->bridge[0], if (i802_check_bridge(drv, bss, params->bridge[0],
params->ifname) < 0) params->ifname) < 0)
goto failed; goto failed;
if (os_strcmp(params->bridge[0], brname) != 0) if (os_strcmp(params->bridge[0], master_ifname) != 0)
br_added = 1; br_added = 1;
} }

View file

@ -219,3 +219,26 @@ int linux_br_get(char *brname, const char *ifname)
os_strlcpy(brname, pos, IFNAMSIZ); os_strlcpy(brname, pos, IFNAMSIZ);
return 0; return 0;
} }
int linux_master_get(char *master_ifname, const char *ifname)
{
char buf[128], masterlink[128], *pos;
ssize_t res;
/* check whether there is a master */
os_snprintf(buf, sizeof(buf), "/sys/class/net/%s/master", ifname);
res = readlink(buf, masterlink, sizeof(masterlink));
if (res < 0 || (size_t) res >= sizeof(masterlink))
return -1;
masterlink[res] = '\0';
pos = os_strrchr(masterlink, '/');
if (pos == NULL)
return -1;
pos++;
os_strlcpy(master_ifname, pos, IFNAMSIZ);
return 0;
}

View file

@ -18,5 +18,6 @@ int linux_br_del(int sock, const char *brname);
int linux_br_add_if(int sock, const char *brname, const char *ifname); int linux_br_add_if(int sock, const char *brname, const char *ifname);
int linux_br_del_if(int sock, const char *brname, const char *ifname); int linux_br_del_if(int sock, const char *brname, const char *ifname);
int linux_br_get(char *brname, const char *ifname); int linux_br_get(char *brname, const char *ifname);
int linux_master_get(char *master_ifname, const char *ifname);
#endif /* LINUX_IOCTL_H */ #endif /* LINUX_IOCTL_H */