mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 17:59:25 +01:00
netconfig: Re-add FILS handling
Load the settings from FILS IE data into our l_netconfig instance when appropriate.
This commit is contained in:
parent
fbdd4471a1
commit
11bae53408
@ -103,6 +103,10 @@ void netconfig_commit(struct netconfig *netconfig, uint8_t family,
|
|||||||
if (family == AF_INET &&
|
if (family == AF_INET &&
|
||||||
!netconfig->static_config[INDEX_FOR_AF(family)])
|
!netconfig->static_config[INDEX_FOR_AF(family)])
|
||||||
netconfig_dhcp_gateway_to_arp(netconfig);
|
netconfig_dhcp_gateway_to_arp(netconfig);
|
||||||
|
|
||||||
|
if (!netconfig->connected[INDEX_FOR_AF(family)] &&
|
||||||
|
netconfig_use_fils_addr(netconfig, family))
|
||||||
|
netconfig_commit_fils_macs(netconfig, family);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +191,53 @@ void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig)
|
|||||||
l_debug("l_rtnl_neighbor_set_hwaddr failed");
|
l_debug("l_rtnl_neighbor_set_hwaddr failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void netconfig_commit_fils_macs(struct netconfig *netconfig, uint8_t family)
|
||||||
|
{
|
||||||
|
const struct ie_fils_ip_addr_response_info *fils =
|
||||||
|
netconfig->fils_override;
|
||||||
|
const void *addr;
|
||||||
|
const void *hwaddr;
|
||||||
|
size_t addr_len = (family == AF_INET ? 4 : 16);
|
||||||
|
uint32_t ifindex = netdev_get_ifindex(netconfig->netdev);
|
||||||
|
|
||||||
|
if (!fils)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to use the gateway/DNS MAC addressed received from the AP
|
||||||
|
* by writing the mapping directly into the netdev's ARP table so as
|
||||||
|
* to save one data frame roundtrip before first IP connections are
|
||||||
|
* established. This is very low-priority but print error messages
|
||||||
|
* just because they may indicate bigger problems.
|
||||||
|
*/
|
||||||
|
|
||||||
|
addr = (family == AF_INET ? (void *) &fils->ipv4_gateway :
|
||||||
|
(void *) &fils->ipv6_gateway);
|
||||||
|
hwaddr = (family == AF_INET ?
|
||||||
|
&fils->ipv4_gateway_mac : &fils->ipv6_gateway_mac);
|
||||||
|
|
||||||
|
if (!l_memeqzero(addr, addr_len) && !l_memeqzero(hwaddr, ETH_ALEN) &&
|
||||||
|
unlikely(!l_rtnl_neighbor_set_hwaddr(rtnl, ifindex,
|
||||||
|
family, addr, hwaddr, ETH_ALEN,
|
||||||
|
netconfig_set_neighbor_entry_cb,
|
||||||
|
NULL, NULL)))
|
||||||
|
l_debug("l_rtnl_neighbor_set_hwaddr(%s, gateway) failed",
|
||||||
|
family == AF_INET ? "AF_INET" : "AF_INET6");
|
||||||
|
|
||||||
|
addr = (family == AF_INET ? (void *) &fils->ipv4_dns :
|
||||||
|
(void *) &fils->ipv6_dns);
|
||||||
|
hwaddr = (family == AF_INET ?
|
||||||
|
&fils->ipv4_dns_mac : &fils->ipv6_dns_mac);
|
||||||
|
|
||||||
|
if (!l_memeqzero(addr, addr_len) && !l_memeqzero(hwaddr, ETH_ALEN) &&
|
||||||
|
unlikely(!l_rtnl_neighbor_set_hwaddr(rtnl, ifindex,
|
||||||
|
family, addr, hwaddr, ETH_ALEN,
|
||||||
|
netconfig_set_neighbor_entry_cb,
|
||||||
|
NULL, NULL)))
|
||||||
|
l_debug("l_rtnl_neighbor_set_hwaddr(%s, DNS) failed",
|
||||||
|
family == AF_INET ? "AF_INET" : "AF_INET6");
|
||||||
|
}
|
||||||
|
|
||||||
static void netconfig_dns_list_update(struct netconfig *netconfig)
|
static void netconfig_dns_list_update(struct netconfig *netconfig)
|
||||||
{
|
{
|
||||||
_auto_(l_strv_free) char **dns_list =
|
_auto_(l_strv_free) char **dns_list =
|
||||||
|
115
src/netconfig.c
115
src/netconfig.c
@ -90,6 +90,26 @@ static void netconfig_free(void *data)
|
|||||||
l_free(netconfig);
|
l_free(netconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool netconfig_addr_to_str(uint8_t af, const void *v4_addr,
|
||||||
|
const void *v6_addr, char *out_str,
|
||||||
|
bool *out_is_zero)
|
||||||
|
{
|
||||||
|
const void *addr = (af == AF_INET ? v4_addr : v6_addr);
|
||||||
|
uint8_t bytes = (af == AF_INET ? 4 : 16);
|
||||||
|
|
||||||
|
if (l_memeqzero(addr, bytes)) {
|
||||||
|
*out_is_zero = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_is_zero = false;
|
||||||
|
|
||||||
|
if (L_WARN_ON(!inet_ntop(af, addr, out_str, INET6_ADDRSTRLEN)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
|
bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
|
||||||
{
|
{
|
||||||
if (!netconfig->enabled[INDEX_FOR_AF(af)])
|
if (!netconfig->enabled[INDEX_FOR_AF(af)])
|
||||||
@ -408,12 +428,96 @@ mdns:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool netconfig_load_fils_settings(struct netconfig *netconfig,
|
||||||
|
uint8_t af)
|
||||||
|
{
|
||||||
|
struct ie_fils_ip_addr_response_info *fils = netconfig->fils_override;
|
||||||
|
char addr_str[INET6_ADDRSTRLEN];
|
||||||
|
char gw_addr_str[INET6_ADDRSTRLEN];
|
||||||
|
char dns_addr_str[INET6_ADDRSTRLEN];
|
||||||
|
_auto_(l_rtnl_address_free) struct l_rtnl_address *rtnl_addr = NULL;
|
||||||
|
bool is_zero = false;
|
||||||
|
uint8_t prefix_len;
|
||||||
|
|
||||||
|
if (!netconfig_addr_to_str(af, &fils->ipv4_addr, &fils->ipv6_addr,
|
||||||
|
addr_str, &is_zero) || is_zero)
|
||||||
|
return is_zero;
|
||||||
|
|
||||||
|
prefix_len = (af == AF_INET ? fils->ipv4_prefix_len :
|
||||||
|
fils->ipv6_prefix_len);
|
||||||
|
|
||||||
|
if (L_WARN_ON(!(rtnl_addr = l_rtnl_address_new(addr_str, prefix_len))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (L_WARN_ON(!l_netconfig_set_static_addr(netconfig->nc, af,
|
||||||
|
rtnl_addr)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (af == AF_INET &&
|
||||||
|
L_WARN_ON(!l_netconfig_set_acd_enabled(netconfig->nc,
|
||||||
|
false)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Done with local address, move on to gateway and DNS.
|
||||||
|
*
|
||||||
|
* Since load_settings is called early, generally before the actual
|
||||||
|
* connection setup starts, and load_fils_settings is called after
|
||||||
|
* 802.11 Authentication & Association, we need to check if either
|
||||||
|
* the gateway or DNS settings were overridden in load_settings so
|
||||||
|
* as not to overwrite the user-provided values. Values received
|
||||||
|
* with FILS are expected to have the same weight as those from
|
||||||
|
* DHCP/SLAAC.
|
||||||
|
*
|
||||||
|
* TODO: If netconfig->fils_override->ipv{4,6}_lifetime is set,
|
||||||
|
* start a timeout to renew the address using FILS IP Address
|
||||||
|
* Assignment or perhaps just start the DHCP client after that
|
||||||
|
* time.
|
||||||
|
*
|
||||||
|
* TODO: validate gateway and/or DNS on local subnet, link-local,
|
||||||
|
* etc.?
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!netconfig_addr_to_str(af, &fils->ipv4_gateway, &fils->ipv6_gateway,
|
||||||
|
gw_addr_str, &is_zero))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!netconfig->gateway_overridden[INDEX_FOR_AF(af)] && !is_zero &&
|
||||||
|
L_WARN_ON(!l_netconfig_set_gateway_override(
|
||||||
|
netconfig->nc,
|
||||||
|
af,
|
||||||
|
gw_addr_str)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!netconfig_addr_to_str(af, &fils->ipv4_dns, &fils->ipv6_dns,
|
||||||
|
dns_addr_str, &is_zero))
|
||||||
|
return is_zero;
|
||||||
|
|
||||||
|
if (!netconfig->dns_overridden[INDEX_FOR_AF(af)] && !is_zero) {
|
||||||
|
char *dns_list[2] = { dns_addr_str, NULL };
|
||||||
|
|
||||||
|
if (L_WARN_ON(!l_netconfig_set_dns_override(netconfig->nc,
|
||||||
|
af, dns_list)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool netconfig_configure(struct netconfig *netconfig,
|
bool netconfig_configure(struct netconfig *netconfig,
|
||||||
netconfig_notify_func_t notify, void *user_data)
|
netconfig_notify_func_t notify, void *user_data)
|
||||||
{
|
{
|
||||||
netconfig->notify = notify;
|
netconfig->notify = notify;
|
||||||
netconfig->user_data = user_data;
|
netconfig->user_data = user_data;
|
||||||
|
|
||||||
|
if (netconfig_use_fils_addr(netconfig, AF_INET) &&
|
||||||
|
!netconfig_load_fils_settings(netconfig, AF_INET))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (netconfig_use_fils_addr(netconfig, AF_INET6) &&
|
||||||
|
!netconfig_load_fils_settings(netconfig, AF_INET6))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (unlikely(!l_netconfig_start(netconfig->nc)))
|
if (unlikely(!l_netconfig_start(netconfig->nc)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -429,9 +533,18 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw)
|
|||||||
* lost or delayed. Try to force the gateway into the ARP cache
|
* lost or delayed. Try to force the gateway into the ARP cache
|
||||||
* to alleviate this
|
* to alleviate this
|
||||||
*/
|
*/
|
||||||
if (set_arp_gw)
|
if (set_arp_gw) {
|
||||||
netconfig_dhcp_gateway_to_arp(netconfig);
|
netconfig_dhcp_gateway_to_arp(netconfig);
|
||||||
|
|
||||||
|
if (netconfig->connected[INDEX_FOR_AF(AF_INET)] &&
|
||||||
|
netconfig_use_fils_addr(netconfig, AF_INET))
|
||||||
|
netconfig_commit_fils_macs(netconfig, AF_INET);
|
||||||
|
|
||||||
|
if (netconfig->connected[INDEX_FOR_AF(AF_INET6)] &&
|
||||||
|
netconfig_use_fils_addr(netconfig, AF_INET6))
|
||||||
|
netconfig_commit_fils_macs(netconfig, AF_INET6);
|
||||||
|
}
|
||||||
|
|
||||||
if (!netconfig->static_config[INDEX_FOR_AF(AF_INET)]) {
|
if (!netconfig->static_config[INDEX_FOR_AF(AF_INET)]) {
|
||||||
/* TODO l_dhcp_client sending a DHCP inform request */
|
/* TODO l_dhcp_client sending a DHCP inform request */
|
||||||
}
|
}
|
||||||
|
@ -83,3 +83,4 @@ void netconfig_commit(struct netconfig *netconfig, uint8_t family,
|
|||||||
enum l_netconfig_event event);
|
enum l_netconfig_event event);
|
||||||
|
|
||||||
void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig);
|
void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig);
|
||||||
|
void netconfig_commit_fils_macs(struct netconfig *netconfig, uint8_t family);
|
||||||
|
Loading…
Reference in New Issue
Block a user