Exemplo n.º 1
0
static void
child_quit (NMDnsPlugin *plugin, gint status)
{
	NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
	NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);
	gboolean failed = TRUE;
	int err;

	if (WIFEXITED (status)) {
		err = WEXITSTATUS (status);
		if (err) {
			_LOGW ("dnsmasq exited with error: %s",
			       nm_utils_dnsmasq_status_to_string (err, NULL, 0));
		} else {
			_LOGD ("dnsmasq exited normally");
			failed = FALSE;
		}
	} else if (WIFSTOPPED (status))
		_LOGW ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status));
	else if (WIFSIGNALED (status))
		_LOGW ("dnsmasq died with signal %d", WTERMSIG (status));
	else
		_LOGW ("dnsmasq died from an unknown cause");

	priv->running = FALSE;

	if (failed)
		g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED);
}
Exemplo n.º 2
0
static void
child_quit (NMDnsPlugin *plugin, gint status)
{
	NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
	gboolean failed = TRUE;
	int err;

	if (WIFEXITED (status)) {
		err = WEXITSTATUS (status);
		if (err) {
			nm_log_warn (LOGD_DNS, "dnsmasq exited with error: %s (%d)",
			             dm_exit_code_to_msg (err),
			             err);
		} else
			failed = FALSE;
	} else if (WIFSTOPPED (status)) {
		nm_log_warn (LOGD_DNS, "dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status));
	} else if (WIFSIGNALED (status)) {
		nm_log_warn (LOGD_DNS, "dnsmasq died with signal %d", WTERMSIG (status));
	} else {
		nm_log_warn (LOGD_DNS, "dnsmasq died from an unknown cause");
	}
	unlink (CONFFILE);

	if (failed)
		g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED);
}
Exemplo n.º 3
0
static gboolean
update (NMDnsPlugin *plugin,
        const NMDnsIPConfigData **configs,
        const NMGlobalDnsConfig *global_config,
        const char *hostname)
{
	NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
	NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);
	GVariantBuilder servers;

	start_dnsmasq (self);

	g_variant_builder_init (&servers, G_VARIANT_TYPE ("aas"));

	if (global_config)
		add_global_config (self, &servers, global_config);
	else {
		while (*configs) {
			add_ip_config_data (self, &servers, *configs);
			configs++;
		}
	}

	g_clear_pointer (&priv->set_server_ex_args, g_variant_unref);
	priv->set_server_ex_args = g_variant_ref_sink (g_variant_new ("(aas)", &servers));

	send_dnsmasq_update (self);

	return TRUE;
}
Exemplo n.º 4
0
static void
dnsmasq_update_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
{
	NMDnsDnsmasq *self;
	NMDnsDnsmasqPrivate *priv;
	gs_free_error GError *error = NULL;
	gs_unref_variant GVariant *response = NULL;

	response = g_dbus_proxy_call_finish (proxy, res, &error);
	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		return;

	self = NM_DNS_DNSMASQ (user_data);
	priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);

	if (!response)
		_LOGW ("dnsmasq update failed: %s", error->message);
	else {
		g_dbus_proxy_call (priv->dnsmasq,
		                   "ClearCache",
		                   NULL,
		                   G_DBUS_CALL_FLAGS_NONE,
		                   -1,
		                   priv->update_cancellable,
		                   (GAsyncReadyCallback) dnsmasq_clear_cache_done,
		                   self);
	}
}
Exemplo n.º 5
0
static void
dnsmasq_clear_cache_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
{
	NMDnsDnsmasq *self;
	gs_free_error GError *error = NULL;
	gs_unref_variant GVariant *response = NULL;

	response = g_dbus_proxy_call_finish (proxy, res, &error);
	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		return;

	self = NM_DNS_DNSMASQ (user_data);

	if (!response)
		_LOGW ("dnsmasq cache clear failed: %s", error->message);
	else
		_LOGD ("dnsmasq update successful, cache cleared");
}
Exemplo n.º 6
0
static void
name_owner_changed (GObject    *object,
                    GParamSpec *pspec,
                    gpointer    user_data)
{
	NMDnsDnsmasq *self = NM_DNS_DNSMASQ (user_data);
	NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);
	gs_free char *owner = NULL;

	owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object));
	if (owner) {
		_LOGI ("dnsmasq appeared as %s", owner);
		priv->running = TRUE;
		send_dnsmasq_update (self);
	} else {
		_LOGI ("dnsmasq disappeared");
		priv->running = FALSE;
		g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED);
	}
}
Exemplo n.º 7
0
static void
dnsmasq_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data)
{
	NMDnsDnsmasq *self;
	NMDnsDnsmasqPrivate *priv;
	gs_free_error GError *error = NULL;
	gs_free char *owner = NULL;
	GDBusProxy *proxy;

	proxy = g_dbus_proxy_new_finish (res, &error);
	if (   !proxy
	    && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
		return;

	self = NM_DNS_DNSMASQ (user_data);

	if (!proxy) {
		_LOGW ("failed to connect to dnsmasq via DBus: %s", error->message);
		g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED);
		return;
	}

	priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);

	priv->dnsmasq = proxy;
	nm_clear_g_cancellable (&priv->dnsmasq_cancellable);

	_LOGD ("dnsmasq proxy creation successful");

	g_signal_connect (priv->dnsmasq, "notify::g-name-owner",
	                  G_CALLBACK (name_owner_changed), self);
	owner = g_dbus_proxy_get_name_owner (priv->dnsmasq);
	priv->running = (owner != NULL);

	if (priv->running)
		send_dnsmasq_update (self);
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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;
}