static gboolean update (NMDnsPlugin *plugin, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, const NMGlobalDnsConfig *global_config, const char *hostname) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); const char *dm_binary; GString *conf; GSList *iter; const char *argv[15]; GError *error = NULL; int ignored; GPid pid = 0; guint idx = 0; /* Kill the old dnsmasq; there doesn't appear to be a way to get dnsmasq * to reread the config file using SIGHUP or similar. This is a small race * here when restarting dnsmasq when DNS requests could go to the upstream * servers instead of to dnsmasq. */ nm_dns_plugin_child_kill (plugin); dm_binary = nm_utils_find_helper ("dnsmasq", DNSMASQ_PATH, NULL); if (!dm_binary) { nm_log_warn (LOGD_DNS, "Could not find dnsmasq binary"); return FALSE; } /* Build up the new dnsmasq config file */ conf = g_string_sized_new (150); if (global_config) add_global_config (conf, global_config); else { /* Use split DNS for VPN configs */ for (iter = (GSList *) vpn_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), TRUE); else if (NM_IS_IP6_CONFIG (iter->data)) add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE); } /* Now add interface configs without split DNS */ for (iter = (GSList *) dev_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); } /* And any other random configs */ for (iter = (GSList *) other_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); } } /* Write out the config file */ if (!g_file_set_contents (CONFFILE, conf->str, -1, &error)) { nm_log_warn (LOGD_DNS, "Failed to write dnsmasq config file %s: (%d) %s", CONFFILE, error ? error->code : -1, error && error->message ? error->message : "(unknown)"); g_clear_error (&error); goto out; } ignored = chmod (CONFFILE, 0644); nm_log_dbg (LOGD_DNS, "dnsmasq local caching DNS configuration:"); nm_log_dbg (LOGD_DNS, "%s", conf->str); argv[idx++] = dm_binary; argv[idx++] = "--no-resolv"; /* Use only commandline */ argv[idx++] = "--keep-in-foreground"; argv[idx++] = "--no-hosts"; /* don't use /etc/hosts to resolve */ argv[idx++] = "--bind-interfaces"; argv[idx++] = "--pid-file=" PIDFILE; argv[idx++] = "--listen-address=127.0.0.1"; /* Should work for both 4 and 6 */ argv[idx++] = "--conf-file=" CONFFILE; argv[idx++] = "--cache-size=400"; argv[idx++] = "--proxy-dnssec"; /* Allow DNSSEC to pass through */ /* dnsmasq exits if the conf dir is not present */ if (g_file_test (CONFDIR, G_FILE_TEST_IS_DIR)) argv[idx++] = "--conf-dir=" CONFDIR; argv[idx++] = NULL; g_warn_if_fail (idx <= G_N_ELEMENTS (argv)); /* And finally spawn dnsmasq */ pid = nm_dns_plugin_child_spawn (NM_DNS_PLUGIN (self), argv, PIDFILE, "bin/dnsmasq"); out: g_string_free (conf, TRUE); return pid ? TRUE : FALSE; }
static gboolean update (NMDnsPlugin *plugin, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, const char *hostname, const char *iface) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); GString *conf; GSList *iter; const char *argv[11]; GError *error = NULL; int ignored; GPid pid = 0; /* Kill the old dnsmasq; there doesn't appear to be a way to get dnsmasq * to reread the config file using SIGHUP or similar. This is a small race * here when restarting dnsmasq when DNS requests could go to the upstream * servers instead of to dnsmasq. */ nm_dns_plugin_child_kill (plugin); /* Build up the new dnsmasq config file */ conf = g_string_sized_new (150); /* Use split DNS for VPN configs */ for (iter = (GSList *) vpn_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), TRUE); else if (NM_IS_IP6_CONFIG (iter->data)) add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE, iface); } /* Now add interface configs without split DNS */ for (iter = (GSList *) dev_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE, iface); } /* And any other random configs */ for (iter = (GSList *) other_configs; iter; iter = g_slist_next (iter)) { if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE, iface); } /* Write out the config file */ if (!g_file_set_contents (CONFFILE, conf->str, -1, &error)) { nm_log_warn (LOGD_DNS, "Failed to write dnsmasq config file %s: (%d) %s", CONFFILE, error ? error->code : -1, error && error->message ? error->message : "(unknown)"); g_clear_error (&error); goto out; } ignored = chmod (CONFFILE, 0600); nm_log_dbg (LOGD_DNS, "dnsmasq local caching DNS configuration:"); nm_log_dbg (LOGD_DNS, "%s", conf->str); argv[0] = find_dnsmasq (); argv[1] = "--no-resolv"; /* Use only commandline */ argv[2] = "--keep-in-foreground"; argv[3] = "--strict-order"; argv[4] = "--bind-interfaces"; argv[5] = "--pid-file=" PIDFILE; argv[6] = "--listen-address=127.0.0.1"; /* Should work for both 4 and 6 */ argv[7] = "--conf-file=" CONFFILE; argv[8] = "--cache-size=400"; argv[9] = NULL; /* And finally spawn dnsmasq */ pid = nm_dns_plugin_child_spawn (NM_DNS_PLUGIN (self), argv, PIDFILE, "bin/dnsmasq"); out: g_string_free (conf, TRUE); return pid ? TRUE : FALSE; }
static void start_dnsmasq (NMDnsDnsmasq *self) { NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); const char *dm_binary; const char *argv[15]; GPid pid = 0; guint idx = 0; NMBusManager *dbus_mgr; GDBusConnection *connection; if (priv->running) { /* the dnsmasq process is running. Nothing to do. */ return; } if (nm_dns_plugin_child_pid ((NMDnsPlugin *) self) > 0) { /* if we already have a child process spawned, don't do * it again. */ return; } dm_binary = nm_utils_find_helper ("dnsmasq", DNSMASQ_PATH, NULL); if (!dm_binary) { _LOGW ("could not find dnsmasq binary"); return; } argv[idx++] = dm_binary; argv[idx++] = "--no-resolv"; /* Use only commandline */ argv[idx++] = "--keep-in-foreground"; argv[idx++] = "--no-hosts"; /* don't use /etc/hosts to resolve */ argv[idx++] = "--bind-interfaces"; argv[idx++] = "--pid-file=" PIDFILE; argv[idx++] = "--listen-address=127.0.0.1"; /* Should work for both 4 and 6 */ argv[idx++] = "--cache-size=400"; argv[idx++] = "--conf-file=/dev/null"; /* avoid loading /etc/dnsmasq.conf */ argv[idx++] = "--proxy-dnssec"; /* Allow DNSSEC to pass through */ argv[idx++] = "--enable-dbus=" DNSMASQ_DBUS_SERVICE; /* dnsmasq exits if the conf dir is not present */ if (g_file_test (CONFDIR, G_FILE_TEST_IS_DIR)) argv[idx++] = "--conf-dir=" CONFDIR; argv[idx++] = NULL; nm_assert (idx <= G_N_ELEMENTS (argv)); /* And finally spawn dnsmasq */ pid = nm_dns_plugin_child_spawn (NM_DNS_PLUGIN (self), argv, PIDFILE, "bin/dnsmasq"); if (!pid) return; if ( priv->dnsmasq || priv->dnsmasq_cancellable) { /* we already have a proxy or are about to create it. * We are done. */ return; } dbus_mgr = nm_bus_manager_get (); g_return_if_fail (dbus_mgr); connection = nm_bus_manager_get_connection (dbus_mgr); g_return_if_fail (connection); priv->dnsmasq_cancellable = g_cancellable_new (); g_dbus_proxy_new (connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, DNSMASQ_DBUS_SERVICE, DNSMASQ_DBUS_PATH, DNSMASQ_DBUS_SERVICE, priv->dnsmasq_cancellable, dnsmasq_proxy_cb, self); }