From cb05808c46539922cf02e9e8527a062e90637ff9 Mon Sep 17 00:00:00 2001 From: Anton Nayshtut Date: Wed, 4 Mar 2015 12:12:36 +0200 Subject: [PATCH] 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 --- src/drivers/driver_nl80211.c | 24 +++++++++++++++--------- src/drivers/linux_ioctl.c | 23 +++++++++++++++++++++++ src/drivers/linux_ioctl.h | 1 + 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index da03e5062..b775bb65f 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5675,8 +5675,8 @@ static void *i802_init(struct hostapd_data *hapd, struct wpa_driver_nl80211_data *drv; struct i802_bss *bss; size_t i; - char brname[IFNAMSIZ]; - int ifindex, br_ifindex; + char master_ifname[IFNAMSIZ]; + int ifindex, br_ifindex = 0; int br_added = 0; bss = wpa_driver_nl80211_drv_init(hapd, params->ifname, @@ -5687,15 +5687,21 @@ static void *i802_init(struct hostapd_data *hapd, 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", - params->ifname, brname); - br_ifindex = if_nametoindex(brname); - os_strlcpy(bss->brname, brname, IFNAMSIZ); + params->ifname, master_ifname); + br_ifindex = if_nametoindex(master_ifname); + 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 { - brname[0] = '\0'; - br_ifindex = 0; + master_ifname[0] = '\0'; } + bss->br_ifindex = br_ifindex; 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], params->ifname) < 0) goto failed; - if (os_strcmp(params->bridge[0], brname) != 0) + if (os_strcmp(params->bridge[0], master_ifname) != 0) br_added = 1; } diff --git a/src/drivers/linux_ioctl.c b/src/drivers/linux_ioctl.c index 837971d25..e21147af1 100644 --- a/src/drivers/linux_ioctl.c +++ b/src/drivers/linux_ioctl.c @@ -219,3 +219,26 @@ int linux_br_get(char *brname, const char *ifname) os_strlcpy(brname, pos, IFNAMSIZ); 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; +} diff --git a/src/drivers/linux_ioctl.h b/src/drivers/linux_ioctl.h index c03fe6e9a..6de4d9b88 100644 --- a/src/drivers/linux_ioctl.h +++ b/src/drivers/linux_ioctl.h @@ -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_del_if(int sock, const 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 */