From 2b1b8cce54c2d62e572b731b0a985514d8856a95 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Thu, 21 Oct 2021 10:50:33 +0200 Subject: [PATCH] netconfig: Track DNS address string lists Cache the latest v4 and v6 DNS IP string lists in struct netconfig state to be able to more easily detect changes in those values in future commits. For that split netconfig_set_dns's code into this function, which now only commit the values in netconfig->dns{4,6}_list to the resolver, and netconfig_dns_list_update() which figures out the active DNS IP address list and saves it in netconfig->dns{4,6} list. This probably saves some cycles as the callers can now decide to only recalculate the dns_list which may have changed. While there simplify netconfig_set_dns return type to void as the result was always 0 anyway and was never checked by callers. --- src/netconfig.c | 101 ++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/src/netconfig.c b/src/netconfig.c index 1ad87e69..ea2fa25d 100644 --- a/src/netconfig.c +++ b/src/netconfig.c @@ -61,6 +61,8 @@ struct netconfig { 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; @@ -278,52 +280,61 @@ static void netconfig_set_neighbor_entry_cb(int error, strerror(-error), error); } -static int netconfig_set_dns(struct netconfig *netconfig) +static void netconfig_set_dns(struct netconfig *netconfig) { - const uint8_t *fils_dns4_mac = NULL; - const uint8_t *fils_dns6_mac = NULL; - char **dns4_list = netconfig_get_dns_list(netconfig, AF_INET, - &fils_dns4_mac); - char **dns6_list = netconfig_get_dns_list(netconfig, AF_INET6, - &fils_dns6_mac); - unsigned int n_entries4 = l_strv_length(dns4_list); - unsigned int n_entries6 = l_strv_length(dns6_list); - char **dns_list; - const struct ie_fils_ip_addr_response_info *fils = - netconfig->fils_override; + if (!netconfig->dns4_list && !netconfig->dns6_list) + return; - if (!dns4_list && !dns6_list) - return 0; + 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)); - dns_list = dns4_list; - - if (dns6_list) { - dns_list = l_realloc(dns_list, - sizeof(char *) * (n_entries4 + n_entries6 + 1)); - memcpy(dns_list + n_entries4, dns6_list, + memcpy(dns_list, netconfig->dns4_list, + sizeof(char *) * n_entries4); + memcpy(dns_list + n_entries4, netconfig->dns6_list, sizeof(char *) * (n_entries6 + 1)); - /* Contents now belong to dns_list, so no l_strfreev */ - l_free(dns6_list); + resolve_set_dns(netconfig->resolve, dns_list); + l_free(dns_list); + return; } - resolve_set_dns(netconfig->resolve, dns_list); - l_strv_free(dns_list); + resolve_set_dns(netconfig->resolve, + netconfig->dns4_list ?: netconfig->dns6_list); +} - if (fils_dns4_mac && !l_rtnl_neighbor_set_hwaddr(rtnl, - netconfig->ifindex, AF_INET, - &fils->ipv4_dns, fils_dns4_mac, 6, - netconfig_set_neighbor_entry_cb, NULL, - NULL)) - l_debug("l_rtnl_neighbor_set_hwaddr failed"); +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 (fils_dns6_mac && !l_rtnl_neighbor_set_hwaddr(rtnl, - netconfig->ifindex, AF_INET6, - fils->ipv6_dns, fils_dns6_mac, 6, - netconfig_set_neighbor_entry_cb, NULL, - NULL)) - l_debug("l_rtnl_neighbor_set_hwaddr failed"); + if (l_strv_eq(*dns_list_ptr, new_dns_list)) { + l_strv_free(new_dns_list); + return false; + } - return 0; + 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, @@ -1010,6 +1021,8 @@ static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client, return; } + netconfig_dns_list_update(netconfig, AF_INET); + L_WARN_ON(!(netconfig->addr4_add_cmd_id = l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, netconfig->v4_address, @@ -1079,12 +1092,14 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client, l_rtnl_address_free(netconfig->v6_address); netconfig->v6_address = address; + netconfig_dns_list_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_set_dns(netconfig); netconfig_set_domains(netconfig); l_rtnl_address_free(netconfig->v6_address); @@ -1118,8 +1133,8 @@ static void netconfig_reset_v4(struct netconfig *netconfig) if (netconfig->rtm_protocol) { netconfig_remove_v4_address(netconfig); - l_strfreev(netconfig->dns4_overrides); - netconfig->dns4_overrides = NULL; + 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; @@ -1204,6 +1219,8 @@ static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig) ip))) return false; + netconfig_dns_list_update(netconfig, AF_INET); + netconfig->acd = l_acd_new(netconfig->ifindex); l_acd_set_event_handler(netconfig->acd, netconfig_ipv4_acd_event, netconfig, @@ -1275,6 +1292,8 @@ static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig) } 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, @@ -1513,8 +1532,8 @@ bool netconfig_reset(struct netconfig *netconfig) l_rtnl_address_free(netconfig->v6_address); netconfig->v6_address = NULL; - l_strfreev(netconfig->dns6_overrides); - netconfig->dns6_overrides = NULL; + 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;