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,
|
static inline int hostapd_drv_br_add_ip_neigh(struct hostapd_data *hapd,
|
||||||
be32 ipaddr, int prefixlen,
|
int version, const u8 *ipaddr,
|
||||||
const u8 *addr)
|
int prefixlen, const u8 *addr)
|
||||||
{
|
{
|
||||||
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
||||||
hapd->driver->br_add_ip_neigh == NULL)
|
hapd->driver->br_add_ip_neigh == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return hapd->driver->br_add_ip_neigh(hapd->drv_priv, ipaddr, prefixlen,
|
return hapd->driver->br_add_ip_neigh(hapd->drv_priv, version, ipaddr,
|
||||||
addr);
|
prefixlen, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int hostapd_drv_br_delete_ip_neigh(struct hostapd_data *hapd,
|
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 ||
|
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
||||||
hapd->driver->br_delete_ip_neigh == NULL)
|
hapd->driver->br_delete_ip_neigh == NULL)
|
||||||
return -1;
|
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,
|
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,
|
wpa_printf(MSG_DEBUG,
|
||||||
"dhcp_snoop: Removing IPv4 address %X from the ip neigh table",
|
"dhcp_snoop: Removing IPv4 address %X from the ip neigh table",
|
||||||
sta->ipaddr);
|
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,
|
res = hostapd_drv_br_add_ip_neigh(hapd, 4, (u8 *) &b->your_ip,
|
||||||
sta->addr);
|
prefixlen, sta->addr);
|
||||||
if (res) {
|
if (res) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"dhcp_snoop: Adding ip neigh table failed: %d",
|
"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);
|
accounting_sta_stop(hapd, sta);
|
||||||
ieee802_1x_free_station(sta);
|
ieee802_1x_free_station(sta);
|
||||||
if (sta->ipaddr)
|
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);
|
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||||
|
|
||||||
if (sta->timeout_next == STA_NULLFUNC ||
|
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);
|
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
|
||||||
|
|
||||||
if (sta->ipaddr)
|
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 &&
|
if (!hapd->iface->driver_ap_teardown &&
|
||||||
!(sta->flags & WLAN_STA_PREAUTH))
|
!(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);
|
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||||
|
|
||||||
if (sta->ipaddr)
|
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",
|
wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
|
||||||
MAC2STR(sta->addr));
|
MAC2STR(sta->addr));
|
||||||
|
|
|
@ -2632,21 +2632,23 @@ struct wpa_driver_ops {
|
||||||
/**
|
/**
|
||||||
* br_add_ip_neigh - Add a neigh to the bridge ip neigh table
|
* br_add_ip_neigh - Add a neigh to the bridge ip neigh table
|
||||||
* @priv: Private driver interface data
|
* @priv: Private driver interface data
|
||||||
* @ipaddr: IPv4 address for the neigh entry
|
* @version: IP version of the IP address, 4 or 6
|
||||||
* @prefixlen: IPv4 address netmask prefix length
|
* @ipaddr: IP address for the neigh entry
|
||||||
|
* @prefixlen: IP address prefix length
|
||||||
* @addr: Corresponding MAC address
|
* @addr: Corresponding MAC address
|
||||||
* Returns: 0 on success, negative (<0) on failure
|
* Returns: 0 on success, negative (<0) on failure
|
||||||
*/
|
*/
|
||||||
int (*br_add_ip_neigh)(void *priv, be32 ipaddr, int prefixlen,
|
int (*br_add_ip_neigh)(void *priv, u8 version, const u8 *ipaddr,
|
||||||
const u8 *addr);
|
int prefixlen, const u8 *addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* br_delete_ip_neigh - Remove a neigh from the bridge ip neigh table
|
* br_delete_ip_neigh - Remove a neigh from the bridge ip neigh table
|
||||||
* @priv: Private driver interface data
|
* @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
|
* 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
|
* br_port_set_attr - Set a bridge port attribute
|
||||||
|
|
|
@ -8949,8 +8949,9 @@ nla_put_failure:
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_br_add_ip_neigh(void *priv, be32 ipaddr,
|
static int wpa_driver_br_add_ip_neigh(void *priv, u8 version,
|
||||||
int prefixlen, const u8 *addr)
|
const u8 *ipaddr, int prefixlen,
|
||||||
|
const u8 *addr)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_LIBNL3_ROUTE
|
#ifdef CONFIG_LIBNL3_ROUTE
|
||||||
struct i802_bss *bss = priv;
|
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 rtnl_neigh *rn;
|
||||||
struct nl_addr *nl_ipaddr = NULL;
|
struct nl_addr *nl_ipaddr = NULL;
|
||||||
struct nl_addr *nl_lladdr = NULL;
|
struct nl_addr *nl_lladdr = NULL;
|
||||||
|
int family, addrsize;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (ipaddr == 0 || prefixlen == 0 || !addr)
|
if (!ipaddr || prefixlen == 0 || !addr)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (bss->br_ifindex == 0) {
|
if (bss->br_ifindex == 0) {
|
||||||
|
@ -8975,12 +8977,22 @@ static int wpa_driver_br_add_ip_neigh(void *priv, be32 ipaddr,
|
||||||
return -1;
|
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();
|
rn = rtnl_neigh_alloc();
|
||||||
if (rn == NULL)
|
if (rn == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* set the destination ip address for neigh */
|
/* 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) {
|
if (nl_ipaddr == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
||||||
res = -ENOMEM;
|
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
|
#ifdef CONFIG_LIBNL3_ROUTE
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
struct rtnl_neigh *rn;
|
struct rtnl_neigh *rn;
|
||||||
struct nl_addr *nl_ipaddr;
|
struct nl_addr *nl_ipaddr;
|
||||||
|
int family, addrsize;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (ipaddr == 0)
|
if (!ipaddr)
|
||||||
return -EINVAL;
|
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) {
|
if (bss->br_ifindex == 0) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: bridge must be set to delete an ip neigh");
|
"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;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* set the destination ip address for neigh */
|
/* 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) {
|
if (nl_ipaddr == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
||||||
res = -ENOMEM;
|
res = -ENOMEM;
|
||||||
|
|
Loading…
Reference in a new issue