AP: Extend the BSS bridge neighbor entry management to support IPv6
This allows adding/deleting an IPv6 neighbor entry to/from the bridge, to which the BSS belongs. This commit adds the needed functionality in driver_nl80211.c for the Linux bridge implementation. In theory, this could be shared with multiple Linux driver interfaces, but for now, only the main nl80211 interface is supported. Signed-off-by: Kyeyoon Park <kyeyoonp@qca.qualcomm.com>
This commit is contained in:
parent
7e4d893978
commit
ed4ddb6d77
6 changed files with 53 additions and 25 deletions
|
@ -281,23 +281,24 @@ static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf,
|
|||
}
|
||||
|
||||
static inline int hostapd_drv_br_add_ip_neigh(struct hostapd_data *hapd,
|
||||
be32 ipaddr, int prefixlen,
|
||||
const u8 *addr)
|
||||
int version, const u8 *ipaddr,
|
||||
int prefixlen, const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
||||
hapd->driver->br_add_ip_neigh == NULL)
|
||||
return -1;
|
||||
return hapd->driver->br_add_ip_neigh(hapd->drv_priv, ipaddr, prefixlen,
|
||||
addr);
|
||||
return hapd->driver->br_add_ip_neigh(hapd->drv_priv, version, ipaddr,
|
||||
prefixlen, addr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_br_delete_ip_neigh(struct hostapd_data *hapd,
|
||||
be32 ipaddr)
|
||||
u8 version, const u8 *ipaddr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
||||
hapd->driver->br_delete_ip_neigh == NULL)
|
||||
return -1;
|
||||
return hapd->driver->br_delete_ip_neigh(hapd->drv_priv, ipaddr);
|
||||
return hapd->driver->br_delete_ip_neigh(hapd->drv_priv, version,
|
||||
ipaddr);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_br_port_set_attr(struct hostapd_data *hapd,
|
||||
|
|
|
@ -114,11 +114,12 @@ static void handle_dhcp(void *ctx, const u8 *src_addr, const u8 *buf,
|
|||
wpa_printf(MSG_DEBUG,
|
||||
"dhcp_snoop: Removing IPv4 address %X from the ip neigh table",
|
||||
sta->ipaddr);
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, sta->ipaddr);
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, 4,
|
||||
(u8 *) &sta->ipaddr);
|
||||
}
|
||||
|
||||
res = hostapd_drv_br_add_ip_neigh(hapd, b->your_ip, prefixlen,
|
||||
sta->addr);
|
||||
res = hostapd_drv_br_add_ip_neigh(hapd, 4, (u8 *) &b->your_ip,
|
||||
prefixlen, sta->addr);
|
||||
if (res) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"dhcp_snoop: Adding ip neigh table failed: %d",
|
||||
|
|
|
@ -1717,7 +1717,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
|
|||
accounting_sta_stop(hapd, sta);
|
||||
ieee802_1x_free_station(sta);
|
||||
if (sta->ipaddr)
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, sta->ipaddr);
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
|
||||
if (sta->timeout_next == STA_NULLFUNC ||
|
||||
|
|
|
@ -157,7 +157,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
|
||||
|
||||
if (sta->ipaddr)
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, sta->ipaddr);
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
|
||||
|
||||
if (!hapd->iface->driver_ap_teardown &&
|
||||
!(sta->flags & WLAN_STA_PREAUTH))
|
||||
|
@ -615,7 +615,7 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
|
||||
if (sta->ipaddr)
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, sta->ipaddr);
|
||||
hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
|
||||
MAC2STR(sta->addr));
|
||||
|
|
|
@ -2632,21 +2632,23 @@ struct wpa_driver_ops {
|
|||
/**
|
||||
* br_add_ip_neigh - Add a neigh to the bridge ip neigh table
|
||||
* @priv: Private driver interface data
|
||||
* @ipaddr: IPv4 address for the neigh entry
|
||||
* @prefixlen: IPv4 address netmask prefix length
|
||||
* @version: IP version of the IP address, 4 or 6
|
||||
* @ipaddr: IP address for the neigh entry
|
||||
* @prefixlen: IP address prefix length
|
||||
* @addr: Corresponding MAC address
|
||||
* Returns: 0 on success, negative (<0) on failure
|
||||
*/
|
||||
int (*br_add_ip_neigh)(void *priv, be32 ipaddr, int prefixlen,
|
||||
const u8 *addr);
|
||||
int (*br_add_ip_neigh)(void *priv, u8 version, const u8 *ipaddr,
|
||||
int prefixlen, const u8 *addr);
|
||||
|
||||
/**
|
||||
* br_delete_ip_neigh - Remove a neigh from the bridge ip neigh table
|
||||
* @priv: Private driver interface data
|
||||
* @ipaddr: IPv4 address for the neigh entry
|
||||
* @version: IP version of the IP address, 4 or 6
|
||||
* @ipaddr: IP address for the neigh entry
|
||||
* Returns: 0 on success, negative (<0) on failure
|
||||
*/
|
||||
int (*br_delete_ip_neigh)(void *priv, be32 ipaddr);
|
||||
int (*br_delete_ip_neigh)(void *priv, u8 version, const u8 *ipaddr);
|
||||
|
||||
/**
|
||||
* br_port_set_attr - Set a bridge port attribute
|
||||
|
|
|
@ -8949,8 +8949,9 @@ nla_put_failure:
|
|||
#endif /* CONFIG_MESH */
|
||||
|
||||
|
||||
static int wpa_driver_br_add_ip_neigh(void *priv, be32 ipaddr,
|
||||
int prefixlen, const u8 *addr)
|
||||
static int wpa_driver_br_add_ip_neigh(void *priv, u8 version,
|
||||
const u8 *ipaddr, int prefixlen,
|
||||
const u8 *addr)
|
||||
{
|
||||
#ifdef CONFIG_LIBNL3_ROUTE
|
||||
struct i802_bss *bss = priv;
|
||||
|
@ -8958,9 +8959,10 @@ static int wpa_driver_br_add_ip_neigh(void *priv, be32 ipaddr,
|
|||
struct rtnl_neigh *rn;
|
||||
struct nl_addr *nl_ipaddr = NULL;
|
||||
struct nl_addr *nl_lladdr = NULL;
|
||||
int family, addrsize;
|
||||
int res;
|
||||
|
||||
if (ipaddr == 0 || prefixlen == 0 || !addr)
|
||||
if (!ipaddr || prefixlen == 0 || !addr)
|
||||
return -EINVAL;
|
||||
|
||||
if (bss->br_ifindex == 0) {
|
||||
|
@ -8975,12 +8977,22 @@ static int wpa_driver_br_add_ip_neigh(void *priv, be32 ipaddr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (version == 4) {
|
||||
family = AF_INET;
|
||||
addrsize = 4;
|
||||
} else if (version == 6) {
|
||||
family = AF_INET6;
|
||||
addrsize = 16;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rn = rtnl_neigh_alloc();
|
||||
if (rn == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* set the destination ip address for neigh */
|
||||
nl_ipaddr = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr));
|
||||
nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
|
||||
if (nl_ipaddr == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
||||
res = -ENOMEM;
|
||||
|
@ -9026,18 +9038,30 @@ errout:
|
|||
}
|
||||
|
||||
|
||||
static int wpa_driver_br_delete_ip_neigh(void *priv, be32 ipaddr)
|
||||
static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
|
||||
const u8 *ipaddr)
|
||||
{
|
||||
#ifdef CONFIG_LIBNL3_ROUTE
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct rtnl_neigh *rn;
|
||||
struct nl_addr *nl_ipaddr;
|
||||
int family, addrsize;
|
||||
int res;
|
||||
|
||||
if (ipaddr == 0)
|
||||
if (!ipaddr)
|
||||
return -EINVAL;
|
||||
|
||||
if (version == 4) {
|
||||
family = AF_INET;
|
||||
addrsize = 4;
|
||||
} else if (version == 6) {
|
||||
family = AF_INET6;
|
||||
addrsize = 16;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bss->br_ifindex == 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: bridge must be set to delete an ip neigh");
|
||||
|
@ -9055,7 +9079,7 @@ static int wpa_driver_br_delete_ip_neigh(void *priv, be32 ipaddr)
|
|||
return -ENOMEM;
|
||||
|
||||
/* set the destination ip address for neigh */
|
||||
nl_ipaddr = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr));
|
||||
nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
|
||||
if (nl_ipaddr == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
||||
res = -ENOMEM;
|
||||
|
|
Loading…
Reference in a new issue