Beispiel #1
0
static const gchar*
_ifupdownplugin_guess_connection_type (if_block *block)
{
	if_data *curr = block->info;
	const gchar* ret_type = NULL;
	const gchar* value = ifparser_getkey(block, "inet");
	if(value && !strcmp("ppp", value)) {
		ret_type = NM_SETTING_PPP_SETTING_NAME;
	}

	while(!ret_type && curr) {
		if(!strncmp("wireless-", curr->key, strlen("wireless-")) ||
		   !strncmp("wpa-", curr->key, strlen("wpa-"))) {
			ret_type = NM_SETTING_WIRELESS_SETTING_NAME;
		}
		curr = curr->next;
	}

	if(!ret_type)
		ret_type = NM_SETTING_WIRED_SETTING_NAME;

	nm_log_info (LOGD_SETTINGS, "guessed connection type (%s) = %s", block->name, ret_type);
	return ret_type;
}
Beispiel #2
0
static void
init (NMSettingsPlugin *config)
{
	SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (config);
	SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self);
	GHashTable *auto_ifaces;
	if_block *block = NULL;
	GList *keys, *iter;
	GHashTableIter con_iter;
	const char *block_name;
	NMIfupdownConnection *connection;
	const char *subsys[2] = { "net", NULL };

	auto_ifaces = g_hash_table_new (g_str_hash, g_str_equal);

	if(!priv->connections)
		priv->connections = g_hash_table_new (g_str_hash, g_str_equal);

	if(!priv->kernel_ifaces)
		priv->kernel_ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);

	if(!priv->eni_ifaces)
		priv->eni_ifaces = g_hash_table_new (g_str_hash, g_str_equal);

	nm_log_info (LOGD_SETTINGS, "init!");

	priv->client = g_udev_client_new (subsys);
	if (!priv->client) {
		nm_log_warn (LOGD_SETTINGS, "    error initializing libgudev");
	} else
		g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self);

	/* Read in all the interfaces */
	ifparser_init (ENI_INTERFACES_FILE, 0);
	block = ifparser_getfirst ();
	while (block) {
		if(!strcmp ("auto", block->type) || !strcmp ("allow-hotplug", block->type))
			g_hash_table_insert (auto_ifaces, block->name, GUINT_TO_POINTER (1));
		else if (!strcmp ("iface", block->type)) {
			NMIfupdownConnection *exported;

			/* Bridge configuration */
			if(!strncmp ("br", block->name, 2)) {
				/* Try to find bridge ports */
				const char *ports = ifparser_getkey (block, "bridge-ports");
				if (ports) {
					int i;
					int state = 0;
					char **port_ifaces;

					nm_log_info (LOGD_SETTINGS, "found bridge ports %s for %s", ports, block->name);

					port_ifaces = g_strsplit_set (ports, " \t", -1);
					for (i = 0; i < g_strv_length (port_ifaces); i++) {
						char *token = port_ifaces[i];
						/* Skip crazy stuff like regex or all */
						if (!strcmp ("all", token)) {
							continue;
						}
						/* Small SM to skip everything inside regex */
						if (!strcmp ("regex", token)) {
							state++;
							continue;
						}
						if (!strcmp ("noregex", token)) {
							state--;
							continue;
						}
						if (state == 0 && strlen (token) > 0) {
							nm_log_info (LOGD_SETTINGS, "adding bridge port %s to eni_ifaces", token);
							g_hash_table_insert (priv->eni_ifaces, g_strdup (token), "known");
						}
					}
					g_strfreev (port_ifaces);
				}
				goto next;
			}

			/* Skip loopback configuration */
			if(!strcmp ("lo", block->name)) {
				goto next;
			}

			/* Remove any connection for this block that was previously found */
			exported = g_hash_table_lookup (priv->connections, block->name);
			if (exported) {
				nm_log_info (LOGD_SETTINGS, "deleting %s from connections", block->name);
				nm_settings_connection_delete (NM_SETTINGS_CONNECTION (exported), NULL, NULL);
				g_hash_table_remove (priv->connections, block->name);
			}

			/* add the new connection */
			exported = nm_ifupdown_connection_new (block);
			if (exported) {
				nm_log_info (LOGD_SETTINGS, "adding %s to connections", block->name);
				g_hash_table_insert (priv->connections, block->name, exported);
			}
			nm_log_info (LOGD_SETTINGS, "adding iface %s to eni_ifaces", block->name);
			g_hash_table_insert (priv->eni_ifaces, block->name, "known");
		} else if (!strcmp ("mapping", block->type)) {
			g_hash_table_insert (priv->eni_ifaces, block->name, "known");
			nm_log_info (LOGD_SETTINGS, "adding mapping %s to eni_ifaces", block->name);
		}
	next:
		block = block->next;
	}

	/* Make 'auto' interfaces autoconnect=TRUE */
	g_hash_table_iter_init (&con_iter, priv->connections);
	while (g_hash_table_iter_next (&con_iter, (gpointer) &block_name, (gpointer) &connection)) {
		NMSettingConnection *setting;

		if (g_hash_table_lookup (auto_ifaces, block_name)) {
			setting = nm_connection_get_setting_connection (NM_CONNECTION (connection));
			g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL);
			nm_log_info (LOGD_SETTINGS, "autoconnect");
		}
	}
	g_hash_table_destroy (auto_ifaces);

	/* Check the config file to find out whether to manage interfaces */
	priv->unmanage_well_known = !nm_config_data_get_value_boolean (NM_CONFIG_GET_DATA_ORIG,
	                                                               NM_CONFIG_KEYFILE_GROUP_IFUPDOWN,
	                                                               NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED,
	                                                               !IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT);
	nm_log_info (LOGD_SETTINGS, "management mode: %s", priv->unmanage_well_known ? "unmanaged" : "managed");

	/* Add well-known interfaces */
	keys = g_udev_client_query_by_subsystem (priv->client, "net");
	for (iter = keys; iter; iter = g_list_next (iter)) {
		udev_device_added (self, G_UDEV_DEVICE (iter->data));
		g_object_unref (G_UDEV_DEVICE (iter->data));
	}
	g_list_free (keys);

	/* Now if we're running in managed mode, let NM know there are new connections */
	if (!priv->unmanage_well_known) {
		GList *con_list = g_hash_table_get_values (priv->connections);
		GList *cl_iter;

		for (cl_iter = con_list; cl_iter; cl_iter = g_list_next (cl_iter)) {
			g_signal_emit_by_name (self,
			                       NM_SETTINGS_PLUGIN_CONNECTION_ADDED,
			                       NM_SETTINGS_CONNECTION (cl_iter->data));
		}
		g_list_free (con_list);
	}

	nm_log_info (LOGD_SETTINGS, "end _init.");
}
Beispiel #3
0
static void
update_wireless_setting_from_if_block(NMConnection *connection,
							   if_block *block)
{
	gint wpa_l= strlen("wpa-");
	gint wireless_l= strlen("wireless-");

	if_data *curr = block->info;
	const gchar* value = ifparser_getkey (block, "inet");
	struct _Mapping mapping[] = {
		{"ssid", "ssid"},
		{"essid", "ssid"},
		{"mode", "mode"},
		{ NULL, NULL}
	};

	NMSettingWireless *wireless_setting = NULL;

	if(value && !strcmp("ppp", value)) {
		return;
	}

	nm_log_info (LOGD_SETTINGS, "update wireless settings (%s).", block->name);
	wireless_setting = NM_SETTING_WIRELESS(nm_setting_wireless_new());

	while(curr) {
		if(strlen(curr->key) > wireless_l &&
		   !strncmp("wireless-", curr->key, wireless_l)) {
			const gchar* newkey = map_by_mapping(mapping, curr->key+wireless_l);
			nm_log_info (LOGD_SETTINGS, "wireless setting key: %s='%s'", newkey, curr->data);
			if(newkey && !strcmp("ssid", newkey)) {
				GBytes *ssid;
				gint len = strlen(curr->data);

				ssid = g_bytes_new (curr->data, len);
				g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL);
				g_bytes_unref (ssid);
				nm_log_info (LOGD_SETTINGS, "setting wireless ssid = %d", len);
			} else if(newkey && !strcmp("mode", newkey)) {
				if (!g_ascii_strcasecmp (curr->data, "Managed") || !g_ascii_strcasecmp (curr->data, "Auto"))
					g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, NULL);
				else if (!g_ascii_strcasecmp (curr->data, "Ad-Hoc"))
					g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_ADHOC, NULL);
				else if (!g_ascii_strcasecmp (curr->data, "Master"))
					g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_AP, NULL);
				else
					nm_log_warn (LOGD_SETTINGS, "Invalid mode '%s' (not 'Ad-Hoc', 'Ap', 'Managed', or 'Auto')", curr->data);
			} else {
				g_object_set(wireless_setting,
					   newkey, curr->data,
					   NULL);
			}
		} else if(strlen(curr->key) > wpa_l &&
				!strncmp("wpa-", curr->key, wpa_l)) {
			const gchar* newkey = map_by_mapping(mapping, curr->key+wpa_l);

			if(newkey && !strcmp("ssid", newkey)) {
				GBytes *ssid;
				gint len = strlen(curr->data);

				ssid = g_bytes_new (curr->data, len);
				g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL);
				g_bytes_unref (ssid);
				nm_log_info (LOGD_SETTINGS, "setting wpa ssid = %d", len);
			} else if(newkey) {

				g_object_set(wireless_setting,
						   newkey, curr->data,
						   NULL);
				nm_log_info (LOGD_SETTINGS, "setting wpa newkey(%s)=data(%s)", newkey, curr->data);
			}
		}
		curr = curr->next;
	}
	nm_connection_add_setting(connection, (NMSetting*) wireless_setting);
}
Beispiel #4
0
static gboolean
update_ip6_setting_from_if_block(NMConnection *connection,
						   if_block *block,
						   GError **error)
{
	NMSettingIPConfig *s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new());
	const char *type = ifparser_getkey(block, "inet6");
	gboolean is_static = type && (!strcmp("static", type) ||
							!strcmp("v4tunnel", type));

	if (!is_static) {
		g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
	} else {
		NMIPAddress *addr;
		const char *address_v;
		const char *prefix_v;
		const char *gateway_v;
		const char *nameserver_v;
		const char *nameservers_v;
		const char *search_v;
		int prefix_int = 128;
		char **list, **iter;

		/* Address */
		address_v = ifparser_getkey(block, "address");
		if (!address_v) {
			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
			             "Missing IPv6 address");
			goto error;
		}

		/* Prefix */
		prefix_v = ifparser_getkey(block, "netmask");
		if (prefix_v)
			prefix_int = g_ascii_strtoll (prefix_v, NULL, 10);

		/* Add the new address to the setting */
		addr = nm_ip_address_new (AF_INET6, address_v, prefix_int, error);
		if (!addr)
			goto error;

		if (nm_setting_ip_config_add_address (s_ip6, addr)) {
			nm_log_info (LOGD_SETTINGS, "addresses count: %d",
			             nm_setting_ip_config_get_num_addresses (s_ip6));
		} else {
			nm_log_info (LOGD_SETTINGS, "ignoring duplicate IP6 address");
		}
		nm_ip_address_unref (addr);

		/* gateway */
		gateway_v = ifparser_getkey (block, "gateway");
		if (gateway_v) {
			if (!nm_utils_ipaddr_valid (AF_INET6, gateway_v)) {
				g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
				             "Invalid IPv6 gateway '%s'", gateway_v);
				goto error;
			}
			if (!nm_setting_ip_config_get_gateway (s_ip6))
				g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL);
		}

		nameserver_v = ifparser_getkey(block, "dns-nameserver");
		ifupdown_ip6_add_dns (s_ip6, nameserver_v);

		nameservers_v = ifparser_getkey(block, "dns-nameservers");
		ifupdown_ip6_add_dns (s_ip6, nameservers_v);

		if (!nm_setting_ip_config_get_num_dns (s_ip6))
			nm_log_info (LOGD_SETTINGS, "No dns-nameserver configured in /etc/network/interfaces");

		/* DNS searches */
		search_v = ifparser_getkey (block, "dns-search");
		if (search_v) {
			list = g_strsplit_set (search_v, " \t", -1);
			for (iter = list; iter && *iter; iter++) {
				g_strstrip (*iter);
				if (isblank (*iter[0]))
					continue;
				if (!nm_setting_ip_config_add_dns_search (s_ip6, *iter))
					nm_log_warn (LOGD_SETTINGS, "    duplicate DNS domain '%s'", *iter);
			}
			g_strfreev (list);
		}

		g_object_set (s_ip6,
		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
		              NULL);
	}

	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
	return TRUE;

error:
	g_object_unref (s_ip6);
	return FALSE;
}
Beispiel #5
0
static gboolean
update_ip4_setting_from_if_block(NMConnection *connection,
						   if_block *block,
						   GError **error)
{

	NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new());
	const char *type = ifparser_getkey(block, "inet");
	gboolean is_static = type && !strcmp("static", type);

	if (!is_static) {
		g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
	} else {
		guint32 tmp_mask;
		NMIPAddress *addr;
		const char *address_v;
		const char *netmask_v;
		const char *gateway_v;
		const char *nameserver_v;
		const char *nameservers_v;
		const char *search_v;
		char **list, **iter;
		guint32 netmask_int = 32;

		/* Address */
		address_v = ifparser_getkey (block, "address");
		if (!address_v) {
			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
			             "Missing IPv4 address");
			goto error;
		}

		/* mask/prefix */
		netmask_v = ifparser_getkey (block, "netmask");
		if (netmask_v) {
			if (strlen (netmask_v) < 7) {
				netmask_int = atoi (netmask_v);
			} else if (!inet_pton (AF_INET, netmask_v, &tmp_mask)) {
				g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
						   "Invalid IPv4 netmask '%s'", netmask_v);
				goto error;
			} else {
				netmask_int = nm_utils_ip4_netmask_to_prefix (tmp_mask);
			}
		}

		/* Add the new address to the setting */
		addr = nm_ip_address_new (AF_INET, address_v, netmask_int, error);
		if (!addr)
			goto error;

		if (nm_setting_ip_config_add_address (s_ip4, addr)) {
			nm_log_info (LOGD_SETTINGS, "addresses count: %d",
			             nm_setting_ip_config_get_num_addresses (s_ip4));
		} else {
			nm_log_info (LOGD_SETTINGS, "ignoring duplicate IP4 address");
		}
		nm_ip_address_unref (addr);

		/* gateway */
		gateway_v = ifparser_getkey (block, "gateway");
		if (gateway_v) {
			if (!nm_utils_ipaddr_valid (AF_INET, gateway_v)) {
				g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
				             "Invalid IPv4 gateway '%s'", gateway_v);
				goto error;
			}
			if (!nm_setting_ip_config_get_gateway (s_ip4))
				g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL);
		}

		nameserver_v = ifparser_getkey (block, "dns-nameserver");
		ifupdown_ip4_add_dns (s_ip4, nameserver_v);

		nameservers_v = ifparser_getkey (block, "dns-nameservers");
		ifupdown_ip4_add_dns (s_ip4, nameservers_v);

		if (!nm_setting_ip_config_get_num_dns (s_ip4))
			nm_log_info (LOGD_SETTINGS, "No dns-nameserver configured in /etc/network/interfaces");

		/* DNS searches */
		search_v = ifparser_getkey (block, "dns-search");
		if (search_v) {
			list = g_strsplit_set (search_v, " \t", -1);
			for (iter = list; iter && *iter; iter++) {
				g_strstrip (*iter);
				if (g_ascii_isspace (*iter[0]))
					continue;
				if (!nm_setting_ip_config_add_dns_search (s_ip4, *iter))
					nm_log_warn (LOGD_SETTINGS, "    duplicate DNS domain '%s'", *iter);
			}
			g_strfreev (list);
		}

		g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
	}

	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
	return TRUE;

error:
	g_object_unref (s_ip4);
	return FALSE;
}
Beispiel #6
0
static void
update_wireless_security_setting_from_if_block(NMConnection *connection,
									  if_block *block)
{
	gint wpa_l= strlen("wpa-");
	gint wireless_l= strlen("wireless-");
	if_data *curr = block->info;
	const gchar* value = ifparser_getkey (block, "inet");
	struct _Mapping mapping[] = {
		{"psk", "psk"},
		{"identity", "leap-username"},
		{"password", "leap-password"},
		{"key", "wep-key0"},
		{"key-mgmt", "key-mgmt"},
		{"group", "group"},
		{"pairwise", "pairwise"},
		{"proto", "proto"},
		{"pin", "pin"},
		{"wep-key0", "wep-key0"},
		{"wep-key1", "wep-key1"},
		{"wep-key2", "wep-key2"},
		{"wep-key3", "wep-key3"},
		{"wep-tx-keyidx", "wep-tx-keyidx"},
		{ NULL, NULL}
	};

	struct _Mapping dupe_mapping[] = {
		{"psk", normalize_psk},
		{"identity", normalize_dupe},
		{"password", normalize_dupe},
		{"key", normalize_dupe_wireless_key},
		{"key-mgmt", normalize_tolower},
		{"group", normalize_tolower},
		{"pairwise", normalize_tolower},
		{"proto", normalize_tolower},
		{"pin", normalize_dupe},
		{"wep-key0", normalize_dupe_wireless_key},
		{"wep-key1", normalize_dupe_wireless_key},
		{"wep-key2", normalize_dupe_wireless_key},
		{"wep-key3", normalize_dupe_wireless_key},
		{"wep-tx-keyidx", normalize_dupe},
		{ NULL, NULL}
	};

	struct _Mapping type_mapping[] = {
		{"group", string_to_glist_of_strings},
		{"pairwise", string_to_glist_of_strings},
		{"proto", string_to_glist_of_strings},
		{"wep-tx-keyidx", string_to_gpointerint},
		{ NULL, NULL}
	};

	struct _Mapping free_type_mapping[] = {
		{"group", slist_free_all},
		{"pairwise", slist_free_all},
		{"proto", slist_free_all},
		{ NULL, NULL}
	};

	NMSettingWirelessSecurity *wireless_security_setting;
	NMSettingWireless *s_wireless;
	gboolean security = FALSE;

	if(value && !strcmp("ppp", value)) {
		return;
	}

	s_wireless = nm_connection_get_setting_wireless(connection);
	g_return_if_fail(s_wireless);

	nm_log_info (LOGD_SETTINGS, "update wireless security settings (%s).", block->name);
	wireless_security_setting =
		NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new());

	while(curr) {
		if(strlen(curr->key) > wireless_l &&
		   !strncmp("wireless-", curr->key, wireless_l)) {

			gchar *property_value = NULL;
			gpointer typed_property_value = NULL;
			const gchar* newkey = map_by_mapping(mapping, curr->key+wireless_l);
			IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, curr->key+wireless_l);
			IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, curr->key+wireless_l);
			GFreeFunc free_func = map_by_mapping (free_type_mapping, curr->key+wireless_l);
			if(!newkey || !dupe_func)
				goto next;

			property_value = (*dupe_func) (curr->data, connection);
			nm_log_info (LOGD_SETTINGS, "setting wireless security key: %s=%s",
			             newkey, property_value);

			if (type_map_func) {
				errno = 0;
				typed_property_value = (*type_map_func) (property_value);
				if(errno)
					goto wireless_next;
			}
		    
			g_object_set(wireless_security_setting,
					   newkey, typed_property_value ? typed_property_value : property_value,
					   NULL);
			security = TRUE;

		wireless_next:
			g_free(property_value);
			if (typed_property_value && free_func)
				(*free_func) (typed_property_value);

		} else if(strlen(curr->key) > wpa_l &&
				!strncmp("wpa-", curr->key, wpa_l)) {

			gchar *property_value = NULL;
			gpointer typed_property_value = NULL;
			const gchar* newkey = map_by_mapping(mapping, curr->key+wpa_l);
			IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, curr->key+wpa_l);
			IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, curr->key+wpa_l);
			GFreeFunc free_func = map_by_mapping (free_type_mapping, curr->key+wpa_l);
			if(!newkey || !dupe_func)
				goto next;

			property_value = (*dupe_func) (curr->data, connection);
			nm_log_info (LOGD_SETTINGS, "setting wpa security key: %s=%s",
			             newkey,
#ifdef DEBUG_SECRETS
			             property_value
#else /* DEBUG_SECRETS */
			             !strcmp("key", newkey) ||
			             !strcmp("leap-password", newkey) ||
			             !strcmp("pin", newkey) ||
			             !strcmp("psk", newkey) ||
			             !strcmp("wep-key0", newkey) ||
			             !strcmp("wep-key1", newkey) ||
			             !strcmp("wep-key2", newkey) ||
			             !strcmp("wep-key3", newkey) ||
			             NULL ?
			             "<omitted>" : property_value
#endif /* DEBUG_SECRETS */
			             );

			if (type_map_func) {
				errno = 0;
				typed_property_value = (*type_map_func) (property_value);
				if(errno)
					goto wpa_next;
			}
		    
			g_object_set(wireless_security_setting,
					   newkey, typed_property_value ? typed_property_value : property_value,
					   NULL);
			security = TRUE;

		wpa_next:
			g_free(property_value);
			if (free_func && typed_property_value)
				(*free_func) (typed_property_value);
		}
	next:
		curr = curr->next;
	}


	if (security)
		nm_connection_add_setting (connection, NM_SETTING (wireless_security_setting));
}
Beispiel #7
0
static void
SCPluginIfupdown_init (NMSystemConfigInterface *config)
{
	SCPluginIfupdown *self = SC_PLUGIN_IFUPDOWN (config);
	SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (self);
	GHashTable *auto_ifaces;
	if_block *block = NULL;
	NMInotifyHelper *inotify_helper;
	GKeyFile* keyfile;
	GError *error = NULL;
	GList *keys, *iter;
	const char *subsys[2] = { "net", NULL };

	auto_ifaces = g_hash_table_new (g_str_hash, g_str_equal);

	if(!priv->iface_connections)
		priv->iface_connections = g_hash_table_new (g_str_hash, g_str_equal);

	if(!priv->well_known_ifaces)
		priv->well_known_ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);

	if(!priv->well_known_interfaces)
		priv->well_known_interfaces = g_hash_table_new (g_str_hash, g_str_equal);

	PLUGIN_PRINT("SCPlugin-Ifupdown", "init!");

	priv->client = g_udev_client_new (subsys);
	if (!priv->client) {
		PLUGIN_WARN ("SCPlugin-Ifupdown", "    error initializing libgudev");
	} else
		g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self);

	priv->unmanage_well_known = IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT;
 
	inotify_helper = nm_inotify_helper_get ();
	priv->inotify_event_id = g_signal_connect (inotify_helper,
	                                           "event",
	                                           G_CALLBACK (update_system_hostname),
	                                           config);

	priv->inotify_system_hostname_wd =
		nm_inotify_helper_add_watch (inotify_helper, IFUPDOWN_SYSTEM_HOSTNAME_FILE);

	update_system_hostname (inotify_helper, NULL, NULL, config);

	/* Read in all the interfaces */
	ifparser_init (ENI_INTERFACES_FILE, 0);
	block = ifparser_getfirst ();
	while (block) {
		if(!strcmp ("auto", block->type) || !strcmp ("allow-hotplug", block->type))
			g_hash_table_insert (auto_ifaces, block->name, GUINT_TO_POINTER (1));
		else if (!strcmp ("iface", block->type)) {
			NMIfupdownConnection *exported;

			/* Bridge configuration */
			if(!strncmp ("br", block->name, 2)) {
				/* Try to find bridge ports */
				const char *ports = ifparser_getkey (block, "bridge-ports");
				if (ports) {
					int i;
					int state = 0;
					char **port_ifaces;

					PLUGIN_PRINT("SCPlugin-Ifupdown", "found bridge ports %s for %s", ports, block->name);

					port_ifaces = g_strsplit_set (ports, " \t", -1);
					for (i = 0; i < g_strv_length (port_ifaces); i++) {
						char *token = port_ifaces[i];
						/* Skip crazy stuff like regex or all */
						if (!strcmp ("all", token)) {
							continue;
						}
						/* Small SM to skip everything inside regex */
						if (!strcmp ("regex", token)) {
							state++;
							continue;
						}
						if (!strcmp ("noregex", token)) {
							state--;
							continue;
						}
						if (state == 0 && strlen (token) > 0) {
							PLUGIN_PRINT("SCPlugin-Ifupdown", "adding bridge port %s to well_known_interfaces", token);
							g_hash_table_insert (priv->well_known_interfaces, g_strdup (token), "known");
						}
					}
					g_strfreev (port_ifaces);
				}
				goto next;
			}

			/* Skip loopback configuration */
			if(!strcmp ("lo", block->name)) {
				goto next;
			}

			/* Remove any connection for this block that was previously found */
			exported = g_hash_table_lookup (priv->iface_connections, block->name);
			if (exported) {
				PLUGIN_PRINT("SCPlugin-Ifupdown", "deleting %s from iface_connections", block->name);
				nm_settings_connection_delete (NM_SETTINGS_CONNECTION (exported), ignore_cb, NULL);
				g_hash_table_remove (priv->iface_connections, block->name);
			}

			/* add the new connection */
			exported = nm_ifupdown_connection_new (block);
			if (exported) {
				PLUGIN_PRINT("SCPlugin-Ifupdown", "adding %s to iface_connections", block->name);
				g_hash_table_insert (priv->iface_connections, block->name, exported);
			}
			PLUGIN_PRINT("SCPlugin-Ifupdown", "adding iface %s to well_known_interfaces", block->name);
			g_hash_table_insert (priv->well_known_interfaces, block->name, "known");
		} else if (!strcmp ("mapping", block->type)) {
			g_hash_table_insert (priv->well_known_interfaces, block->name, "known");
			PLUGIN_PRINT("SCPlugin-Ifupdown", "adding mapping %s to well_known_interfaces", block->name);
		}
	next:
		block = block->next;
	}

	/* Make 'auto' interfaces autoconnect=TRUE */
	keys = g_hash_table_get_keys (priv->iface_connections);
	for (iter = keys; iter; iter = g_list_next (iter)) {
		NMIfupdownConnection *exported;
		NMSetting *setting;

		if (!g_hash_table_lookup (auto_ifaces, iter->data))
			continue;

		exported = g_hash_table_lookup (priv->iface_connections, iter->data);
		setting = NM_SETTING (nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_CONNECTION));
		g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL);

		nm_settings_connection_commit_changes (NM_SETTINGS_CONNECTION (exported), ignore_cb, NULL);

		PLUGIN_PRINT("SCPlugin-Ifupdown", "autoconnect");
	}
	g_list_free (keys);
	g_hash_table_destroy (auto_ifaces);

	/* Find the config file */
	if (g_file_test (IFUPDOWN_SYSTEM_SETTINGS_KEY_FILE, G_FILE_TEST_EXISTS))
		priv->conf_file = IFUPDOWN_SYSTEM_SETTINGS_KEY_FILE;
	else
		priv->conf_file = IFUPDOWN_OLD_SYSTEM_SETTINGS_KEY_FILE;

	keyfile = g_key_file_new ();
	if (!g_key_file_load_from_file (keyfile,
	                                priv->conf_file,
	                                G_KEY_FILE_NONE,
	                                &error)) {
		nm_log_info (LOGD_SETTINGS, "loading system config file (%s) caused error: (%d) %s",
		         priv->conf_file,
		         error ? error->code : -1,
		         error && error->message ? error->message : "(unknown)");
	} else {
		gboolean manage_well_known;
		error = NULL;

		manage_well_known = g_key_file_get_boolean (keyfile,
		                                            IFUPDOWN_KEY_FILE_GROUP,
		                                            IFUPDOWN_KEY_FILE_KEY_MANAGED,
		                                            &error);
		if (error) {
			nm_log_info (LOGD_SETTINGS, "getting keyfile key '%s' in group '%s' failed: (%d) %s",
			         IFUPDOWN_KEY_FILE_GROUP,
			         IFUPDOWN_KEY_FILE_KEY_MANAGED,
			         error ? error->code : -1,
			         error && error->message ? error->message : "(unknown)");
		} else
			priv->unmanage_well_known = !manage_well_known;
	}
	PLUGIN_PRINT ("SCPluginIfupdown", "management mode: %s", priv->unmanage_well_known ? "unmanaged" : "managed");
	if (keyfile)
		g_key_file_free (keyfile);

	/* Add well-known interfaces */
	keys = g_udev_client_query_by_subsystem (priv->client, "net");
	for (iter = keys; iter; iter = g_list_next (iter)) {
		udev_device_added (self, G_UDEV_DEVICE (iter->data));
		g_object_unref (G_UDEV_DEVICE (iter->data));
	}
	g_list_free (keys);

	/* Now if we're running in managed mode, let NM know there are new connections */
	if (!priv->unmanage_well_known) {
		GList *con_list = g_hash_table_get_values (priv->iface_connections);
		GList *cl_iter;

		for (cl_iter = con_list; cl_iter; cl_iter = g_list_next (cl_iter)) {
			g_signal_emit_by_name (self,
			                       NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED,
			                       NM_SETTINGS_CONNECTION (cl_iter->data));
		}
		g_list_free (con_list);
	}

	PLUGIN_PRINT("SCPlugin-Ifupdown", "end _init.");
}