static char * get_virtual_iface_name (NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { const char *ifname; NMSettingVlan *s_vlan; g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME), NULL); s_vlan = nm_connection_get_setting_vlan (connection); g_assert (s_vlan); if (!parent_iface) return NULL; ifname = nm_connection_get_interface_name (connection); if (ifname) return g_strdup (ifname); /* If the connection doesn't specify the interface name for the VLAN * device, we create one for it using the VLAN ID and the parent * interface's name. */ return nm_utils_new_vlan_name (parent_iface, nm_setting_vlan_get_id (s_vlan)); }
NMDevice * nm_device_vlan_new_for_connection (NMConnection *connection, NMDevice *parent) { NMDevice *device; NMSettingVlan *s_vlan; char *iface; g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (NM_IS_DEVICE (parent), NULL); s_vlan = nm_connection_get_setting_vlan (connection); g_return_val_if_fail (s_vlan != NULL, NULL); iface = g_strdup (nm_connection_get_interface_name (connection)); if (!iface) { iface = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent), nm_setting_vlan_get_id (s_vlan)); } if ( !nm_platform_vlan_add (iface, nm_device_get_ifindex (parent), nm_setting_vlan_get_id (s_vlan), nm_setting_vlan_get_flags (s_vlan)) && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) { nm_log_warn (LOGD_DEVICE | LOGD_VLAN, "(%s) failed to add VLAN interface for '%s'", iface, nm_connection_get_id (connection)); g_free (iface); return NULL; } device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, NM_DEVICE_IFACE, iface, NM_DEVICE_VLAN_PARENT, parent, NM_DEVICE_DRIVER, "8021q", NM_DEVICE_TYPE_DESC, "VLAN", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN, NULL); g_free (iface); if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) { g_object_unref (device); device = NULL; } return device; }
static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingConnection *s_con; NMSettingVlan *s_vlan; NMSettingWired *s_wired; const char *ctype, *dev_iface_name, *vlan_iface_name; const GByteArray *mac_address; char *mac_address_str; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); ctype = nm_setting_connection_get_connection_type (s_con); if (strcmp (ctype, NM_SETTING_VLAN_SETTING_NAME) != 0) { g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION, "The connection was not a VLAN connection."); return FALSE; } s_vlan = nm_connection_get_setting_vlan (connection); if (!s_vlan) { g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION, "The connection was not a valid VLAN connection."); return FALSE; } if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))) { g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_ID_MISMATCH, "The VLAN identifiers of the device and the connection didn't match."); return FALSE; } dev_iface_name = nm_device_get_iface (device); vlan_iface_name = nm_setting_vlan_get_interface_name (s_vlan); if (vlan_iface_name && g_strcmp0 (dev_iface_name, vlan_iface_name) != 0) { g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH, "The interfaces of the device and the connection didn't match."); return FALSE; } s_wired = nm_connection_get_setting_wired (connection); if (s_wired) mac_address = nm_setting_wired_get_mac_address (s_wired); else mac_address = NULL; if (mac_address) { mac_address_str = nm_utils_hwaddr_ntoa_len (mac_address->data, mac_address->len); if (!g_strcmp0 (mac_address_str, NM_DEVICE_VLAN_GET_PRIVATE (device)->hw_address)) { g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_MAC_MISMATCH, "The hardware address of the device and the connection didn't match."); } g_free (mac_address_str); } return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->connection_compatible (device, connection, error); }
static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceVlan *self = NM_DEVICE_VLAN (device); NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection); int ifindex = nm_device_get_ifindex (device); int parent_ifindex = -1, vlan_id = -1; NMDevice *parent; const char *setting_parent, *new_parent; if (!s_vlan) { s_vlan = (NMSettingVlan *) nm_setting_vlan_new (); nm_connection_add_setting (connection, (NMSetting *) s_vlan); } if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, ifindex, &parent_ifindex, &vlan_id)) { _LOGW (LOGD_VLAN, "failed to get VLAN interface info while updating connection."); return; } if (priv->vlan_id != vlan_id) { priv->vlan_id = vlan_id; g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID); } if (vlan_id != nm_setting_vlan_get_id (s_vlan)) g_object_set (s_vlan, NM_SETTING_VLAN_ID, priv->vlan_id, NULL); if (parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); else parent = NULL; nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent); /* Update parent in the connection; default to parent's interface name */ if (parent) { new_parent = nm_device_get_iface (parent); setting_parent = nm_setting_vlan_get_parent (s_vlan); if (setting_parent && nm_utils_is_uuid (setting_parent)) { NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } if (new_parent) g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL); } else g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, NULL, NULL); }
static gboolean create_and_realize (NMDevice *device, NMConnection *connection, NMDevice *parent, NMPlatformLink *out_plink, GError **error) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); const char *iface = nm_device_get_iface (device); NMSettingVlan *s_vlan; int parent_ifindex, vlan_id; NMPlatformError plerr; g_assert (out_plink); s_vlan = nm_connection_get_setting_vlan (connection); g_assert (s_vlan); if (!nm_device_supports_vlans (parent)) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "no support for VLANs on interface %s of type %s", nm_device_get_iface (parent), nm_device_get_type_desc (parent)); return FALSE; } parent_ifindex = nm_device_get_ifindex (parent); g_warn_if_fail (parent_ifindex > 0); vlan_id = nm_setting_vlan_get_id (s_vlan); plerr = nm_platform_vlan_add (NM_PLATFORM_GET, iface, parent_ifindex, vlan_id, nm_setting_vlan_get_flags (s_vlan), out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create VLAN interface '%s' for '%s': %s", iface, nm_connection_get_id (connection), nm_platform_error_to_string (plerr)); return FALSE; } g_warn_if_fail (priv->parent == NULL); nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent); priv->vlan_id = vlan_id; return TRUE; }
static void vlan_settings_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { NMEditorVlanWidgetBinding *binding = user_data; const char *ifname, *parent; char *ifname_parent; int ifname_id, id; if (binding->updating) return; ifname = nm_setting_connection_get_interface_name (binding->s_con); parent = nm_setting_vlan_get_parent (binding->s_vlan); id = nm_setting_vlan_get_id (binding->s_vlan); if (!parse_interface_name (ifname, &ifname_parent, &ifname_id)) return; /* If the id in INTERFACE_NAME changed, and ID is either unset, or was previously * in sync with INTERFACE_NAME, then update ID. */ if ( id != ifname_id && (id == binding->last_ifname_id || id == 0)) { binding->updating = TRUE; g_object_set (G_OBJECT (binding->s_vlan), NM_SETTING_VLAN_ID, ifname_id, NULL); binding->updating = FALSE; } /* If the PARENT in INTERFACE_NAME changed, and PARENT is either unset, or was * previously in sync with INTERFACE_NAME, then update PARENT. */ if ( g_strcmp0 (parent, ifname_parent) != 0 && ( g_strcmp0 (parent, binding->last_ifname_parent) == 0 || !parent || !*parent)) { binding->updating = TRUE; g_object_set (G_OBJECT (binding->s_vlan), NM_SETTING_VLAN_PARENT, ifname_parent, NULL); binding->updating = FALSE; } g_free (binding->last_ifname_parent); binding->last_ifname_parent = ifname_parent; binding->last_ifname_id = ifname_id; }
static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMDeviceVlanPrivate *priv; NMSettingVlan *s_vlan; NMSettingWired *s_wired; const char *setting_hwaddr; if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->connection_compatible (device, connection, error)) return FALSE; if (!nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The connection was not a VLAN connection.")); return FALSE; } s_vlan = nm_connection_get_setting_vlan (connection); if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The VLAN identifiers of the device and the connection didn't match.")); return FALSE; } s_wired = nm_connection_get_setting_wired (connection); if (s_wired) setting_hwaddr = nm_setting_wired_get_mac_address (s_wired); else setting_hwaddr = NULL; if (setting_hwaddr) { priv = NM_DEVICE_VLAN_GET_PRIVATE (device); if ( !priv->hw_address || !nm_utils_hwaddr_matches (setting_hwaddr, -1, priv->hw_address, -1)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The hardware address of the device and the connection didn't match.")); } } return TRUE; }
static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); NMSettingVlan *s_vlan; const char *parent, *iface = NULL; if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection)) return FALSE; s_vlan = nm_connection_get_setting_vlan (connection); if (!s_vlan) return FALSE; if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) return FALSE; /* Check parent interface; could be an interface name or a UUID */ parent = nm_setting_vlan_get_parent (s_vlan); if (parent) { if (!match_parent (NM_DEVICE_VLAN (device), parent)) return FALSE; } else { /* Parent could be a MAC address in an NMSettingWired */ if (!match_hwaddr (device, connection, TRUE)) return FALSE; } /* Ensure the interface name matches. If not specified we assume a match * since both the parent interface and the VLAN ID matched by the time we * get here. */ iface = nm_connection_get_interface_name (connection); if (iface) { if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) return FALSE; } return TRUE; }
static void populate_ui (CEPageVlan *self) { CEPageVlanPrivate *priv = CE_PAGE_VLAN_GET_PRIVATE (self); GSList *devices, *d_iter; NMConnection *parent_connection = NULL; NMDevice *device, *parent_device = NULL; const char *parent, *iface, *current_parent; int i, mtu_def, mtu_val; devices = get_vlan_devices (self); /* Parent */ build_vlan_parent_list (self, devices); parent = nm_setting_vlan_get_parent (priv->setting); if (parent) { /* UUID? */ parent_connection = (NMConnection *)nm_remote_settings_get_connection_by_uuid (CE_PAGE (self)->settings, parent); if (!parent_connection) { /* Interface name? */ for (d_iter = devices; d_iter; d_iter = d_iter->next) { device = d_iter->data; if (!g_strcmp0 (parent, nm_device_get_iface (device))) { parent_device = device; break; } } } } /* If NMSettingVlan:parent didn't indicate a device, but we have a * wired setting, figure out the device from that. */ if (priv->s_hw && !parent_device) { const GByteArray *mac; const char *device_mac_str; char *mac_str; if (NM_IS_SETTING_WIRED (priv->s_hw)) mac = nm_setting_wired_get_mac_address (NM_SETTING_WIRED (priv->s_hw)); else mac = NULL; if (mac) { mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER); for (d_iter = devices; d_iter; d_iter = d_iter->next) { device = d_iter->data; if (NM_IS_DEVICE_ETHERNET (device)) device_mac_str = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device)); else device_mac_str = NULL; if (!g_strcmp0 (mac_str, device_mac_str)) { parent_device = device; break; } } } } current_parent = parent; if (parent_device || parent_connection) { for (i = 0; priv->parents[i]; i++) { if (parent_device && parent_device != priv->parents[i]->device) continue; if (parent_connection != priv->parents[i]->connection) continue; current_parent = priv->parents[i]->label; break; } } ce_page_setup_mac_combo (CE_PAGE (self), priv->parent, current_parent, priv->parent_labels); g_signal_connect (priv->parent, "changed", G_CALLBACK (parent_changed), self); if (current_parent) priv->last_parent = g_strndup (current_parent, strcspn (current_parent, " ")); /* Name */ iface = nm_setting_vlan_get_interface_name (priv->setting); if (iface) gtk_entry_set_text (priv->name_entry, iface); g_signal_connect (priv->name_entry, "changed", G_CALLBACK (name_changed), self); /* ID */ priv->last_id = nm_setting_vlan_get_id (priv->setting); gtk_spin_button_set_value (priv->id_entry, priv->last_id); g_signal_connect (priv->id_entry, "value-changed", G_CALLBACK (id_changed), self); /* Cloned MAC address */ if (NM_IS_SETTING_WIRED (priv->s_hw)) { ce_page_mac_to_entry (nm_setting_wired_get_cloned_mac_address (NM_SETTING_WIRED (priv->s_hw)), ARPHRD_ETHER, priv->cloned_mac); } g_signal_connect (priv->cloned_mac, "changed", G_CALLBACK (stuff_changed), self); /* MTU */ if (NM_IS_SETTING_WIRED (priv->s_hw)) { mtu_def = ce_get_property_default (priv->s_hw, NM_SETTING_WIRED_MTU); mtu_val = nm_setting_wired_get_mtu (NM_SETTING_WIRED (priv->s_hw)); } else { mtu_def = mtu_val = 1500; } g_signal_connect (priv->mtu, "output", G_CALLBACK (ce_spin_output_with_default), GINT_TO_POINTER (mtu_def)); gtk_spin_button_set_value (priv->mtu, (gdouble) mtu_val); g_signal_connect (priv->mtu, "value-changed", G_CALLBACK (stuff_changed), self); g_slist_free (devices); }