static gboolean add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) { const struct in6_addr *addr; char *buf = NULL; int nnameservers, i_nameserver, n, i; gboolean added = FALSE; const char *iface; nnameservers = nm_ip6_config_get_num_nameservers (ip6); iface = g_object_get_data (G_OBJECT (ip6), IP_CONFIG_IFACE_TAG); g_assert (iface); if (split) { if (nnameservers == 0) return FALSE; for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { addr = nm_ip6_config_get_nameserver (ip6, i_nameserver); buf = ip6_addr_to_string (addr, iface); /* searches are preferred over domains */ n = nm_ip6_config_get_num_searches (ip6); for (i = 0; i < n; i++) { g_string_append_printf (str, "server=/%s/%s\n", nm_ip6_config_get_search (ip6, i), buf); added = TRUE; } if (n == 0) { /* If not searches, use any domains */ n = nm_ip6_config_get_num_domains (ip6); for (i = 0; i < n; i++) { g_string_append_printf (str, "server=/%s/%s\n", nm_ip6_config_get_domain (ip6, i), buf); added = TRUE; } } g_free (buf); } } /* If no searches or domains, just add the namservers */ if (!added) { for (i = 0; i < nnameservers; i++) { addr = nm_ip6_config_get_nameserver (ip6, i); buf = ip6_addr_to_string (addr, iface); if (buf) { g_string_append_printf (str, "server=%s\n", buf); g_free (buf); } } } return TRUE; }
static gboolean add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split, const char *iface) { const struct in6_addr *addr; char *buf; int n, i; gboolean added = FALSE; if (split) { /* FIXME: it appears that dnsmasq can only handle one nameserver * per domain (at the manpage seems to indicate that) so only use * the first nameserver here. */ addr = nm_ip6_config_get_nameserver (ip6, 0); buf = ip6_addr_to_string (addr, iface); if (!buf) return FALSE; /* searches are preferred over domains */ n = nm_ip6_config_get_num_searches (ip6); for (i = 0; i < n; i++) { g_string_append_printf (str, "server=/%s/%s\n", nm_ip6_config_get_search (ip6, i), buf); added = TRUE; } if (n == 0) { /* If not searches, use any domains */ n = nm_ip6_config_get_num_domains (ip6); for (i = 0; i < n; i++) { g_string_append_printf (str, "server=/%s/%s\n", nm_ip6_config_get_domain (ip6, i), buf); added = TRUE; } } g_free (buf); } /* If no searches or domains, just add the namservers */ if (!added) { n = nm_ip6_config_get_num_nameservers (ip6); for (i = 0; i < n; i++) { addr = nm_ip6_config_get_nameserver (ip6, i); buf = ip6_addr_to_string (addr, iface); if (buf) { g_string_append_printf (str, "server=%s\n", buf); g_free (buf); } } } return TRUE; }
void nm_ip6_config_hash (NMIP6Config *config, GChecksum *sum, gboolean dns_only) { guint32 i; const struct in6_addr *in6a; const char *s; g_return_if_fail (config != NULL); g_return_if_fail (sum != NULL); if (dns_only == FALSE) { for (i = 0; i < nm_ip6_config_get_num_addresses (config); i++) { NMIP6Address *a = nm_ip6_config_get_address (config, i); hash_in6addr (sum, nm_ip6_address_get_address (a)); hash_u32 (sum, nm_ip6_address_get_prefix (a)); hash_in6addr (sum, nm_ip6_address_get_gateway (a)); } for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) { NMIP6Route *r = nm_ip6_config_get_route (config, i); hash_in6addr (sum, nm_ip6_route_get_dest (r)); hash_u32 (sum, nm_ip6_route_get_prefix (r)); hash_in6addr (sum, nm_ip6_route_get_next_hop (r)); hash_u32 (sum, nm_ip6_route_get_metric (r)); } in6a = nm_ip6_config_get_ptp_address (config); if (in6a) hash_in6addr (sum, in6a); } for (i = 0; i < nm_ip6_config_get_num_nameservers (config); i++) hash_in6addr (sum, nm_ip6_config_get_nameserver (config, i)); for (i = 0; i < nm_ip6_config_get_num_domains (config); i++) { s = nm_ip6_config_get_domain (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } for (i = 0; i < nm_ip6_config_get_num_searches (config); i++) { s = nm_ip6_config_get_search (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } }
static void merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src, const char *iface) { guint32 num, i; num = nm_ip6_config_get_num_nameservers (src); for (i = 0; i < num; i++) { const struct in6_addr *addr; char buf[INET6_ADDRSTRLEN]; addr = nm_ip6_config_get_nameserver (src, i); /* inet_ntop is probably supposed to do this for us, but it doesn't */ if (IN6_IS_ADDR_V4MAPPED (addr)) { if (inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, INET_ADDRSTRLEN) > 0) add_string_item (rc->nameservers, buf); } else { if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0) { if (IN6_IS_ADDR_LINKLOCAL (addr) && strchr (buf, '%') == NULL) { char *tmp; tmp = g_strdup_printf ("%s%%%s", buf, iface); add_string_item (rc->nameservers, tmp); g_free (tmp); } else add_string_item (rc->nameservers, buf); } } } num = nm_ip6_config_get_num_domains (src); for (i = 0; i < num; i++) { const char *domain; domain = nm_ip6_config_get_domain (src, i); if (!rc->domain) rc->domain = domain; add_string_item (rc->searches, domain); } num = nm_ip6_config_get_num_searches (src); for (i = 0; i < num; i++) add_string_item (rc->searches, nm_ip6_config_get_search (src, i)); }
/* This is exactly identical to nm_utils_merge_ip4_config, with s/4/6/, * except that we can't compare addresses with ==. */ void nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting) { int i, j; if (!setting) return; /* Defaults are just fine */ if (nm_setting_ip6_config_get_ignore_auto_dns (setting)) { nm_ip6_config_reset_nameservers (ip6_config); nm_ip6_config_reset_domains (ip6_config); nm_ip6_config_reset_searches (ip6_config); } if (nm_setting_ip6_config_get_ignore_auto_routes (setting)) nm_ip6_config_reset_routes (ip6_config); for (i = 0; i < nm_setting_ip6_config_get_num_dns (setting); i++) { const struct in6_addr *ns; gboolean found = FALSE; /* Avoid dupes */ ns = nm_setting_ip6_config_get_dns (setting, i); for (j = 0; j < nm_ip6_config_get_num_nameservers (ip6_config); j++) { if (ip6_addresses_equal (nm_ip6_config_get_nameserver (ip6_config, j), ns)) { found = TRUE; break; } } if (!found) nm_ip6_config_add_nameserver (ip6_config, ns); } /* DNS search domains */ for (i = 0; i < nm_setting_ip6_config_get_num_dns_searches (setting); i++) { const char *search = nm_setting_ip6_config_get_dns_search (setting, i); gboolean found = FALSE; /* Avoid dupes */ for (j = 0; j < nm_ip6_config_get_num_searches (ip6_config); j++) { if (!strcmp (search, nm_ip6_config_get_search (ip6_config, j))) { found = TRUE; break; } } if (!found) nm_ip6_config_add_search (ip6_config, search); } /* IPv6 addresses */ for (i = 0; i < nm_setting_ip6_config_get_num_addresses (setting); i++) { NMIP6Address *setting_addr = nm_setting_ip6_config_get_address (setting, i); guint32 num; num = nm_ip6_config_get_num_addresses (ip6_config); for (j = 0; j < num; j++) { NMIP6Address *cfg_addr = nm_ip6_config_get_address (ip6_config, j); /* Dupe, override with user-specified address */ if (ip6_addresses_equal (nm_ip6_address_get_address (cfg_addr), nm_ip6_address_get_address (setting_addr))) { nm_ip6_config_replace_address (ip6_config, j, setting_addr); break; } } if (j == num) nm_ip6_config_add_address (ip6_config, setting_addr); } /* IPv6 routes */ for (i = 0; i < nm_setting_ip6_config_get_num_routes (setting); i++) { NMIP6Route *setting_route = nm_setting_ip6_config_get_route (setting, i); guint32 num; num = nm_ip6_config_get_num_routes (ip6_config); for (j = 0; j < num; j++) { NMIP6Route *cfg_route = nm_ip6_config_get_route (ip6_config, j); /* Dupe, override with user-specified route */ if ( ip6_addresses_equal (nm_ip6_route_get_dest (cfg_route), nm_ip6_route_get_dest (setting_route)) && (nm_ip6_route_get_prefix (cfg_route) == nm_ip6_route_get_prefix (setting_route)) && ip6_addresses_equal (nm_ip6_route_get_next_hop (cfg_route), nm_ip6_route_get_next_hop (setting_route))) { nm_ip6_config_replace_route (ip6_config, j, setting_route); break; } } if (j == num) nm_ip6_config_add_route (ip6_config, setting_route); } if (nm_setting_ip6_config_get_never_default (setting)) nm_ip6_config_set_never_default (ip6_config, TRUE); }
static gboolean add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, const char *iface, gboolean split) { const struct in6_addr *addr; char *buf = NULL; int nnameservers, i_nameserver, n, i; gboolean added = FALSE; g_return_val_if_fail (iface, FALSE); nnameservers = nm_ip6_config_get_num_nameservers (ip6); if (split) { char **domains, **iter; if (nnameservers == 0) return FALSE; for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { addr = nm_ip6_config_get_nameserver (ip6, i_nameserver); buf = ip6_addr_to_string (addr, iface); /* searches are preferred over domains */ n = nm_ip6_config_get_num_searches (ip6); for (i = 0; i < n; i++) { add_dnsmasq_nameserver (self, servers, buf, nm_ip6_config_get_search (ip6, i)); added = TRUE; } if (n == 0) { /* If not searches, use any domains */ n = nm_ip6_config_get_num_domains (ip6); for (i = 0; i < n; i++) { add_dnsmasq_nameserver (self, servers, buf, nm_ip6_config_get_domain (ip6, i)); added = TRUE; } } /* Ensure reverse-DNS works by directing queries for ip6.arpa * domains to the split domain's nameserver. */ domains = get_ip6_rdns_domains (ip6); if (domains) { for (iter = domains; iter && *iter; iter++) add_dnsmasq_nameserver (self, servers, buf, *iter); g_strfreev (domains); } g_free (buf); } } /* If no searches or domains, just add the nameservers */ if (!added) { for (i = 0; i < nnameservers; i++) { addr = nm_ip6_config_get_nameserver (ip6, i); buf = ip6_addr_to_string (addr, iface); if (buf) { add_dnsmasq_nameserver (self, servers, buf, NULL); g_free (buf); } } } return TRUE; }