mirror of
				https://git.kernel.org/pub/scm/network/wireless/iwd.git
				synced 2025-10-31 04:57: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 && | ||||
| 				!netconfig->static_config[INDEX_FOR_AF(family)]) | ||||
| 			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"); | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	_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); | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	if (!netconfig->enabled[INDEX_FOR_AF(af)]) | ||||
| @ -408,12 +428,96 @@ mdns: | ||||
| 	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, | ||||
| 				netconfig_notify_func_t notify, void *user_data) | ||||
| { | ||||
| 	netconfig->notify = notify; | ||||
| 	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))) | ||||
| 		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 | ||||
| 	 * to alleviate this | ||||
| 	 */ | ||||
| 	if (set_arp_gw) | ||||
| 	if (set_arp_gw) { | ||||
| 		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)]) { | ||||
| 		/* 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); | ||||
| 
 | ||||
| void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig); | ||||
| void netconfig_commit_fils_macs(struct netconfig *netconfig, uint8_t family); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Andrew Zaborowski
						Andrew Zaborowski