示例#1
0
static GObject*
constructor (GType type,
             guint n_construct_params,
             GObjectConstructParam *construct_params)
{
	GObject *object;
	DBusGConnection *connection;
	NMIP6ConfigPrivate *priv;

	object = G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructor (type,
	                                                                   n_construct_params,
	                                                                   construct_params);
	if (!object)
		return NULL;

	priv = NM_IP6_CONFIG_GET_PRIVATE (object);
	connection = nm_object_get_connection (NM_OBJECT (object));

	priv->proxy = dbus_g_proxy_new_for_name (connection,
	                                         NM_DBUS_SERVICE,
	                                         nm_object_get_path (NM_OBJECT (object)),
	                                         NM_DBUS_INTERFACE_IP6_CONFIG);

	register_for_property_changed (NM_IP6_CONFIG (object));

	return object;
}
示例#2
0
static void
get_property (GObject *object,
              guint prop_id,
              GValue *value,
              GParamSpec *pspec)
{
	NMIP6Config *self = NM_IP6_CONFIG (object);
	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);

	_nm_object_ensure_inited (NM_OBJECT (object));

	switch (prop_id) {
	case PROP_GATEWAY:
		g_value_set_string (value, nm_ip6_config_get_gateway (self));
		break;
	case PROP_ADDRESSES:
		nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
		break;
	case PROP_ROUTES:
		nm_utils_ip6_routes_to_gvalue (priv->routes, value);
		break;
	case PROP_NAMESERVERS:
		g_value_set_boxed (value, nm_ip6_config_get_nameservers (self));
		break;
	case PROP_DOMAINS:
		g_value_set_boxed (value, nm_ip6_config_get_domains (self));
		break;
	case PROP_SEARCHES:
		g_value_set_boxed (value, nm_ip6_config_get_searches (self));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
示例#3
0
static void
constructed (GObject *object)
{
	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);

	G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructed (object);

	priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_IP6_CONFIG);
	register_properties (NM_IP6_CONFIG (object));
}
示例#4
0
static gboolean
demarshal_ip6_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
{
	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
	const char *path;
	NMIP6Config *config = NULL;
	DBusGConnection *connection;

	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
		return FALSE;

	priv->null_ip6_config = FALSE;

	path = g_value_get_boxed (value);
	if (path) {
		if (!strcmp (path, "/"))
			priv->null_ip6_config = TRUE;
		else {
			config = NM_IP6_CONFIG (_nm_object_cache_get (path));
			if (config)
				config = g_object_ref (config);
			else {
				connection = nm_object_get_connection (object);
				config = NM_IP6_CONFIG (nm_ip6_config_new (connection, path));
			}
		}
	}

	if (priv->ip6_config) {
		g_object_unref (priv->ip6_config);
		priv->ip6_config = NULL;
	}

	if (config)
		priv->ip6_config = config;

	_nm_object_queue_notify (object, NM_DEVICE_IP6_CONFIG);
	return TRUE;
}
示例#5
0
static void
ip6_add_domain_search (gpointer data, gpointer user_data)
{
	nm_ip6_config_add_search (NM_IP6_CONFIG (user_data), (const char *) data);
}
示例#6
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;
}
示例#7
0
static gboolean
update_dns (NMDnsManager *self,
            const char *iface,
            gboolean no_caching,
            GError **error)
{
    NMDnsManagerPrivate *priv;
    NMResolvConfData rc;
    GSList *iter, *vpn_configs = NULL, *dev_configs = NULL, *other_configs = NULL;
    const char *domain = NULL;
    const char *nis_domain = NULL;
    char **searches = NULL;
    char **nameservers = NULL;
    char **nis_servers = NULL;
    int num, i, len;
    gboolean success = FALSE, caching = FALSE;

    g_return_val_if_fail (error != NULL, FALSE);
    g_return_val_if_fail (*error == NULL, FALSE);

    priv = NM_DNS_MANAGER_GET_PRIVATE (self);

    if (iface && (iface != priv->last_iface)) {
        g_free (priv->last_iface);
        priv->last_iface = g_strdup (iface);
    }

    /* Update hash with config we're applying */
    compute_hash (self, priv->hash);

    rc.nameservers = g_ptr_array_new ();
    rc.domain = NULL;
    rc.searches = g_ptr_array_new ();
    rc.nis_domain = NULL;
    rc.nis_servers = g_ptr_array_new ();

    if (priv->ip4_vpn_config)
        merge_one_ip4_config (&rc, priv->ip4_vpn_config);
    if (priv->ip4_device_config)
        merge_one_ip4_config (&rc, priv->ip4_device_config);

    if (priv->ip6_vpn_config)
        merge_one_ip6_config (&rc, priv->ip6_vpn_config, iface);
    if (priv->ip6_device_config)
        merge_one_ip6_config (&rc, priv->ip6_device_config, iface);

    for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
        if (   (iter->data == priv->ip4_vpn_config)
                || (iter->data == priv->ip4_device_config)
                || (iter->data == priv->ip6_vpn_config)
                || (iter->data == priv->ip6_device_config))
            continue;

        if (NM_IS_IP4_CONFIG (iter->data)) {
            NMIP4Config *config = NM_IP4_CONFIG (iter->data);

            merge_one_ip4_config (&rc, config);
        } else if (NM_IS_IP6_CONFIG (iter->data)) {
            NMIP6Config *config = NM_IP6_CONFIG (iter->data);

            merge_one_ip6_config (&rc, config, iface);
        } else
            g_assert_not_reached ();
    }

    /* Add the current domain name (from the hostname) to the searches list;
     * see rh #600407.  The bug report is that when the hostname is set to
     * something like 'dcbw.foobar.com' (ie an FQDN) that pinging 'dcbw' doesn't
     * work because the resolver doesn't have anything to append to 'dcbw' when
     * looking it up.
     */
    if (priv->hostname) {
        const char *hostsearch = strchr (priv->hostname, '.');

        /* +1 to get rid of the dot */
        if (hostsearch && strlen (hostsearch + 1))
            add_string_item (rc.searches, hostsearch + 1);
    }

    domain = rc.domain;

    /* Per 'man resolv.conf', the search list is limited to 6 domains
     * totalling 256 characters.
     */
    num = MIN (rc.searches->len, 6);
    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);
    if (rc.searches->len) {
        g_ptr_array_add (rc.searches, NULL);
        searches = (char **) g_ptr_array_free (rc.searches, FALSE);
    } else
        g_ptr_array_free (rc.searches, TRUE);

    if (rc.nameservers->len) {
        g_ptr_array_add (rc.nameservers, NULL);
        nameservers = (char **) g_ptr_array_free (rc.nameservers, FALSE);
    } else
        g_ptr_array_free (rc.nameservers, TRUE);

    if (rc.nis_servers->len) {
        g_ptr_array_add (rc.nis_servers, NULL);
        nis_servers = (char **) g_ptr_array_free (rc.nis_servers, FALSE);
    } else
        g_ptr_array_free (rc.nis_servers, TRUE);

    nis_domain = rc.nis_domain;

    /* Build up config lists for plugins; we use the raw configs here, not the
     * merged information that we write to resolv.conf so that the plugins can
     * still use the domain information in each config to provide split DNS if
     * they want to.
     */
    if (priv->ip4_vpn_config)
        vpn_configs = g_slist_append (vpn_configs, priv->ip4_vpn_config);
    if (priv->ip6_vpn_config)
        vpn_configs = g_slist_append (vpn_configs, priv->ip6_vpn_config);
    if (priv->ip4_device_config)
        dev_configs = g_slist_append (dev_configs, priv->ip4_device_config);
    if (priv->ip6_device_config)
        dev_configs = g_slist_append (dev_configs, priv->ip6_device_config);

    for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
        if (   (iter->data != priv->ip4_vpn_config)
                && (iter->data != priv->ip4_device_config)
                && (iter->data != priv->ip6_vpn_config)
                && (iter->data != priv->ip6_device_config))
            other_configs = g_slist_append (other_configs, iter->data);
    }

    /* Let any plugins do their thing first */
    for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
        NMDnsPlugin *plugin = NM_DNS_PLUGIN (iter->data);
        const char *plugin_name = nm_dns_plugin_get_name (plugin);

        if (nm_dns_plugin_is_caching (plugin)) {
            if (no_caching) {
                nm_log_dbg (LOGD_DNS, "DNS: plugin %s ignored (caching disabled)",
                            plugin_name);
                continue;
            }
            caching = TRUE;
        }

        nm_log_dbg (LOGD_DNS, "DNS: updating plugin %s", plugin_name);
        if (!nm_dns_plugin_update (plugin,
                                   vpn_configs,
                                   dev_configs,
                                   other_configs,
                                   priv->hostname,
                                   iface)) {
            nm_log_warn (LOGD_DNS, "DNS: plugin %s update failed", plugin_name);

            /* If the plugin failed to update, we shouldn't write out a local
             * caching DNS configuration to resolv.conf.
             */
            caching = FALSE;
        }
    }
    g_slist_free (vpn_configs);
    g_slist_free (dev_configs);
    g_slist_free (other_configs);

    /* If caching was successful, we only send 127.0.0.1 to /etc/resolv.conf
     * to ensure that the glibc resolver doesn't try to round-robin nameservers,
     * but only uses the local caching nameserver.
     */
    if (caching) {
        if (nameservers)
            g_strfreev (nameservers);
        nameservers = g_new0 (char*, 2);
        nameservers[0] = g_strdup ("127.0.0.1");
    }

#ifdef RESOLVCONF_PATH
    success = dispatch_resolvconf (domain, searches, nameservers, iface, error);
#endif

#ifdef TARGET_SUSE
    if (success == FALSE) {
        success = dispatch_netconfig (domain, searches, nameservers,
                                      nis_domain, nis_servers,
                                      iface, error);
    }
#endif

    if (success == FALSE)
        success = update_resolv_conf (domain, searches, nameservers, iface, error);

    if (success)
        nm_backend_update_dns ();

    if (searches)
        g_strfreev (searches);
    if (nameservers)
        g_strfreev (nameservers);
    if (nis_servers)
        g_strfreev (nis_servers);

    return success;
}
示例#8
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;
}