diff options
Diffstat (limited to 'src/dns')
| -rw-r--r-- | src/dns/nm-dns-dnsmasq.c | 13 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.c | 163 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.h | 6 |
3 files changed, 117 insertions, 65 deletions
diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index b48c6b87..b54df730 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -254,9 +254,16 @@ name_owner_changed (GObject *object, priv->running = TRUE; send_dnsmasq_update (self); } else { - _LOGI ("dnsmasq disappeared"); - priv->running = FALSE; - g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); + if (priv->running) { + _LOGI ("dnsmasq disappeared"); + priv->running = FALSE; + g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); + } else { + /* The only reason for which (!priv->running) here + * is that the dnsmasq process quit. We don't care + * of that here, the manager handles child restarts + * by itself. */ + } } } diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 6a59b41c..aebe3e12 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -55,7 +55,7 @@ #include "nm-dns-systemd-resolved.h" #include "nm-dns-unbound.h" -#define HASH_LEN 20 +#define HASH_LEN NM_UTILS_CHECKSUM_LENGTH_SHA1 #ifndef RESOLVCONF_PATH #define RESOLVCONF_PATH "/sbin/resolvconf" @@ -582,53 +582,85 @@ again: } static char * -create_resolv_conf (char **searches, - char **nameservers, - char **options) +create_resolv_conf (const char *const*searches, + const char *const*nameservers, + const char *const*options) { - gs_free char *searches_str = NULL; - gs_free char *nameservers_str = NULL; - gs_free char *options_str = NULL; - char *tmp_str; GString *str; - int i; + gsize i; - if (searches) { - tmp_str = g_strjoinv (" ", searches); - searches_str = g_strconcat ("search ", tmp_str, "\n", NULL); - g_free (tmp_str); - } + str = g_string_new_len (NULL, 245); - if (options) { - tmp_str = g_strjoinv (" ", options); - options_str = g_strconcat ("options ", tmp_str, "\n", NULL); - g_free (tmp_str); - } + g_string_append (str, "# Generated by NetworkManager\n"); - if (nameservers) { - int num = g_strv_length (nameservers); + if (searches && searches[0]) { + gsize search_base_idx; - str = g_string_new (""); - for (i = 0; i < num; i++) { - if (i == 3) { - g_string_append (str, "# "); - g_string_append (str, "NOTE: the libc resolver may not support more than 3 nameservers."); - g_string_append (str, "\n# "); - g_string_append (str, "The nameservers listed below may not be recognized."); - g_string_append_c (str, '\n'); + g_string_append (str, "search"); + search_base_idx = str->len; + + for (i = 0; searches[i]; i++) { + const char *s = searches[i]; + gsize l = strlen (s); + + if ( l == 0 + || NM_STRCHAR_ANY (s, ch, NM_IN_SET (ch, ' ', '\t', '\n'))) { + /* there should be no such characters in the search entry. Also, + * because glibc parser would treat them as line/word separator. + * + * Skip the value silently. */ + continue; } + if (search_base_idx > 0) { + if (str->len - search_base_idx + 1 + l > 254) { + /* this entry crosses the 256 character boundery. Older glibc versions + * would truncate the entry at this point. + * + * Fill the line with spaces to cross the 256 char boundary and continue + * afterwards. This way, the truncation happens between two search entries. */ + while (str->len - search_base_idx < 257) + g_string_append_c (str, ' '); + search_base_idx = 0; + } + } + + g_string_append_c (str, ' '); + g_string_append_len (str, s, l); + } + g_string_append_c (str, '\n'); + } + + if (nameservers && nameservers[0]) { + for (i = 0; nameservers[i]; i++) { + if (i == 3) { + g_string_append (str, "# NOTE: the libc resolver may not support more than 3 nameservers.\n"); + g_string_append (str, "# The nameservers listed below may not be recognized.\n"); + } g_string_append (str, "nameserver "); g_string_append (str, nameservers[i]); g_string_append_c (str, '\n'); } - nameservers_str = g_string_free (str, FALSE); } - return g_strdup_printf ("# Generated by NetworkManager\n%s%s%s", - searches_str ?: "", - nameservers_str ?: "", - options_str ?: ""); + if (options && options[0]) { + g_string_append (str, "options"); + for (i = 0; options[i]; i++) { + g_string_append_c (str, ' '); + g_string_append (str, options[i]); + } + g_string_append_c (str, '\n'); + } + + return g_string_free (str, FALSE); +} + +char * +nmtst_dns_create_resolv_conf (const char *const*searches, + const char *const*nameservers, + const char *const*options) +{ + return create_resolv_conf (searches, nameservers, options); } static gboolean @@ -654,9 +686,9 @@ write_resolv_conf_contents (FILE *f, static gboolean write_resolv_conf (FILE *f, - char **searches, - char **nameservers, - char **options, + const char *const*searches, + const char *const*nameservers, + const char *const*options, GError **error) { gs_free char *content = NULL; @@ -718,7 +750,11 @@ dispatch_resolvconf (NMDnsManager *self, return SR_ERROR; } - success = write_resolv_conf (f, searches, nameservers, options, error); + success = write_resolv_conf (f, + NM_CAST_STRV_CC (searches), + NM_CAST_STRV_CC (nameservers), + NM_CAST_STRV_CC (options), + error); err = pclose (f); if (err < 0) { errnosv = errno; @@ -757,9 +793,9 @@ _read_link_cached (const char *path, gboolean *is_cached, char **cached) static SpawnResult update_resolv_conf (NMDnsManager *self, - char **searches, - char **nameservers, - char **options, + const char *const*searches, + const char *const*nameservers, + const char *const*options, GError **error, NMDnsManagerResolvConfManager rc_manager) { @@ -958,12 +994,11 @@ update_resolv_conf (NMDnsManager *self, static void compute_hash (NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[HASH_LEN]) { - GChecksum *sum; - gsize len = HASH_LEN; + nm_auto_free_checksum GChecksum *sum = NULL; NMDnsIPConfigData *ip_data; sum = g_checksum_new (G_CHECKSUM_SHA1); - nm_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); + nm_assert (HASH_LEN == g_checksum_type_get_length (G_CHECKSUM_SHA1)); if (global) nm_global_dns_config_update_checksum (global, sum); @@ -977,8 +1012,7 @@ compute_hash (NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer nm_ip_config_hash (ip_data->ip_config, sum, TRUE); } - g_checksum_get_digest (sum, buffer, &len); - g_checksum_free (sum); + nm_utils_checksum_get_digest_len (sum, buffer, HASH_LEN); } static gboolean @@ -1066,7 +1100,6 @@ _collect_resolv_conf_data (NMDnsManager *self, const char **out_nis_domain) { NMDnsManagerPrivate *priv; - guint i, num, len; NMResolvConfData rc = { .nameservers = g_ptr_array_new (), .searches = g_ptr_array_new (), @@ -1136,17 +1169,6 @@ _collect_resolv_conf_data (NMDnsManager *self, } } - /* Per 'man resolv.conf', the search list is limited to 6 domains - * totalling 256 characters. - */ - num = MIN (rc.searches->len, 6u); - for (i = 0, len = 0; i < num; i++) { - len += strlen (rc.searches->pdata[i]) + 1; /* +1 for spaces */ - if (len > 256) - break; - } - g_ptr_array_set_size (rc.searches, i); - *out_searches = _ptrarray_to_strv (rc.searches); *out_options = _ptrarray_to_strv (rc.options); *out_nameservers = _ptrarray_to_strv (rc.nameservers); @@ -1449,7 +1471,12 @@ update_dns (NMDnsManager *self, switch (priv->rc_manager) { case NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: - result = update_resolv_conf (self, searches, nameservers, options, error, priv->rc_manager); + result = update_resolv_conf (self, + NM_CAST_STRV_CC (searches), + NM_CAST_STRV_CC (nameservers), + NM_CAST_STRV_CC (options), + error, + priv->rc_manager); resolv_conf_updated = TRUE; /* If we have ended with no nameservers avoid updating again resolv.conf * on stop, as some external changes may be applied to it in the meanwhile */ @@ -1474,15 +1501,26 @@ update_dns (NMDnsManager *self, if (result == SR_NOTFOUND) { _LOGD ("update-dns: program not available, writing to resolv.conf"); g_clear_error (error); - result = update_resolv_conf (self, searches, nameservers, options, error, NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK); + result = update_resolv_conf (self, + NM_CAST_STRV_CC (searches), + NM_CAST_STRV_CC (nameservers), + NM_CAST_STRV_CC (options), + error, + NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK); resolv_conf_updated = TRUE; } } /* Unless we've already done it, update private resolv.conf in NMRUNDIR ignoring any errors */ - if (!resolv_conf_updated) - update_resolv_conf (self, searches, nameservers, options, NULL, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED); + if (!resolv_conf_updated) { + update_resolv_conf (self, + NM_CAST_STRV_CC (searches), + NM_CAST_STRV_CC (nameservers), + NM_CAST_STRV_CC (options), + NULL, + NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED); + } /* signal that resolv.conf was changed */ if (update && result == SR_SUCCESS) @@ -1542,6 +1580,7 @@ plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data) } else { priv->plugin_ratelimit.num_restarts++; if (priv->plugin_ratelimit.num_restarts > PLUGIN_RATELIMIT_BURST) { + plugin_failed (plugin, self); _LOGW ("plugin %s child respawning too fast, delaying update for %u seconds", nm_dns_plugin_get_name (plugin), PLUGIN_RATELIMIT_DELAY); priv->plugin_ratelimit.timer = g_timeout_add_seconds (PLUGIN_RATELIMIT_DELAY, diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h index ed1974a5..a3e9472e 100644 --- a/src/dns/nm-dns-manager.h +++ b/src/dns/nm-dns-manager.h @@ -129,4 +129,10 @@ typedef enum { void nm_dns_manager_stop (NMDnsManager *self); +/*****************************************************************************/ + +char *nmtst_dns_create_resolv_conf (const char *const*searches, + const char *const*nameservers, + const char *const*options); + #endif /* __NETWORKMANAGER_DNS_MANAGER_H__ */ |