All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/10] doc: Update Netconfig Agent API doc
@ 2022-08-29 17:35 Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 02/10] netconfig: Drop dhcp, dhcp6 and acd client instances Andrew Zaborowski
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

Update ConfigureIPv{4,6}() parameters to simplify mapping our sets of
addresses and routes directly to D-Bus dictionaries.  Split Cancel()
into CancelIPv{4,6}().
---
 doc/agent-api.txt | 123 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 97 insertions(+), 26 deletions(-)

diff --git a/doc/agent-api.txt b/doc/agent-api.txt
index 250628eb..e9bb95ca 100644
--- a/doc/agent-api.txt
+++ b/doc/agent-api.txt
@@ -145,50 +145,121 @@ Methods		void Release() [noreply]
 			agent, because when this method gets called it has
 			already been unregistered.
 
-		void ConfigureIPv4(object device, string interface, dict config)
-
-			This method gets called during a connection setup
-			when a new set of IPv4 configuration values is to
-			be written to a network interface.  The connection
-			is aborted if the method call returns an error or
-			times out.  The 'config' dictionary (a{sv}) maps
-			string keys to values of types defined per key.
-
-			The following key/value pairs are used, but more
+		void ConfigureIPv4(object device, dict config)
+
+			This method gets called during connection setup
+			and later while the connection is operational
+			whenever a new set of IPv4 configuration values is to
+			be written to a network interface.  The connection is
+			aborted if the method call returns an error or times
+			out.
+
+			In case of a station-mode connection, the 'device'
+			parameter points at an object with a
+			net.connman.iwd.Device interface whose Name property
+			contains the name of network interface.  In case of a
+			P2P connection, the object will have
+			a net.connman.iwd.p2p.Peer interface whose
+			ConnectectedInterface property contains the name of
+			the target network interface.
+
+			The 'config' dictionary (a{sv}) maps string keys to
+			values of types defined per key.  Each call receives
+			the full set of values which supersede those from
+			previous calls.
+
+			The following key/value pairs are defined, but more
 			may be added in future versions.
 
 			string Method - Indicates whether the local address
 			was set statically (value "static") or obtained
 			automatically such as through DHCP (value "auto").
-			Even when the address was obtained from the remote
+			Even when addresses were obtained from the remote
 			end some configuration bits, such as DNS addresses,
 			may have been overridden locally.
 
-			string Address - Local IP address string.
-
-			byte PrefixLength - Holds the prefix-length of the
-			local subnet.  For IPv4 this maps to the netmask.
+			array(dict) Addresses - Local IP addresses.  Each
+			address is described by a set of key/value properties
+			as documented further down.
 
-			string Gateway [optional] - Local subnet's gateway
-			address if one exists.
+			array(dict) Routes - Routes for on-link and off-link
+			prefixes/subnets and default routers.  Each route is
+			described by a set of key/value properties as
+			documented further down.
 
 			array(string) DomainNameServers [optional] - Holds
-			the list of DNS addresses configured if any exist.
+			the list of DNS server addresses configured if any
+			exist.
 
 			array(string) DomainNames [optional] - Holds the
 			network's local domain names if any exist.
 
+			string MDNS [optional] - One of "true", "false" and
+			"resolve".  Controls whether Multicast DNS support is
+			to be enabled on the link.  When set to "resolve",
+			only resolution is enabled, but not host or service
+			registration and announcement (see systemd.network(5).)
+
+			The following properties are defined for local
+			addresses, but more may be added in the future:
+
+			string Address - Holds the IP address string.
+
+			byte PrefixLength [optional] - Prefix length
+			associated with the address's subnet (IPv4 only).
+
+			string Broadcast [optional] - Broadcast address
+			associated with the address's subnet (IPv4 only).
+
+			uint32 ValidLifetime [optional] - Remaining validity
+			and ownership time for this address assignment/lease,
+			in seconds at the time of the method call.
+			If absent the address doesn't expire.
+
+			uint32 PreferredLifetime [optional] - Number of
+			seconds left at the time of the method call for this
+			address to be preferred over other addresses.
+
+			The following properties are defined for routes,
+			but more may be added in the future:
+
+			string, byte Destination [optional] - Holds the
+			route's destination IP prefix string and the prefix
+			length in bits.  Absent for default routes.
+
+			string Router [optional] - Holds the router's IP
+			address.  Absent for on-link routes.
+
+			string PreferredSource [optional] - Route source IP
+			address.
+
+			uint32 Lifetime [optional] - Remaining route validity
+			time in seconds at the time of the method call.
+			If absent the route doesn't expire.
+
+			uint32 Priority - Relative route priority.
+
+			byte Preference [optional] - ICMPv6 route preference:
+			0 for medium, 1 for high and 3 for low.
+
+			uint32 MTU [optional] - Router MTU.
+
 			Possible Errors: net.connman.iwd.Agent.Error.Canceled
+					 net.connman.iwd.Agent.Error.Failed
 
-		void ConfigureIPv6(object device, string interface, dict config)
+		void ConfigureIPv6(object device, dict config)
 
 			Same as ConfigureIPv4 above but for IPv6.
 
-		void Cancel(object device, string interface,
-						string reason) [noreply]
+		void CancelIPv4(object device, string reason) [noreply]
 
-			This method gets called to indicate that the connection
-			request failed before a reply was returned.  The
-			argument will indicate why the request is being
-			cancelled and may be "out-of-range", "user-canceled",
-			"timed-out" or "shutdown".
+			This method gets called to indicate that the network
+			configuration was aborted before a reply was received
+			for an ongoing ConfigureIPv4 or ConfigureIPv6 call.
+			The last argument will indicate why the request is being
+			cancelled and may be one of: "aborted", "superseded",
+			"timed-out".
+
+		void CancelIPv6(object device, string reason) [noreply]
+
+			Same as CancelIPv4 above but for IPv6.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/10] netconfig: Drop dhcp, dhcp6 and acd client instances
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
@ 2022-08-29 17:35 ` Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 03/10] netconfig: Keep configuration directly in struct l_netconfig Andrew Zaborowski
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

In anticipation of switching to use the l_netconfig API, which
internally handles DHCPv4, DHCPv6, ACD, etc., drop pointers to
instances of l_dhcp_client, l_dhcp6_client and l_acd from struct
netconfig.  Also drop all code used for handling events from these
APIs, including code to commit the received configurations to the
system.  Committing the final settings to the system netdevs is going to
be handled by a new set of utilities in a new file.
---
Note this temporarily leaves IWD network configuration non-functional.
---
 src/netconfig.c | 1199 +----------------------------------------------
 1 file changed, 12 insertions(+), 1187 deletions(-)

diff --git a/src/netconfig.c b/src/netconfig.c
index 4a70b0ca..ea9846f6 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -54,8 +54,6 @@
 
 struct netconfig {
 	uint32_t ifindex;
-	struct l_dhcp_client *dhcp_client;
-	struct l_dhcp6_client *dhcp6_client;
 	uint8_t rtm_protocol;
 	uint8_t rtm_v6_protocol;
 	struct l_rtnl_address *v4_address;
@@ -77,17 +75,9 @@ struct netconfig {
 	void *user_data;
 
 	struct resolve *resolve;
-
-	struct l_acd *acd;
-
-	uint32_t addr4_add_cmd_id;
-	uint32_t addr6_add_cmd_id;
-	uint32_t route4_add_gateway_cmd_id;
-	uint32_t route6_add_cmd_id;
 };
 
 static struct l_netlink *rtnl;
-static struct l_queue *netconfig_list;
 
 /*
  * Routing priority offset, configurable in main.conf. The route with lower
@@ -123,59 +113,9 @@ static void netconfig_free(void *data)
 {
 	struct netconfig *netconfig = data;
 
-	l_dhcp_client_destroy(netconfig->dhcp_client);
-	l_dhcp6_client_destroy(netconfig->dhcp6_client);
-
 	l_free(netconfig);
 }
 
-static struct netconfig *netconfig_find(uint32_t ifindex)
-{
-	const struct l_queue_entry *entry;
-
-	for (entry = l_queue_get_entries(netconfig_list); entry;
-							entry = entry->next) {
-		struct netconfig *netconfig = entry->data;
-
-		if (netconfig->ifindex != ifindex)
-			continue;
-
-		return netconfig;
-	}
-
-	return NULL;
-}
-
-static inline char *netconfig_ipv4_to_string(uint32_t addr)
-{
-	struct in_addr in_addr = { .s_addr = addr };
-	char *addr_str = l_malloc(INET_ADDRSTRLEN);
-
-	if (L_WARN_ON(unlikely(!inet_ntop(AF_INET, &in_addr, addr_str,
-						INET_ADDRSTRLEN)))) {
-		l_free(addr_str);
-		return NULL;
-	}
-
-	return addr_str;
-}
-
-static inline char *netconfig_ipv6_to_string(const uint8_t *addr)
-{
-	struct in6_addr in6_addr;
-	char *addr_str = l_malloc(INET6_ADDRSTRLEN);
-
-	memcpy(in6_addr.s6_addr, addr, 16);
-
-	if (L_WARN_ON(unlikely(!inet_ntop(AF_INET6, &in6_addr, addr_str,
-						INET6_ADDRSTRLEN)))) {
-		l_free(addr_str);
-		return NULL;
-	}
-
-	return addr_str;
-}
-
 static bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
 {
 	if ((af == AF_INET ? netconfig->rtm_protocol :
@@ -191,88 +131,6 @@ static bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
 	return !l_memeqzero(netconfig->fils_override->ipv6_addr, 16);
 }
 
-static bool netconfig_use_fils_gateway(struct netconfig *netconfig, int af)
-{
-	if ((af == AF_INET ? netconfig->rtm_protocol :
-				netconfig->rtm_v6_protocol) != RTPROT_DHCP)
-		return false;
-
-	if (!netconfig->fils_override)
-		return false;
-
-	if (af == AF_INET)
-		return !!netconfig->fils_override->ipv4_gateway;
-
-	return !l_memeqzero(netconfig->fils_override->ipv6_gateway, 16);
-}
-
-static char **netconfig_get_dns_list(struct netconfig *netconfig, int af,
-					const uint8_t **out_dns_mac)
-{
-	const struct ie_fils_ip_addr_response_info *fils =
-		netconfig->fils_override;
-
-	if (af == AF_INET) {
-		const struct l_dhcp_lease *lease;
-
-		if (netconfig->dns4_overrides)
-			return l_strv_copy(netconfig->dns4_overrides);
-
-		if (netconfig->rtm_protocol != RTPROT_DHCP)
-			return NULL;
-
-		if (fils && fils->ipv4_dns) {
-			char **dns_list = l_new(char *, 2);
-
-			if (!l_memeqzero(fils->ipv4_dns_mac, 6) &&
-					out_dns_mac &&
-					util_ip_subnet_match(
-							fils->ipv4_prefix_len,
-							&fils->ipv4_addr,
-							&fils->ipv4_dns))
-				*out_dns_mac = fils->ipv4_dns_mac;
-
-			dns_list[0] = netconfig_ipv4_to_string(fils->ipv4_dns);
-			return dns_list;
-		}
-
-		lease = l_dhcp_client_get_lease(netconfig->dhcp_client);
-		if (!lease)
-			return NULL;
-
-		return l_dhcp_lease_get_dns(lease);
-	} else {
-		const struct l_dhcp6_lease *lease;
-
-		if (netconfig->dns6_overrides)
-			return l_strv_copy(netconfig->dns6_overrides);
-
-		if (netconfig->rtm_v6_protocol != RTPROT_DHCP)
-			return NULL;
-
-		if (fils && !l_memeqzero(fils->ipv6_dns, 16)) {
-			char **dns_list = l_new(char *, 2);
-
-			if (!l_memeqzero(fils->ipv6_dns_mac, 6) &&
-					out_dns_mac &&
-					util_ip_subnet_match(
-							fils->ipv6_prefix_len,
-							fils->ipv6_addr,
-							fils->ipv6_dns))
-				*out_dns_mac = fils->ipv6_dns_mac;
-
-			dns_list[0] = netconfig_ipv6_to_string(fils->ipv6_dns);
-			return dns_list;
-		}
-
-		lease = l_dhcp6_client_get_lease(netconfig->dhcp6_client);
-		if (!lease)
-			return NULL;
-
-		return l_dhcp6_lease_get_dns(lease);
-	}
-}
-
 static void netconfig_set_neighbor_entry_cb(int error,
 						uint16_t type, const void *data,
 						uint32_t len, void *user_data)
@@ -282,146 +140,6 @@ static void netconfig_set_neighbor_entry_cb(int error,
 			strerror(-error), error);
 }
 
-static void netconfig_set_dns(struct netconfig *netconfig)
-{
-	if (!netconfig->dns4_list && !netconfig->dns6_list)
-		return;
-
-	if (netconfig->dns4_list && netconfig->dns6_list) {
-		unsigned int n_entries4 = l_strv_length(netconfig->dns4_list);
-		unsigned int n_entries6 = l_strv_length(netconfig->dns6_list);
-		char **dns_list = l_malloc(sizeof(char *) *
-					(n_entries4 + n_entries6 + 1));
-
-		memcpy(dns_list, netconfig->dns4_list,
-			sizeof(char *) * n_entries4);
-		memcpy(dns_list + n_entries4, netconfig->dns6_list,
-			sizeof(char *) * (n_entries6 + 1));
-		resolve_set_dns(netconfig->resolve, dns_list);
-		l_free(dns_list);
-		return;
-	}
-
-	resolve_set_dns(netconfig->resolve,
-			netconfig->dns4_list ?: netconfig->dns6_list);
-}
-
-static bool netconfig_dns_list_update(struct netconfig *netconfig, uint8_t af)
-{
-	const uint8_t *fils_dns_mac = NULL;
-	char ***dns_list_ptr = af == AF_INET ?
-		&netconfig->dns4_list : &netconfig->dns6_list;
-	char **new_dns_list = netconfig_get_dns_list(netconfig, af,
-							&fils_dns_mac);
-
-	if (l_strv_eq(*dns_list_ptr, new_dns_list)) {
-		l_strv_free(new_dns_list);
-		return false;
-	}
-
-	l_strv_free(*dns_list_ptr);
-	*dns_list_ptr = new_dns_list;
-
-	if (fils_dns_mac) {
-		const struct ie_fils_ip_addr_response_info *fils =
-			netconfig->fils_override;
-		const void *dns_ip = af == AF_INET ?
-			(const void *) &fils->ipv4_dns :
-			(const void *) &fils->ipv6_dns;
-
-		if (!l_rtnl_neighbor_set_hwaddr(rtnl, netconfig->ifindex, af,
-						dns_ip, fils_dns_mac, 6,
-						netconfig_set_neighbor_entry_cb,
-						NULL, NULL))
-			l_debug("l_rtnl_neighbor_set_hwaddr failed");
-	}
-
-	return true;
-}
-
-static void append_domain(char **domains, unsigned int *n_domains,
-				size_t max, char *domain)
-{
-	unsigned int i;
-
-	if (*n_domains == max)
-		return;
-
-	for (i = 0; i < *n_domains; i++)
-		if (!strcmp(domains[i], domain))
-			return;
-
-	domains[*n_domains] = domain;
-	*n_domains += 1;
-}
-
-static void netconfig_set_domains(struct netconfig *netconfig)
-{
-	char *domains[31];
-	unsigned int n_domains = 0;
-	char **p;
-
-	memset(domains, 0, sizeof(domains));
-
-	append_domain(domains, &n_domains,
-			L_ARRAY_SIZE(domains) - 1, netconfig->v4_domain);
-
-	for (p = netconfig->v6_domains; p && *p; p++)
-		append_domain(domains, &n_domains,
-				L_ARRAY_SIZE(domains) - 1, *p);
-
-	resolve_set_domains(netconfig->resolve, domains);
-}
-
-static bool netconfig_domains_update(struct netconfig *netconfig, uint8_t af)
-{
-	bool changed = false;
-
-	if (af == AF_INET) {
-		/* Allow to override the DHCP domain name with setting entry. */
-		char *v4_domain = l_settings_get_string(
-						netconfig->active_settings,
-						"IPv4", "DomainName");
-
-		if (!v4_domain && netconfig->rtm_protocol == RTPROT_DHCP) {
-			const struct l_dhcp_lease *lease =
-				l_dhcp_client_get_lease(netconfig->dhcp_client);
-
-			if (lease)
-				v4_domain = l_dhcp_lease_get_domain_name(lease);
-		}
-
-		if (l_streq0(v4_domain, netconfig->v4_domain))
-			l_free(v4_domain);
-		else {
-			l_free(netconfig->v4_domain);
-			netconfig->v4_domain = v4_domain;
-			changed = true;
-		}
-	} else {
-		char **v6_domains = NULL;
-
-		if (netconfig->rtm_v6_protocol == RTPROT_DHCP) {
-			const struct l_dhcp6_lease *lease =
-				l_dhcp6_client_get_lease(
-						netconfig->dhcp6_client);
-
-			if (lease)
-				v6_domains = l_dhcp6_lease_get_domains(lease);
-		}
-
-		if (l_strv_eq(netconfig->v6_domains, v6_domains))
-			l_strv_free(v6_domains);
-		else {
-			l_strv_free(netconfig->v6_domains);
-			netconfig->v6_domains = v6_domains;
-			changed = true;
-		}
-	}
-
-	return changed;
-}
-
 static struct l_rtnl_address *netconfig_get_static4_address(
 				const struct l_settings *active_settings)
 {
@@ -470,46 +188,6 @@ static struct l_rtnl_address *netconfig_get_static4_address(
 	return ifaddr;
 }
 
-static char *netconfig_ipv4_get_gateway(struct netconfig *netconfig,
-					const uint8_t **out_mac)
-{
-	const struct l_dhcp_lease *lease;
-	char *gateway;
-	const struct ie_fils_ip_addr_response_info *fils =
-		netconfig->fils_override;
-
-	switch (netconfig->rtm_protocol) {
-	case RTPROT_STATIC:
-		gateway = l_settings_get_string(netconfig->active_settings,
-							"IPv4", "Gateway");
-		if (!gateway)
-			gateway = l_settings_get_string(
-						netconfig->active_settings,
-						"IPv4", "gateway");
-
-		return gateway;
-
-	case RTPROT_DHCP:
-		if (netconfig_use_fils_gateway(netconfig, AF_INET)) {
-			gateway = netconfig_ipv4_to_string(fils->ipv4_gateway);
-
-			if (gateway && out_mac &&
-					!l_memeqzero(fils->ipv4_gateway_mac, 6))
-				*out_mac = fils->ipv4_gateway_mac;
-
-			return gateway;
-		}
-
-		lease = l_dhcp_client_get_lease(netconfig->dhcp_client);
-		if (!lease)
-			return NULL;
-
-		return l_dhcp_lease_get_gateway(lease);
-	}
-
-	return NULL;
-}
-
 static struct l_rtnl_address *netconfig_get_static6_address(
 				const struct l_settings *active_settings)
 {
@@ -549,75 +227,9 @@ no_prefix_len:
 	return ret;
 }
 
-static struct l_rtnl_route *netconfig_get_static6_gateway(
-						struct netconfig *netconfig,
-						char **out_str,
-						const uint8_t **out_mac)
-{
-	L_AUTO_FREE_VAR(char *, gateway);
-	struct l_rtnl_route *ret;
-	const uint8_t *mac = NULL;
-
-	gateway = l_settings_get_string(netconfig->active_settings,
-						"IPv6", "Gateway");
-	if (!gateway && netconfig_use_fils_gateway(netconfig, AF_INET6)) {
-		gateway = netconfig_ipv6_to_string(
-					netconfig->fils_override->ipv6_gateway);
-
-		if (!l_memeqzero(netconfig->fils_override->ipv6_gateway_mac, 6))
-			mac = netconfig->fils_override->ipv6_gateway_mac;
-	} else if (!gateway)
-		return NULL;
-
-	ret = l_rtnl_route_new_gateway(gateway);
-	if (!ret) {
-		l_error("netconfig: Invalid IPv6 gateway address %s is "
-			"provided in network configuration file.",
-			gateway);
-		return ret;
-	}
-
-	l_rtnl_route_set_priority(ret, ROUTE_PRIORITY_OFFSET);
-	l_rtnl_route_set_protocol(ret, RTPROT_STATIC);
-	*out_str = l_steal_ptr(gateway);
-	*out_mac = mac;
-
-	return ret;
-}
-
-static struct l_rtnl_address *netconfig_get_dhcp4_address(
-						struct netconfig *netconfig)
-{
-	const struct l_dhcp_lease *lease =
-			l_dhcp_client_get_lease(netconfig->dhcp_client);
-	L_AUTO_FREE_VAR(char *, ip) = NULL;
-	L_AUTO_FREE_VAR(char *, broadcast) = NULL;
-	uint32_t prefix_len;
-	struct l_rtnl_address *ret;
-
-	if (L_WARN_ON(!lease))
-		return NULL;
-
-	ip = l_dhcp_lease_get_address(lease);
-	broadcast = l_dhcp_lease_get_broadcast(lease);
-
-	prefix_len = l_dhcp_lease_get_prefix_length(lease);
-	if (!prefix_len)
-		prefix_len = 24;
-
-	ret = l_rtnl_address_new(ip, prefix_len);
-	if (!ret)
-		return ret;
-
-	if (broadcast)
-		l_rtnl_address_set_broadcast(ret, broadcast);
-
-	l_rtnl_address_set_noprefixroute(ret, true);
-	return ret;
-}
-
 static void netconfig_gateway_to_arp(struct netconfig *netconfig)
 {
+	struct l_dhcp_client *dhcp = NULL; /* TODO */
 	const struct l_dhcp_lease *lease;
 	_auto_(l_free) char *server_id = NULL;
 	_auto_(l_free) char *gw = NULL;
@@ -628,7 +240,7 @@ static void netconfig_gateway_to_arp(struct netconfig *netconfig)
 	if (netconfig->rtm_protocol != RTPROT_DHCP)
 		return;
 
-	lease = l_dhcp_client_get_lease(netconfig->dhcp_client);
+	lease = l_dhcp_client_get_lease(dhcp);
 	if (!lease)
 		return;
 
@@ -649,515 +261,11 @@ static void netconfig_gateway_to_arp(struct netconfig *netconfig)
 		l_debug("l_rtnl_neighbor_set_hwaddr failed");
 }
 
-static void netconfig_ifaddr_added(struct netconfig *netconfig,
-					const struct ifaddrmsg *ifa,
-					uint32_t len)
-{
-	L_AUTO_FREE_VAR(char *, label) = NULL;
-	L_AUTO_FREE_VAR(char *, ip) = NULL;
-	L_AUTO_FREE_VAR(char *, broadcast) = NULL;
-
-	l_rtnl_ifaddr4_extract(ifa, len, &label, &ip, &broadcast);
-	l_debug("%s: ifaddr %s/%u broadcast %s", label,
-					ip, ifa->ifa_prefixlen, broadcast);
-}
-
-static void netconfig_ifaddr_deleted(struct netconfig *netconfig,
-					const struct ifaddrmsg *ifa,
-					uint32_t len)
-{
-	L_AUTO_FREE_VAR(char *, ip);
-
-	l_rtnl_ifaddr4_extract(ifa, len, NULL, &ip, NULL);
-	l_debug("ifaddr %s/%u", ip, ifa->ifa_prefixlen);
-}
-
-static void netconfig_ifaddr_notify(uint16_t type, const void *data,
-						uint32_t len, void *user_data)
-{
-	const struct ifaddrmsg *ifa = data;
-	struct netconfig *netconfig;
-	uint32_t bytes;
-
-	netconfig = netconfig_find(ifa->ifa_index);
-	if (!netconfig)
-		/* Ignore the interfaces which aren't managed by iwd. */
-		return;
-
-	bytes = len - NLMSG_ALIGN(sizeof(struct ifaddrmsg));
-
-	switch (type) {
-	case RTM_NEWADDR:
-		netconfig_ifaddr_added(netconfig, ifa, bytes);
-		break;
-	case RTM_DELADDR:
-		netconfig_ifaddr_deleted(netconfig, ifa, bytes);
-		break;
-	}
-}
-
-static void netconfig_ifaddr_cmd_cb(int error, uint16_t type,
-						const void *data, uint32_t len,
-						void *user_data)
-{
-	if (error) {
-		l_error("netconfig: ifaddr command failure. "
-				"Error %d: %s", error, strerror(-error));
-		return;
-	}
-
-	if (type != RTM_NEWADDR)
-		return;
-
-	netconfig_ifaddr_notify(type, data, len, user_data);
-}
-
-static void netconfig_ifaddr_ipv6_added(struct netconfig *netconfig,
-					const struct ifaddrmsg *ifa,
-					uint32_t len)
-{
-	struct in6_addr in6;
-	L_AUTO_FREE_VAR(char *, ip) = NULL;
-
-	if (ifa->ifa_flags & IFA_F_TENTATIVE)
-		return;
-
-	l_rtnl_ifaddr6_extract(ifa, len, &ip);
-
-	l_debug("ifindex %u: ifaddr %s/%u", netconfig->ifindex,
-			ip, ifa->ifa_prefixlen);
-
-	if (netconfig->rtm_v6_protocol != RTPROT_DHCP ||
-			netconfig_use_fils_addr(netconfig, AF_INET6))
-		return;
-
-	inet_pton(AF_INET6, ip, &in6);
-	if (!IN6_IS_ADDR_LINKLOCAL(&in6))
-		return;
-
-	l_dhcp6_client_set_link_local_address(netconfig->dhcp6_client, ip);
-
-	if (l_dhcp6_client_start(netconfig->dhcp6_client))
-		return;
-
-	l_error("netconfig: Failed to start DHCPv6 client for "
-			"interface %u", netconfig->ifindex);
-}
-
-static void netconfig_ifaddr_ipv6_deleted(struct netconfig *netconfig,
-						const struct ifaddrmsg *ifa,
-						uint32_t len)
-{
-	L_AUTO_FREE_VAR(char *, ip);
-
-	l_rtnl_ifaddr6_extract(ifa, len, &ip);
-	l_debug("ifindex %u: ifaddr %s/%u", netconfig->ifindex,
-			ip, ifa->ifa_prefixlen);
-}
-
-static void netconfig_ifaddr_ipv6_notify(uint16_t type, const void *data,
-						uint32_t len, void *user_data)
-{
-	const struct ifaddrmsg *ifa = data;
-	struct netconfig *netconfig;
-	uint32_t bytes;
-
-	netconfig = netconfig_find(ifa->ifa_index);
-	if (!netconfig)
-		/* Ignore the interfaces which aren't managed by iwd. */
-		return;
-
-	bytes = len - NLMSG_ALIGN(sizeof(struct ifaddrmsg));
-
-	switch (type) {
-	case RTM_NEWADDR:
-		netconfig_ifaddr_ipv6_added(netconfig, ifa, bytes);
-		break;
-	case RTM_DELADDR:
-		netconfig_ifaddr_ipv6_deleted(netconfig, ifa, bytes);
-		break;
-	}
-}
-
-static void netconfig_ifaddr_ipv6_cmd_cb(int error, uint16_t type,
-						const void *data, uint32_t len,
-						void *user_data)
-{
-	if (error) {
-		l_error("netconfig: ifaddr IPv6 command failure. "
-				"Error %d: %s", error, strerror(-error));
-		return;
-	}
-
-	if (type != RTM_NEWADDR)
-		return;
-
-	netconfig_ifaddr_ipv6_notify(type, data, len, user_data);
-}
-
-static void netconfig_route_generic_cb(int error, uint16_t type,
-					const void *data, uint32_t len,
-					void *user_data)
-{
-	if (error) {
-		l_error("netconfig: Failed to add route. Error %d: %s",
-						error, strerror(-error));
-		return;
-	}
-}
-
-static void netconfig_route_add_cmd_cb(int error, uint16_t type,
-						const void *data, uint32_t len,
-						void *user_data)
-{
-	struct netconfig *netconfig = user_data;
-
-	netconfig->route4_add_gateway_cmd_id = 0;
-
-	if (error) {
-		l_error("netconfig: Failed to add route. Error %d: %s",
-						error, strerror(-error));
-		return;
-	}
-
-	if (!netconfig->notify)
-		return;
-
-	netconfig->notify(NETCONFIG_EVENT_CONNECTED, netconfig->user_data);
-	netconfig->notify = NULL;
-}
-
-static void netconfig_route6_add_cb(int error, uint16_t type,
-					const void *data, uint32_t len,
-					void *user_data)
-{
-	struct netconfig *netconfig = user_data;
-
-	netconfig->route6_add_cmd_id = 0;
-
-	if (error) {
-		l_error("netconfig: Failed to add route. Error %d: %s",
-						error, strerror(-error));
-		return;
-	}
-}
-
-static bool netconfig_ipv4_subnet_route_install(struct netconfig *netconfig)
-{
-	struct in_addr in_addr;
-	char ip[INET_ADDRSTRLEN];
-	char network[INET_ADDRSTRLEN];
-	unsigned int prefix_len =
-		l_rtnl_address_get_prefix_length(netconfig->v4_address);
-
-	if (!l_rtnl_address_get_address(netconfig->v4_address, ip) ||
-			inet_pton(AF_INET, ip, &in_addr) < 1)
-		return false;
-
-	in_addr.s_addr = in_addr.s_addr &
-				htonl(0xFFFFFFFFLU << (32 - prefix_len));
-
-	if (!inet_ntop(AF_INET, &in_addr, network, INET_ADDRSTRLEN))
-		return false;
-
-	if (!l_rtnl_route4_add_connected(rtnl, netconfig->ifindex,
-						prefix_len, network, ip,
-						netconfig->rtm_protocol,
-						netconfig_route_generic_cb,
-						netconfig, NULL)) {
-		l_error("netconfig: Failed to add subnet route.");
-		return false;
-	}
-
-	return true;
-}
-
-static bool netconfig_ipv4_gateway_route_install(struct netconfig *netconfig)
-{
-	L_AUTO_FREE_VAR(char *, gateway) = NULL;
-	const uint8_t *gateway_mac = NULL;
-	struct in_addr in_addr;
-	char ip[INET_ADDRSTRLEN];
-
-	gateway = netconfig_ipv4_get_gateway(netconfig, &gateway_mac);
-	if (!gateway) {
-		l_debug("No gateway obtained from %s.",
-				netconfig->rtm_protocol == RTPROT_STATIC ?
-				"setting file" : "DHCPv4 lease");
-
-		if (netconfig->notify) {
-			netconfig->notify(NETCONFIG_EVENT_CONNECTED,
-						netconfig->user_data);
-			netconfig->notify = NULL;
-		}
-
-		return true;
-	}
-
-	if (!l_rtnl_address_get_address(netconfig->v4_address, ip) ||
-			inet_pton(AF_INET, ip, &in_addr) < 1)
-		return false;
-
-	netconfig->route4_add_gateway_cmd_id =
-		l_rtnl_route4_add_gateway(rtnl, netconfig->ifindex, gateway, ip,
-						ROUTE_PRIORITY_OFFSET,
-						netconfig->rtm_protocol,
-						netconfig_route_add_cmd_cb,
-						netconfig, NULL);
-	if (!netconfig->route4_add_gateway_cmd_id) {
-		l_error("netconfig: Failed to add route for: %s gateway.",
-								gateway);
-
-		return false;
-	}
-
-	/*
-	 * Attempt to use the gateway MAC address 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.
-	 */
-	if (gateway_mac && !l_rtnl_neighbor_set_hwaddr(rtnl, netconfig->ifindex,
-					AF_INET,
-					&netconfig->fils_override->ipv4_gateway,
-					gateway_mac, 6,
-					netconfig_set_neighbor_entry_cb, NULL,
-					NULL))
-		l_debug("l_rtnl_neighbor_set_hwaddr failed");
-
-	return true;
-}
-
-static void netconfig_ipv4_ifaddr_add_cmd_cb(int error, uint16_t type,
-						const void *data, uint32_t len,
-						void *user_data)
-{
-	struct netconfig *netconfig = user_data;
-
-	netconfig->addr4_add_cmd_id = 0;
-
-	if (error && error != -EEXIST) {
-		l_error("netconfig: Failed to add IP address. "
-				"Error %d: %s", error, strerror(-error));
-		return;
-	}
-
-	netconfig_gateway_to_arp(netconfig);
-
-	if (!netconfig_ipv4_subnet_route_install(netconfig) ||
-			!netconfig_ipv4_gateway_route_install(netconfig))
-		return;
-
-	netconfig_set_dns(netconfig);
-	netconfig_set_domains(netconfig);
-}
-
-static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type,
-						const void *data, uint32_t len,
-						void *user_data)
-{
-	struct netconfig *netconfig = user_data;
-	struct l_rtnl_route *gateway;
-	const uint8_t *gateway_mac;
-
-	netconfig->addr6_add_cmd_id = 0;
-
-	if (error && error != -EEXIST) {
-		l_error("netconfig: Failed to add IPv6 address. "
-				"Error %d: %s", error, strerror(-error));
-		return;
-	}
-
-	gateway = netconfig_get_static6_gateway(netconfig,
-						&netconfig->v6_gateway_str,
-						&gateway_mac);
-	if (gateway) {
-		netconfig->route6_add_cmd_id = l_rtnl_route_add(rtnl,
-							netconfig->ifindex,
-							gateway,
-							netconfig_route6_add_cb,
-							netconfig, NULL);
-		L_WARN_ON(unlikely(!netconfig->route6_add_cmd_id));
-		l_rtnl_route_free(gateway);
-
-		if (gateway_mac && !l_rtnl_neighbor_set_hwaddr(rtnl,
-					netconfig->ifindex, AF_INET6,
-					netconfig->fils_override->ipv6_gateway,
-					gateway_mac, 6,
-					netconfig_set_neighbor_entry_cb, NULL,
-					NULL))
-			l_debug("l_rtnl_neighbor_set_hwaddr failed");
-	}
-
-	netconfig_set_dns(netconfig);
-	netconfig_set_domains(netconfig);
-}
-
-static void netconfig_ifaddr_del_cmd_cb(int error, uint16_t type,
-						const void *data, uint32_t len,
-						void *user_data)
-{
-	if (error == -ENODEV)
-		/* The device is unplugged, we are done. */
-		return;
-
-	if (!error)
-		/*
-		 * The kernel removes all of the routes associated with the
-		 * deleted IP on its own. There is no need to explicitly remove
-		 * them.
-		 */
-		return;
-
-	l_error("netconfig: Failed to delete IP address. "
-				"Error %d: %s", error, strerror(-error));
-}
-
-static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client,
-						enum l_dhcp_client_event event,
-						void *userdata)
-{
-	struct netconfig *netconfig = userdata;
-
-	l_debug("DHCPv4 event %d", event);
-
-	switch (event) {
-	case L_DHCP_CLIENT_EVENT_IP_CHANGED:
-		L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl, netconfig->ifindex,
-					netconfig->v4_address,
-					netconfig_ifaddr_del_cmd_cb,
-					netconfig, NULL));
-		/* Fall through. */
-	case L_DHCP_CLIENT_EVENT_LEASE_OBTAINED:
-	{
-		char *gateway_str;
-		struct l_rtnl_address *address;
-
-		gateway_str = netconfig_ipv4_get_gateway(netconfig, NULL);
-		if (l_streq0(netconfig->v4_gateway_str, gateway_str))
-			l_free(gateway_str);
-		else {
-			l_free(netconfig->v4_gateway_str);
-			netconfig->v4_gateway_str = gateway_str;
-		}
-
-		address = netconfig_get_dhcp4_address(netconfig);
-		l_rtnl_address_free(netconfig->v4_address);
-		netconfig->v4_address = address;
-
-		if (!netconfig->v4_address) {
-			l_error("netconfig: Failed to obtain IP addresses from "
-							"DHCPv4 lease.");
-			return;
-		}
-
-		netconfig_dns_list_update(netconfig, AF_INET);
-		netconfig_domains_update(netconfig, AF_INET);
-
-		L_WARN_ON(!(netconfig->addr4_add_cmd_id =
-				l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
-					netconfig->v4_address,
-					netconfig_ipv4_ifaddr_add_cmd_cb,
-					netconfig, NULL)));
-		break;
-	}
-	case L_DHCP_CLIENT_EVENT_LEASE_RENEWED:
-		break;
-	case L_DHCP_CLIENT_EVENT_LEASE_EXPIRED:
-		L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl, netconfig->ifindex,
-					netconfig->v4_address,
-					netconfig_ifaddr_del_cmd_cb,
-					netconfig, NULL));
-		l_rtnl_address_free(netconfig->v4_address);
-		netconfig->v4_address = NULL;
-		l_free(l_steal_ptr(netconfig->v4_gateway_str));
-
-		/* Fall through. */
-	case L_DHCP_CLIENT_EVENT_NO_LEASE:
-		/*
-		 * The requested address is no longer available, try to restart
-		 * the client.
-		 */
-		if (!l_dhcp_client_start(client))
-			l_error("netconfig: Failed to re-start DHCPv4 client "
-					"for interface %u", netconfig->ifindex);
-
-		break;
-	default:
-		l_error("netconfig: Received unsupported DHCPv4 event: %d",
-									event);
-	}
-}
-
-static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
-						enum l_dhcp6_client_event event,
-						void *userdata)
-{
-	struct netconfig *netconfig = userdata;
-
-	switch (event) {
-	case L_DHCP6_CLIENT_EVENT_IP_CHANGED:
-	case L_DHCP6_CLIENT_EVENT_LEASE_OBTAINED:
-	case L_DHCP6_CLIENT_EVENT_LEASE_RENEWED:
-	{
-		const struct l_dhcp6_lease *lease =
-			l_dhcp6_client_get_lease(netconfig->dhcp6_client);
-		_auto_(l_free) char *addr_str =
-			l_dhcp6_lease_get_address(lease);
-		struct l_rtnl_address *address;
-		struct l_icmp6_client *icmp6 =
-			l_dhcp6_client_get_icmp6(netconfig->dhcp6_client);
-		const struct l_icmp6_router *router =
-			l_icmp6_client_get_router(icmp6);
-		char *gateway_str = l_icmp6_router_get_address(router);
-
-		if (l_streq0(netconfig->v6_gateway_str, gateway_str))
-			l_free(gateway_str);
-		else {
-			l_free(netconfig->v6_gateway_str);
-			netconfig->v6_gateway_str = gateway_str;
-		}
-
-		address = l_rtnl_address_new(addr_str,
-					l_dhcp6_lease_get_prefix_length(lease));
-		l_rtnl_address_free(netconfig->v6_address);
-		netconfig->v6_address = address;
-
-		netconfig_dns_list_update(netconfig, AF_INET6);
-		netconfig_domains_update(netconfig, AF_INET6);
-		netconfig_set_dns(netconfig);
-		netconfig_set_domains(netconfig);
-		break;
-	}
-	case L_DHCP6_CLIENT_EVENT_LEASE_EXPIRED:
-		l_debug("Lease for interface %u expired", netconfig->ifindex);
-		netconfig_dns_list_update(netconfig, AF_INET6);
-		netconfig_domains_update(netconfig, AF_INET6);
-		netconfig_set_dns(netconfig);
-		netconfig_set_domains(netconfig);
-		l_rtnl_address_free(netconfig->v6_address);
-		netconfig->v6_address = NULL;
-		l_free(l_steal_ptr(netconfig->v6_gateway_str));
-
-		/* Fall through */
-	case L_DHCP6_CLIENT_EVENT_NO_LEASE:
-		if (!l_dhcp6_client_start(netconfig->dhcp6_client))
-			l_error("netconfig: Failed to re-start DHCPv6 client "
-					"for interface %u", netconfig->ifindex);
-		break;
-	}
-}
-
 static void netconfig_remove_v4_address(struct netconfig *netconfig)
 {
 	if (!netconfig->v4_address)
 		return;
 
-	L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl, netconfig->ifindex,
-					netconfig->v4_address,
-					netconfig_ifaddr_del_cmd_cb,
-					netconfig, NULL));
 	l_rtnl_address_free(netconfig->v4_address);
 	netconfig->v4_address = NULL;
 }
@@ -1170,178 +278,14 @@ static void netconfig_reset_v4(struct netconfig *netconfig)
 		l_strv_free(l_steal_ptr(netconfig->dns4_overrides));
 		l_strv_free(l_steal_ptr(netconfig->dns4_list));
 
-		l_dhcp_client_stop(netconfig->dhcp_client);
 		netconfig->rtm_protocol = 0;
 
-		l_acd_destroy(netconfig->acd);
-		netconfig->acd = NULL;
-
 		l_free(l_steal_ptr(netconfig->v4_gateway_str));
 
 		l_free(l_steal_ptr(netconfig->v4_domain));
 	}
 }
 
-static void netconfig_ipv4_acd_event(enum l_acd_event event, void *user_data)
-{
-	struct netconfig *netconfig = user_data;
-
-	switch (event) {
-	case L_ACD_EVENT_AVAILABLE:
-		L_WARN_ON(!(netconfig->addr4_add_cmd_id =
-				l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
-					netconfig->v4_address,
-					netconfig_ipv4_ifaddr_add_cmd_cb,
-					netconfig, NULL)));
-		return;
-	case L_ACD_EVENT_CONFLICT:
-		/*
-		 * Conflict found, no IP was actually set so just free/unset
-		 * anything we set prior to starting ACD.
-		 */
-		l_error("netconfig: statically configured address conflict!");
-		l_rtnl_address_free(netconfig->v4_address);
-		netconfig->v4_address = NULL;
-		netconfig->rtm_protocol = 0;
-		break;
-	case L_ACD_EVENT_LOST:
-		/*
-		 * Set IP but lost it some time after. Full (IPv4) reset in this
-		 * case.
-		 */
-		l_error("netconfig: statically configured address was lost");
-		netconfig_remove_v4_address(netconfig);
-		break;
-	}
-}
-
-static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig)
-{
-	struct netdev *netdev = netdev_find(netconfig->ifindex);
-	bool set_address = (netconfig->rtm_protocol == RTPROT_STATIC);
-
-	if (netconfig_use_fils_addr(netconfig, AF_INET)) {
-		L_AUTO_FREE_VAR(char *, addr_str) = netconfig_ipv4_to_string(
-					netconfig->fils_override->ipv4_addr);
-		uint8_t prefix_len = netconfig->fils_override->ipv4_prefix_len;
-
-		if (unlikely(!addr_str))
-			return false;
-
-		netconfig->v4_address = l_rtnl_address_new(addr_str,
-								prefix_len);
-		if (L_WARN_ON(!netconfig->v4_address))
-			return false;
-
-		l_rtnl_address_set_noprefixroute(netconfig->v4_address, true);
-		set_address = true;
-
-		/*
-		 * TODO: If netconfig->fils_override->ipv4_lifetime is set,
-		 * start a timeout to renew the address using FILS IP Address
-		 * Assignment or perhaps just start the DHCP client at that
-		 * time.
-		 */
-	}
-
-	if (set_address) {
-		char ip[INET6_ADDRSTRLEN];
-
-		if (L_WARN_ON(!netconfig->v4_address ||
-					!l_rtnl_address_get_address(
-							netconfig->v4_address,
-							ip)))
-			return false;
-
-		netconfig_dns_list_update(netconfig, AF_INET);
-		netconfig_domains_update(netconfig, AF_INET);
-
-		netconfig->acd = l_acd_new(netconfig->ifindex);
-		l_acd_set_event_handler(netconfig->acd,
-					netconfig_ipv4_acd_event, netconfig,
-					NULL);
-		if (getenv("IWD_ACD_DEBUG"))
-			l_acd_set_debug(netconfig->acd, do_debug,
-					"[ACD] ", NULL);
-
-		if (!l_acd_start(netconfig->acd, ip)) {
-			l_error("failed to start ACD, continuing anyways");
-			l_acd_destroy(netconfig->acd);
-			netconfig->acd = NULL;
-
-			L_WARN_ON(!(netconfig->addr4_add_cmd_id =
-				l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
-					netconfig->v4_address,
-					netconfig_ipv4_ifaddr_add_cmd_cb,
-					netconfig, NULL)));
-		}
-
-		return true;
-	}
-
-	l_dhcp_client_set_address(netconfig->dhcp_client, ARPHRD_ETHER,
-					netdev_get_address(netdev), ETH_ALEN);
-
-	if (l_dhcp_client_start(netconfig->dhcp_client))
-		return true;
-
-	l_error("netconfig: Failed to start DHCPv4 client for interface %u",
-							netconfig->ifindex);
-	return false;
-}
-
-static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig)
-{
-	struct netdev *netdev = netdev_find(netconfig->ifindex);
-
-	if (netconfig->rtm_v6_protocol == RTPROT_UNSPEC) {
-		l_debug("IPV6 configuration disabled");
-		return true;
-	}
-
-	sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "0");
-
-	if (netconfig_use_fils_addr(netconfig, AF_INET6)) {
-		uint8_t prefix_len = netconfig->fils_override->ipv6_prefix_len;
-		L_AUTO_FREE_VAR(char *, addr_str) = netconfig_ipv6_to_string(
-					netconfig->fils_override->ipv6_addr);
-
-		if (unlikely(!addr_str))
-			return false;
-
-		netconfig->v6_address = l_rtnl_address_new(addr_str,
-								prefix_len);
-		if (L_WARN_ON(unlikely(!netconfig->v6_address)))
-			return false;
-
-		l_rtnl_address_set_noprefixroute(netconfig->v6_address, true);
-
-		/*
-		 * TODO: If netconfig->fils_override->ipv6_lifetime is set,
-		 * start a timeout to renew the address using FILS IP Address
-		 * Assignment or perhaps just start the DHCP client at that
-		 * time.
-		 */
-	}
-
-	if (netconfig->v6_address) {
-		netconfig_dns_list_update(netconfig, AF_INET6);
-
-		L_WARN_ON(!(netconfig->addr6_add_cmd_id =
-			l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
-					netconfig->v6_address,
-					netconfig_ipv6_ifaddr_add_cmd_cb,
-					netconfig, NULL)));
-		return true;
-	}
-
-	/* DHCPv6 or RA, update MAC */
-	l_dhcp6_client_set_address(netconfig->dhcp6_client, ARPHRD_ETHER,
-					netdev_get_address(netdev), ETH_ALEN);
-
-	return true;
-}
-
 static int validate_dns_list(int family, char **dns_list)
 {
 	unsigned int n_valid = 0;
@@ -1465,9 +409,6 @@ bool netconfig_load_settings(struct netconfig *netconfig,
 	else
 		netconfig->rtm_v6_protocol = RTPROT_DHCP;
 
-	if (send_hostname)
-		l_dhcp_client_set_hostname(netconfig->dhcp_client, hostname);
-
 	netconfig_free_settings(netconfig);
 
 	if (netconfig->rtm_protocol == RTPROT_STATIC)
@@ -1489,11 +430,7 @@ bool netconfig_configure(struct netconfig *netconfig,
 	netconfig->notify = notify;
 	netconfig->user_data = user_data;
 
-	if (unlikely(!netconfig_ipv4_select_and_install(netconfig)))
-		return false;
-
-	if (unlikely(!netconfig_ipv6_select_and_install(netconfig)))
-		return false;
+	/* TODO */
 
 	resolve_set_mdns(netconfig->resolve, netconfig->mdns);
 
@@ -1525,31 +462,6 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw)
 
 bool netconfig_reset(struct netconfig *netconfig)
 {
-	struct netdev *netdev = netdev_find(netconfig->ifindex);
-
-	if (netconfig->route4_add_gateway_cmd_id) {
-		l_netlink_cancel(rtnl, netconfig->route4_add_gateway_cmd_id);
-		netconfig->route4_add_gateway_cmd_id = 0;
-	}
-
-	if (netconfig->route6_add_cmd_id) {
-		l_netlink_cancel(rtnl, netconfig->route6_add_cmd_id);
-		netconfig->route6_add_cmd_id = 0;
-	}
-
-	if (netconfig->addr4_add_cmd_id) {
-		l_netlink_cancel(rtnl, netconfig->addr4_add_cmd_id);
-		netconfig->addr4_add_cmd_id = 0;
-	}
-
-	if (netconfig->addr6_add_cmd_id) {
-		l_netlink_cancel(rtnl, netconfig->addr6_add_cmd_id);
-		netconfig->addr6_add_cmd_id = 0;
-	}
-
-	if (netconfig->rtm_protocol || netconfig->rtm_v6_protocol)
-		resolve_revert(netconfig->resolve);
-
 	netconfig_reset_v4(netconfig);
 
 	if (netconfig->rtm_v6_protocol) {
@@ -1559,12 +471,8 @@ bool netconfig_reset(struct netconfig *netconfig)
 		l_strv_free(l_steal_ptr(netconfig->dns6_overrides));
 		l_strv_free(l_steal_ptr(netconfig->dns6_list));
 
-		l_dhcp6_client_stop(netconfig->dhcp6_client);
 		netconfig->rtm_v6_protocol = 0;
 
-		sysfs_write_ipv6_setting(netdev_get_name(netdev),
-						"disable_ipv6", "1");
-
 		l_free(l_steal_ptr(netconfig->v6_gateway_str));
 
 		l_strv_free(l_steal_ptr(netconfig->v6_domains));
@@ -1577,12 +485,10 @@ bool netconfig_reset(struct netconfig *netconfig)
 
 char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig)
 {
+	struct l_dhcp_client *client = NULL; /* TODO */
 	const struct l_dhcp_lease *lease;
 
-	if (!netconfig->dhcp_client)
-		return NULL;
-
-	lease = l_dhcp_client_get_lease(netconfig->dhcp_client);
+	lease = l_dhcp_client_get_lease(client);
 	if (!lease)
 		return NULL;
 
@@ -1622,28 +528,17 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 {
 	struct netdev *netdev = netdev_find(ifindex);
 	struct netconfig *netconfig;
-	struct l_icmp6_client *icmp6;
 	const char *debug_level = NULL;
 	int dhcp_priority = L_LOG_INFO;
-
-	if (!netconfig_list)
-		return NULL;
+	struct l_dhcp_client *dhcp = NULL; /* TODO */
+	struct l_dhcp6_client *dhcp6 = NULL; /* TODO */
 
 	l_debug("Starting netconfig for interface: %d", ifindex);
 
-	netconfig = netconfig_find(ifindex);
-	if (netconfig)
-		return netconfig;
-
 	netconfig = l_new(struct netconfig, 1);
 	netconfig->ifindex = ifindex;
 	netconfig->resolve = resolve_new(ifindex);
 
-	netconfig->dhcp_client = l_dhcp_client_new(ifindex);
-	l_dhcp_client_set_event_handler(netconfig->dhcp_client,
-					netconfig_ipv4_dhcp_event_handler,
-					netconfig, NULL);
-
 	debug_level = getenv("IWD_DHCP_DEBUG");
 	if (debug_level != NULL) {
 		if (!strcmp("debug", debug_level))
@@ -1658,42 +553,22 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 			dhcp_priority = L_LOG_DEBUG;
 	}
 
-	l_dhcp_client_set_debug(netconfig->dhcp_client, do_debug,
-					"[DHCPv4] ", NULL, dhcp_priority);
+	l_dhcp_client_set_debug(dhcp, do_debug, "[DHCPv4] ", NULL,
+				dhcp_priority);
 
-	netconfig->dhcp6_client = l_dhcp6_client_new(ifindex);
-	l_dhcp6_client_set_event_handler(netconfig->dhcp6_client,
-						netconfig_dhcp6_event_handler,
-						netconfig, NULL);
-	l_dhcp6_client_set_lla_randomized(netconfig->dhcp6_client, true);
-	l_dhcp6_client_set_nodelay(netconfig->dhcp6_client, true);
-	l_dhcp6_client_set_rtnl(netconfig->dhcp6_client, rtnl);
+	l_dhcp6_client_set_lla_randomized(dhcp6, true);
+	l_dhcp6_client_set_nodelay(dhcp6, true);
 
 	if (getenv("IWD_DHCP_DEBUG"))
-		l_dhcp6_client_set_debug(netconfig->dhcp6_client, do_debug,
-							"[DHCPv6] ", NULL);
-
-	icmp6 = l_dhcp6_client_get_icmp6(netconfig->dhcp6_client);
-	l_icmp6_client_set_rtnl(icmp6, rtnl);
-	l_icmp6_client_set_route_priority(icmp6, ROUTE_PRIORITY_OFFSET);
-
-	l_queue_push_tail(netconfig_list, netconfig);
-
-	sysfs_write_ipv6_setting(netdev_get_name(netdev), "accept_ra", "0");
-	sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "1");
+		l_dhcp6_client_set_debug(dhcp6, do_debug, "[DHCPv6] ", NULL);
 
 	return netconfig;
 }
 
 void netconfig_destroy(struct netconfig *netconfig)
 {
-	if (!netconfig_list)
-		return;
-
 	l_debug("");
 
-	l_queue_remove(netconfig_list, netconfig);
-
 	netconfig_reset(netconfig);
 	resolve_free(netconfig->resolve);
 	netconfig_free(netconfig);
@@ -1710,43 +585,6 @@ bool netconfig_enabled(void)
 
 static int netconfig_init(void)
 {
-	uint32_t r;
-
-	if (netconfig_list)
-		return -EALREADY;
-
-	rtnl = iwd_get_rtnl();
-
-	r = l_netlink_register(rtnl, RTNLGRP_IPV4_IFADDR,
-					netconfig_ifaddr_notify, NULL, NULL);
-	if (!r) {
-		l_error("netconfig: Failed to register for RTNL link address"
-							" notifications.");
-		goto error;
-	}
-
-	r = l_rtnl_ifaddr4_dump(rtnl, netconfig_ifaddr_cmd_cb, NULL, NULL);
-	if (!r) {
-		l_error("netconfig: Failed to get addresses from RTNL link.");
-		goto error;
-	}
-
-	r = l_netlink_register(rtnl, RTNLGRP_IPV6_IFADDR,
-				netconfig_ifaddr_ipv6_notify, NULL, NULL);
-	if (!r) {
-		l_error("netconfig: Failed to register for RTNL link IPv6 "
-					"address notifications.");
-		goto error;
-	}
-
-	r = l_rtnl_ifaddr6_dump(rtnl, netconfig_ifaddr_ipv6_cmd_cb, NULL,
-									NULL);
-	if (!r) {
-		l_error("netconfig: Failed to get IPv6 addresses from RTNL"
-								" link.");
-		goto error;
-	}
-
 	if (!l_settings_get_uint(iwd_get_config(), "Network",
 							"RoutePriorityOffset",
 							&ROUTE_PRIORITY_OFFSET))
@@ -1757,24 +595,11 @@ static int netconfig_init(void)
 					&ipv6_enabled))
 		ipv6_enabled = false;
 
-	netconfig_list = l_queue_new();
-
 	return 0;
-
-error:
-	rtnl = NULL;
-
-	return r;
 }
 
 static void netconfig_exit(void)
 {
-	if (!netconfig_list)
-		return;
-
-	rtnl = NULL;
-
-	l_queue_destroy(netconfig_list, netconfig_free);
 }
 
 IWD_MODULE(netconfig, netconfig_init, netconfig_exit)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/10] netconfig: Keep configuration directly in struct l_netconfig
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 02/10] netconfig: Drop dhcp, dhcp6 and acd client instances Andrew Zaborowski
@ 2022-08-29 17:35 ` Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 04/10] netconfig: Clean up netconfig_get_static{4,6}_address Andrew Zaborowski
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

Drop all the struct netconfig members where we were keeping the parsed
netconfig settings and add a struct l_netconfig object.  In
netconfig_load_settings load all of the settings once parsed directly
into the l_netconfig object.  Only preserve the mdns configuration and
save some boolean values needed to properly handle static configuration
and FILS.  Update functions to use the new set of struct netconfig
members.

These booleans mirroring the l_netconfig state could be replaced by
adding l_netconfig getters for settings which currently only have
setters.
---
 Makefile.am     |   6 +-
 src/netconfig.c | 387 ++++++++++++++++++++++++++----------------------
 2 files changed, 216 insertions(+), 177 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index ed93d000..31b7e24b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -62,7 +62,8 @@ ell_headers = ell/util.h \
 			ell/icmp6.h \
 			ell/dhcp6.h \
 			ell/acd.h \
-			ell/cleanup.h
+			ell/cleanup.h \
+			ell/netconfig.h
 
 ell_sources = ell/private.h \
 			ell/missing.h \
@@ -141,7 +142,8 @@ ell_sources = ell/private.h \
 			ell/icmp6-private.h \
 			ell/dhcp6-lease.c \
 			ell/dhcp6-transport.c \
-			ell/acd.c
+			ell/acd.c \
+			ell/netconfig.c
 
 ell_shared = ell/useful.h ell/asn1-private.h
 
diff --git a/src/netconfig.c b/src/netconfig.c
index ea9846f6..98764346 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -53,21 +53,15 @@
 #include "src/sysfs.h"
 
 struct netconfig {
+	struct l_netconfig *nc;
 	uint32_t ifindex;
-	uint8_t rtm_protocol;
-	uint8_t rtm_v6_protocol;
-	struct l_rtnl_address *v4_address;
-	struct l_rtnl_address *v6_address;
-	char **dns4_overrides;
-	char **dns6_overrides;
-	char **dns4_list;
-	char **dns6_list;
+
 	char *mdns;
 	struct ie_fils_ip_addr_response_info *fils_override;
-	char *v4_gateway_str;
-	char *v6_gateway_str;
-	char *v4_domain;
-	char **v6_domains;
+	bool enabled[2];
+	bool static_config[2];
+	bool gateway_overridden[2];
+	bool dns_overridden[2];
 
 	const struct l_settings *active_settings;
 
@@ -77,6 +71,9 @@ struct netconfig {
 	struct resolve *resolve;
 };
 
+/* 0 for AF_INET, 1 for AF_INET6 */
+#define INDEX_FOR_AF(af)	((af) != AF_INET)
+
 static struct l_netlink *rtnl;
 
 /*
@@ -95,31 +92,36 @@ static void do_debug(const char *str, void *user_data)
 
 static void netconfig_free_settings(struct netconfig *netconfig)
 {
-	l_rtnl_address_free(netconfig->v4_address);
-	netconfig->v4_address = NULL;
-	l_rtnl_address_free(netconfig->v6_address);
-	netconfig->v6_address = NULL;
-
-	l_strfreev(netconfig->dns4_overrides);
-	netconfig->dns4_overrides = NULL;
-	l_strfreev(netconfig->dns6_overrides);
-	netconfig->dns6_overrides = NULL;
+	netconfig->enabled[0] = true;
+	netconfig->enabled[1] = false;
+	netconfig->static_config[0] = false;
+	netconfig->static_config[1] = false;
+	netconfig->gateway_overridden[0] = false;
+	netconfig->gateway_overridden[1] = false;
+	netconfig->dns_overridden[0] = false;
+	netconfig->dns_overridden[1] = false;
+	l_netconfig_reset_config(netconfig->nc);
 
 	l_free(netconfig->mdns);
 	netconfig->mdns = NULL;
+
+	l_free(l_steal_ptr(netconfig->fils_override));
 }
 
 static void netconfig_free(void *data)
 {
 	struct netconfig *netconfig = data;
 
+	l_netconfig_destroy(netconfig->nc);
 	l_free(netconfig);
 }
 
 static bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
 {
-	if ((af == AF_INET ? netconfig->rtm_protocol :
-				netconfig->rtm_v6_protocol) != RTPROT_DHCP)
+	if (!netconfig->enabled[INDEX_FOR_AF(af)])
+		return false;
+
+	if (netconfig->static_config[INDEX_FOR_AF(af)])
 		return false;
 
 	if (!netconfig->fils_override)
@@ -229,7 +231,7 @@ no_prefix_len:
 
 static void netconfig_gateway_to_arp(struct netconfig *netconfig)
 {
-	struct l_dhcp_client *dhcp = NULL; /* TODO */
+	struct l_dhcp_client *dhcp = l_netconfig_get_dhcp_client(netconfig->nc);
 	const struct l_dhcp_lease *lease;
 	_auto_(l_free) char *server_id = NULL;
 	_auto_(l_free) char *gw = NULL;
@@ -237,7 +239,8 @@ static void netconfig_gateway_to_arp(struct netconfig *netconfig)
 	struct in_addr in_gw;
 
 	/* Can only do this for DHCP in certain network setups */
-	if (netconfig->rtm_protocol != RTPROT_DHCP)
+	if (netconfig->static_config[INDEX_FOR_AF(AF_INET)] ||
+			netconfig->fils_override)
 		return;
 
 	lease = l_dhcp_client_get_lease(dhcp);
@@ -261,167 +264,207 @@ static void netconfig_gateway_to_arp(struct netconfig *netconfig)
 		l_debug("l_rtnl_neighbor_set_hwaddr failed");
 }
 
-static void netconfig_remove_v4_address(struct netconfig *netconfig)
+static bool netconfig_load_dns(struct netconfig *netconfig,
+				const struct l_settings *active_settings,
+				const char *group_name, uint8_t family)
 {
-	if (!netconfig->v4_address)
-		return;
+	_auto_(l_strv_free) char **dns_str_list = NULL;
 
-	l_rtnl_address_free(netconfig->v4_address);
-	netconfig->v4_address = NULL;
-}
+	if (!l_settings_has_key(active_settings, group_name, "DNS"))
+		return true;
 
-static void netconfig_reset_v4(struct netconfig *netconfig)
-{
-	if (netconfig->rtm_protocol) {
-		netconfig_remove_v4_address(netconfig);
-
-		l_strv_free(l_steal_ptr(netconfig->dns4_overrides));
-		l_strv_free(l_steal_ptr(netconfig->dns4_list));
-
-		netconfig->rtm_protocol = 0;
-
-		l_free(l_steal_ptr(netconfig->v4_gateway_str));
+	dns_str_list = l_settings_get_string_list(active_settings,
+							group_name, "DNS", ' ');
+	if (unlikely(!dns_str_list)) {
+		l_error("netconfig: Can't load [%s].DNS", group_name);
+		return false;
+	}
 
-		l_free(l_steal_ptr(netconfig->v4_domain));
+	if (unlikely(!l_netconfig_set_dns_override(netconfig->nc, family,
+							dns_str_list))) {
+		l_error("netconfig: l_netconfig_set_dns_override(%s) failed",
+			family == AF_INET ? "AF_INET" : "AF_INET6");
+		return false;
 	}
+
+	netconfig->dns_overridden[INDEX_FOR_AF(family)] = true;
+	return true;
 }
 
-static int validate_dns_list(int family, char **dns_list)
+static bool netconfig_load_gateway(struct netconfig *netconfig,
+				const struct l_settings *active_settings,
+				const char *group_name, uint8_t family)
 {
-	unsigned int n_valid = 0;
-	struct in_addr in_addr;
-	struct in6_addr in6_addr;
-	char **p;
-
-	for (p = dns_list; *p; p++) {
-		int r;
-
-		if (family == AF_INET)
-			r = inet_pton(AF_INET, *p, &in_addr);
-		else if (family == AF_INET6)
-			r = inet_pton(AF_INET6, *p, &in6_addr);
-		else
-			r = -EAFNOSUPPORT;
-
-		if (r > 0) {
-			n_valid += 1;
-			continue;
-		}
+	_auto_(l_free) char *gateway_str = NULL;
+
+	if (!l_settings_has_key(active_settings, group_name, "Gateway"))
+		return true;
 
-		l_error("netconfig: Invalid DNS address '%s'.", *p);
-		return -EINVAL;
+	gateway_str = l_settings_get_string(active_settings, group_name,
+						"Gateway");
+	if (unlikely(!gateway_str)) {
+		l_error("netconfig: Can't load [%s].Gateway", group_name);
+		return false;
+	}
+
+	if (unlikely(!l_netconfig_set_gateway_override(netconfig->nc, family,
+							gateway_str))) {
+		l_error("netconfig: l_netconfig_set_gateway_override(%s) "
+			"failed", family == AF_INET ? "AF_INET" : "AF_INET6");
+		return false;
 	}
 
-	return n_valid;
+	netconfig->gateway_overridden[INDEX_FOR_AF(family)] = true;
+	return true;
 }
 
 bool netconfig_load_settings(struct netconfig *netconfig,
 				const struct l_settings *active_settings)
 {
-	_auto_(l_free) char *mdns = NULL;
-	bool send_hostname;
-	bool v6_enabled;
+	bool send_hostname = false;
 	char hostname[HOST_NAME_MAX + 1];
-	_auto_(l_strv_free) char **dns4_overrides = NULL;
-	_auto_(l_strv_free) char **dns6_overrides = NULL;
-	_auto_(l_rtnl_address_free) struct l_rtnl_address *v4_address = NULL;
-	_auto_(l_rtnl_address_free) struct l_rtnl_address *v6_address = NULL;
-
-	dns4_overrides = l_settings_get_string_list(active_settings,
-							"IPv4", "DNS", ' ');
-	if (dns4_overrides) {
-		int r = validate_dns_list(AF_INET, dns4_overrides);
-
-		if (unlikely(r <= 0)) {
-			l_strfreev(dns4_overrides);
-			dns4_overrides = NULL;
-
-			if (r < 0)
-				return false;
-		}
+	_auto_(l_free) char *mdns = NULL;
+	bool success = true;
+	bool static_ipv4 = false;
+	bool static_ipv6 = false;
+	bool enable_ipv4 = true;
+	bool enable_ipv6 = ipv6_enabled;
 
-		if (r == 0)
-			l_error("netconfig: Empty IPv4.DNS entry, skipping...");
-	}
+	netconfig_free_settings(netconfig);
 
-	dns6_overrides = l_settings_get_string_list(active_settings,
-							"IPv6", "DNS", ' ');
+	/*
+	 * Note we try to print errors and continue validating the
+	 * configuration until we've gone through all the settings so
+	 * as to make fixing the settings more efficient for the user.
+	 */
 
-	if (dns6_overrides) {
-		int r = validate_dns_list(AF_INET6, dns6_overrides);
+	if (l_settings_has_key(active_settings, "IPv4", "Address")) {
+		_auto_(l_rtnl_address_free) struct l_rtnl_address *addr =
+			netconfig_get_static4_address(active_settings);
 
-		if (unlikely(r <= 0)) {
-			l_strfreev(dns6_overrides);
-			dns6_overrides = NULL;
+		if (unlikely(!addr)) {
+			success = false;
+			goto ipv6_addr;
+		}
 
-			if (r < 0)
-				return false;
+		if (!l_netconfig_set_static_addr(netconfig->nc, AF_INET,
+							addr)) {
+			l_error("netconfig: l_netconfig_set_static_addr("
+				"AF_INET) failed");
+			success = false;
+			goto ipv6_addr;
 		}
 
-		if (r == 0)
-			l_error("netconfig: Empty IPv6.DNS entry, skipping...");
+		static_ipv4 = true;
 	}
 
-	if (!l_settings_get_bool(active_settings,
-					"IPv4", "SendHostname", &send_hostname))
-		send_hostname = false;
+ipv6_addr:
+	if (l_settings_has_key(active_settings, "IPv6", "Address")) {
+		_auto_(l_rtnl_address_free) struct l_rtnl_address *addr =
+			netconfig_get_static6_address(active_settings);
+
+		if (unlikely(!addr)) {
+			success = false;
+			goto gateway;
+		}
 
-	if (send_hostname) {
-		if (gethostname(hostname, sizeof(hostname)) != 0) {
-			l_warn("netconfig: Unable to get hostname. "
-					"Error %d: %s", errno, strerror(errno));
-			send_hostname = false;
+		if (!l_netconfig_set_static_addr(netconfig->nc, AF_INET6,
+							addr)) {
+			l_error("netconfig: l_netconfig_set_static_addr("
+				"AF_INET6) failed");
+			success = false;
+			goto gateway;
 		}
+
+		static_ipv6 = true;
 	}
 
-	mdns = l_settings_get_string(active_settings,
-					"Network", "MulticastDNS");
+gateway:
+	if (!netconfig_load_gateway(netconfig, active_settings,
+					"IPv4", AF_INET))
+		success = false;
 
-	if (l_settings_has_key(active_settings, "IPv4", "Address")) {
-		v4_address = netconfig_get_static4_address(active_settings);
+	if (!netconfig_load_gateway(netconfig, active_settings,
+					"IPv6", AF_INET6))
+		success = false;
 
-		if (unlikely(!v4_address)) {
-			l_error("netconfig: Can't parse IPv4 address");
-			return false;
-		}
+	if (!netconfig_load_dns(netconfig, active_settings, "IPv4", AF_INET))
+		success = false;
+
+	if (!netconfig_load_dns(netconfig, active_settings, "IPv6", AF_INET6))
+		success = false;
+
+	if (l_settings_has_key(active_settings, "IPv6", "Enabled") &&
+			!l_settings_get_bool(active_settings, "IPv6", "Enabled",
+						&enable_ipv6)) {
+		l_error("netconfig: Can't load IPv6.Enabled");
+		success = false;
+		goto send_hostname;
 	}
 
-	if (!l_settings_get_bool(active_settings, "IPv6",
-					"Enabled", &v6_enabled))
-		v6_enabled = ipv6_enabled;
+	if (!l_netconfig_set_family_enabled(netconfig->nc, AF_INET,
+						enable_ipv4) ||
+			!l_netconfig_set_family_enabled(netconfig->nc, AF_INET6,
+							enable_ipv6)) {
+		l_error("netconfig: l_netconfig_set_family_enabled() failed");
+		success = false;
+	}
 
-	if (l_settings_has_key(active_settings, "IPv6", "Address")) {
-		v6_address = netconfig_get_static6_address(active_settings);
+send_hostname:
+	if (l_settings_has_key(active_settings, "IPv4", "SendHostname") &&
+			!l_settings_get_bool(active_settings, "IPv4",
+						"SendHostname",
+						&send_hostname)) {
+		l_error("netconfig: Can't load [IPv4].SendHostname");
+		success = false;
+		goto mdns;
+	}
 
-		if (unlikely(!v6_address)) {
-			l_error("netconfig: Can't parse IPv6 address");
-			return false;
-		}
+	if (send_hostname && gethostname(hostname, sizeof(hostname)) != 0) {
+		/* Warning only */
+		l_warn("netconfig: Unable to get hostname. "
+			"Error %d: %s", errno, strerror(errno));
+		goto mdns;
 	}
 
-	/* No more validation steps for now, commit new values */
-	netconfig->rtm_protocol = v4_address ? RTPROT_STATIC : RTPROT_DHCP;
+	if (send_hostname &&
+			!l_netconfig_set_hostname(netconfig->nc, hostname)) {
+		l_error("netconfig: l_netconfig_set_hostname() failed");
+		success = false;
+		goto mdns;
+	}
 
-	if (!v6_enabled)
-		netconfig->rtm_v6_protocol = RTPROT_UNSPEC;
-	else if (v6_address)
-		netconfig->rtm_v6_protocol = RTPROT_STATIC;
-	else
-		netconfig->rtm_v6_protocol = RTPROT_DHCP;
+mdns:
+	if (l_settings_has_key(active_settings, "Network", "MulticastDNS") &&
+			!(mdns = l_settings_get_string(active_settings,
+							"Network",
+							"MulticastDNS"))) {
+		l_error("netconfig: Can't load Network.MulticastDNS");
+		success = false;
+	}
 
-	netconfig_free_settings(netconfig);
+	if (mdns && !L_IN_STRSET(mdns, "true", "false", "resolve")) {
+		l_error("netconfig: Bad Network.MulticastDNS value '%s'", mdns);
+		success = false;
+	}
 
-	if (netconfig->rtm_protocol == RTPROT_STATIC)
-		netconfig->v4_address = l_steal_ptr(v4_address);
+	if (!l_netconfig_check_config(netconfig->nc)) {
+		l_error("netconfig: Invalid configuration");
+		success = false;
+	}
 
-	if (netconfig->rtm_v6_protocol == RTPROT_STATIC)
-		netconfig->v6_address = l_steal_ptr(v6_address);
+	if (success) {
+		netconfig->active_settings = active_settings;
+		netconfig->static_config[INDEX_FOR_AF(AF_INET)] = static_ipv4;
+		netconfig->static_config[INDEX_FOR_AF(AF_INET6)] = static_ipv6;
+		netconfig->enabled[INDEX_FOR_AF(AF_INET)] = enable_ipv4;
+		netconfig->enabled[INDEX_FOR_AF(AF_INET6)] = enable_ipv6;
+		netconfig->mdns = l_steal_ptr(mdns);
+		return true;
+	}
 
-	netconfig->active_settings = active_settings;
-	netconfig->dns4_overrides = l_steal_ptr(dns4_overrides);
-	netconfig->dns6_overrides = l_steal_ptr(dns6_overrides);
-	netconfig->mdns = l_steal_ptr(mdns);
-	return true;
+	l_netconfig_reset_config(netconfig->nc);
+	return false;
 }
 
 bool netconfig_configure(struct netconfig *netconfig,
@@ -449,11 +492,11 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw)
 	if (set_arp_gw)
 		netconfig_gateway_to_arp(netconfig);
 
-	if (netconfig->rtm_protocol == RTPROT_DHCP) {
+	if (!netconfig->static_config[INDEX_FOR_AF(AF_INET)]) {
 		/* TODO l_dhcp_client sending a DHCP inform request */
 	}
 
-	if (netconfig->rtm_v6_protocol == RTPROT_DHCP) {
+	if (!netconfig->static_config[INDEX_FOR_AF(AF_INET6)]) {
 		/* TODO l_dhcp_v6_client sending a DHCP inform request */
 	}
 
@@ -462,32 +505,22 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw)
 
 bool netconfig_reset(struct netconfig *netconfig)
 {
-	netconfig_reset_v4(netconfig);
-
-	if (netconfig->rtm_v6_protocol) {
-		l_rtnl_address_free(netconfig->v6_address);
-		netconfig->v6_address = NULL;
-
-		l_strv_free(l_steal_ptr(netconfig->dns6_overrides));
-		l_strv_free(l_steal_ptr(netconfig->dns6_list));
-
-		netconfig->rtm_v6_protocol = 0;
-
-		l_free(l_steal_ptr(netconfig->v6_gateway_str));
-
-		l_strv_free(l_steal_ptr(netconfig->v6_domains));
-	}
-
-	l_free(l_steal_ptr(netconfig->fils_override));
+	l_netconfig_unconfigure(netconfig->nc);
+	l_netconfig_stop(netconfig->nc);
 
+	netconfig_free_settings(netconfig);
 	return true;
 }
 
 char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig)
 {
-	struct l_dhcp_client *client = NULL; /* TODO */
+	struct l_dhcp_client *client =
+		l_netconfig_get_dhcp_client(netconfig->nc);
 	const struct l_dhcp_lease *lease;
 
+	if (!client)
+		return NULL;
+
 	lease = l_dhcp_client_get_lease(client);
 	if (!lease)
 		return NULL;
@@ -504,15 +537,16 @@ bool netconfig_get_fils_ip_req(struct netconfig *netconfig,
 	 * configuration (usually DHCP).  If we're configured with static
 	 * values return false to mean the IE should not be sent.
 	 */
-	if (netconfig->rtm_protocol != RTPROT_DHCP &&
-			netconfig->rtm_v6_protocol != RTPROT_DHCP)
+	if (netconfig->static_config[0] && netconfig->static_config[1])
 		return false;
 
 	memset(info, 0, sizeof(*info));
-	info->ipv4 = (netconfig->rtm_protocol == RTPROT_DHCP);
-	info->ipv6 = (netconfig->rtm_v6_protocol == RTPROT_DHCP);
-	info->dns = (info->ipv4 && !netconfig->dns4_overrides) ||
-		(info->ipv6 && !netconfig->dns6_overrides);
+	info->ipv4 = !netconfig->static_config[INDEX_FOR_AF(AF_INET)];
+	info->ipv6 = !netconfig->static_config[INDEX_FOR_AF(AF_INET6)];
+	info->dns = (info->ipv4 &&
+			!netconfig->dns_overridden[INDEX_FOR_AF(AF_INET)]) ||
+		(info->ipv6 &&
+			!netconfig->dns_overridden[INDEX_FOR_AF(AF_INET)]);
 
 	return true;
 }
@@ -530,12 +564,12 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 	struct netconfig *netconfig;
 	const char *debug_level = NULL;
 	int dhcp_priority = L_LOG_INFO;
-	struct l_dhcp_client *dhcp = NULL; /* TODO */
-	struct l_dhcp6_client *dhcp6 = NULL; /* TODO */
+	struct l_dhcp6_client *dhcp6;
 
-	l_debug("Starting netconfig for interface: %d", ifindex);
+	l_debug("Creating netconfig for interface: %d", ifindex);
 
 	netconfig = l_new(struct netconfig, 1);
+	netconfig->nc = l_netconfig_new(ifindex);
 	netconfig->ifindex = ifindex;
 	netconfig->resolve = resolve_new(ifindex);
 
@@ -553,15 +587,18 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 			dhcp_priority = L_LOG_DEBUG;
 	}
 
-	l_dhcp_client_set_debug(dhcp, do_debug, "[DHCPv4] ", NULL,
-				dhcp_priority);
+	l_dhcp_client_set_debug(l_netconfig_get_dhcp_client(netconfig->nc),
+				do_debug, "[DHCPv4] ", NULL, dhcp_priority);
 
+	dhcp6 = l_netconfig_get_dhcp6_client(netconfig->nc);
 	l_dhcp6_client_set_lla_randomized(dhcp6, true);
 	l_dhcp6_client_set_nodelay(dhcp6, true);
 
-	if (getenv("IWD_DHCP_DEBUG"))
+	if (debug_level)
 		l_dhcp6_client_set_debug(dhcp6, do_debug, "[DHCPv6] ", NULL);
 
+	l_netconfig_set_route_priority(netconfig->nc, ROUTE_PRIORITY_OFFSET);
+
 	return netconfig;
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/10] netconfig: Clean up netconfig_get_static{4,6}_address
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 02/10] netconfig: Drop dhcp, dhcp6 and acd client instances Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 03/10] netconfig: Keep configuration directly in struct l_netconfig Andrew Zaborowski
@ 2022-08-29 17:35 ` Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 05/10] netconfig: Store pointer to netdev instead of ifindex Andrew Zaborowski
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

 * make the error handling simpler,
 * make error messages more consistent,
 * validate address families,
 * for IPv4 skip l_rtnl_address_set_noprefixroute()
   as l_netconfig will do this internally as needed.
 * for IPv6 set the default prefix length to 64 as that's going to be
   used for the local prefix route's prefix length and is a more
   practical value.
---
 src/netconfig.c | 43 +++++++++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/src/netconfig.c b/src/netconfig.c
index 98764346..13960c53 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -145,7 +145,7 @@ static void netconfig_set_neighbor_entry_cb(int error,
 static struct l_rtnl_address *netconfig_get_static4_address(
 				const struct l_settings *active_settings)
 {
-	struct l_rtnl_address *ifaddr = NULL;
+	_auto_(l_rtnl_address_free) struct l_rtnl_address *ifaddr = NULL;
 	L_AUTO_FREE_VAR(char *, ip) = NULL;
 	L_AUTO_FREE_VAR(char *, netmask) = NULL;
 	struct in_addr in_addr;
@@ -153,13 +153,22 @@ static struct l_rtnl_address *netconfig_get_static4_address(
 	uint32_t prefix_len;
 
 	ip = l_settings_get_string(active_settings, "IPv4", "Address");
-	if (!ip)
+	if (unlikely(!ip)) {
+		l_error("netconfig: Can't load IPv4.Address");
 		return NULL;
+	}
+
+	if (l_settings_has_key(active_settings, "IPv4", "Netmask") &&
+			!(netmask = l_settings_get_string(active_settings,
+								"IPv4",
+								"Netmask"))) {
+		l_error("netconfig: Can't load IPv4.Netmask");
+		return NULL;
+	}
 
-	netmask = l_settings_get_string(active_settings, "IPv4", "Netmask");
 	if (netmask) {
 		if (inet_pton(AF_INET, netmask, &in_addr) != 1) {
-			l_error("netconfig: Can't parse IPv4 Netmask");
+			l_error("netconfig: Can't parse IPv4.Netmask");
 			return NULL;
 		}
 
@@ -167,14 +176,14 @@ static struct l_rtnl_address *netconfig_get_static4_address(
 
 		if (ntohl(in_addr.s_addr) !=
 				util_netmask_from_prefix(prefix_len)) {
-			l_error("netconfig: Invalid IPv4 Netmask");
+			l_error("netconfig: Invalid IPv4.Netmask");
 			return NULL;
 		}
 	} else
 		prefix_len = 24;
 
 	ifaddr = l_rtnl_address_new(ip, prefix_len);
-	if (!ifaddr) {
+	if (!ifaddr || l_rtnl_address_get_family(ifaddr) != AF_INET) {
 		l_error("netconfig: Unable to parse IPv4.Address");
 		return NULL;
 	}
@@ -182,12 +191,10 @@ static struct l_rtnl_address *netconfig_get_static4_address(
 	broadcast = l_settings_get_string(active_settings, "IPv4", "Broadcast");
 	if (broadcast && !l_rtnl_address_set_broadcast(ifaddr, broadcast)) {
 		l_error("netconfig: Unable to parse IPv4.Broadcast");
-		l_rtnl_address_free(ifaddr);
 		return NULL;
 	}
 
-	l_rtnl_address_set_noprefixroute(ifaddr, true);
-	return ifaddr;
+	return l_steal_ptr(ifaddr);
 }
 
 static struct l_rtnl_address *netconfig_get_static6_address(
@@ -196,12 +203,14 @@ static struct l_rtnl_address *netconfig_get_static6_address(
 	L_AUTO_FREE_VAR(char *, ip);
 	char *p;
 	char *endp;
-	struct l_rtnl_address *ret;
-	uint32_t prefix_len = 128;
+	_auto_(l_rtnl_address_free) struct l_rtnl_address *ret = NULL;
+	uint32_t prefix_len = 64;
 
 	ip = l_settings_get_string(active_settings, "IPv6", "Address");
-	if (!ip)
+	if (unlikely(!ip)) {
+		l_error("netconfig: Can't load IPv6.Address");
 		return NULL;
+	}
 
 	p = strrchr(ip, '/');
 	if (!p)
@@ -222,11 +231,13 @@ static struct l_rtnl_address *netconfig_get_static6_address(
 
 no_prefix_len:
 	ret = l_rtnl_address_new(ip, prefix_len);
-	if (!ret)
-		l_error("netconfig: Invalid IPv6 address %s is "
-				"provided in network configuration file.", ip);
+	if (!ret || l_rtnl_address_get_family(ret) != AF_INET6) {
+		l_error("netconfig: Invalid IPv6 address %s provided in "
+			"network configuration file.", ip);
+		return NULL;
+	}
 
-	return ret;
+	return l_steal_ptr(ret);
 }
 
 static void netconfig_gateway_to_arp(struct netconfig *netconfig)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/10] netconfig: Store pointer to netdev instead of ifindex
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
                   ` (2 preceding siblings ...)
  2022-08-29 17:35 ` [PATCH 04/10] netconfig: Clean up netconfig_get_static{4,6}_address Andrew Zaborowski
@ 2022-08-29 17:35 ` Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 06/10] netconfig: Add netconfig-commit API Andrew Zaborowski
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

To avoid repeated lookups by ifindex, replace the ifindex member in
struct netconfig with a struct netdev pointer.  A struct netconfig
always lives shorter than the struct netdev.
---
 src/netconfig.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/netconfig.c b/src/netconfig.c
index 13960c53..74eaca16 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -54,7 +54,7 @@
 
 struct netconfig {
 	struct l_netconfig *nc;
-	uint32_t ifindex;
+	struct netdev *netdev;
 
 	char *mdns;
 	struct ie_fils_ip_addr_response_info *fils_override;
@@ -581,7 +581,7 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 
 	netconfig = l_new(struct netconfig, 1);
 	netconfig->nc = l_netconfig_new(ifindex);
-	netconfig->ifindex = ifindex;
+	netconfig->netdev = netdev;
 	netconfig->resolve = resolve_new(ifindex);
 
 	debug_level = getenv("IWD_DHCP_DEBUG");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 06/10] netconfig: Add netconfig-commit API
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
                   ` (3 preceding siblings ...)
  2022-08-29 17:35 ` [PATCH 05/10] netconfig: Store pointer to netdev instead of ifindex Andrew Zaborowski
@ 2022-08-29 17:35 ` Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 07/10] netconfig: Handle l_netconfig events Andrew Zaborowski
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

Add netconfig-commit.c whose main method, netconfig_commit actually sets
the configuration obtained by l_netconfig to the system netdev,
specifically it sets local addresses on the interface, adds routes to the
routing table, sets DNS related data and may add entries to the neighbor
cache.  netconfig-commit.c uses a backend-ops type structure to allow
for switching backends.  In this commit there's only a default backend
that uses l_netconfig_rtnl_apply() and a struct resolve object to write
the configuration.

netconfig_gateway_to_arp is moved from netconfig.c to netconfig-commit.c
(and renamed.)  The struct netconfig definition is moved to netconfig.h
so that both files can access the settings stored in the struct.
---
 Makefile.am            |   3 +-
 src/netconfig-commit.c | 203 +++++++++++++++++++++++++++++++++++++++++
 src/netconfig.c        |  77 +---------------
 src/netconfig.h        |  33 +++++++
 4 files changed, 243 insertions(+), 73 deletions(-)
 create mode 100644 src/netconfig-commit.c

diff --git a/Makefile.am b/Makefile.am
index 31b7e24b..bc26d052 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -237,7 +237,8 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
 					src/anqp.h src/anqp.c \
 					src/anqputil.h src/anqputil.c \
 					src/netconfig.h src/netconfig.c\
-					src/resolve.h src/resolve.c\
+					src/netconfig-commit.c \
+					src/resolve.h src/resolve.c \
 					src/hotspot.c \
 					src/p2p.h src/p2p.c \
 					src/p2putil.h src/p2putil.c \
diff --git a/src/netconfig-commit.c b/src/netconfig-commit.c
new file mode 100644
index 00000000..48ebe847
--- /dev/null
+++ b/src/netconfig-commit.c
@@ -0,0 +1,203 @@
+/*
+ *
+ *  Wireless daemon for Linux
+ *
+ *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <arpa/inet.h>
+#include <netinet/if_ether.h>
+#include <linux/icmpv6.h>
+
+#include <ell/ell.h>
+
+#include "ell/useful.h"
+#include "src/iwd.h"
+#include "src/common.h"
+#include "src/util.h"
+#include "src/netdev.h"
+#include "src/ie.h"
+#include "src/resolve.h"
+#include "src/netconfig.h"
+
+struct netconfig_commit_ops {
+	bool (*init_data)(struct netconfig *netconfig);
+	void (*free_data)(struct netconfig *netconfig, const char *reasonstr);
+	void (*commit)(struct netconfig *netconfig, uint8_t family,
+			enum l_netconfig_event event);
+};
+
+static struct l_netlink *rtnl;
+
+static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
+					enum l_netconfig_event event);
+
+/* Default backend */
+static struct netconfig_commit_ops netconfig_rtnl_ops = {
+	.commit = netconfig_rtnl_commit,
+};
+
+/* Same backend for all netconfig objects */
+static const struct netconfig_commit_ops *commit_ops = &netconfig_rtnl_ops;
+
+static struct l_queue *netconfig_list;
+
+void netconfig_commit_init(struct netconfig *netconfig)
+{
+	if (!rtnl)
+		rtnl = l_rtnl_get();
+
+	if (!netconfig_list)
+		netconfig_list = l_queue_new();
+
+	l_queue_push_tail(netconfig_list, netconfig);
+
+	L_WARN_ON(netconfig->commit_data);
+
+	if (commit_ops->init_data)
+		commit_ops->init_data(netconfig);
+}
+
+void netconfig_commit_free(struct netconfig *netconfig, const char *reasonstr)
+{
+	if (commit_ops->free_data)
+		commit_ops->free_data(netconfig, reasonstr);
+
+	L_WARN_ON(!l_queue_remove(netconfig_list, netconfig));
+
+	if (l_queue_isempty(netconfig_list))
+		l_queue_destroy(l_steal_ptr(netconfig_list), NULL);
+}
+
+void netconfig_commit(struct netconfig *netconfig, uint8_t family,
+			enum l_netconfig_event event)
+{
+	commit_ops->commit(netconfig, family, event);
+
+	if (event == L_NETCONFIG_EVENT_CONFIGURE) {
+		/*
+		 * Done here instead of in ops->commit because the MACs are
+		 * not considered part of the network configuration
+		 * (particularly Network Manager's "level 3 config" or l3cfg)
+		 * so we can handle this ourselves independent of the backend.
+		 */
+		if (family == AF_INET &&
+				!netconfig->static_config[INDEX_FOR_AF(family)])
+			netconfig_dhcp_gateway_to_arp(netconfig);
+	}
+}
+
+/*
+ * Called by all backends when netconfig_commit finishes, synchronously or
+ * asynchronously.
+ */
+static void netconfig_commit_done(struct netconfig *netconfig, uint8_t family,
+					enum l_netconfig_event event,
+					bool success)
+{
+}
+
+static void netconfig_set_neighbor_entry_cb(int error,
+						uint16_t type, const void *data,
+						uint32_t len, void *user_data)
+{
+	if (error)
+		l_error("l_rtnl_neighbor_set_hwaddr failed: %s (%i)",
+			strerror(-error), error);
+}
+
+void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig)
+{
+	struct l_dhcp_client *dhcp = l_netconfig_get_dhcp_client(netconfig->nc);
+	const struct l_dhcp_lease *lease;
+	_auto_(l_free) char *server_id = NULL;
+	_auto_(l_free) char *gw = NULL;
+	const uint8_t *server_mac;
+	struct in_addr in_gw;
+	uint32_t ifindex = netdev_get_ifindex(netconfig->netdev);
+
+	/* Can only do this for DHCP in certain network setups */
+	if (netconfig->static_config[INDEX_FOR_AF(AF_INET)] ||
+			netconfig->fils_override)
+		return;
+
+	lease = l_dhcp_client_get_lease(dhcp);
+	if (!lease)
+		return;
+
+	server_id = l_dhcp_lease_get_server_id(lease);
+	gw = l_dhcp_lease_get_gateway(lease);
+	server_mac = l_dhcp_lease_get_server_mac(lease);
+
+	if (!gw || strcmp(server_id, gw) || !server_mac)
+		return;
+
+	l_debug("Gateway MAC is known, setting into ARP cache");
+	in_gw.s_addr = l_dhcp_lease_get_gateway_u32(lease);
+
+	if (!l_rtnl_neighbor_set_hwaddr(rtnl, ifindex, AF_INET,
+					&in_gw, server_mac, ETH_ALEN,
+					netconfig_set_neighbor_entry_cb, NULL,
+					NULL))
+		l_debug("l_rtnl_neighbor_set_hwaddr failed");
+}
+
+static void netconfig_dns_list_update(struct netconfig *netconfig)
+{
+	_auto_(l_strv_free) char **dns_list =
+		l_netconfig_get_dns_list(netconfig->nc);
+
+	if (netconfig->resolve && dns_list)
+		resolve_set_dns(netconfig->resolve, dns_list);
+}
+
+static void netconfig_domains_update(struct netconfig *netconfig)
+{
+	_auto_(l_strv_free) char **domains =
+		l_netconfig_get_domain_names(netconfig->nc);
+
+	if (netconfig->resolve && domains)
+		resolve_set_domains(netconfig->resolve, domains);
+}
+
+static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
+					enum l_netconfig_event event)
+{
+	l_netconfig_apply_rtnl(netconfig->nc);
+
+	/* TODO: cache values and skip updates if unchanged */
+	netconfig_dns_list_update(netconfig);
+	netconfig_domains_update(netconfig);
+
+	if (event == L_NETCONFIG_EVENT_CONFIGURE && family == AF_INET)
+		/*
+		 * netconfig->mdns is currently only loaded in
+		 * netconfig_load_settings() so we can set it once on
+		 * the CONFIGURE event.
+		 */
+		resolve_set_mdns(netconfig->resolve, netconfig->mdns);
+
+	if (event == L_NETCONFIG_EVENT_UNCONFIGURE && family == AF_INET)
+		resolve_revert(netconfig->resolve);
+
+	netconfig_commit_done(netconfig, family, event, true);
+}
diff --git a/src/netconfig.c b/src/netconfig.c
index 74eaca16..5b7a21ee 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -27,9 +27,7 @@
 #include <errno.h>
 #include <arpa/inet.h>
 #include <net/if_arp.h>
-#include <netinet/if_ether.h>
 #include <netinet/in.h>
-#include <linux/rtnetlink.h>
 #include <limits.h>
 #include <string.h>
 #include <fcntl.h>
@@ -52,30 +50,6 @@
 #include "src/netconfig.h"
 #include "src/sysfs.h"
 
-struct netconfig {
-	struct l_netconfig *nc;
-	struct netdev *netdev;
-
-	char *mdns;
-	struct ie_fils_ip_addr_response_info *fils_override;
-	bool enabled[2];
-	bool static_config[2];
-	bool gateway_overridden[2];
-	bool dns_overridden[2];
-
-	const struct l_settings *active_settings;
-
-	netconfig_notify_func_t notify;
-	void *user_data;
-
-	struct resolve *resolve;
-};
-
-/* 0 for AF_INET, 1 for AF_INET6 */
-#define INDEX_FOR_AF(af)	((af) != AF_INET)
-
-static struct l_netlink *rtnl;
-
 /*
  * Routing priority offset, configurable in main.conf. The route with lower
  * priority offset is preferred.
@@ -116,7 +90,7 @@ static void netconfig_free(void *data)
 	l_free(netconfig);
 }
 
-static 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)])
 		return false;
@@ -133,15 +107,6 @@ static bool netconfig_use_fils_addr(struct netconfig *netconfig, int af)
 	return !l_memeqzero(netconfig->fils_override->ipv6_addr, 16);
 }
 
-static void netconfig_set_neighbor_entry_cb(int error,
-						uint16_t type, const void *data,
-						uint32_t len, void *user_data)
-{
-	if (error)
-		l_error("l_rtnl_neighbor_set_hwaddr failed: %s (%i)",
-			strerror(-error), error);
-}
-
 static struct l_rtnl_address *netconfig_get_static4_address(
 				const struct l_settings *active_settings)
 {
@@ -240,41 +205,6 @@ no_prefix_len:
 	return l_steal_ptr(ret);
 }
 
-static void netconfig_gateway_to_arp(struct netconfig *netconfig)
-{
-	struct l_dhcp_client *dhcp = l_netconfig_get_dhcp_client(netconfig->nc);
-	const struct l_dhcp_lease *lease;
-	_auto_(l_free) char *server_id = NULL;
-	_auto_(l_free) char *gw = NULL;
-	const uint8_t *server_mac;
-	struct in_addr in_gw;
-
-	/* Can only do this for DHCP in certain network setups */
-	if (netconfig->static_config[INDEX_FOR_AF(AF_INET)] ||
-			netconfig->fils_override)
-		return;
-
-	lease = l_dhcp_client_get_lease(dhcp);
-	if (!lease)
-		return;
-
-	server_id = l_dhcp_lease_get_server_id(lease);
-	gw = l_dhcp_lease_get_gateway(lease);
-	server_mac = l_dhcp_lease_get_server_mac(lease);
-
-	if (!gw || strcmp(server_id, gw) || !server_mac)
-		return;
-
-	l_debug("Gateway MAC is known, setting into ARP cache");
-	in_gw.s_addr = l_dhcp_lease_get_gateway_u32(lease);
-
-	if (!l_rtnl_neighbor_set_hwaddr(rtnl, netconfig->ifindex, AF_INET,
-					&in_gw, server_mac, ETH_ALEN,
-					netconfig_set_neighbor_entry_cb, NULL,
-					NULL))
-		l_debug("l_rtnl_neighbor_set_hwaddr failed");
-}
-
 static bool netconfig_load_dns(struct netconfig *netconfig,
 				const struct l_settings *active_settings,
 				const char *group_name, uint8_t family)
@@ -501,7 +431,7 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw)
 	 * to alleviate this
 	 */
 	if (set_arp_gw)
-		netconfig_gateway_to_arp(netconfig);
+		netconfig_dhcp_gateway_to_arp(netconfig);
 
 	if (!netconfig->static_config[INDEX_FOR_AF(AF_INET)]) {
 		/* TODO l_dhcp_client sending a DHCP inform request */
@@ -584,6 +514,8 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 	netconfig->netdev = netdev;
 	netconfig->resolve = resolve_new(ifindex);
 
+	netconfig_commit_init(netconfig);
+
 	debug_level = getenv("IWD_DHCP_DEBUG");
 	if (debug_level != NULL) {
 		if (!strcmp("debug", debug_level))
@@ -618,6 +550,7 @@ void netconfig_destroy(struct netconfig *netconfig)
 	l_debug("");
 
 	netconfig_reset(netconfig);
+	netconfig_commit_free(netconfig, "aborted");
 	resolve_free(netconfig->resolve);
 	netconfig_free(netconfig);
 }
diff --git a/src/netconfig.h b/src/netconfig.h
index c9ac6f8f..9f4f3b77 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -20,6 +20,7 @@
  *
  */
 
+struct netdev;
 struct netconfig;
 struct ie_fils_ip_addr_request_info;
 struct ie_fils_ip_addr_response_info;
@@ -31,6 +32,30 @@ enum netconfig_event {
 typedef void (*netconfig_notify_func_t)(enum netconfig_event event,
 							void *user_data);
 
+struct netconfig {
+	struct l_netconfig *nc;
+	struct netdev *netdev;
+
+	char *mdns;
+	struct ie_fils_ip_addr_response_info *fils_override;
+	bool enabled[2];
+	bool static_config[2];
+	bool gateway_overridden[2];
+	bool dns_overridden[2];
+
+	const struct l_settings *active_settings;
+
+	netconfig_notify_func_t notify;
+	void *user_data;
+
+	struct resolve *resolve;
+
+	void *commit_data;
+};
+
+/* 0 for AF_INET, 1 for AF_INET6 */
+#define INDEX_FOR_AF(af)	((af) != AF_INET)
+
 bool netconfig_load_settings(struct netconfig *netconfig,
 				const struct l_settings *active_settings);
 bool netconfig_configure(struct netconfig *netconfig,
@@ -43,8 +68,16 @@ bool netconfig_get_fils_ip_req(struct netconfig *netconfig,
 				struct ie_fils_ip_addr_request_info *info);
 void netconfig_handle_fils_ip_resp(struct netconfig *netconfig,
 			const struct ie_fils_ip_addr_response_info *info);
+bool netconfig_use_fils_addr(struct netconfig *netconfig, int af);
 
 struct netconfig *netconfig_new(uint32_t ifindex);
 void netconfig_destroy(struct netconfig *netconfig);
 
 bool netconfig_enabled(void);
+
+void netconfig_commit_init(struct netconfig *netconfig);
+void netconfig_commit_free(struct netconfig *netconfig, const char *reasonstr);
+void netconfig_commit(struct netconfig *netconfig, uint8_t family,
+			enum l_netconfig_event event);
+
+void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 07/10] netconfig: Handle l_netconfig events
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
                   ` (4 preceding siblings ...)
  2022-08-29 17:35 ` [PATCH 06/10] netconfig: Add netconfig-commit API Andrew Zaborowski
@ 2022-08-29 17:35 ` Andrew Zaborowski
  2022-08-29 17:35 ` [PATCH 08/10] netconfig: Re-add FILS handling Andrew Zaborowski
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

Add netconfig_event_handler() that responds to events emitted by
the l_netconfig object by calling netconfig_commit, tracking whether
we're connected for either address family and emitting
NETCONFIG_EVENT_CONNECTED or NETCONFIG_EVENT_FAILED as necessary.

NETCONFIG_EVENT_FAILED is a new event as until now failures would cause
the netconfig state machine to stop but no event emitted so that
station.c could take action.  As before, these events are only
emitted based on the IPv4 configuration state, not IPv6.
---
 src/netconfig-commit.c | 26 ++++++++++++++++++++++
 src/netconfig.c        | 49 +++++++++++++++++++++++++++++++++++++++---
 src/netconfig.h        |  2 ++
 3 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/src/netconfig-commit.c b/src/netconfig-commit.c
index 48ebe847..95b2a9d9 100644
--- a/src/netconfig-commit.c
+++ b/src/netconfig-commit.c
@@ -114,6 +114,32 @@ static void netconfig_commit_done(struct netconfig *netconfig, uint8_t family,
 					enum l_netconfig_event event,
 					bool success)
 {
+	bool connected = netconfig->connected[INDEX_FOR_AF(family)];
+
+	if (!success) {
+		netconfig->connected[INDEX_FOR_AF(family)] = false;
+
+		if (netconfig->notify && family == AF_INET)
+			netconfig->notify(NETCONFIG_EVENT_FAILED,
+						netconfig->user_data);
+		return;
+	}
+
+	switch (event) {
+	case L_NETCONFIG_EVENT_CONFIGURE:
+	case L_NETCONFIG_EVENT_UPDATE:
+		netconfig->connected[INDEX_FOR_AF(family)] = true;
+
+		if (family == AF_INET && !connected && netconfig->notify)
+			netconfig->notify(NETCONFIG_EVENT_CONNECTED,
+						netconfig->user_data);
+
+		break;
+
+	case L_NETCONFIG_EVENT_UNCONFIGURE:
+	case L_NETCONFIG_EVENT_FAILED:
+		break;
+	}
 }
 
 static void netconfig_set_neighbor_entry_cb(int error,
diff --git a/src/netconfig.c b/src/netconfig.c
index 5b7a21ee..91830416 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -414,9 +414,8 @@ bool netconfig_configure(struct netconfig *netconfig,
 	netconfig->notify = notify;
 	netconfig->user_data = user_data;
 
-	/* TODO */
-
-	resolve_set_mdns(netconfig->resolve, netconfig->mdns);
+	if (unlikely(!l_netconfig_start(netconfig->nc)))
+		return false;
 
 	return true;
 }
@@ -449,6 +448,9 @@ bool netconfig_reset(struct netconfig *netconfig)
 	l_netconfig_unconfigure(netconfig->nc);
 	l_netconfig_stop(netconfig->nc);
 
+	netconfig->connected[0] = false;
+	netconfig->connected[1] = false;
+
 	netconfig_free_settings(netconfig);
 	return true;
 }
@@ -499,6 +501,44 @@ void netconfig_handle_fils_ip_resp(struct netconfig *netconfig,
 	netconfig->fils_override = l_memdup(info, sizeof(*info));
 }
 
+static void netconfig_event_handler(struct l_netconfig *nc, uint8_t family,
+					enum l_netconfig_event event,
+					void *user_data)
+{
+	struct netconfig *netconfig = user_data;
+
+	l_debug("l_netconfig event %d", event);
+
+	netconfig_commit(netconfig, family, event);
+
+	switch (event) {
+	case L_NETCONFIG_EVENT_CONFIGURE:
+	case L_NETCONFIG_EVENT_UPDATE:
+		break;
+
+	case L_NETCONFIG_EVENT_UNCONFIGURE:
+		break;
+
+	case L_NETCONFIG_EVENT_FAILED:
+		netconfig->connected[INDEX_FOR_AF(family)] = false;
+
+		/*
+		 * l_netconfig might have emitted an UNCONFIGURE before this
+		 * but now it tells us it's given up on (re)establishing the
+		 * IP setup.
+		 */
+		if (family == AF_INET && netconfig->notify)
+			netconfig->notify(NETCONFIG_EVENT_FAILED,
+						netconfig->user_data);
+
+		break;
+
+	default:
+		l_error("netconfig: Received unsupported l_netconfig event: %d",
+			event);
+	}
+}
+
 struct netconfig *netconfig_new(uint32_t ifindex)
 {
 	struct netdev *netdev = netdev_find(ifindex);
@@ -530,6 +570,9 @@ struct netconfig *netconfig_new(uint32_t ifindex)
 			dhcp_priority = L_LOG_DEBUG;
 	}
 
+	l_netconfig_set_event_handler(netconfig->nc, netconfig_event_handler,
+					netconfig, NULL);
+
 	l_dhcp_client_set_debug(l_netconfig_get_dhcp_client(netconfig->nc),
 				do_debug, "[DHCPv4] ", NULL, dhcp_priority);
 
diff --git a/src/netconfig.h b/src/netconfig.h
index 9f4f3b77..50085aa7 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -27,6 +27,7 @@ struct ie_fils_ip_addr_response_info;
 
 enum netconfig_event {
 	NETCONFIG_EVENT_CONNECTED,
+	NETCONFIG_EVENT_FAILED,
 };
 
 typedef void (*netconfig_notify_func_t)(enum netconfig_event event,
@@ -42,6 +43,7 @@ struct netconfig {
 	bool static_config[2];
 	bool gateway_overridden[2];
 	bool dns_overridden[2];
+	bool connected[2];
 
 	const struct l_settings *active_settings;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 08/10] netconfig: Re-add FILS handling
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
                   ` (5 preceding siblings ...)
  2022-08-29 17:35 ` [PATCH 07/10] netconfig: Handle l_netconfig events Andrew Zaborowski
@ 2022-08-29 17:35 ` Andrew Zaborowski
  2022-08-29 17:36 ` [PATCH 09/10] netconfig: Add NetworkConfigurationAgent DBus API Andrew Zaborowski
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:35 UTC (permalink / raw)
  To: iwd

Load the settings from FILS IE data into our l_netconfig instance when
appropriate.
---
 src/netconfig-commit.c |  51 ++++++++++++++++++
 src/netconfig.c        | 115 ++++++++++++++++++++++++++++++++++++++++-
 src/netconfig.h        |   1 +
 3 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/src/netconfig-commit.c b/src/netconfig-commit.c
index 95b2a9d9..d675d396 100644
--- a/src/netconfig-commit.c
+++ b/src/netconfig-commit.c
@@ -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 =
diff --git a/src/netconfig.c b/src/netconfig.c
index 91830416..feb7f87a 100644
--- a/src/netconfig.c
+++ b/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 */
 	}
diff --git a/src/netconfig.h b/src/netconfig.h
index 50085aa7..0ecd2583 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -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);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 09/10] netconfig: Add NetworkConfigurationAgent DBus API
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
                   ` (6 preceding siblings ...)
  2022-08-29 17:35 ` [PATCH 08/10] netconfig: Re-add FILS handling Andrew Zaborowski
@ 2022-08-29 17:36 ` Andrew Zaborowski
  2022-08-29 17:36 ` [PATCH 10/10] netconfig: Skip update if resolver data unchanged Andrew Zaborowski
  2022-09-13 14:00 ` [PATCH 01/10] doc: Update Netconfig Agent API doc Denis Kenzior
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:36 UTC (permalink / raw)
  To: iwd

Add a second netconfig-commit backend which, if enabled, doesn't
directly send any of the network configuration to the kernel or system
files but delegates the operation to an interested client's D-Bus
method as described in doc/agent-api.txt.  This backend is switched to
when a client registers a netconfig agent object and is swiched away
from when the client disconnects or unregisters the agent.  Only one
netconfig agent can be registered any given time.
---
 src/agent.c            |  62 +++++++
 src/dbus.h             |   2 +
 src/netconfig-commit.c | 380 +++++++++++++++++++++++++++++++++++++++++
 src/netconfig.h        |   2 +
 4 files changed, 446 insertions(+)

diff --git a/src/agent.c b/src/agent.c
index 63361a5d..0f718b87 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -28,6 +28,7 @@
 
 #include <ell/ell.h>
 #include "src/dbus.h"
+#include "src/netconfig.h"
 #include "src/agent.h"
 #include "src/iwd.h"
 #include "src/module.h"
@@ -584,6 +585,60 @@ static struct l_dbus_message *agent_unregister(struct l_dbus *dbus,
 	return reply;
 }
 
+static struct l_dbus_message *netconfig_agent_register(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+						void *user_data)
+{
+	struct l_dbus_message *reply;
+	const char *path;
+	int r;
+
+	l_debug("");
+
+	if (!l_dbus_message_get_arguments(message, "o", &path))
+		return dbus_error_invalid_args(message);
+
+	if (!netconfig_enabled())
+		return dbus_error_not_supported(message);
+
+	r = netconfig_register_agent(l_dbus_message_get_sender(message), path);
+	if (r)
+		return dbus_error_from_errno(r, message);
+
+	l_debug("agent %s path %s",
+		l_dbus_message_get_sender(message), path);
+
+	reply = l_dbus_message_new_method_return(message);
+	l_dbus_message_set_arguments(reply, "");
+	return reply;
+}
+
+static struct l_dbus_message *netconfig_agent_unregister(struct l_dbus *dbus,
+						struct l_dbus_message *message,
+					void *user_data)
+{
+	struct l_dbus_message *reply;
+	const char *path;
+	int r;
+
+	l_debug("");
+
+	if (!l_dbus_message_get_arguments(message, "o", &path))
+		return dbus_error_invalid_args(message);
+
+	if (!netconfig_enabled())
+		return dbus_error_not_supported(message);
+
+	r = netconfig_unregister_agent(l_dbus_message_get_sender(message),
+					path);
+	if (r)
+		return dbus_error_from_errno(r, message);
+
+	reply = l_dbus_message_new_method_return(message);
+	l_dbus_message_set_arguments(reply, "");
+	return reply;
+}
+
 static void setup_agent_interface(struct l_dbus_interface *interface)
 {
 	l_dbus_interface_method(interface, "RegisterAgent", 0,
@@ -592,6 +647,13 @@ static void setup_agent_interface(struct l_dbus_interface *interface)
 	l_dbus_interface_method(interface, "UnregisterAgent", 0,
 				agent_unregister,
 				"", "o", "path");
+
+	l_dbus_interface_method(interface,
+				"RegisterNetworkConfigurationAgent", 0,
+				netconfig_agent_register, "", "o", "path");
+	l_dbus_interface_method(interface,
+				"UnregisterNetworkConfigurationAgent", 0,
+				netconfig_agent_unregister, "", "o", "path");
 }
 
 static bool release_agent(void *data, void *user_data)
diff --git a/src/dbus.h b/src/dbus.h
index bbc76608..00c2df57 100644
--- a/src/dbus.h
+++ b/src/dbus.h
@@ -44,6 +44,8 @@
 #define IWD_AP_DIAGNOSTIC_INTERFACE "net.connman.iwd.AccessPointDiagnostic"
 #define IWD_STATION_DEBUG_INTERFACE "net.connman.iwd.StationDebug"
 #define IWD_DPP_INTERFACE "net.connman.iwd.DeviceProvisioning"
+#define IWD_NETCONFIG_AGENT_INTERFACE \
+	"net.connman.iwd.NetworkConfigurationAgent"
 
 #define IWD_BASE_PATH "/net/connman/iwd"
 #define IWD_AGENT_MANAGER_PATH IWD_BASE_PATH
diff --git a/src/netconfig-commit.c b/src/netconfig-commit.c
index d675d396..78670166 100644
--- a/src/netconfig-commit.c
+++ b/src/netconfig-commit.c
@@ -37,6 +37,7 @@
 #include "src/netdev.h"
 #include "src/ie.h"
 #include "src/resolve.h"
+#include "src/dbus.h"
 #include "src/netconfig.h"
 
 struct netconfig_commit_ops {
@@ -110,6 +111,24 @@ void netconfig_commit(struct netconfig *netconfig, uint8_t family,
 	}
 }
 
+static void netconfig_switch_backend(const struct netconfig_commit_ops *new_ops)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(netconfig_list); entry;
+			entry = entry->next) {
+		struct netconfig *netconfig = entry->data;
+
+		if (commit_ops->free_data)
+			commit_ops->free_data(netconfig, "");
+
+		if (new_ops->init_data)
+			new_ops->init_data(netconfig);
+	}
+
+	commit_ops = new_ops;
+}
+
 /*
  * Called by all backends when netconfig_commit finishes, synchronously or
  * asynchronously.
@@ -278,3 +297,364 @@ static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
 
 	netconfig_commit_done(netconfig, family, event, true);
 }
+
+struct netconfig_agent_data {
+	uint32_t pending_id[2];
+};
+
+struct netconfig_agent_call_data {
+	struct netconfig *netconfig;
+	uint8_t family;
+	enum l_netconfig_event event;
+};
+
+static char *netconfig_agent_name;
+static char *netconfig_agent_path;
+static unsigned int netconfig_agent_watch;
+
+static void netconfig_agent_cancel(struct netconfig *netconfig, uint8_t family,
+					const char *reasonstr)
+{
+	struct netconfig_agent_data *data = netconfig->commit_data;
+	struct l_dbus *dbus = dbus_get_bus();
+	const char *dev_path = netdev_get_path(netconfig->netdev);
+	struct l_dbus_message *message;
+	const char *method;
+
+	if (!data || !data->pending_id[INDEX_FOR_AF(family)])
+		return;
+
+	l_dbus_cancel(dbus, data->pending_id[INDEX_FOR_AF(family)]);
+	data->pending_id[INDEX_FOR_AF(family)] = 0;
+
+	method = (family == AF_INET ? "CancelIPv4" : "CancelIPv6");
+	l_debug("sending a %s(%s, %s) to %s %s", method, dev_path, reasonstr,
+		netconfig_agent_name, netconfig_agent_path);
+
+	message = l_dbus_message_new_method_call(dbus, netconfig_agent_name,
+						netconfig_agent_path,
+						IWD_NETCONFIG_AGENT_INTERFACE,
+						method);
+	l_dbus_message_set_arguments(message, "os", dev_path, reasonstr);
+	l_dbus_message_set_no_reply(message, true);
+	l_dbus_send(dbus, message);
+}
+
+static void netconfig_agent_receive_reply(struct l_dbus_message *reply,
+						void *user_data)
+{
+	struct netconfig_agent_call_data *cd = user_data;
+	struct netconfig_agent_data *data = cd->netconfig->commit_data;
+	const char *error, *text;
+	bool success = true;
+
+	l_debug("agent reply from %s %s", l_dbus_message_get_sender(reply),
+		l_dbus_message_get_path(reply));
+
+	data->pending_id[INDEX_FOR_AF(cd->family)] = 0;
+
+	if (l_dbus_message_get_error(reply, &error, &text)) {
+		success = false;
+		l_error("netconfig agent call returned %s(\"%s\")",
+			error, text);
+	} else if (!l_dbus_message_get_arguments(reply, "")) {
+		success = false;
+		l_error("netconfig agent call reply signature wrong: %s",
+			l_dbus_message_get_signature(reply));
+	}
+
+	netconfig_commit_done(cd->netconfig, cd->family, cd->event, success);
+}
+
+#define IS_IPV6_STR_FAST(str)	(strchr(str, ':') != NULL)
+
+typedef void (*netconfig_build_entry_fn)(struct l_dbus_message_builder *builder,
+					const void *data, uint8_t family);
+
+static void netconfig_agent_append_dict_dict_array(
+					struct l_dbus_message_builder *builder,
+					const char *key,
+					const struct l_queue_entry *value,
+					netconfig_build_entry_fn build_entry,
+					uint8_t family)
+{
+	l_dbus_message_builder_enter_dict(builder, "sv");
+	l_dbus_message_builder_append_basic(builder, 's', key);
+	l_dbus_message_builder_enter_variant(builder, "aa{sv}");
+	l_dbus_message_builder_enter_array(builder, "a{sv}");
+
+	for (; value; value = value->next)
+		build_entry(builder, value->data, family);
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_leave_variant(builder);
+	l_dbus_message_builder_leave_dict(builder);
+}
+
+static void netconfig_agent_append_dict_strv(
+					struct l_dbus_message_builder *builder,
+					const char *key, char **value,
+					uint8_t family)
+{
+	if (!value)
+		return;
+
+	l_dbus_message_builder_enter_dict(builder, "sv");
+	l_dbus_message_builder_append_basic(builder, 's', key);
+	l_dbus_message_builder_enter_variant(builder, "as");
+	l_dbus_message_builder_enter_array(builder, "s");
+
+	for (; *value; value++) {
+		uint8_t value_family = IS_IPV6_STR_FAST((char *) *value) ?
+			AF_INET6 : AF_INET;
+
+		if (family == AF_UNSPEC || value_family == family)
+			l_dbus_message_builder_append_basic(builder, 's',
+								*value);
+	}
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_leave_variant(builder);
+	l_dbus_message_builder_leave_dict(builder);
+}
+
+static void netconfig_agent_append_address(
+					struct l_dbus_message_builder *builder,
+					const void *data, uint8_t family)
+{
+	const struct l_rtnl_address *addr = data;
+	char addr_str[INET6_ADDRSTRLEN];
+	uint64_t valid_expiry_time;
+	uint64_t preferred_expiry_time;
+	uint64_t now = l_time_now();
+
+	if (l_rtnl_address_get_family(addr) != family)
+		return;
+
+	l_dbus_message_builder_enter_array(builder, "{sv}");
+
+	l_rtnl_address_get_address(addr, addr_str);
+	dbus_append_dict_basic(builder, "Address", 's', addr_str);
+
+	if (family == AF_INET) {
+		uint8_t plen = l_rtnl_address_get_prefix_length(addr);
+		dbus_append_dict_basic(builder, "PrefixLength", 'y', &plen);
+
+		if (l_rtnl_address_get_broadcast(addr, addr_str) &&
+				strcmp(addr_str, "0.0.0.0"))
+			dbus_append_dict_basic(builder, "Broadcast", 's',
+						addr_str);
+	}
+
+	l_rtnl_address_get_expiry(addr, &preferred_expiry_time,
+					&valid_expiry_time);
+
+	if (valid_expiry_time > now) {
+		uint32_t lt = l_time_to_secs(valid_expiry_time - now);
+
+		dbus_append_dict_basic(builder, "ValidLifetime", 'u', &lt);
+	}
+
+	if (preferred_expiry_time > now) {
+		uint32_t lt = l_time_to_secs(preferred_expiry_time - now);
+
+		dbus_append_dict_basic(builder, "PreferredLifetime", 'u', &lt);
+	}
+
+	l_dbus_message_builder_leave_array(builder);
+}
+
+static void netconfig_agent_append_route(struct l_dbus_message_builder *builder,
+						const void *data,
+						uint8_t family)
+{
+	const struct l_rtnl_route *rt = data;
+	char addr_str[INET6_ADDRSTRLEN];
+	uint8_t prefix_len;
+	uint64_t expiry_time;
+	uint64_t now = l_time_now();
+	uint32_t priority;
+	uint8_t preference;
+	uint32_t mtu;
+
+	if (l_rtnl_route_get_family(rt) != family)
+		return;
+
+	l_dbus_message_builder_enter_array(builder, "{sv}");
+
+	if (l_rtnl_route_get_dst(rt, addr_str, &prefix_len) && prefix_len) {
+		l_dbus_message_builder_enter_dict(builder, "sv");
+		l_dbus_message_builder_append_basic(builder, 's',
+							"Destination");
+		l_dbus_message_builder_enter_variant(builder, "(sy)");
+		l_dbus_message_builder_enter_struct(builder, "sy");
+		l_dbus_message_builder_append_basic(builder, 's', addr_str);
+		l_dbus_message_builder_append_basic(builder, 'y', &prefix_len);
+		l_dbus_message_builder_leave_struct(builder);
+		l_dbus_message_builder_leave_variant(builder);
+		l_dbus_message_builder_leave_dict(builder);
+	}
+
+	if (l_rtnl_route_get_gateway(rt, addr_str))
+		dbus_append_dict_basic(builder, "Router", 's', addr_str);
+
+	if (l_rtnl_route_get_prefsrc(rt, addr_str))
+		dbus_append_dict_basic(builder, "PreferredSource", 's',
+					addr_str);
+
+	expiry_time = l_rtnl_route_get_expiry(rt);
+	if (expiry_time > now) {
+		uint32_t lt = l_time_to_secs(expiry_time - now);
+
+		dbus_append_dict_basic(builder, "Lifetime", 'u', &lt);
+	}
+
+	priority = l_rtnl_route_get_priority(rt);
+	dbus_append_dict_basic(builder, "Priority", 'u', &priority);
+
+	/*
+	 * ICMPV6_ROUTER_PREF_MEDIUM is returned by default even for IPv4
+	 * routes where this property doesn't make sense so filter those out.
+	 */
+	preference = l_rtnl_route_get_preference(rt);
+	if (preference != ICMPV6_ROUTER_PREF_INVALID && family == AF_INET6)
+		dbus_append_dict_basic(builder, "Preference", 'y', &preference);
+
+	mtu = l_rtnl_route_get_mtu(rt);
+	if (mtu)
+		dbus_append_dict_basic(builder, "Priority", 'u', &mtu);
+
+	l_dbus_message_builder_leave_array(builder);
+}
+
+static void netconfig_agent_commit(struct netconfig *netconfig, uint8_t family,
+					enum l_netconfig_event event)
+{
+	struct netconfig_agent_data *data;
+	struct netconfig_agent_call_data *cd;
+	struct l_dbus *dbus = dbus_get_bus();
+	struct l_dbus_message *message;
+	struct l_dbus_message_builder *builder;
+	const char *dev_path = netdev_get_path(netconfig->netdev);
+	const char *dbus_method =
+		(family == AF_INET ? "ConfigureIPv4" : "ConfigureIPv6");
+	const char *cfg_method =
+		netconfig->static_config[INDEX_FOR_AF(family)] ?
+		"static" : "auto";
+	_auto_(l_strv_free) char **dns_list = NULL;
+	_auto_(l_strv_free) char **domains = NULL;
+
+	if (!netconfig->commit_data)
+		netconfig->commit_data = l_new(struct netconfig_agent_data, 1);
+
+	netconfig_agent_cancel(netconfig, family, "superseded");
+
+	l_debug("sending a %s(%s, ...) to %s %s", dbus_method, dev_path,
+		netconfig_agent_name, netconfig_agent_path);
+
+	message = l_dbus_message_new_method_call(dbus, netconfig_agent_name,
+						netconfig_agent_path,
+						IWD_NETCONFIG_AGENT_INTERFACE,
+						dbus_method);
+
+	/*
+	 * Build the call arguments: the Device object path and
+	 * the complicated config dict.
+	 */
+	builder = l_dbus_message_builder_new(message);
+	l_dbus_message_builder_append_basic(builder, 'o', dev_path);
+	l_dbus_message_builder_enter_array(builder, "{sv}");
+	dbus_append_dict_basic(builder, "Method", 's', cfg_method);
+
+	netconfig_agent_append_dict_dict_array(builder, "Addresses",
+					l_netconfig_get_addresses(netconfig->nc,
+							NULL, NULL, NULL, NULL),
+					netconfig_agent_append_address, family);
+
+	netconfig_agent_append_dict_dict_array(builder, "Routes",
+					l_netconfig_get_routes(netconfig->nc,
+							NULL, NULL, NULL, NULL),
+					netconfig_agent_append_route, family);
+
+	dns_list = l_netconfig_get_dns_list(netconfig->nc);
+	netconfig_agent_append_dict_strv(builder, "DomainNameServers",
+						dns_list, family);
+
+	domains = l_netconfig_get_domain_names(netconfig->nc);
+	netconfig_agent_append_dict_strv(builder, "DomainNames",
+						domains, AF_UNSPEC);
+
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	cd = l_new(struct netconfig_agent_call_data, 1);
+	cd->netconfig = netconfig;
+	cd->family = family;
+	cd->event = event;
+	data = netconfig->commit_data;
+	data->pending_id[INDEX_FOR_AF(family)] =
+		l_dbus_send_with_reply(dbus, message,
+					netconfig_agent_receive_reply,
+					cd, l_free);
+}
+
+static void netconfig_agent_free_data(struct netconfig *netconfig,
+					const char *reasonstr)
+{
+	if (!netconfig->commit_data)
+		return;
+
+	netconfig_agent_cancel(netconfig, AF_INET, reasonstr);
+	netconfig_agent_cancel(netconfig, AF_INET6, reasonstr);
+	l_free(l_steal_ptr(netconfig->commit_data));
+}
+
+static struct netconfig_commit_ops netconfig_agent_ops = {
+	.commit    = netconfig_agent_commit,
+	.free_data = netconfig_agent_free_data,
+};
+
+static void netconfig_agent_disconnect_handle(void *user_data)
+{
+	netconfig_unregister_agent(netconfig_agent_name, netconfig_agent_path);
+}
+
+static void netconfig_agent_disconnect_cb(struct l_dbus *dbus, void *user_data)
+{
+	l_debug("");
+	l_idle_oneshot(netconfig_agent_disconnect_handle, NULL, NULL);
+}
+
+int netconfig_register_agent(const char *name, const char *path)
+{
+	if (netconfig_agent_path)
+		return -EEXIST;
+
+	netconfig_agent_name = l_strdup(name);
+	netconfig_agent_path = l_strdup(path);
+	netconfig_agent_watch = l_dbus_add_disconnect_watch(dbus_get_bus(),
+						name,
+						netconfig_agent_disconnect_cb,
+						NULL, NULL);
+
+	netconfig_switch_backend(&netconfig_agent_ops);
+
+	return 0;
+}
+
+int netconfig_unregister_agent(const char *name, const char *path)
+{
+	if (!netconfig_agent_path || strcmp(netconfig_agent_path, path))
+		return -ENOENT;
+
+	if (strcmp(netconfig_agent_name, name))
+		return -EPERM;
+
+	l_free(l_steal_ptr(netconfig_agent_name));
+	l_free(l_steal_ptr(netconfig_agent_path));
+	l_dbus_remove_watch(dbus_get_bus(), netconfig_agent_watch);
+
+	netconfig_switch_backend(&netconfig_rtnl_ops);
+	return 0;
+}
diff --git a/src/netconfig.h b/src/netconfig.h
index 0ecd2583..289a78e9 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -81,6 +81,8 @@ void netconfig_commit_init(struct netconfig *netconfig);
 void netconfig_commit_free(struct netconfig *netconfig, const char *reasonstr);
 void netconfig_commit(struct netconfig *netconfig, uint8_t family,
 			enum l_netconfig_event event);
+int netconfig_register_agent(const char *name, const char *path);
+int netconfig_unregister_agent(const char *name, const char *path);
 
 void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig);
 void netconfig_commit_fils_macs(struct netconfig *netconfig, uint8_t family);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 10/10] netconfig: Skip update if resolver data unchanged
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
                   ` (7 preceding siblings ...)
  2022-08-29 17:36 ` [PATCH 09/10] netconfig: Add NetworkConfigurationAgent DBus API Andrew Zaborowski
@ 2022-08-29 17:36 ` Andrew Zaborowski
  2022-09-13 14:00 ` [PATCH 01/10] doc: Update Netconfig Agent API doc Denis Kenzior
  9 siblings, 0 replies; 11+ messages in thread
From: Andrew Zaborowski @ 2022-08-29 17:36 UTC (permalink / raw)
  To: iwd

---
 src/netconfig-commit.c | 31 ++++++++++++++++++++++++++++---
 src/netconfig.h        |  2 ++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/src/netconfig-commit.c b/src/netconfig-commit.c
index 78670166..9894ace2 100644
--- a/src/netconfig-commit.c
+++ b/src/netconfig-commit.c
@@ -51,10 +51,13 @@ static struct l_netlink *rtnl;
 
 static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
 					enum l_netconfig_event event);
+static void netconfig_rtnl_free_data(struct netconfig *netconfig,
+					const char *reasonstr);
 
 /* Default backend */
 static struct netconfig_commit_ops netconfig_rtnl_ops = {
-	.commit = netconfig_rtnl_commit,
+	.commit    = netconfig_rtnl_commit,
+	.free_data = netconfig_rtnl_free_data,
 };
 
 /* Same backend for all netconfig objects */
@@ -262,8 +265,14 @@ static void netconfig_dns_list_update(struct netconfig *netconfig)
 	_auto_(l_strv_free) char **dns_list =
 		l_netconfig_get_dns_list(netconfig->nc);
 
+	if (l_strv_eq(netconfig->dns_list, dns_list))
+		return;
+
 	if (netconfig->resolve && dns_list)
 		resolve_set_dns(netconfig->resolve, dns_list);
+
+	l_strv_free(netconfig->dns_list);
+	netconfig->dns_list = l_steal_ptr(dns_list);
 }
 
 static void netconfig_domains_update(struct netconfig *netconfig)
@@ -271,8 +280,14 @@ static void netconfig_domains_update(struct netconfig *netconfig)
 	_auto_(l_strv_free) char **domains =
 		l_netconfig_get_domain_names(netconfig->nc);
 
+	if (l_strv_eq(netconfig->domains, domains))
+		return;
+
 	if (netconfig->resolve && domains)
 		resolve_set_domains(netconfig->resolve, domains);
+
+	l_strv_free(netconfig->domains);
+	netconfig->dns_list = l_steal_ptr(domains);
 }
 
 static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
@@ -280,7 +295,6 @@ static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
 {
 	l_netconfig_apply_rtnl(netconfig->nc);
 
-	/* TODO: cache values and skip updates if unchanged */
 	netconfig_dns_list_update(netconfig);
 	netconfig_domains_update(netconfig);
 
@@ -292,12 +306,23 @@ static void netconfig_rtnl_commit(struct netconfig *netconfig, uint8_t family,
 		 */
 		resolve_set_mdns(netconfig->resolve, netconfig->mdns);
 
-	if (event == L_NETCONFIG_EVENT_UNCONFIGURE && family == AF_INET)
+	if (event == L_NETCONFIG_EVENT_UNCONFIGURE && family == AF_INET) {
+		l_strv_free(l_steal_ptr(netconfig->dns_list));
+		l_strv_free(l_steal_ptr(netconfig->domains));
 		resolve_revert(netconfig->resolve);
+	}
 
 	netconfig_commit_done(netconfig, family, event, true);
 }
 
+static void netconfig_rtnl_free_data(struct netconfig *netconfig,
+					const char *reasonstr)
+{
+	l_strv_free(l_steal_ptr(netconfig->dns_list));
+	l_strv_free(l_steal_ptr(netconfig->domains));
+}
+
+
 struct netconfig_agent_data {
 	uint32_t pending_id[2];
 };
diff --git a/src/netconfig.h b/src/netconfig.h
index 289a78e9..f04899ad 100644
--- a/src/netconfig.h
+++ b/src/netconfig.h
@@ -44,6 +44,8 @@ struct netconfig {
 	bool gateway_overridden[2];
 	bool dns_overridden[2];
 	bool connected[2];
+	char **dns_list;
+	char **domains;
 
 	const struct l_settings *active_settings;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 01/10] doc: Update Netconfig Agent API doc
  2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
                   ` (8 preceding siblings ...)
  2022-08-29 17:36 ` [PATCH 10/10] netconfig: Skip update if resolver data unchanged Andrew Zaborowski
@ 2022-09-13 14:00 ` Denis Kenzior
  9 siblings, 0 replies; 11+ messages in thread
From: Denis Kenzior @ 2022-09-13 14:00 UTC (permalink / raw)
  To: Andrew Zaborowski, iwd

Hi Andrew,

On 8/29/22 12:35, Andrew Zaborowski wrote:
> Update ConfigureIPv{4,6}() parameters to simplify mapping our sets of
> addresses and routes directly to D-Bus dictionaries.  Split Cancel()
> into CancelIPv{4,6}().
> ---
>   doc/agent-api.txt | 123 ++++++++++++++++++++++++++++++++++++----------
>   1 file changed, 97 insertions(+), 26 deletions(-)
> 

All applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-09-13 14:17 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-29 17:35 [PATCH 01/10] doc: Update Netconfig Agent API doc Andrew Zaborowski
2022-08-29 17:35 ` [PATCH 02/10] netconfig: Drop dhcp, dhcp6 and acd client instances Andrew Zaborowski
2022-08-29 17:35 ` [PATCH 03/10] netconfig: Keep configuration directly in struct l_netconfig Andrew Zaborowski
2022-08-29 17:35 ` [PATCH 04/10] netconfig: Clean up netconfig_get_static{4,6}_address Andrew Zaborowski
2022-08-29 17:35 ` [PATCH 05/10] netconfig: Store pointer to netdev instead of ifindex Andrew Zaborowski
2022-08-29 17:35 ` [PATCH 06/10] netconfig: Add netconfig-commit API Andrew Zaborowski
2022-08-29 17:35 ` [PATCH 07/10] netconfig: Handle l_netconfig events Andrew Zaborowski
2022-08-29 17:35 ` [PATCH 08/10] netconfig: Re-add FILS handling Andrew Zaborowski
2022-08-29 17:36 ` [PATCH 09/10] netconfig: Add NetworkConfigurationAgent DBus API Andrew Zaborowski
2022-08-29 17:36 ` [PATCH 10/10] netconfig: Skip update if resolver data unchanged Andrew Zaborowski
2022-09-13 14:00 ` [PATCH 01/10] doc: Update Netconfig Agent API doc Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.