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 */