static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMIP4Config *self = NM_IP4_CONFIG (object); NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); switch (prop_id) { case PROP_ADDRESSES: nm_utils_ip4_addresses_to_gvalue (priv->addresses, value); break; case PROP_NAMESERVERS: g_value_set_boxed (value, nm_ip4_config_get_nameservers (self)); break; case PROP_DOMAINS: g_value_set_boxed (value, nm_ip4_config_get_domains (self)); break; case PROP_ROUTES: nm_utils_ip4_routes_to_gvalue (priv->routes, value); break; case PROP_WINS_SERVERS: g_value_set_boxed (value, nm_ip4_config_get_wins_servers (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static GObject* constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params) { NMObject *object; DBusGConnection *connection; NMIP4ConfigPrivate *priv; object = (NMObject *) G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructor (type, n_construct_params, construct_params); if (!object) return NULL; priv = NM_IP4_CONFIG_GET_PRIVATE (object); connection = nm_object_get_connection (object); priv->proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, nm_object_get_path (object), NM_DBUS_INTERFACE_IP4_CONFIG); register_for_property_changed (NM_IP4_CONFIG (object)); return G_OBJECT (object); }
static void constructed (GObject *object) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructed (object); priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_IP4_CONFIG); register_properties (NM_IP4_CONFIG (object)); }
static gboolean demarshal_ip4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); const char *path; NMIP4Config *config = NULL; DBusGConnection *connection; if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) return FALSE; priv->null_ip4_config = FALSE; path = g_value_get_boxed (value); if (path) { if (!strcmp (path, "/")) priv->null_ip4_config = TRUE; else { config = NM_IP4_CONFIG (_nm_object_cache_get (path)); if (config) config = g_object_ref (config); else { connection = nm_object_get_connection (object); config = NM_IP4_CONFIG (nm_ip4_config_new (connection, path)); } } } if (priv->ip4_config) { g_object_unref (priv->ip4_config); priv->ip4_config = NULL; } if (config) priv->ip4_config = config; _nm_object_queue_notify (object, NM_DEVICE_IP4_CONFIG); return TRUE; }
static void constructed (GObject *object) { DBusGConnection *connection; NMIP4ConfigPrivate *priv; G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructed (object); priv = NM_IP4_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_IP4_CONFIG); register_properties (NM_IP4_CONFIG (object)); }
static void ip4_add_domain_search (gpointer data, gpointer user_data) { nm_ip4_config_add_search (NM_IP4_CONFIG (user_data), (const char *) data); }
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 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; }
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; }