static NMDevice * find_vlan_parent (GSList *connections, NMApplet *applet) { const GPtrArray *devices; NMDevice *parent_device; GSList *iter; devices = nm_client_get_devices (applet->nm_client); if (!devices) return NULL; for (iter = connections; iter; iter = iter->next) { NMConnection *connection = iter->data; NMSettingVlan *s_vlan; const char *parent; s_vlan = nm_connection_get_setting_vlan (connection); g_return_val_if_fail (s_vlan != NULL, NULL); parent = nm_setting_vlan_get_parent (s_vlan); if (parent && nm_utils_iface_valid_name (parent)) { parent_device = find_device_by_iface (parent, devices); } else { NMSettingConnection *s_con; NMSetting *s_hw; const char *type; GByteArray *mac; s_con = nm_connection_get_setting_connection (connection); type = nm_setting_connection_get_connection_type (s_con); s_hw = nm_connection_get_setting_by_name (connection, type); if (!s_hw) { g_warn_if_reached (); continue; } if (!g_object_class_find_property (G_OBJECT_GET_CLASS (s_hw), "mac-address")) continue; g_object_get (G_OBJECT (s_hw), "mac-address", &mac, NULL); if (mac) { parent_device = find_device_by_mac (mac, devices); g_byte_array_unref (mac); } else parent_device = NULL; } if (parent_device) return parent_device; } return NULL; }
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 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 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 const char * get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) { NMSettingVlan *s_vlan; NMSettingWired *s_wired; const char *parent = NULL; 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); parent = nm_setting_vlan_get_parent (s_vlan); if (parent) return parent; /* Try the hardware address from the VLAN connection's hardware setting */ s_wired = nm_connection_get_setting_wired (connection); if (s_wired) return nm_setting_wired_get_mac_address (s_wired); return NULL; }
static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, const GSList *existing_connections, GError **error) { NMSettingVlan *s_vlan; nm_utils_complete_generic (connection, NM_SETTING_VLAN_SETTING_NAME, existing_connections, NULL, _("VLAN connection"), NULL, TRUE); s_vlan = nm_connection_get_setting_vlan (connection); if (!s_vlan) { g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, "A 'vlan' setting is required."); return FALSE; } /* If there's no VLAN interface, no parent, and no hardware address in the * settings, then there's not enough information to complete the setting. */ if ( !nm_setting_vlan_get_parent (s_vlan) && !match_hwaddr (device, connection, TRUE)) { g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID, "The 'vlan' setting had no interface name, parent, or hardware address."); 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); }