summary refs log tree commit diff
path: root/src/devices/nm-device-bridge.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2015-01-22 00:29:39 +0100
committerMichael Biebl <biebl@debian.org>2015-01-22 00:29:39 +0100
commit2c032d8f1c6292c1338a615e6ec40252889ba85c (patch)
tree1f77182220b2b0264288ba4a476ab47e5bc48716 /src/devices/nm-device-bridge.c
parent33491bc4279481db8ae47213e34a6d695a0e8830 (diff)
Imported Upstream version 1.0.0 upstream/1.0.0
Diffstat (limited to 'src/devices/nm-device-bridge.c')
-rw-r--r--src/devices/nm-device-bridge.c288
1 files changed, 122 insertions, 166 deletions
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index edc41838..a70cfd95 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -23,29 +23,29 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 
-#include <netinet/ether.h>
 #include <stdlib.h>
 
 #include "gsystem-local-alloc.h"
 #include "nm-device-bridge.h"
 #include "nm-logging.h"
-#include "nm-utils.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-dbus-manager.h"
 #include "nm-enum-types.h"
 #include "nm-platform.h"
+#include "nm-device-factory.h"
+#include "nm-core-internal.h"
 
 #include "nm-device-bridge-glue.h"
 
+#include "nm-device-logging.h"
+_LOG_DECLARE_SELF(NMDeviceBridge);
 
 G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgePrivate))
 
-#define NM_BRIDGE_ERROR (nm_bridge_error_quark ())
-
 typedef struct {
 	int dummy;
 } NMDeviceBridgePrivate;
@@ -59,17 +59,6 @@ enum {
 
 /******************************************************************/
 
-static GQuark
-nm_bridge_error_quark (void)
-{
-	static GQuark quark = 0;
-	if (!quark)
-		quark = g_quark_from_static_string ("nm-bridge-error");
-	return quark;
-}
-
-/******************************************************************/
-
 static guint32
 get_generic_capabilities (NMDevice *dev)
 {
@@ -100,7 +89,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 {
 	const char *iface;
 	NMSettingBridge *s_bridge;
-	const GByteArray *mac_address;
+	const char *mac_address;
 
 	if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->check_connection_compatible (device, connection))
 		return FALSE;
@@ -110,19 +99,16 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 		return FALSE;
 
 	/* Bridge connections must specify the virtual interface name */
-	iface = nm_connection_get_virtual_iface_name (connection);
+	iface = nm_connection_get_interface_name (connection);
 	if (!iface || strcmp (nm_device_get_iface (device), iface))
 		return FALSE;
 
 	mac_address = nm_setting_bridge_get_mac_address (s_bridge);
 	if (mac_address) {
-		guint hw_len;
-		const guint8 *hw_addr;
+		const char *hw_addr;
 
-		hw_addr = nm_device_get_hw_address (device, &hw_len);
-		if (   !hw_addr
-		    || hw_len != mac_address->len
-		    || memcmp (mac_address->data, hw_addr, hw_len) != 0)
+		hw_addr = nm_device_get_hw_address (device);
+		if (!hw_addr || !nm_utils_hwaddr_matches (hw_addr, -1, mac_address, -1))
 			return FALSE;
 	}
 
@@ -136,17 +122,14 @@ complete_connection (NMDevice *device,
                      const GSList *existing_connections,
                      GError **error)
 {
-	NMSettingBridge *s_bridge, *tmp;
-	guint32 i = 0;
-	char *name;
-	const GSList *iter;
-	gboolean found;
+	NMSettingBridge *s_bridge;
 
 	nm_utils_complete_generic (connection,
 	                           NM_SETTING_BRIDGE_SETTING_NAME,
 	                           existing_connections,
-	                           _("Bridge connection %d"),
 	                           NULL,
+	                           _("Bridge connection"),
+	                           "bridge",
 	                           TRUE);
 
 	s_bridge = nm_connection_get_setting_bridge (connection);
@@ -155,34 +138,6 @@ complete_connection (NMDevice *device,
 		nm_connection_add_setting (connection, NM_SETTING (s_bridge));
 	}
 
-	/* Grab the first name that doesn't exist in either our connections
-	 * or a device on the system.
-	 */
-	while (i < 500 && !nm_setting_bridge_get_interface_name (s_bridge)) {
-		name = g_strdup_printf ("br%u", i);
-		/* check interface names */
-		if (!nm_platform_link_exists (name)) {
-			/* check existing bridge connections */
-			for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) {
-				NMConnection *candidate = iter->data;
-
-				tmp = nm_connection_get_setting_bridge (candidate);
-				if (tmp && nm_connection_is_type (candidate, NM_SETTING_BRIDGE_SETTING_NAME)) {
-					if (g_strcmp0 (nm_setting_bridge_get_interface_name (tmp), name) == 0) {
-						found = TRUE;
-						break;
-					}
-				}
-			}
-
-			if (!found)
-				g_object_set (G_OBJECT (s_bridge), NM_SETTING_BRIDGE_INTERFACE_NAME, name, NULL);
-		}
-
-		g_free (name);
-		i++;
-	}
-
 	return TRUE;
 }
 
@@ -292,15 +247,14 @@ commit_slave_options (NMDevice *device, NMSettingBridgePort *setting)
 static void
 update_connection (NMDevice *device, NMConnection *connection)
 {
+	NMDeviceBridge *self = NM_DEVICE_BRIDGE (device);
 	NMSettingBridge *s_bridge = nm_connection_get_setting_bridge (connection);
-	const char *ifname = nm_device_get_iface (device);
 	int ifindex = nm_device_get_ifindex (device);
 	const Option *option;
 
 	if (!s_bridge) {
 		s_bridge = (NMSettingBridge *) nm_setting_bridge_new ();
 		nm_connection_add_setting (connection, (NMSetting *) s_bridge);
-		g_object_set (s_bridge, NM_SETTING_BRIDGE_INTERFACE_NAME, ifname, NULL);
 	}
 
 	for (option = master_options; option->name; option++) {
@@ -315,34 +269,27 @@ update_connection (NMDevice *device, NMConnection *connection)
 				value /= 100;
 
 			g_object_set (s_bridge, option->name, value, NULL);
-		} else {
-			nm_log_warn (LOGD_BRIDGE, "(%s): failed to read bridge setting '%s'",
-			             nm_device_get_iface (device), option->sysname);
-		}
+		} else
+			_LOGW (LOGD_BRIDGE, "failed to read bridge setting '%s'", option->sysname);
 	}
 }
 
-/**
- * nm_bridge_update_slave_connection:
- * @slave: the slave #NMDevice, is *not* necessarily a bridge interface
- * @connection: the #NMConnection to update with the bridge port settings
- *
- * Reads bridge port configuration and updates @connection with those
- * properties.
- *
- * Returns: %TRUE if the port configuration was read and @connection updated,
- * %FALSE if not.
- */
-gboolean
-nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection)
+static gboolean
+master_update_slave_connection (NMDevice *device,
+                                NMDevice *slave,
+                                NMConnection *connection,
+                                GError **error)
 {
+	NMDeviceBridge *self = NM_DEVICE_BRIDGE (device);
+	NMSettingConnection *s_con;
 	NMSettingBridgePort *s_port;
-	int ifindex = nm_device_get_ifindex (slave);
+	int ifindex_slave = nm_device_get_ifindex (slave);
+	const char *iface = nm_device_get_iface (device);
 	const Option *option;
 
-	g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE);
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+	g_return_val_if_fail (ifindex_slave > 0, FALSE);
 
+	s_con = nm_connection_get_setting_connection (connection);
 	s_port = nm_connection_get_setting_bridge_port (connection);
 	if (!s_port) {
 		s_port = (NMSettingBridgePort *) nm_setting_bridge_port_new ();
@@ -350,7 +297,7 @@ nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection)
 	}
 
 	for (option = slave_options; option->name; option++) {
-		gs_free char *str = nm_platform_slave_get_option (ifindex, option->sysname);
+		gs_free char *str = nm_platform_slave_get_option (ifindex_slave, option->sysname);
 		int value;
 
 		if (str) {
@@ -361,12 +308,14 @@ nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection)
 				value /= 100;
 
 			g_object_set (s_port, option->name, value, NULL);
-		} else {
-			nm_log_warn (LOGD_BRIDGE, "(%s): failed to read bridge port setting '%s'",
-			             nm_device_get_iface (slave), option->sysname);
-		}
+		} else
+			_LOGW (LOGD_BRIDGE, "failed to read bridge port setting '%s'", option->sysname);
 	}
 
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_MASTER, iface,
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME,
+	              NULL);
 	return TRUE;
 }
 
@@ -393,19 +342,19 @@ enslave_slave (NMDevice *device,
                NMConnection *connection,
                gboolean configure)
 {
+	NMDeviceBridge *self = NM_DEVICE_BRIDGE (device);
+
 	if (configure) {
 		if (!nm_platform_link_enslave (nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)))
 			return FALSE;
 
 		commit_slave_options (slave, nm_connection_get_setting_bridge_port (connection));
 
-		nm_log_info (LOGD_BRIDGE, "(%s): attached bridge port %s",
-		             nm_device_get_ip_iface (device),
-		             nm_device_get_ip_iface (slave));
+		_LOGI (LOGD_BRIDGE, "attached bridge port %s",
+		       nm_device_get_ip_iface (slave));
 	} else {
-		nm_log_info (LOGD_BRIDGE, "(%s): bridge port %s was attached",
-		             nm_device_get_ip_iface (device),
-		             nm_device_get_ip_iface (slave));
+		_LOGI (LOGD_BRIDGE, "bridge port %s was attached",
+		       nm_device_get_ip_iface (slave));
 	}
 
 	g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
@@ -418,6 +367,7 @@ release_slave (NMDevice *device,
                NMDevice *slave,
                gboolean configure)
 {
+	NMDeviceBridge *self = NM_DEVICE_BRIDGE (device);
 	gboolean success = TRUE;
 
 	if (configure) {
@@ -425,18 +375,15 @@ release_slave (NMDevice *device,
 		                                    nm_device_get_ip_ifindex (slave));
 
 		if (success) {
-			nm_log_info (LOGD_BRIDGE, "(%s): detached bridge port %s",
-			             nm_device_get_ip_iface (device),
-			             nm_device_get_ip_iface (slave));
+			_LOGI (LOGD_BRIDGE, "detached bridge port %s",
+			       nm_device_get_ip_iface (slave));
 		} else {
-			nm_log_warn (LOGD_BRIDGE, "(%s): failed to detach bridge port %s",
-			             nm_device_get_ip_iface (device),
-			             nm_device_get_ip_iface (slave));
+			_LOGW (LOGD_BRIDGE, "failed to detach bridge port %s",
+			       nm_device_get_ip_iface (slave));
 		}
 	} else {
-		nm_log_info (LOGD_BRIDGE, "(%s): bridge port %s was detached",
-		             nm_device_get_ip_iface (device),
-		             nm_device_get_ip_iface (slave));
+		_LOGI (LOGD_BRIDGE, "bridge port %s was detached",
+		       nm_device_get_ip_iface (slave));
 	}
 
 	g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
@@ -445,66 +392,6 @@ release_slave (NMDevice *device,
 
 /******************************************************************/
 
-NMDevice *
-nm_device_bridge_new (NMPlatformLink *platform_device)
-{
-	g_return_val_if_fail (platform_device != NULL, NULL);
-
-	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
-	                                  NM_DEVICE_PLATFORM_DEVICE, platform_device,
-	                                  NM_DEVICE_DRIVER, "bridge",
-	                                  NM_DEVICE_TYPE_DESC, "Bridge",
-	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
-	                                  NM_DEVICE_IS_MASTER, TRUE,
-	                                  NULL);
-}
-
-NMDevice *
-nm_device_bridge_new_for_connection (NMConnection *connection)
-{
-	const char *iface;
-	NMSettingBridge *s_bridge;
-	const GByteArray *mac_address;
-
-	g_return_val_if_fail (connection != NULL, NULL);
-
-	iface = nm_connection_get_virtual_iface_name (connection);
-	g_return_val_if_fail (iface != NULL, NULL);
-
-	s_bridge = nm_connection_get_setting_bridge (connection);
-	g_return_val_if_fail (s_bridge, NULL);
-
-	mac_address = nm_setting_bridge_get_mac_address (s_bridge);
-
-	if (   !nm_platform_bridge_add (iface,
-	                                mac_address ? mac_address->data : NULL,
-	                                mac_address ? mac_address->len : 0)
-	    && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) {
-		nm_log_warn (LOGD_DEVICE | LOGD_BRIDGE, "(%s): failed to create bridge master interface for '%s': %s",
-		             iface, nm_connection_get_id (connection),
-		             nm_platform_get_error_msg ());
-		return NULL;
-	}
-
-	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
-	                                  NM_DEVICE_IFACE, iface,
-	                                  NM_DEVICE_DRIVER, "bridge",
-	                                  NM_DEVICE_TYPE_DESC, "Bridge",
-	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
-	                                  NM_DEVICE_IS_MASTER, TRUE,
-	                                  NULL);
-}
-
-static void
-constructed (GObject *object)
-{
-	G_OBJECT_CLASS (nm_device_bridge_parent_class)->constructed (object);
-
-	nm_log_dbg (LOGD_HW | LOGD_BRIDGE, "(%s): kernel ifindex %d",
-	            nm_device_get_iface (NM_DEVICE (object)),
-	            nm_device_get_ifindex (NM_DEVICE (object)));
-}
-
 static void
 nm_device_bridge_init (NMDeviceBridge * self)
 {
@@ -518,7 +405,6 @@ get_property (GObject *object, guint prop_id,
 	GSList *list, *iter;
 
 	switch (prop_id) {
-		break;
 	case PROP_SLAVES:
 		slaves = g_ptr_array_new ();
 		list = nm_device_master_get_slaves (NM_DEVICE (object));
@@ -555,7 +441,6 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
 	parent_class->connection_type = NM_SETTING_BRIDGE_SETTING_NAME;
 
 	/* virtual methods */
-	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 
@@ -566,6 +451,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
 	parent_class->complete_connection = complete_connection;
 
 	parent_class->update_connection = update_connection;
+	parent_class->master_update_slave_connection = master_update_slave_connection;
 
 	parent_class->act_stage1_prepare = act_stage1_prepare;
 	parent_class->enslave_slave = enslave_slave;
@@ -574,15 +460,85 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
 	/* properties */
 	g_object_class_install_property
 		(object_class, PROP_SLAVES,
-		 g_param_spec_boxed (NM_DEVICE_BRIDGE_SLAVES,
-		                     "Slaves",
-		                     "Slaves",
+		 g_param_spec_boxed (NM_DEVICE_BRIDGE_SLAVES, "", "",
 		                     DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
-		                     G_PARAM_READABLE));
+		                     G_PARAM_READABLE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
 	                                        G_TYPE_FROM_CLASS (klass),
 	                                        &dbus_glib_nm_device_bridge_object_info);
+}
+
+/*************************************************************/
 
-	dbus_g_error_domain_register (NM_BRIDGE_ERROR, NULL, NM_TYPE_BRIDGE_ERROR);
+#define NM_TYPE_BRIDGE_FACTORY (nm_bridge_factory_get_type ())
+#define NM_BRIDGE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BRIDGE_FACTORY, NMBridgeFactory))
+
+static NMDevice *
+new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
+{
+	if (plink->type == NM_LINK_TYPE_BRIDGE) {
+		return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
+		                                  NM_DEVICE_PLATFORM_DEVICE, plink,
+		                                  NM_DEVICE_DRIVER, "bridge",
+		                                  NM_DEVICE_TYPE_DESC, "Bridge",
+		                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
+		                                  NM_DEVICE_IS_MASTER, TRUE,
+		                                  NULL);
+	}
+	return NULL;
 }
+
+static NMDevice *
+create_virtual_device_for_connection (NMDeviceFactory *factory,
+                                      NMConnection *connection,
+                                      NMDevice *parent,
+                                      GError **error)
+{
+	const char *iface;
+	NMSettingBridge *s_bridge;
+	const char *mac_address_str;
+	guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX];
+
+	if (!nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
+		return NULL;
+
+	g_return_val_if_fail (connection != NULL, NULL);
+
+	iface = nm_connection_get_interface_name (connection);
+	g_return_val_if_fail (iface != NULL, NULL);
+
+	s_bridge = nm_connection_get_setting_bridge (connection);
+	g_return_val_if_fail (s_bridge, NULL);
+
+	mac_address_str = nm_setting_bridge_get_mac_address (s_bridge);
+	if (mac_address_str) {
+		if (!nm_utils_hwaddr_aton (mac_address_str, mac_address, ETH_ALEN))
+			mac_address_str = NULL;
+	}
+
+	if (   !nm_platform_bridge_add (iface,
+	                                mac_address_str ? mac_address : NULL,
+	                                mac_address_str ? ETH_ALEN : 0)
+	    && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) {
+		nm_log_warn (LOGD_DEVICE | LOGD_BRIDGE, "(%s): failed to create bridge master interface for '%s': %s",
+		             iface, nm_connection_get_id (connection),
+		             nm_platform_get_error_msg ());
+		return NULL;
+	}
+
+	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
+	                                  NM_DEVICE_IFACE, iface,
+	                                  NM_DEVICE_DRIVER, "bridge",
+	                                  NM_DEVICE_TYPE_DESC, "Bridge",
+	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
+	                                  NM_DEVICE_IS_MASTER, TRUE,
+	                                  NULL);
+}
+
+DEFINE_DEVICE_FACTORY_INTERNAL(BRIDGE, Bridge, bridge,
+	factory_iface->new_link = new_link;
+	factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
+	)
+