diff options
Diffstat (limited to 'src/devices/nm-device-bridge.c')
| -rw-r--r-- | src/devices/nm-device-bridge.c | 288 |
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; + ) + |