diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -722,7 +722,8 @@ ifp->if_baudrate = IF_Mbps(maxrate); ether_ifattach(ifp, macaddr); - IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp)); + /* Do initial MAC address sync */ + ieee80211_vap_copy_mac_address(vap); /* hook output method setup by ether_ifattach */ vap->iv_output = ifp->if_output; ifp->if_output = ieee80211_output; diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -540,6 +540,9 @@ #define DEBUGNET80211_SET(ic, driver) #endif /* DEBUGNET */ +void ieee80211_vap_sync_mac_address(struct ieee80211vap *); +void ieee80211_vap_copy_mac_address(struct ieee80211vap *); + #endif /* _KERNEL */ /* XXX this stuff belongs elsewhere */ diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -1192,6 +1192,51 @@ } #endif +/** + * @brief Check if the MAC address was changed by the upper layer. + * + * This is specifically to handle cases like the MAC address + * being changed via an ioctl (eg SIOCSIFLLADDR). + * + * @param vap VAP to sync MAC address for + */ +void +ieee80211_vap_sync_mac_address(struct ieee80211vap *vap) +{ + struct epoch_tracker et; + const struct ifnet *ifp = vap->iv_ifp; + + /* + * Check if the MAC address was changed + * via SIOCSIFLLADDR ioctl. + * + * NB: device may be detached during initialization; + * use if_ioctl for existence check. + */ + NET_EPOCH_ENTER(et); + if (ifp->if_ioctl == ieee80211_ioctl && + (ifp->if_flags & IFF_UP) == 0 && + !IEEE80211_ADDR_EQ(vap->iv_myaddr, IF_LLADDR(ifp))) + IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp)); + NET_EPOCH_EXIT(et); +} + +/** + * @brief Initial MAC address setup for a VAP. + * + * @param vap VAP to sync MAC address for + */ +void +ieee80211_vap_copy_mac_address(struct ieee80211vap *vap) +{ + struct epoch_tracker et; + const struct ifnet *ifp = vap->iv_ifp; + + NET_EPOCH_ENTER(et); + IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp)); + NET_EPOCH_EXIT(et); +} + /* * Module glue. * diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -3631,24 +3631,8 @@ IEEE80211_UNLOCK(ic); /* Wait for parent ioctl handler if it was queued */ if (wait) { - struct epoch_tracker et; - ieee80211_waitfor_parent(ic); - - /* - * Check if the MAC address was changed - * via SIOCSIFLLADDR ioctl. - * - * NB: device may be detached during initialization; - * use if_ioctl for existence check. - */ - NET_EPOCH_ENTER(et); - if (ifp->if_ioctl == ieee80211_ioctl && - (ifp->if_flags & IFF_UP) == 0 && - !IEEE80211_ADDR_EQ(vap->iv_myaddr, IF_LLADDR(ifp))) - IEEE80211_ADDR_COPY(vap->iv_myaddr, - IF_LLADDR(ifp)); - NET_EPOCH_EXIT(et); + ieee80211_vap_sync_mac_address(vap); } break; case SIOCADDMULTI: diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -634,10 +634,10 @@ * XXX process data frames whilst scanning. */ if ((! IEEE80211_IS_MULTICAST(wh->i_addr1)) - && (! IEEE80211_ADDR_EQ(wh->i_addr1, IF_LLADDR(ifp)))) { + && (! IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr))) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, bssid, NULL, "not to cur sta: lladdr=%6D, addr1=%6D", - IF_LLADDR(ifp), ":", wh->i_addr1, ":"); + vap->iv_myaddr, ":", wh->i_addr1, ":"); vap->iv_stats.is_rx_wrongbss++; goto out; }