From 97ed9a06df566357f0ebe57f8080f78726e78db6 Mon Sep 17 00:00:00 2001 From: Kyeyoon Park Date: Tue, 9 Sep 2014 15:38:03 -0700 Subject: [PATCH] nl80211: Remove bridge FDB entry upon sta_remove() The FDB entry removal ensures that the traffic destined for a disassociated station's MAC address is no longer forwarded from the bridge to the BSS. Signed-off-by: Kyeyoon Park --- src/drivers/driver_nl80211.c | 64 ++++++++++++++++++++++++++++++++++++ src/drivers/drivers.mak | 4 +++ src/drivers/drivers.mk | 4 +++ 3 files changed, 72 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 26e31a3a8..5c922a057 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -19,6 +19,9 @@ #include #include #include +#ifdef CONFIG_LIBNL3_ROUTE +#include +#endif /* CONFIG_LIBNL3_ROUTE */ #include #include #include @@ -328,6 +331,8 @@ struct wpa_driver_nl80211_data { int eapol_sock; /* socket for EAPOL frames */ + struct nl_sock *rtnl_sk; /* nl_sock for NETLINK_ROUTE */ + int default_if_indices[16]; int *if_indices; int num_if_indices; @@ -4932,6 +4937,8 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) wpa_printf(MSG_INFO, "nl80211: Failed to remove " "interface %s from bridge %s: %s", bss->ifname, bss->brname, strerror(errno)); + if (drv->rtnl_sk) + nl_socket_free(drv->rtnl_sk); } if (bss->added_bridge) { if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0) @@ -7751,6 +7758,43 @@ static int wpa_driver_nl80211_sta_add(void *priv, } +static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr) +{ +#ifdef CONFIG_LIBNL3_ROUTE + struct wpa_driver_nl80211_data *drv = bss->drv; + struct rtnl_neigh *rn; + struct nl_addr *nl_addr; + int err; + + rn = rtnl_neigh_alloc(); + if (!rn) + return; + + rtnl_neigh_set_family(rn, AF_BRIDGE); + rtnl_neigh_set_ifindex(rn, bss->ifindex); + nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN); + if (!nl_addr) { + rtnl_neigh_put(rn); + return; + } + rtnl_neigh_set_lladdr(rn, nl_addr); + + err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0); + if (err < 0) { + wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for " + MACSTR " ifindex=%d failed: %s", MAC2STR(addr), + bss->ifindex, nl_geterror(err)); + } else { + wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for " + MACSTR, MAC2STR(addr)); + } + + nl_addr_put(nl_addr); + rtnl_neigh_put(rn); +#endif /* CONFIG_LIBNL3_ROUTE */ +} + + static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr) { struct wpa_driver_nl80211_data *drv = bss->drv; @@ -7771,6 +7815,10 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr) wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR " --> %d (%s)", bss->ifname, MAC2STR(addr), ret, strerror(-ret)); + + if (drv->rtnl_sk) + rtnl_neigh_delete_fdb_entry(bss, addr); + if (ret == -ENOENT) return 0; return ret; @@ -10054,6 +10102,22 @@ static void *i802_init(struct hostapd_data *hapd, i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0) goto failed; +#ifdef CONFIG_LIBNL3_ROUTE + if (bss->added_if_into_bridge) { + drv->rtnl_sk = nl_socket_alloc(); + if (drv->rtnl_sk == NULL) { + wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock"); + goto failed; + } + + if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) { + wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s", + strerror(errno)); + goto failed; + } + } +#endif /* CONFIG_LIBNL3_ROUTE */ + drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); if (drv->eapol_sock < 0) { wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s", diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak index 40aaba591..cdb913e31 100644 --- a/src/drivers/drivers.mak +++ b/src/drivers/drivers.mak @@ -36,6 +36,10 @@ ifdef CONFIG_LIBNL32 DRV_LIBS += -lnl-3 DRV_LIBS += -lnl-genl-3 DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3 +ifdef CONFIG_LIBNL3_ROUTE + DRV_LIBS += -lnl-route-3 + DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE +endif else ifdef CONFIG_LIBNL_TINY DRV_LIBS += -lnl-tiny diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk index db8561ae6..9fa70d9c9 100644 --- a/src/drivers/drivers.mk +++ b/src/drivers/drivers.mk @@ -31,6 +31,10 @@ ifdef CONFIG_LIBNL32 DRV_LIBS += -lnl-3 DRV_LIBS += -lnl-genl-3 DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3 +ifdef CONFIG_LIBNL3_ROUTE + DRV_LIBS += -lnl-route-3 + DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE +endif else ifdef CONFIG_LIBNL_TINY DRV_LIBS += -lnl-tiny