diff options
| author | Michael Biebl <biebl@debian.org> | 2018-05-11 22:08:45 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-05-11 22:08:45 +0200 |
| commit | ee9c73a923909e23a649407be77e25235d769e25 (patch) | |
| tree | e21c923621fa278e737da693df9eb60ea31a6067 /src/dns/nm-dns-manager.c | |
| parent | f60117b41d5433be1b4a96d82cd11d0c3dce9b63 (diff) | |
New upstream version 1.10.8 upstream/1.10.8
Diffstat (limited to 'src/dns/nm-dns-manager.c')
| -rw-r--r-- | src/dns/nm-dns-manager.c | 819 |
1 files changed, 350 insertions, 469 deletions
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 10a16e57..dc545470 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -46,7 +46,6 @@ #include "nm-ip6-config.h" #include "NetworkManagerUtils.h" #include "nm-config.h" -#include "nm-dbus-object.h" #include "devices/nm-device.h" #include "nm-manager.h" @@ -55,6 +54,8 @@ #include "nm-dns-systemd-resolved.h" #include "nm-dns-unbound.h" +#include "introspection/org.freedesktop.NetworkManager.DnsManager.h" + #define HASH_LEN 20 #ifndef RESOLVCONF_PATH @@ -69,24 +70,6 @@ #define PLUGIN_RATELIMIT_BURST 5 #define PLUGIN_RATELIMIT_DELAY 300 -/*****************************************************************************/ - -typedef enum { - SR_SUCCESS, - SR_NOTFOUND, - SR_ERROR -} SpawnResult; - -typedef struct { - GPtrArray *nameservers; - GPtrArray *searches; - GPtrArray *options; - const char *nis_domain; - GPtrArray *nis_servers; -} NMResolvConfData; - -/*****************************************************************************/ - enum { CONFIG_CHANGED, @@ -101,16 +84,44 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDnsManager, static guint signals[LAST_SIGNAL] = { 0 }; -typedef struct { - GHashTable *configs; - CList ip_config_lst_head; - GVariant *config_variant; +typedef enum { + SR_SUCCESS, + SR_NOTFOUND, + SR_ERROR +} SpawnResult; - NMDnsIPConfigData *best_ip_config_4; - NMDnsIPConfigData *best_ip_config_6; +NM_DEFINE_SINGLETON_GETTER (NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER); - bool ip_config_lst_need_sort:1; +/*****************************************************************************/ +#define _NMLOG_PREFIX_NAME "dns-mgr" +#define _NMLOG_DOMAIN LOGD_DNS +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ + char __prefix[20]; \ + const NMDnsManager *const __self = (self); \ + \ + _nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \ + "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((!__self || __self == singleton_instance) \ + ? "" \ + : nm_sprintf_buf (__prefix, "[%p]", __self)) \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + +typedef struct { + GPtrArray *configs; + GVariant *config_variant; + NMDnsIPConfigData *best_conf4, *best_conf6; + + bool need_sort:1; bool dns_touched:1; bool is_stopped:1; @@ -134,52 +145,20 @@ typedef struct { } NMDnsManagerPrivate; struct _NMDnsManager { - NMDBusObject parent; + NMExportedObject parent; NMDnsManagerPrivate _priv; }; struct _NMDnsManagerClass { - NMDBusObjectClass parent; + NMExportedObjectClass parent; }; -G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, NM_TYPE_DBUS_OBJECT) +G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, NM_TYPE_EXPORTED_OBJECT) #define NM_DNS_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDnsManager, NM_IS_DNS_MANAGER) -NM_DEFINE_SINGLETON_GETTER (NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER); - -/*****************************************************************************/ - -#define _NMLOG_PREFIX_NAME "dns-mgr" -#define _NMLOG_DOMAIN LOGD_DNS -#define _NMLOG(level, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ - char __prefix[20]; \ - const NMDnsManager *const __self = (self); \ - \ - _nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((!__self || __self == singleton_instance) \ - ? "" \ - : nm_sprintf_buf (__prefix, "[%p]", __self)) \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END - -/*****************************************************************************/ - -static void _ip_config_dns_priority_changed (gpointer config, - GParamSpec *pspec, - NMDnsIPConfigData *ip_data); - -/*****************************************************************************/ - static gboolean -domain_is_valid (const char *domain, gboolean check_public_suffix) +domain_is_valid (const gchar *domain, gboolean check_public_suffix) { if (*domain == '\0') return FALSE; @@ -190,14 +169,16 @@ domain_is_valid (const char *domain, gboolean check_public_suffix) return TRUE; } -static gboolean -domain_is_routing (const char *domain) -{ - return domain[0] == '~'; -} - /*****************************************************************************/ +typedef struct { + GPtrArray *nameservers; + GPtrArray *searches; + GPtrArray *options; + const char *nis_domain; + GPtrArray *nis_servers; +} NMResolvConfData; + NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConfManager, NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "unknown"), @@ -211,109 +192,44 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConf NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_config_type_to_string, NMDnsIPConfigType, NM_UTILS_LOOKUP_DEFAULT_WARN ("<unknown>"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_REMOVED, "removed"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_DEFAULT, "default"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, "best"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_VPN, "vpn"), ); -/*****************************************************************************/ - -static void -_ASSERT_config_data (const NMDnsConfigData *data) -{ - nm_assert (data); - nm_assert (NM_IS_DNS_MANAGER (data->self)); - nm_assert (data->ifindex > 0); -} - -static void -_ASSERT_ip_config_data (const NMDnsIPConfigData *ip_data) -{ - nm_assert (ip_data); - _ASSERT_config_data (ip_data->data); - nm_assert (NM_IS_IP_CONFIG (ip_data->ip_config)); - nm_assert (c_list_contains (&ip_data->data->data_lst_head, &ip_data->data_lst)); - nm_assert (ip_data->data->ifindex == nm_ip_config_get_ifindex (ip_data->ip_config)); -} - static NMDnsIPConfigData * -_ip_config_data_new (NMDnsConfigData *data, - NMIPConfig *ip_config, - NMDnsIPConfigType ip_config_type) -{ - NMDnsIPConfigData *ip_data; - - _ASSERT_config_data (data); - nm_assert (NM_IS_IP_CONFIG (ip_config)); - nm_assert (ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED); - - ip_data = g_slice_new0 (NMDnsIPConfigData); - ip_data->data = data; - ip_data->ip_config = g_object_ref (ip_config); - ip_data->ip_config_type = ip_config_type; - c_list_link_tail (&data->data_lst_head, &ip_data->data_lst); - c_list_link_tail (&NM_DNS_MANAGER_GET_PRIVATE (data->self)->ip_config_lst_head, &ip_data->ip_config_lst); - - g_signal_connect (ip_config, - NM_IS_IP4_CONFIG (ip_config) - ? "notify::" NM_IP4_CONFIG_DNS_PRIORITY - : "notify::" NM_IP6_CONFIG_DNS_PRIORITY, - (GCallback) _ip_config_dns_priority_changed, ip_data); - - _ASSERT_ip_config_data (ip_data); - return ip_data; -} - -static void -_ip_config_data_free (NMDnsIPConfigData *ip_data) +ip_config_data_new (gpointer config, NMDnsIPConfigType type, const char *iface) { - _ASSERT_ip_config_data (ip_data); + NMDnsIPConfigData *data; - c_list_unlink_stale (&ip_data->data_lst); - c_list_unlink_stale (&ip_data->ip_config_lst); + data = g_slice_new0 (NMDnsIPConfigData); + data->config = g_object_ref (config); + data->iface = g_strdup (iface); + data->type = type; - g_signal_handlers_disconnect_by_func (ip_data->ip_config, - _ip_config_dns_priority_changed, - ip_data); - - g_object_unref (ip_data->ip_config); - g_slice_free (NMDnsIPConfigData, ip_data); -} - -static NMDnsIPConfigData * -_config_data_find_ip_config (NMDnsConfigData *data, - NMIPConfig *ip_config) -{ - NMDnsIPConfigData *ip_data; - - _ASSERT_config_data (data); - - c_list_for_each_entry (ip_data, &data->data_lst_head, data_lst) { - _ASSERT_ip_config_data (ip_data); - - if (ip_data->ip_config == ip_config) - return ip_data; - } - return NULL; + return data; } static void -_config_data_free (NMDnsConfigData *data) +ip_config_data_destroy (gpointer ptr) { - _ASSERT_config_data (data); + NMDnsIPConfigData *data = ptr; + + if (!data) + return; - nm_assert (c_list_is_empty (&data->data_lst_head)); - g_slice_free (NMDnsConfigData, data); + g_object_unref (data->config); + g_free (data->iface); + g_slice_free (NMDnsIPConfigData, data); } static gint -_ip_config_data_cmp (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) +ip_config_data_compare (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) { int a_prio, b_prio; - a_prio = nm_ip_config_get_dns_priority (a->ip_config); - b_prio = nm_ip_config_get_dns_priority (b->ip_config); + a_prio = nm_ip_config_get_dns_priority (a->config); + b_prio = nm_ip_config_get_dns_priority (b->config); /* Configurations with lower priority value first */ if (a_prio < b_prio) @@ -322,40 +238,24 @@ _ip_config_data_cmp (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) return 1; /* Sort also according to type */ - if (a->ip_config_type > b->ip_config_type) + if (a->type > b->type) return -1; - else if (a->ip_config_type < b->ip_config_type) + else if (a->type < b->type) return 1; return 0; } static gint -_ip_config_lst_cmp (const CList *a, - const CList *b, - const void *user_data) +ip_config_data_ptr_compare (gconstpointer a, gconstpointer b) { - return _ip_config_data_cmp (c_list_entry (a, NMDnsIPConfigData, ip_config_lst), - c_list_entry (b, NMDnsIPConfigData, ip_config_lst)); -} + const NMDnsIPConfigData *const *ptr_a = a, *const *ptr_b = b; -static CList * -_ip_config_lst_head (NMDnsManager *self) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - if (priv->ip_config_lst_need_sort) { - priv->ip_config_lst_need_sort = FALSE; - c_list_sort (&priv->ip_config_lst_head, _ip_config_lst_cmp, NULL); - } - - return &priv->ip_config_lst_head; + return ip_config_data_compare (*ptr_a, *ptr_b); } -/*****************************************************************************/ - static void -add_string_item (GPtrArray *array, const char *str, gboolean dup) +add_string_item (GPtrArray *array, const char *str) { int i; @@ -371,7 +271,7 @@ add_string_item (GPtrArray *array, const char *str, gboolean dup) } /* No dupes, add the new item */ - g_ptr_array_add (array, dup ? g_strdup (str): (gpointer) str); + g_ptr_array_add (array, g_strdup (str)); } static void @@ -382,55 +282,24 @@ add_dns_option_item (GPtrArray *array, const char *str) } static void -add_dns_domains (GPtrArray *array, const NMIPConfig *ip_config, - gboolean include_routing, gboolean dup) -{ - guint num_domains, num_searches, i; - const char *str; - - num_domains = nm_ip_config_get_num_domains (ip_config); - num_searches = nm_ip_config_get_num_searches (ip_config); - - for (i = 0; i < num_searches; i++) { - str = nm_ip_config_get_search (ip_config, i); - if (!include_routing && domain_is_routing (str)) - continue; - if (!domain_is_valid (nm_utils_parse_dns_domain (str, NULL), FALSE)) - continue; - add_string_item (array, str, dup); - } - if (num_domains > 1 || !num_searches) { - for (i = 0; i < num_domains; i++) { - str = nm_ip_config_get_domain (ip_config, i); - if (!include_routing && domain_is_routing (str)) - continue; - if (!domain_is_valid (nm_utils_parse_dns_domain (str, NULL), FALSE)) - continue; - add_string_item (array, str, dup); - } - } -} - -static void merge_one_ip_config (NMResolvConfData *rc, - int ifindex, - const NMIPConfig *ip_config) + const NMIPConfig *config, + const char *iface) { int addr_family; - guint num, i; + guint num, num_domains, num_searches, i; char buf[NM_UTILS_INET_ADDRSTRLEN + 50]; + const char *str; - addr_family = nm_ip_config_get_addr_family (ip_config); + addr_family = nm_ip_config_get_addr_family (config); nm_assert_addr_family (addr_family); - nm_assert (ifindex > 0); - nm_assert (ifindex == nm_ip_config_get_ifindex (ip_config)); - num = nm_ip_config_get_num_nameservers (ip_config); + num = nm_ip_config_get_num_nameservers (config); for (i = 0; i < num; i++) { const NMIPAddr *addr; - addr = nm_ip_config_get_nameserver (ip_config, i); + addr = nm_ip_config_get_nameserver (config, i); if (addr_family == AF_INET) nm_utils_inet_ntop (addr_family, addr, buf); else if (IN6_IS_ADDR_V4MAPPED (addr)) @@ -438,42 +307,49 @@ merge_one_ip_config (NMResolvConfData *rc, else { nm_utils_inet6_ntop (&addr->addr6, buf); if (IN6_IS_ADDR_LINKLOCAL (addr)) { - const char *ifname; - - ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex); - if (ifname) { - g_strlcat (buf, "%", sizeof (buf)); - g_strlcat (buf, ifname, sizeof (buf)); - } + g_strlcat (buf, "%", sizeof (buf)); + g_strlcat (buf, iface, sizeof (buf)); } } - add_string_item (rc->nameservers, buf, TRUE); + add_string_item (rc->nameservers, buf); } - add_dns_domains (rc->searches, ip_config, FALSE, TRUE); + num_domains = nm_ip_config_get_num_domains (config); + num_searches = nm_ip_config_get_num_searches (config); + for (i = 0; i < num_searches; i++) { + str = nm_ip_config_get_search (config, i); + if (domain_is_valid (str, FALSE)) + add_string_item (rc->searches, str); + } + if (num_domains > 1 || !num_searches) { + for (i = 0; i < num_domains; i++) { + str = nm_ip_config_get_domain (config, i); + if (domain_is_valid (str, FALSE)) + add_string_item (rc->searches, str); + } + } - num = nm_ip_config_get_num_dns_options (ip_config); + num = nm_ip_config_get_num_dns_options (config); for (i = 0; i < num; i++) { add_dns_option_item (rc->options, - nm_ip_config_get_dns_option (ip_config, i)); + nm_ip_config_get_dns_option (config, i)); } if (addr_family == AF_INET) { - const NMIP4Config *ip4_config = (const NMIP4Config *) ip_config; + const NMIP4Config *config4 = (const NMIP4Config *) config; /* NIS stuff */ - num = nm_ip4_config_get_num_nis_servers (ip4_config); + num = nm_ip4_config_get_num_nis_servers (config4); for (i = 0; i < num; i++) { add_string_item (rc->nis_servers, - nm_utils_inet4_ntop (nm_ip4_config_get_nis_server (ip4_config, i), buf), - TRUE); + nm_utils_inet4_ntop (nm_ip4_config_get_nis_server (config4, i), buf)); } - if (nm_ip4_config_get_nis_domain (ip4_config)) { + if (nm_ip4_config_get_nis_domain (config4)) { /* FIXME: handle multiple domains */ if (!rc->nis_domain) - rc->nis_domain = nm_ip4_config_get_nis_domain (ip4_config); + rc->nis_domain = nm_ip4_config_get_nis_domain (config4); } } } @@ -502,59 +378,58 @@ run_netconfig (NMDnsManager *self, GError **error, gint *stdin_fd) } static void -netconfig_construct_str (NMDnsManager *self, GString *str, const char *key, const char *value) +write_to_netconfig (NMDnsManager *self, gint fd, const char *key, const char *value) { - if (value) { - _LOGD ("writing to netconfig: %s='%s'", key, value); - g_string_append_printf (str, "%s='%s'\n", key, value); - } -} + char *str; + int x; -static void -netconfig_construct_strv (NMDnsManager *self, GString *str, const char *key, const char *const*values) -{ - if (values) { - gs_free char *value = NULL; - - value = g_strjoinv (" ", (char **) values); - netconfig_construct_str (self, str, key, value); - } + str = g_strdup_printf ("%s='%s'\n", key, value); + _LOGD ("writing to netconfig: %s", str); + x = write (fd, str, strlen (str)); + g_free (str); } static SpawnResult dispatch_netconfig (NMDnsManager *self, - const char *const*searches, - const char *const*nameservers, + char **searches, + char **nameservers, const char *nis_domain, - const char *const*nis_servers, + char **nis_servers, GError **error) { + char *str; GPid pid; gint fd; int status; - gssize l; - nm_auto_free_gstring GString *str = NULL; pid = run_netconfig (self, error, &fd); if (pid <= 0) return SR_NOTFOUND; - str = g_string_new (""); - /* NM is writing already-merged DNS information to netconfig, so it * does not apply to a specific network interface. */ - netconfig_construct_str (self, str, "INTERFACE", "NetworkManager"); - netconfig_construct_strv (self, str, "DNSSEARCH", searches); - netconfig_construct_strv (self, str, "DNSSERVERS", nameservers); - netconfig_construct_str (self, str, "NISDOMAIN", nis_domain); - netconfig_construct_strv (self, str, "NISSERVERS", nis_servers); + write_to_netconfig (self, fd, "INTERFACE", "NetworkManager"); -again: - l = write (fd, str->str, str->len); - if (l == -1) { - if (errno == EINTR) - goto again; + if (searches) { + str = g_strjoinv (" ", searches); + write_to_netconfig (self, fd, "DNSSEARCH", str); + g_free (str); + } + + if (nameservers) { + str = g_strjoinv (" ", nameservers); + write_to_netconfig (self, fd, "DNSSERVERS", str); + g_free (str); + } + + if (nis_domain) + write_to_netconfig (self, fd, "NISDOMAIN", nis_domain); + + if (nis_servers) { + str = g_strjoinv (" ", nis_servers); + write_to_netconfig (self, fd, "NISSERVERS", str); + g_free (str); } nm_close (fd); @@ -868,7 +743,7 @@ update_resolv_conf (NMDnsManager *self, if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) { _LOGT ("update-resolv-conf: write internal file %s succeeded (rc-manager=%s)", - MY_RESOLV_CONF, _rc_manager_to_string (rc_manager)); + rc_path, _rc_manager_to_string (rc_manager)); return write_file_result; } @@ -942,21 +817,25 @@ update_resolv_conf (NMDnsManager *self, static void compute_hash (NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[HASH_LEN]) { + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); GChecksum *sum; gsize len = HASH_LEN; - NMDnsIPConfigData *ip_data; + guint i; sum = g_checksum_new (G_CHECKSUM_SHA1); - nm_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); + g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); if (global) nm_global_dns_config_update_checksum (global, sum); else { - const CList *head; + for (i = 0; i < priv->configs->len; i++) { + NMDnsIPConfigData *data = priv->configs->pdata[i]; - head = _ip_config_lst_head (self); - c_list_for_each_entry (ip_data, head, ip_config_lst) - nm_ip_config_hash (ip_data->ip_config, sum, TRUE); + if (NM_IS_IP4_CONFIG (data->config)) + nm_ip4_config_hash ((NMIP4Config *) data->config, sum, TRUE); + else if (NM_IS_IP6_CONFIG (data->config)) + nm_ip6_config_hash ((NMIP6Config *) data->config, sum, TRUE); + } } g_checksum_get_digest (sum, buffer, &len); @@ -970,36 +849,27 @@ merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) const char *const *searches; const char *const *options; const char *const *servers; - guint i; + gint i; if (!global_conf) return FALSE; searches = nm_global_dns_config_get_searches (global_conf); - if (searches) { - for (i = 0; searches[i]; i++) { - if (domain_is_routing (searches[i])) - continue; - if (!domain_is_valid (searches[i], FALSE)) - continue; - add_string_item (rc->searches, searches[i], TRUE); - } - } - options = nm_global_dns_config_get_options (global_conf); - if (options) { - for (i = 0; options[i]; i++) - add_string_item (rc->options, options[i], TRUE); + + for (i = 0; searches && searches[i]; i++) { + if (domain_is_valid (searches[i], FALSE)) + add_string_item (rc->searches, searches[i]); } - default_domain = nm_global_dns_config_lookup_domain (global_conf, "*"); - nm_assert (default_domain); + for (i = 0; options && options[i]; i++) + add_string_item (rc->options, options[i]); + default_domain = nm_global_dns_config_lookup_domain (global_conf, "*"); + g_assert (default_domain); servers = nm_global_dns_domain_get_servers (default_domain); - if (servers) { - for (i = 0; servers[i]; i++) - add_string_item (rc->nameservers, servers[i], TRUE); - } + for (i = 0; servers && servers[i]; i++) + add_string_item (rc->nameservers, servers[i]); return TRUE; } @@ -1039,16 +909,17 @@ _ptrarray_to_strv (GPtrArray *parray) } static void -_collect_resolv_conf_data (NMDnsManager *self, +_collect_resolv_conf_data (NMDnsManager *self, /* only for logging context, no other side-effects */ NMGlobalDnsConfig *global_config, + const GPtrArray *configs, + const char *hostname, char ***out_searches, char ***out_options, char ***out_nameservers, char ***out_nis_servers, const char **out_nis_domain) { - NMDnsManagerPrivate *priv; - guint i, num, len; + guint i, j, num, len; NMResolvConfData rc = { .nameservers = g_ptr_array_new (), .searches = g_ptr_array_new (), @@ -1057,44 +928,37 @@ _collect_resolv_conf_data (NMDnsManager *self, .nis_servers = g_ptr_array_new (), }; - priv = NM_DNS_MANAGER_GET_PRIVATE (self); - if (global_config) merge_global_dns_config (&rc, global_config); else { nm_auto_free_gstring GString *tmp_gstring = NULL; int prio, first_prio = 0; - const NMDnsIPConfigData *ip_data; - const CList *head; - gboolean is_first = TRUE; + NMDnsIPConfigData *current; - head = _ip_config_lst_head (self); - c_list_for_each_entry (ip_data, head, ip_config_lst) { + for (i = 0, j = 0; i < configs->len; i++) { gboolean skip = FALSE; - _ASSERT_ip_config_data (ip_data); + current = configs->pdata[i]; - prio = nm_ip_config_get_dns_priority (ip_data->ip_config); + prio = nm_ip_config_get_dns_priority (current->config); - if (is_first) { - is_first = FALSE; + if (i == 0) first_prio = prio; - } else if ( first_prio < 0 - && first_prio != prio) + else if (first_prio < 0 && first_prio != prio) skip = TRUE; - if (nm_ip_config_get_num_nameservers (ip_data->ip_config)) { - _LOGT ("config: %8d %-7s v%c %-5d %s: %s", + if (nm_ip_config_get_num_nameservers (current->config)) { + _LOGT ("config: %8d %-7s v%c %-16s %s: %s", prio, - _config_type_to_string (ip_data->ip_config_type), - nm_utils_addr_family_to_char (nm_ip_config_get_addr_family (ip_data->ip_config)), - ip_data->data->ifindex, + _config_type_to_string (current->type), + nm_utils_addr_family_to_char (nm_ip_config_get_addr_family (current->config)), + current->iface, skip ? "<SKIP>" : "", - get_nameserver_list (ip_data->ip_config, &tmp_gstring)); + get_nameserver_list (current->config, &tmp_gstring)); } if (!skip) - merge_one_ip_config (&rc, ip_data->data->ifindex, ip_data->ip_config); + merge_one_ip_config (&rc, current->config, current->iface); } } @@ -1105,16 +969,16 @@ _collect_resolv_conf_data (NMDnsManager *self, * (eg, "example.com"), then use the hostname itself as the search (since the user is * unlikely to want "com" as a search domain). */ - if (priv->hostname) { - const char *hostdomain = strchr (priv->hostname, '.'); + if (hostname) { + const char *hostdomain = strchr (hostname, '.'); if ( hostdomain - && !nm_utils_ipaddr_valid (AF_UNSPEC, priv->hostname)) { + && !nm_utils_ipaddr_valid (AF_UNSPEC, hostname)) { hostdomain++; if (domain_is_valid (hostdomain, TRUE)) - add_string_item (rc.searches, hostdomain, TRUE); - else if (domain_is_valid (priv->hostname, TRUE)) - add_string_item (rc.searches, priv->hostname, TRUE); + add_string_item (rc.searches, hostdomain); + else if (domain_is_valid (hostname, TRUE)) + add_string_item (rc.searches, hostname); } } @@ -1176,12 +1040,16 @@ update_dns (NMDnsManager *self, data = nm_config_get_data (priv->config); global_config = nm_config_data_get_global_dns_config (data); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + /* Update hash with config we're applying */ compute_hash (self, global_config, priv->hash); - _collect_resolv_conf_data (self, global_config, - &searches, &options, &nameservers, - &nis_servers, &nis_domain); + _collect_resolv_conf_data (self, global_config, priv->configs, priv->hostname, + &searches, &options, &nameservers, &nis_servers, &nis_domain); /* Let any plugins do their thing first */ if (priv->plugin) { @@ -1199,8 +1067,8 @@ update_dns (NMDnsManager *self, _LOGD ("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update (plugin, + priv->configs, global_config, - _ip_config_lst_head (self), priv->hostname)) { _LOGW ("update-dns: plugin %s update failed", plugin_name); @@ -1246,12 +1114,8 @@ update_dns (NMDnsManager *self, result = dispatch_resolvconf (self, searches, nameservers, options, error); break; case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: - result = dispatch_netconfig (self, - (const char *const*) searches, - (const char *const*) nameservers, - nis_domain, - (const char *const*) nis_servers, - error); + result = dispatch_netconfig (self, searches, nameservers, nis_domain, + nis_servers, error); break; default: g_assert_not_reached (); @@ -1341,96 +1205,82 @@ plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data) } static void -_ip_config_dns_priority_changed (gpointer config, - GParamSpec *pspec, - NMDnsIPConfigData *ip_data) +ip_config_dns_priority_changed (gpointer config, + GParamSpec *pspec, + NMDnsManager *self) { - _ASSERT_ip_config_data (ip_data); + NM_DNS_MANAGER_GET_PRIVATE (self)->need_sort = TRUE; +} - NM_DNS_MANAGER_GET_PRIVATE (ip_data->data->self)->ip_config_lst_need_sort = TRUE; +static void +forget_data (NMDnsManager *self, NMDnsIPConfigData *data) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if (data == priv->best_conf4) + priv->best_conf4 = NULL; + else if (data == priv->best_conf6) + priv->best_conf6 = NULL; + + g_signal_handlers_disconnect_by_func (data->config, ip_config_dns_priority_changed, self); } gboolean -nm_dns_manager_set_ip_config (NMDnsManager *self, - NMIPConfig *ip_config, - NMDnsIPConfigType ip_config_type) +nm_dns_manager_add_ip_config (NMDnsManager *self, + const char *iface, + gpointer config, + NMDnsIPConfigType cfg_type) { NMDnsManagerPrivate *priv; GError *error = NULL; - NMDnsIPConfigData *ip_data; - NMDnsConfigData *data; - int ifindex; - NMDnsIPConfigData **p_best; + NMDnsIPConfigData *data; + gboolean v4 = NM_IS_IP4_CONFIG (config); + guint i; g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); - g_return_val_if_fail (NM_IS_IP_CONFIG (ip_config), FALSE); - - ifindex = nm_ip_config_get_ifindex (ip_config); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (config, FALSE); + g_return_val_if_fail (iface && iface[0], FALSE); + nm_assert (NM_IS_IP_CONFIG (config)); priv = NM_DNS_MANAGER_GET_PRIVATE (self); - data = g_hash_table_lookup (priv->configs, GINT_TO_POINTER (ifindex)); - if (!data) - ip_data = NULL; - else - ip_data = _config_data_find_ip_config (data, ip_config); - - if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) { - if (!ip_data) - return FALSE; - if (priv->best_ip_config_4 == ip_data) - priv->best_ip_config_4 = NULL; - if (priv->best_ip_config_6 == ip_data) - priv->best_ip_config_6 = NULL; - /* deleting a config doesn't invalidate the configs' sort order. */ - _ip_config_data_free (ip_data); - if (c_list_is_empty (&data->data_lst_head)) - g_hash_table_remove (priv->configs, GINT_TO_POINTER (ifindex)); - goto changed; - } - - if ( ip_data - && ip_data->ip_config_type == ip_config_type) { - /* nothing to do. */ - return FALSE; - } - - if (!data) { - data = g_slice_new0 (NMDnsConfigData); - data->ifindex = ifindex; - data->self = self; - c_list_init (&data->data_lst_head); - _ASSERT_config_data (data); - g_hash_table_insert (priv->configs, GINT_TO_POINTER (ifindex), data); + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + if (data->config == config) { + if ( nm_streq (data->iface, iface) + && data->type == cfg_type) + return FALSE; + else { + forget_data (self, data); + g_ptr_array_remove_index_fast (priv->configs, i); + break; + } + } } - if (!ip_data) - ip_data = _ip_config_data_new (data, ip_config, ip_config_type); - else - ip_data->ip_config_type = ip_config_type; - - priv->ip_config_lst_need_sort = TRUE; - - p_best = NM_IS_IP4_CONFIG (ip_config) - ? &priv->best_ip_config_4 - : &priv->best_ip_config_6; + data = ip_config_data_new (config, cfg_type, iface); + g_ptr_array_add (priv->configs, data); + g_signal_connect (config, + v4 ? + "notify::" NM_IP4_CONFIG_DNS_PRIORITY : + "notify::" NM_IP6_CONFIG_DNS_PRIORITY, + (GCallback) ip_config_dns_priority_changed, self); + priv->need_sort = TRUE; - if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) { + if (cfg_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) { /* Only one best-device per IP version is allowed */ - if (*p_best != ip_data) { - if (*p_best) - (*p_best)->ip_config_type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; - *p_best = ip_data; + if (v4) { + if (priv->best_conf4) + priv->best_conf4->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf4 = data; + } else { + if (priv->best_conf6) + priv->best_conf6->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf6 = data; } - } else { - if (*p_best == ip_data) - *p_best = NULL; } -changed: - if ( !priv->updates_queue - && !update_dns (self, FALSE, &error)) { + if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { _LOGW ("could not commit DNS changes: %s", error->message); g_clear_error (&error); } @@ -1438,6 +1288,38 @@ changed: return TRUE; } +gboolean +nm_dns_manager_remove_ip_config (NMDnsManager *self, gpointer config) +{ + NMDnsManagerPrivate *priv; + GError *error = NULL; + NMDnsIPConfigData *data; + guint i; + + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + g_return_val_if_fail (config, FALSE); + nm_assert (NM_IS_IP_CONFIG (config)); + + priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + + if (data->config == config) { + forget_data (self, data); + g_ptr_array_remove_index (priv->configs, i); + + if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { + _LOGW ("could not commit DNS changes: %s", error->message); + g_clear_error (&error); + } + + return TRUE; + } + } + return FALSE; +} + void nm_dns_manager_set_initial_hostname (NMDnsManager *self, const char *hostname) @@ -1480,6 +1362,23 @@ nm_dns_manager_set_hostname (NMDnsManager *self, } } +gboolean +nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self) +{ + NMDnsManagerPrivate *priv; + + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + + priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if ( NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE) + || priv->plugin) + return FALSE; + + return TRUE; +} + void nm_dns_manager_begin_updates (NMDnsManager *self, const char *func) { @@ -1510,6 +1409,11 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) priv = NM_DNS_MANAGER_GET_PRIVATE (self); g_return_if_fail (priv->updates_queue > 0); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), new); changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE; _LOGD ("(%s): DNS configuration %s", func, changed ? "changed" : "did not change"); @@ -1906,14 +1810,14 @@ _get_config_variant (NMDnsManager *self) NMGlobalDnsConfig *global_config; gs_free char *str = NULL; GVariantBuilder builder; - NMDnsIPConfigData *ip_data; - const CList *head; - gs_unref_ptrarray GPtrArray *array_domains = NULL; + NMConfigData *data; + guint i, j; if (priv->config_variant) return priv->config_variant; - global_config = nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)); + data = nm_config_get_data (priv->config); + global_config = nm_config_data_get_global_dns_config (data); if (global_config) { priv->config_variant = _get_global_config_variant (global_config); _LOGT ("current configuration: %s", (str = g_variant_print (priv->config_variant, TRUE))); @@ -1922,26 +1826,25 @@ _get_config_variant (NMDnsManager *self) g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); - head = _ip_config_lst_head (self); - c_list_for_each_entry (ip_data, head, ip_config_lst) { - const NMIPConfig *ip_config = ip_data->ip_config; + for (i = 0; i < priv->configs->len; i++) { + NMDnsIPConfigData *current = priv->configs->pdata[i]; + const NMIPConfig *config = current->config; GVariantBuilder entry_builder; GVariantBuilder strv_builder; - guint i, num; - const int addr_family = nm_ip_config_get_addr_family (ip_config); + guint num; + const int addr_family = nm_ip_config_get_addr_family (config); char buf[NM_UTILS_INET_ADDRSTRLEN]; const NMIPAddr *addr; - const char *ifname; - num = nm_ip_config_get_num_nameservers (ip_config); + num = nm_ip_config_get_num_nameservers (config); if (!num) continue; g_variant_builder_init (&entry_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&strv_builder, G_VARIANT_TYPE ("as")); - for (i = 0; i < num; i++) { - addr = nm_ip_config_get_nameserver (ip_config, i); + for (j = 0; j < num; j++) { + addr = nm_ip_config_get_nameserver (config, j); g_variant_builder_add (&strv_builder, "s", nm_utils_inet_ntop (addr_family, addr, buf)); @@ -1951,47 +1854,36 @@ _get_config_variant (NMDnsManager *self) "nameservers", g_variant_builder_end (&strv_builder)); - - num = nm_ip_config_get_num_domains (ip_config); - num += nm_ip_config_get_num_searches (ip_config); + num = nm_ip_config_get_num_domains (config); if (num > 0) { - if (!array_domains) - array_domains = g_ptr_array_sized_new (num); - else - g_ptr_array_set_size (array_domains, 0); - - add_dns_domains (array_domains, ip_config, TRUE, FALSE); - if (array_domains->len) { - g_variant_builder_init (&strv_builder, G_VARIANT_TYPE ("as")); - for (i = 0; i < array_domains->len; i++) { - g_variant_builder_add (&strv_builder, - "s", - array_domains->pdata[i]); - } - g_variant_builder_add (&entry_builder, - "{sv}", - "domains", - g_variant_builder_end (&strv_builder)); + g_variant_builder_init (&strv_builder, G_VARIANT_TYPE ("as")); + for (j = 0; j < num; j++) { + g_variant_builder_add (&strv_builder, + "s", + nm_ip_config_get_domain (config, j)); } + g_variant_builder_add (&entry_builder, + "{sv}", + "domains", + g_variant_builder_end (&strv_builder)); } - ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ip_data->data->ifindex); - if (ifname) { + if (current->iface) { g_variant_builder_add (&entry_builder, "{sv}", "interface", - g_variant_new_string (ifname)); + g_variant_new_string (current->iface)); } g_variant_builder_add (&entry_builder, "{sv}", "priority", - g_variant_new_int32 (nm_ip_config_get_dns_priority (ip_config))); + g_variant_new_int32 (nm_ip_config_get_dns_priority (config))); g_variant_builder_add (&entry_builder, "{sv}", "vpn", - g_variant_new_boolean (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN)); + g_variant_new_boolean (current->type == NM_DNS_IP_CONFIG_TYPE_VPN)); g_variant_builder_add (&builder, "a{sv}", &entry_builder); } @@ -2032,12 +1924,8 @@ nm_dns_manager_init (NMDnsManager *self) _LOGT ("creating..."); - c_list_init (&priv->ip_config_lst_head); - priv->config = g_object_ref (nm_config_get ()); - - priv->configs = g_hash_table_new_full (nm_direct_hash, NULL, - NULL, (GDestroyNotify) _config_data_free); + priv->configs = g_ptr_array_new_full (8, ip_config_data_destroy); /* Set the initial hash */ compute_hash (self, NULL, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); @@ -2054,33 +1942,33 @@ dispose (GObject *object) { NMDnsManager *self = NM_DNS_MANAGER (object); NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - NMDnsIPConfigData *ip_data, *ip_data_safe; + NMDnsIPConfigData *data; + guint i; _LOGT ("disposing"); if (!priv->is_stopped) nm_dns_manager_stop (self); - if (priv->config) - g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self); - _clear_plugin (self); - priv->best_ip_config_4 = NULL; - priv->best_ip_config_6 = NULL; - - c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst) - _ip_config_data_free (ip_data); + if (priv->config) { + g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self); + g_clear_object (&priv->config); + } - g_clear_pointer (&priv->configs, g_hash_table_destroy); + if (priv->configs) { + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + forget_data (self, data); + } + g_ptr_array_free (priv->configs, TRUE); + priv->configs = NULL; + } nm_clear_g_source (&priv->plugin_ratelimit.timer); - g_clear_object (&priv->config); - G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); - - g_clear_pointer (&priv->config_variant, g_variant_unref); } static void @@ -2095,30 +1983,18 @@ finalize (GObject *object) G_OBJECT_CLASS (nm_dns_manager_parent_class)->finalize (object); } -static const NMDBusInterfaceInfoExtended interface_info_dns_manager = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE_DNS_MANAGER, - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Mode", "s", NM_DNS_MANAGER_MODE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("RcManager", "s", NM_DNS_MANAGER_RC_MANAGER), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Configuration", "aa{sv}", NM_DNS_MANAGER_CONFIGURATION), - ), - ), -}; - static void nm_dns_manager_class_init (NMDnsManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (klass); object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; - dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_STATIC (NM_DBUS_PATH "/DnsManager"); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_dns_manager); - dbus_object_class->export_on_construction = TRUE; + exported_object_class->export_path = NM_DBUS_PATH "/DnsManager"; + exported_object_class->export_on_construction = TRUE; obj_properties[PROP_MODE] = g_param_spec_string (NM_DNS_MANAGER_MODE, "", "", @@ -2148,4 +2024,9 @@ nm_dns_manager_class_init (NMDnsManagerClass *klass) 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DNS_MANAGER_SKELETON, + NULL); } + |