diff --git a/src/nm-netlink-compat.h b/src/nm-netlink-compat.h index 2ed99d5f6..5446bbc42 100644 --- a/src/nm-netlink-compat.h +++ b/src/nm-netlink-compat.h @@ -243,6 +243,55 @@ rtnl_link_bond_release_ifindex (struct nl_sock *h, int slave_ifidx) /* Bonding only in libnl3 */ return -NLE_OPNOTSUPP; } + +static inline int +rtnl_link_vlan_set_id (struct rtnl_link *l, int id) +{ + /* VLAN only in libnl3 */ + return -NLE_OPNOTSUPP; +} + +static inline int +rtnl_link_vlan_set_flags (struct rtnl_link *l, unsigned int flags) +{ + /* VLAN only in libnl3 */ + return -NLE_OPNOTSUPP; +} + +static inline int +rtnl_link_vlan_set_ingress_map (struct rtnl_link *l, int from, uint32_t to) +{ + /* VLAN only in libnl3 */ + return -NLE_OPNOTSUPP; +} + +static inline int +rtnl_link_vlan_set_egress_map (struct rtnl_link *l, int from, uint32_t to) +{ + /* VLAN only in libnl3 */ + return -NLE_OPNOTSUPP; +} + +static inline int +rtnl_link_set_type (struct rtnl_link *l, const char *type) +{ + /* Operation only in libnl3 */ + return -NLE_OPNOTSUPP; +} + +static inline int +rtnl_link_add (struct nl_sock *sk, struct rtnl_link *l, int flags) +{ + /* Operation only in libnl3 */ + return -NLE_OPNOTSUPP; +} + +static inline int +rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *l) +{ + /* Operation only in libnl3 */ + return -NLE_OPNOTSUPP; +} #endif /* HAVE_LIBNL1 || HAVE_LIBNL2 */ #endif /* NM_NETLINK_COMPAT_H */ diff --git a/src/nm-system.c b/src/nm-system.c index b35422aad..0a5dcfa60 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -59,10 +59,10 @@ #include #include #include -#include #ifdef HAVE_LIBNL3 #include +#include #endif static void nm_system_device_set_priority (int ifindex, @@ -1529,130 +1529,114 @@ out: return res; } -static void ingress_priority_iterator (gpointer data, gpointer user_data) -{ - struct rtnl_link *new_link = user_data; - vlan_priority_map *item = data; - - g_return_if_fail (item != NULL); - g_return_if_fail (new_link != NULL); - - if ((item->from < 0) || (item->from > 7)) - return; - - rtnl_link_vlan_set_ingress_map (new_link, item->from, item->to); -} - -static void egress_priority_iterator(gpointer data, gpointer user_data) -{ - struct rtnl_link *new_link = user_data; - vlan_priority_map *item = data; - - g_return_if_fail (item != NULL); - g_return_if_fail (new_link != NULL); - - if ((item->to < 0) || (item->to > 7)) - return; - - rtnl_link_vlan_set_egress_map (new_link, item->from, item->to); -} - /** - * nm_system_add_vlan_device: - * @setting: NMSettingVlan + * nm_system_add_vlan_iface: + * @connection: the #NMConnection that describes the VLAN interface + * @iface: the interface name of the new VLAN interface + * @master_ifindex: the interface index of the new VLAN interface's master + * interface * - * Add a VLAN device specified in @setting. + * Add a VLAN device named @iface and specified in @connection. * - * Returns: %TRUE on success, or %FALSE + * Returns: %TRUE on success, %FALSE on failure */ gboolean -nm_system_add_vlan_device (NMSettingVlan *setting) +nm_system_add_vlan_iface (NMConnection *connection, + const char *iface, + int master_ifindex) { - int ret = 0; - int if_index = 0; + NMSettingVlan *s_vlan; + int ret = -1; struct rtnl_link *new_link = NULL; struct nl_sock *nlh = NULL; - const GSList *list = NULL; - - const char *interface_name = NULL; - const char *vlan_slave = NULL; guint32 vlan_id = 0; guint32 vlan_flags = 0; + guint32 num, i, from, to; - g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE); - - vlan_slave = nm_setting_vlan_get_slave (setting); - g_return_val_if_fail (vlan_slave != NULL, FALSE); - - vlan_id = nm_setting_vlan_get_id (setting); - g_return_val_if_fail (vlan_id != 0, FALSE); - g_return_val_if_fail (vlan_id < 4096, FALSE); + g_return_val_if_fail (master_ifindex >= 0, FALSE); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, FALSE); - interface_name = nm_setting_vlan_get_interface_name (setting); - g_return_val_if_fail (interface_name != NULL, FALSE); + s_vlan = nm_connection_get_setting_vlan (connection); + g_return_val_if_fail (s_vlan, FALSE); - if_index = nm_netlink_iface_to_index (vlan_slave); - g_return_val_if_fail (if_index > 0, FALSE); + vlan_id = nm_setting_vlan_get_id (s_vlan); + + if (!iface) { + iface = nm_connection_get_virtual_iface_name (connection); + g_return_val_if_fail (iface != NULL, FALSE); + } new_link = rtnl_link_alloc (); - g_return_val_if_fail (new_link != NULL, FALSE); + if (!new_link) { + g_warn_if_fail (new_link != NULL); + goto out; + } ret = rtnl_link_set_type (new_link, "vlan"); if (ret < 0) - goto free_new_link; + goto out; - rtnl_link_set_link (new_link, if_index); - rtnl_link_set_name (new_link, interface_name); + rtnl_link_set_link (new_link, master_ifindex); + rtnl_link_set_name (new_link, iface); rtnl_link_vlan_set_id (new_link, vlan_id); - vlan_flags = nm_setting_vlan_get_flags (setting); - if (vlan_flags) - rtnl_link_vlan_set_flags (new_link, vlan_flags); + vlan_flags = nm_setting_vlan_get_flags (s_vlan); + if (vlan_flags) { + guint kernel_flags = 0; - list = nm_setting_vlan_get_ingress_priority_map (setting); - if (list != NULL) - g_slist_foreach ((GSList *)list, (GFunc)ingress_priority_iterator, new_link); + if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS) + kernel_flags |= VLAN_FLAG_REORDER_HDR; + if (vlan_flags & NM_VLAN_FLAG_GVRP) + kernel_flags |= VLAN_FLAG_GVRP; + if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING) + kernel_flags |= VLAN_FLAG_LOOSE_BINDING; - list = nm_setting_vlan_get_egress_priority_map (setting); - if (list != NULL) - g_slist_foreach((GSList *)list, (GFunc)egress_priority_iterator, new_link); + rtnl_link_vlan_set_flags (new_link, kernel_flags); + } + + num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP); + for (i = 0; i < num; i++) { + if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to)) + rtnl_link_vlan_set_ingress_map (new_link, (int) from, (int) to); + } + + num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP); + for (i = 0; i < num; i++) { + if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) + rtnl_link_vlan_set_egress_map (new_link, (int) from, (int) to); + } ret = rtnl_link_add (nlh, new_link, NLM_F_CREATE); - if (ret < 0) - goto free_new_link; - rtnl_link_put (new_link); - - return TRUE; - -free_new_link: - rtnl_link_put (new_link); - - return FALSE; +out: + if (new_link) + rtnl_link_put (new_link); + return (ret == 0); } /** - * nm_system_del_vlan_device: - * @setting: NMSettingVlan + * nm_system_del_vlan_iface: + * @iface: the interface name * - * Delete a VLAN device specified in @setting. + * Delete a VLAN interface specified by @iface. * * Returns: %TRUE on success, or %FALSE */ gboolean -nm_system_del_vlan_device (NMSettingVlan *setting) +nm_system_del_vlan_iface (const char *iface) { int ret = 0; struct nl_sock *nlh = NULL; struct nl_cache *cache = NULL; struct rtnl_link *new_link = NULL; - const char *interface_name = NULL; + int itype; - interface_name = nm_setting_vlan_get_interface_name (setting); - g_return_val_if_fail (interface_name != NULL, FALSE); + g_return_val_if_fail (iface != NULL, FALSE); + + itype = nm_system_get_iface_type (-1, iface); + g_return_val_if_fail (itype == NM_IFACE_TYPE_VLAN, FALSE); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, FALSE); @@ -1661,22 +1645,12 @@ nm_system_del_vlan_device (NMSettingVlan *setting) g_return_val_if_fail (ret == 0, FALSE); g_return_val_if_fail (cache != NULL, FALSE); - new_link = rtnl_link_get_by_name (cache, interface_name); - if (!new_link) - goto free_cache; + new_link = rtnl_link_get_by_name (cache, iface); + if (new_link) { + ret = rtnl_link_delete (nlh, new_link); + rtnl_link_put (new_link); + } - ret = rtnl_link_delete (nlh, new_link); - if (ret < 0) - goto free_new_link; - - rtnl_link_put (new_link); - - return TRUE; - -free_new_link: - rtnl_link_put (new_link); - -free_cache: nl_cache_free (cache); - return FALSE; + return (ret == 0) ? TRUE : FALSE; } diff --git a/src/nm-system.h b/src/nm-system.h index 95d6d56e8..c7f518281 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -103,7 +103,9 @@ enum { int nm_system_get_iface_type (int ifindex, const char *name); -gboolean nm_system_add_vlan_device (NMSettingVlan *setting); -gboolean nm_system_del_vlan_device (NMSettingVlan *setting); +gboolean nm_system_add_vlan_iface (NMConnection *connection, + const char *iface, + int master_ifindex); +gboolean nm_system_del_vlan_iface (const char *iface); #endif