diff --git a/src/settings/plugins/ifcfg-rh/common.h b/src/settings/plugins/ifcfg-rh/common.h index 13b89d752b..7993af26e9 100644 --- a/src/settings/plugins/ifcfg-rh/common.h +++ b/src/settings/plugins/ifcfg-rh/common.h @@ -46,6 +46,7 @@ #define TYPE_INFINIBAND "Infiniband" #define TYPE_BRIDGE "Bridge" #define TYPE_BOND "Bond" +#define TYPE_VLAN "Vlan" #define SECRET_FLAG_AGENT "user" #define SECRET_FLAG_NOT_SAVED "ask" diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 0aa1e7566d..c863e0932c 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -3708,10 +3709,171 @@ is_bond_device (const char *name, shvarFile *parsed) return FALSE; } +static NMSetting * +make_vlan_setting (shvarFile *ifcfg, + const char *file, + gboolean nm_controlled, + char **unmanaged, + NMSetting8021x **s_8021x, + GError **error) +{ + NMSettingVlan *s_vlan = NULL; + char *value = NULL; + char *interface_name = NULL; + char *vlan_slave = NULL; + char *p = NULL; + guint32 vlan_id = 0; + guint32 vlan_flags = 0; + + s_vlan = NM_SETTING_VLAN (nm_setting_vlan_new ()); + + interface_name = svGetValue (ifcfg, "DEVICE", FALSE); + if (!interface_name) + goto error_return; + else + g_object_set (s_vlan, NM_SETTING_VLAN_INTERFACE_NAME, interface_name, NULL); + + p = strchr (interface_name, -1, '.'); + if (p) { + /* + * eth0.43 + * PHYSDEV is assumed from it + */ + vlan_slave = g_strndup (interface_name, p - interface_name); + p++; + } else { + /* + * vlan43 + * PHYSDEV must be set + */ + p = interface_name + 4; + vlan_slave = svGetValue (ifcfg, "PHYSDEV", FALSE); + } + + vlan_id = g_ascii_strtoull (p, NULL, 10); + if (vlan_id >= 0 && vlan_id < 4096) + g_object_set (s_vlan, NM_SETTING_VLAN_ID, vlan_id, NULL); + else + goto free_interface_name; + + if (vlan_slave) { + g_object_set (s_vlan, NM_SETTING_VLAN_SLAVE, vlan_slave, NULL); + g_free (vlan_slave); + } + + value = svGetValue (ifcfg, "REORDER_HDR", FALSE); + if (value) + vlan_flags |= NM_VLAN_FLAG_REORDER_HDR; + g_free (value); + + value = svGetValue (ifcfg, "VLAN_FLAGS", FALSE); + if (g_strstr_len (value, -1, "GVRP")) + vlan_flags |= NM_VLAN_FLAG_GVRP; + if (g_strstr_len (value, -1, "LOOSE_BINDING")) + vlan_flags |= NM_VLAN_FLAG_LOOSE_BINDING; + + g_object_set (s_vlan, NM_SETTING_VLAN_FLAGS, vlan_flags, NULL); + g_free (value); + + value = svGetValue (ifcfg, "VLAN_INGRESS_PRIORITY_MAP", FALSE); + if (value) { + gchar **list = NULL, **iter; + list = g_strsplit_set (value, ",", -1); + for (iter = list; iter && *iter; iter++) { + if (!g_strrstr (*iter, ":")) + continue; + + if (!nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_INGRESS_MAP, *iter)) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid priority map '%s'", *iter); + } + g_free (value); + g_strfreev (list); + } + + value = svGetValue (ifcfg, "VLAN_EGRESS_PRIORITY_MAP", FALSE); + if (value) { + gchar **list = NULL, **iter; + list = g_strsplit_set (value, ",", -1); + for (iter = list; iter && *iter; iter++) { + if (!g_strrstr (*iter, ":")) + continue; + + if (!nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_EGRESS_MAP, *iter)) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid priority map '%s'", *iter); + } + g_free (value); + g_strfreev (list); + } + + return (NMSetting *) s_vlan; + +free_interface_name: + g_free (vlan_slave); + g_free (interface_name); +error_return: + g_object_unref (s_vlan); + return NULL; +} + +static NMConnection * +vlan_connection_from_ifcfg (const char *file, + shvarFile *ifcfg, + gboolean nm_controlled, + char **unmanaged, + GError **error) +{ + NMConnection *connection = NULL; + NMSetting *con_setting = NULL; + NMSetting *wired_setting = NULL; + NMSetting *vlan_setting = NULL; + NMSetting8021x *s_8021x = NULL; + + g_return_val_if_fail (file != NULL, NULL); + g_return_val_if_fail (ifcfg != NULL, NULL); + + connection = nm_connection_new (); + if (!connection) { + g_set_error (error, IFCFG_PLUGIN_ERROR, 0, + "Failed to allocate new connection for %s.", file); + return NULL; + } + + con_setting = make_connection_setting (file, ifcfg, NM_SETTING_VLAN_SETTING_NAME, NULL, "Vlan"); + if (!con_setting) { + g_set_error (error, IFCFG_PLUGIN_ERROR, 0, + "Failed to create connection setting."); + g_object_unref (connection); + return NULL; + } + nm_connection_add_setting (connection, con_setting); + + vlan_setting = make_vlan_setting (ifcfg, file, nm_controlled, unmanaged, &s_8021x, error); + if (!vlan_setting) { + g_object_unref (connection); + return NULL; + } + nm_connection_add_setting (connection, vlan_setting); + + wired_setting = make_wired_setting (ifcfg, file, nm_controlled, unmanaged, &s_8021x, error); + if (!wired_setting) { + g_object_unref (connection); + return NULL; + } + nm_connection_add_setting (connection, wired_setting); + + if (s_8021x) + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + if (!nm_connection_verify (connection, error)) { + g_object_unref (connection); + return NULL; + } + + return connection; +} + enum { IGNORE_REASON_NONE = 0x00, IGNORE_REASON_BRIDGE = 0x01, - IGNORE_REASON_VLAN = 0x02, }; NMConnection * @@ -3831,7 +3993,7 @@ connection_from_file (const char *filename, goto done; } - /* Ignore BRIDGE= and VLAN= connections for now too (rh #619863) */ + /* Ignore BRIDGE= connections for now too (rh #619863) */ tmp = svGetValue (parsed, "BRIDGE", FALSE); if (tmp) { g_free (tmp); @@ -3839,15 +4001,6 @@ connection_from_file (const char *filename, ignore_reason = IGNORE_REASON_BRIDGE; } - if (nm_controlled) { - tmp = svGetValue (parsed, "VLAN", FALSE); - if (tmp) { - g_free (tmp); - nm_controlled = FALSE; - ignore_reason = IGNORE_REASON_VLAN; - } - } - /* Construct the connection */ if (!strcasecmp (type, TYPE_ETHERNET)) connection = wired_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error); @@ -3855,11 +4008,13 @@ connection_from_file (const char *filename, connection = wireless_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error); else if (!strcasecmp (type, TYPE_INFINIBAND)) connection = infiniband_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error); - else if (!strcasecmp (type, TYPE_BRIDGE)) { + else if (!strcasecmp (type, TYPE_BOND)) + connection = bond_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error); + else if (!strcasecmp (type, TYPE_VLAN)) + connection = vlan_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error); + else if (!strcasecmp (type, TYPE_BRIDGE)) g_set_error (&error, IFCFG_PLUGIN_ERROR, 0, "Bridge connections are not yet supported"); - } else if (!strcasecmp (type, TYPE_BOND)) - connection = bond_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error); else { g_set_error (&error, IFCFG_PLUGIN_ERROR, 0, "Unknown connection type '%s'", type); diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface index 6c841855ed..ccd75d7ffb 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface @@ -1,7 +1,12 @@ -DEVICE=eth1.43 VLAN=yes +TYPE=Vlan +DEVICE=vlan43 +PHYSDEV=eth9 +REORDER_HDR=0 +VLAN_FLAGS=GVRP,LOOSE_BINDING +VLAN_INGRESS_PRIORITY_MAP=0:1,2:5 +VLAN_EGRESS_PRIORITY_MAP=12:3,14:7,3:1 ONBOOT=yes -BOOTPROTO=none +BOOTPROTO=static IPADDR=192.168.43.149 NETMASK=255.255.255.0 - diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index d54584d97b..62c66c7f52 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -11755,6 +11755,9 @@ test_read_vlan_interface (void) char *route6file = NULL; gboolean ignore_error = FALSE; GError *error = NULL; + NMSettingConnection *s_con; + NMSettingVlan *s_vlan; + guint32 from = 0, to = 0; connection = connection_from_file (TEST_IFCFG_VLAN_INTERFACE, NULL, @@ -11766,13 +11769,55 @@ test_read_vlan_interface (void) &route6file, &error, &ignore_error); - ASSERT (connection == NULL, + ASSERT (connection != NULL, "vlan-interface-read", "unexpected success reading %s", TEST_IFCFG_VLAN_INTERFACE); g_free (unmanaged); g_free (keyfile); g_free (routefile); g_free (route6file); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, "eth9"); + g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_VLAN_SETTING_NAME); + + s_vlan = nm_connection_get_setting_vlan (connection); + g_assert (s_vlan); + + g_assert_cmpstr (nm_setting_vlan_get_interface_name (s_vlan), ==, "vlan43"); + g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 43); + g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, + NM_VLAN_FLAG_GVRP | NM_VLAN_FLAG_LOOSE_BINDING); + + /* Ingress map */ + g_assert_cmpint (nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP), ==, 2); + + g_assert (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, 0, &from, &to)); + g_assert_cmpint (from, ==, 0); + g_assert_cmpint (to, ==, 1); + + g_assert (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1, &from, &to)); + g_assert_cmpint (from, ==, 2); + g_assert_cmpint (to, ==, 5); + + /* Egress map */ + g_assert_cmpint (nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP), ==, 3); + + g_assert (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, 0, &from, &to)); + g_assert_cmpint (from, ==, 12); + g_assert_cmpint (to, ==, 3); + + g_assert (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1, &from, &to)); + g_assert_cmpint (from, ==, 14); + g_assert_cmpint (to, ==, 7); + + g_assert (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, 2, &from, &to)); + g_assert_cmpint (from, ==, 3); + g_assert_cmpint (to, ==, 1); + + g_object_unref (connection); } #define TEST_IFCFG_BOND_MAIN TEST_IFCFG_DIR"/network-scripts/ifcfg-test-bond-main"