From patchwork Mon Aug 29 17:35:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958283 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 778074699 for ; Mon, 29 Aug 2022 17:36:09 +0000 (UTC) Received: by mail-wr1-f47.google.com with SMTP id e20so11067108wri.13 for ; Mon, 29 Aug 2022 10:36:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc; bh=Y0uxsS8vrws1d0DMmgdCkfHsloe+nE0GWY/7OyKDWU4=; b=kj4StaiNiF0haAaCFV8XwLVeY/8RisqRNITaPT0ug4yquKWejk8EBll9Lp7DdOGx8G o6m7gFP9XTVDe+6S92dlxwsDjKoDqtDvryQwXEAF370ZVU8kx/ZWjAudJeScdEVzijl6 eZBov9OiLM8+v+blr9HhR0Ehc+YZ/jLULIEVWmo7IQY9cdVBbL5IGPirBirc/YwqKI10 Luz+KLqCSOGnpUgiAQcwNIiVVfcAC85IGeehe/MUv/5D/hYe9y05lVr9AQceSaV+WwqT 7o5iY0et4mK9WfktNa0dD/ItY2yd8MsLRoQEufn4hAcjfRexHbzs5E/FzkPCiYU0rWlI S19w== X-Gm-Message-State: ACgBeo1OcCV7qWqodktEli3qq3OMmUnP6yf2QDLkD4FwpAjD2IutUJRr jCTlM0glgLwikaSWWGverqIZyu0DMDbP1Q== X-Google-Smtp-Source: AA6agR70fK5vOLRD22dyEPEmksbiJ51DuAh+Y5SvCR8avNIzgclfVGeWAl3YHlboNTRDxXuWUAIMcg== X-Received: by 2002:a5d:5c0a:0:b0:225:b956:4e56 with SMTP id cc10-20020a5d5c0a000000b00225b9564e56mr6872559wrb.218.1661794567339; Mon, 29 Aug 2022 10:36:07 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:07 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 01/10] doc: Update Netconfig Agent API doc Date: Mon, 29 Aug 2022 19:35:52 +0200 Message-Id: <20220829173601.1963953-1-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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. From patchwork Mon Aug 29 17:35:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958286 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F20453BF for ; Mon, 29 Aug 2022 17:36:10 +0000 (UTC) Received: by mail-wr1-f51.google.com with SMTP id bq11so11088655wrb.12 for ; Mon, 29 Aug 2022 10:36:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=7KJlcaVekh3vqgKf/5jWY+CJnJzM8CoGb0+3BHE5lhI=; b=tU/deJbzcOWcb+dyGMSoqQAJMD0ToBSZVrBU7hZ7alZI+F/SrDIjQ44arHALB7U9IU oV5Q2yU5YdKdcm6zSH0lkyQyQAYI3sgJstQCc+NuN/4AeIlZ7BuI35v2JaQ7jVvYHh7B Qrmanre1IVMNZ2/m4Z2Rc0gOMYAqMJSdArxfmy4XzISYRG0PWpY+D9sjFv0MAiNkh3Vz 9TlyZJimEDaMVXy6qDuWXNMotzOAIJ64hA/VLBGNwDEvCCQA40TYKxWxyLtXlIvBiPiL yNFjt9VRjGxb2jPHHB9CaqT9Ls1PcGrx7LmUyMjnOATYsUuYrMsjxUhr0fOaNzoLjAbM e4KA== X-Gm-Message-State: ACgBeo3j//rN9bebR8RmktOBVGvYyLsxsa9qBwH4spcx+71Hb66temeJ 97CXQRq4llCUzDvVIdcdCwAtbjfsCxPlcA== X-Google-Smtp-Source: AA6agR650qcvQ+wpWaPk5qdLxt3IjpkQbVGMCeL3cu1Hwg+cjEHaCRTKGmfnTLnt27OQRIVKs97kvA== X-Received: by 2002:a05:6000:1b92:b0:220:7d86:2e30 with SMTP id r18-20020a0560001b9200b002207d862e30mr7167456wru.530.1661794568111; Mon, 29 Aug 2022 10:36:08 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:07 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 02/10] netconfig: Drop dhcp, dhcp6 and acd client instances Date: Mon, 29 Aug 2022 19:35:53 +0200 Message-Id: <20220829173601.1963953-2-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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) From patchwork Mon Aug 29 17:35:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958285 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 085F85C80 for ; Mon, 29 Aug 2022 17:36:10 +0000 (UTC) Received: by mail-wr1-f41.google.com with SMTP id m16so11074736wru.9 for ; Mon, 29 Aug 2022 10:36:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=JIsWuqr8TnvEqnvOmTJ4X2yqWH2vbn6bRtUT8qm0CVk=; b=xbDemWM40wHOnwm32iOmkcjfHxkOXnp2jd2Ed4z5T34/dYhEOKoEMqRCnFrDP9q9Ab tuCFgRADCHsAzPsDk87BdzL1Slk/aCzjLuSSkda15xssoTuO1qCua4QsubRqNjYZ00+5 4yPMfHSElUJ9kY7ej9wO7xq4N6eiumvexlyS8ncesI3M0TqHA82ixaJJviP6bMIG+/+U fIe4ijpBc8OMP7fkAAPPp9f+o9e2vT8Dg1j63UsomeTGRrlc38vzf61Bm0mcari+9S9O mpVVZMIt66SZ/8i9S7rXde6He1kEoB9NzRIUMrV/kQyrjzpSjrORTAXvaMU0b4PFZ2XN 18SQ== X-Gm-Message-State: ACgBeo2iKRs9Wb1dLbQI4DrhNKAHTXG2WrFDOevwKj9yAKcgBmbYLWvO w0y5BQegUXoMa29CAnGMw2sZIvzWCcCvaQ== X-Google-Smtp-Source: AA6agR5Y2PZgIEfUg263s1wkLD9q89RNHLqtVFCyutEz1DA2X7iHtcghvE1y8oG9ALFZ6gCeh7JkYQ== X-Received: by 2002:a5d:6d46:0:b0:21f:8b7:4c1d with SMTP id k6-20020a5d6d46000000b0021f08b74c1dmr7047802wri.455.1661794568818; Mon, 29 Aug 2022 10:36:08 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:08 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 03/10] netconfig: Keep configuration directly in struct l_netconfig Date: Mon, 29 Aug 2022 19:35:54 +0200 Message-Id: <20220829173601.1963953-3-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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; } From patchwork Mon Aug 29 17:35:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958284 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA4574699 for ; Mon, 29 Aug 2022 17:36:11 +0000 (UTC) Received: by mail-wm1-f47.google.com with SMTP id i188-20020a1c3bc5000000b003a7b6ae4eb2so3596864wma.4 for ; Mon, 29 Aug 2022 10:36:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=bWgDuzr1E0y/XP+5VBRXCSVYEWrKFox+H+VE5tzcWlg=; b=O6fhQPrxduexHymR9nJbph69WIwHpTnMdt/4aLq6RvG6drMqLVzLlMlbP+RTLiEHc/ sJGCRgaGvlziK6DIsT/CwD1ivuAW8GbqgPn53rTV5meQ6+oSrWmuIeIeM0Yq5FNQhTyp 0nPl0u4bN3AMvcvD5M7Qzqzuw5SIzgROOTKnXT9W/mUftcL2YAnS3JzdO02SXFtkQJOE Rq8ElCGEWKyRa3XT5POF1ZZ0gZHCwwgowNlYqwaFrbCXjZsGadERUq4NHn4kJalIXsf+ jBHoazGpBtIr5+tXeCMzFgIAcXRfeVUo8EZdlJs4fs+pFkR/oCPdnOoSL/l6D59qvu0t 5/Uw== X-Gm-Message-State: ACgBeo3LSTi1rX/LTEEfq+g3LOEf2Kv3w3PREuVixYzMGS9IEeosmoZP Xrbm0TyOAMjlu3HirqPlf+VKr4w6XCbpqQ== X-Google-Smtp-Source: AA6agR6rJWkG9Egj6fD3J1dgRQPNU/pl8A8QK8UITPA9+TNKXDePrH2gtdQ5ufB7sNfcKcap7epQVA== X-Received: by 2002:a05:600c:5114:b0:3a6:1ab9:5b3d with SMTP id o20-20020a05600c511400b003a61ab95b3dmr7191111wms.93.1661794569734; Mon, 29 Aug 2022 10:36:09 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:09 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 04/10] netconfig: Clean up netconfig_get_static{4,6}_address Date: Mon, 29 Aug 2022 19:35:55 +0200 Message-Id: <20220829173601.1963953-4-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 * 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) From patchwork Mon Aug 29 17:35:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958287 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 609C55C85 for ; Mon, 29 Aug 2022 17:36:12 +0000 (UTC) Received: by mail-wr1-f43.google.com with SMTP id az27so11097639wrb.6 for ; Mon, 29 Aug 2022 10:36:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=erzAfbwNpaswzKoJ9WFNP4c5bfvxXP/GZw9ba4+4iz4=; b=AX2F2mpnkbIcBJQEnHOwUgITD5TECsjWbQb6Mgco7SkjuLqx26PPBkndLtyBWTyFc4 m8JYoPab+bwjcWRVGk0s4jhNI50yCi/MuwVL2/uqcZhTM60gyzETE+ZH6/crO1o0cuHh Fw1iiiT8OkgRJRUb2P3T0Rbk4zEMBRXVXz+SvObhXahVPHloOLrSTXdVjLIoYmHnBuh/ G9mfefoVIQnfw+uyfJ2IL5D07pWuoB/+ReSvsa86bfX1pnJOS3HRbU3eOUnK0HKFy6nk afHmRohOGZ+icFSavXv1YI34Emmy/Uli9CE5CBcJ2oyQCvqkFC5S1rHTK2fsBIm1cehK hGOA== X-Gm-Message-State: ACgBeo1dwUZsLu4sVpdjrhWdkUGJVHTfUAwjvEs6v8/giAZWBGifPAxc r20wV8DumTOfGWfizTdgLyRQY9Rta3xrng== X-Google-Smtp-Source: AA6agR5IcgtB7iBqYMd7C5cRxuh9qy74EU/vhjSmhQxzSrEl2y3+hE+yDWQEcnsrfowsbzhZGP0qRg== X-Received: by 2002:a05:6000:137b:b0:226:d465:c8a9 with SMTP id q27-20020a056000137b00b00226d465c8a9mr5463692wrz.267.1661794570484; Mon, 29 Aug 2022 10:36:10 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:10 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 05/10] netconfig: Store pointer to netdev instead of ifindex Date: Mon, 29 Aug 2022 19:35:56 +0200 Message-Id: <20220829173601.1963953-5-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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"); From patchwork Mon Aug 29 17:35:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958288 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DA945C84 for ; Mon, 29 Aug 2022 17:36:13 +0000 (UTC) Received: by mail-wr1-f42.google.com with SMTP id b5so11100735wrr.5 for ; Mon, 29 Aug 2022 10:36:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=U19CAqqM7R30yGEpKDIghGBBzBPOgXZRUqCAnTUWybY=; b=2v9n37zdvpkB18OE1E1xuF+Nf5x3PILSxKFk9//Pfpvl2OsvN7Sdwf4d/Rva2k73i7 tx/Ae9h+PfL6xOnPQBN18nq6+gNWzHL++7pHlu8OF2vlCkhUQ0fxFyTIB4Af8hH72RpV Cx9rUOmNeojyOAWMMri2IPzQLzisFaVTOLmZCGhaRTujoEHfVuuCNHFY9WoCPeRyxDs7 sm94M0kePpJobuyok0vM15/33bS+JQ2cfwh+BTOFmULFxFd+UVapfCGaTBp6QlkYScjn 13OkJvXXY6ODhakXqmPYaF7SvyvtDAaDmQBt3mEg+DqRULAiFk+Xwd5+fHJxG7A5IP3I 3x2w== X-Gm-Message-State: ACgBeo385NvVE3J1hWQtNntJz66qfFae69QbvHoXVZYVcGKO8dX3Qxs9 5CZeaa6wGG9+ypf/8u9qDEZT2FtHJRhRIg== X-Google-Smtp-Source: AA6agR6KVmUEvgxyr/GSmo38hYVIyibFuNGtVTWQBV47w4CMSabLBVsrGCZerI2P2gmwXzs9jXsC4A== X-Received: by 2002:adf:e0c3:0:b0:226:d598:85ee with SMTP id m3-20020adfe0c3000000b00226d59885eemr4662820wri.589.1661794571148; Mon, 29 Aug 2022 10:36:11 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:10 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 06/10] netconfig: Add netconfig-commit API Date: Mon, 29 Aug 2022 19:35:57 +0200 Message-Id: <20220829173601.1963953-6-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 +#endif + +#include +#include +#include + +#include + +#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 #include #include -#include #include -#include #include #include #include @@ -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); From patchwork Mon Aug 29 17:35:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958289 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F31945C80 for ; Mon, 29 Aug 2022 17:36:13 +0000 (UTC) Received: by mail-wr1-f42.google.com with SMTP id m16so11074867wru.9 for ; Mon, 29 Aug 2022 10:36:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=hzMPDc19jTnqYsToQ6LR13UurvQ3Ly7led/rV25ZcV4=; b=i1ZnJAVQnKUowiQWvGxdXetVhL3tYYZGFUrH7f14qE/AQ8iJsAReHUdf2EIHymozmn sq0eX5U0BE+4yBffi9A5SlRHACI/FAWyq5d3RGtS3NuyLc96CMhS5RkKnOIQ0AunYePB 6MtA7h3/dyOGilfrSYxDEEvizypaR2sAauqoWg67BBXRrrBb/wuhwBI4llYM7yhKU+zB TJvDrQj6/ti0lWP/x6NXEalRs+K50/NSUkper0vy37voZrpTIo7g2NWQUDHy2mpNP9ou lsI+lZEbA6IuWu3WlGDPv2Sjz51gbBubPpzIGEtA5aYz3XT5xQzPTPCr5B4CK12SpTVe YHUQ== X-Gm-Message-State: ACgBeo2QBa5MXiSz/IUFw34bUyvRJcWWUopEjJXsRf/0zJ4jq7rgBEDM TZtY60pMe+FHe+/PZpokzs2DxGElzmDvBQ== X-Google-Smtp-Source: AA6agR4/obbEqebGdrTj+Ps5idgWRQ6wD9+1bkr9BO9mvZV+640etgXU86oMJny5p8H/+O9HOhRCYw== X-Received: by 2002:adf:d1c1:0:b0:220:5ec3:fb62 with SMTP id b1-20020adfd1c1000000b002205ec3fb62mr6855310wrd.69.1661794572012; Mon, 29 Aug 2022 10:36:12 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:11 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 07/10] netconfig: Handle l_netconfig events Date: Mon, 29 Aug 2022 19:35:58 +0200 Message-Id: <20220829173601.1963953-7-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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; From patchwork Mon Aug 29 17:35:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958290 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DF6645C85 for ; Mon, 29 Aug 2022 17:36:14 +0000 (UTC) Received: by mail-wr1-f50.google.com with SMTP id n17so11112523wrm.4 for ; Mon, 29 Aug 2022 10:36:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=MEFEdZFCnyPpgnda0MwMbvW4bJWLsUrQyP4TlzDzLv4=; b=XEuQbIb730AwpjV9DoYeCZJ3gPGF3/qqxiENEXaoMpzawTCZR/mbBDw8gJmZMY68kK QR6I3VRFJcMaB52ZCPhBRfr+fdRuD9P7sL8mV6t3O3iVhpXpJ5TYaoSQkRoV1B4PSMzn yWQtur5bPtc3VNBJW7VvZh01ZZQRn7HcRbxWdmlNGvxF6W/SjTdXYsh+06WVAm0tJWpv KcljTrdRwS7aDgi06aqlhC8FR2AtLY3BCOH5bIllFTp+01ABaZjSDa3MOQuUl5gDvttq mdkrIThJkgkaOJS6TwbJFn/qBI64Xb8jHQy22VH6zr240WYHOjip5/HPAHpIlkTMf34V doAg== X-Gm-Message-State: ACgBeo2vgoK1htCK4+tws0o1S5wNkENpPqUe/3nSYk6VII0kam/X8oza mOL+Aszj4ljWzN23F7UaU2xmMJJ9ym9X+w== X-Google-Smtp-Source: AA6agR5wRuTvAZaACWvjauvtv6OgC3qMCpGaYPHIo4rrPLRABMHTus61zyx47h+L1AtlRfhVZIZPng== X-Received: by 2002:a5d:508c:0:b0:226:e033:c042 with SMTP id a12-20020a5d508c000000b00226e033c042mr950743wrt.389.1661794572765; Mon, 29 Aug 2022 10:36:12 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:12 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 08/10] netconfig: Re-add FILS handling Date: Mon, 29 Aug 2022 19:35:59 +0200 Message-Id: <20220829173601.1963953-8-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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); From patchwork Mon Aug 29 17:36:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958292 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6F405C80 for ; Mon, 29 Aug 2022 17:36:15 +0000 (UTC) Received: by mail-wm1-f54.google.com with SMTP id bd26-20020a05600c1f1a00b003a5e82a6474so4802980wmb.4 for ; Mon, 29 Aug 2022 10:36:15 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=lOK0Puls0Yvt1XrnUvQytMvRvxv1YFhpHm7B3/DyZbQ=; b=se13hk5RIMMxYl37l4V5vRZ61FcYGGNEQbNWxOFvv1GYiU48gXM2Lbo9Pk1p+o/a2M +/dWJ95ZS67X65d5CHrc669el5BnmcKNTJEaMDxTkw1fuqIZQ1Ekc8Chb+bX6dqxVswI A2U+fRVF8Rv57RNEoW04H2UimWz5NcUkPdzTpSXXF3QZ/Yj1V0c7N7UOiHRaewhsj7no Tx/0JGOdNDedj6b/LCSUFc7vU8LAiUr3TqBVyCVB22r5cp5mQ8P9eQrWDDax4lVvltod Sk3PG5/OBcDYhspU0kwN3shqyEBLasPcwh0909/zF4hG5skKrjznaGneDROUrnDP8Nzn DEjw== X-Gm-Message-State: ACgBeo3Yqxip90zlSxiAlGVvym0z+/Rv72fxm8L2/0hBmYuGPcLpfh+6 BLyGHQ3L4GZDjYB81JYS8wBmxDqWdlEYlg== X-Google-Smtp-Source: AA6agR7RlMFvpIlplvXgT0gn661LgeW+8TDOYagEGdE3QuwLHkC2Fr8U3/p+EX6PLFDOntTR06G0mA== X-Received: by 2002:a05:600c:a02:b0:39c:97cc:82e3 with SMTP id z2-20020a05600c0a0200b0039c97cc82e3mr7477054wmp.97.1661794573682; Mon, 29 Aug 2022 10:36:13 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:13 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 09/10] netconfig: Add NetworkConfigurationAgent DBus API Date: Mon, 29 Aug 2022 19:36:00 +0200 Message-Id: <20220829173601.1963953-9-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 #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', <); + } + + if (preferred_expiry_time > now) { + uint32_t lt = l_time_to_secs(preferred_expiry_time - now); + + dbus_append_dict_basic(builder, "PreferredLifetime", 'u', <); + } + + 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', <); + } + + 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); From patchwork Mon Aug 29 17:36:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12958291 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36C155C8C for ; Mon, 29 Aug 2022 17:36:16 +0000 (UTC) Received: by mail-wr1-f54.google.com with SMTP id n17so11112586wrm.4 for ; Mon, 29 Aug 2022 10:36:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=ajapKYbC1wXoK0puSRpzhKGYSAuPgMPOI5PRE+fqPiI=; b=FGhYc5TidG9K8jXQa3oG+iqH+ICCRH29w9fOarkgdCgN1/tqiuW34m26J/l4F5ED8b XSq/W6S+I2tjlrIOEWMahYYxqBr9RbfBtNAX4OV4DYTAIK67Jm7VVUujY+EC2T+igArv 2nQos2/sn2ETPxDJFJ5knK0/1XocQpgS4OAQ6NAsapPqn2jAOW9elk4FHGhIM0/N+LtI i1b+TFVDqXTt4rCKhK1A9SU35QXHvhdO2Skv7IKUOtSH9JXKBNl9gHuepbmJA8hm/IZ7 ZrHTahSpzET1CMbUuVC1Ha7F5ZT2Qmhy/KSYwefNXJ4i3HZWPB6vckoJbvpTUhoz5VBm FZzQ== X-Gm-Message-State: ACgBeo2CTn8ln6LWGUUVivVIPNZU6GIsxz4zJ6JAnQdtavsAizP7WjfB GRS+3YeVEYOuoV48YF8Hpyu9tqxGkvMypg== X-Google-Smtp-Source: AA6agR5cxLc6EsXEE11MTisFscrWqcH5Zrwg5Zcln5LOjg/jIoD2jvWo4mrdFOFqQ4T6JItIeft5DQ== X-Received: by 2002:a05:6000:1ac8:b0:220:6af3:935d with SMTP id i8-20020a0560001ac800b002206af3935dmr6913414wry.549.1661794574274; Mon, 29 Aug 2022 10:36:14 -0700 (PDT) Received: from iss.ger.corp.intel.com ([82.213.228.103]) by smtp.gmail.com with ESMTPSA id q3-20020a1ce903000000b003a61306d79dsm9830551wmc.41.2022.08.29.10.36.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Aug 2022 10:36:13 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 10/10] netconfig: Skip update if resolver data unchanged Date: Mon, 29 Aug 2022 19:36:01 +0200 Message-Id: <20220829173601.1963953-10-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220829173601.1963953-1-andrew.zaborowski@intel.com> References: <20220829173601.1963953-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- 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;