Beispiel #1
0
static gboolean
udev_read_cb (GIOChannel *source,
              GIOCondition condition,
              gpointer user_data)
{
  OdccmDeviceManagerPrivate *priv = ODCCM_DEVICE_MANAGER_GET_PRIVATE (user_data);
#define UEVENT_BUFFER_SIZE 2048
  gchar buf[UEVENT_BUFFER_SIZE*2];
  GIOStatus status;
  GError *error = NULL;
  guint buflen = 0;
  size_t bufpos;
  gboolean is_net = FALSE, is_ppp = FALSE, added = FALSE;
  gchar iface[10];
  gchar udi[UEVENT_BUFFER_SIZE];
  
  status = g_io_channel_read_chars(priv->udev_chann, &buf, sizeof(buf), &buflen, &error);

  if (status != G_IO_STATUS_NORMAL) {
    g_warning("%s: error reading event: %s",G_STRFUNC,error->message);
    g_error_free(error);
    error = NULL;
  }  

  bufpos = strlen(buf) + 1;
  while (bufpos < (size_t)buflen) {
    int keylen;
    char *key;
    char *tmpptr;
    
    key = &buf[bufpos];
    keylen = strlen(key);
    if (keylen == 0) break;
    
    if (strncmp("SUBSYSTEM=net",key,13)==0) is_net = TRUE;
    if (strncmp("INTERFACE=ppp",key,13)==0){
      is_ppp = TRUE;
      tmpptr = strchr(key,'=');
      strncpy(iface,tmpptr+1,10);
    }
    if (strncmp("ACTION=remove",key,13)==0) added = FALSE;
    if (strncmp("ACTION=add",key,13)==0) added = TRUE;
    if (strncmp("DEVPATH",key,7)==0) {
      tmpptr = strchr(key,'=');
      strncpy(udi,tmpptr+1,UEVENT_BUFFER_SIZE);
    }
    bufpos += keylen + 1;
  }

  if (is_net == TRUE && is_ppp == TRUE) {
    if (added == TRUE) {
      udev_device_added(user_data,iface,udi);
    } else {
      udev_device_removed(user_data,iface,udi);
    }
  }

  return TRUE;
}
Beispiel #2
0
static void
handle_uevent (GUdevClient *client,
               const char *action,
               GUdevDevice *device,
               gpointer user_data)
{
	SCPluginIfupdown *self = SC_PLUGIN_IFUPDOWN (user_data);
	const char *subsys;

	g_return_if_fail (action != NULL);

	/* A bit paranoid */
	subsys = g_udev_device_get_subsystem (device);
	g_return_if_fail (subsys != NULL);
	g_return_if_fail (strcmp (subsys, "net") == 0);

	if (!strcmp (action, "add"))
		udev_device_added (self, device);
	else if (!strcmp (action, "remove"))
		udev_device_removed (self, device);
}
Beispiel #3
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 #4
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.");
}