From 13a981fc389eb7622df8d3b7015c4fff954c60bc Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sun, 6 Sep 2015 13:11:11 +0200 Subject: [PATCH 01/18] libnm-core: add nm_utils_enum_get_values() Add function nm_utils_enum_get_values() which returns a string array containing the enum values. It can be used, for example, to build a list of allowed values for user. --- libnm-core/nm-utils.c | 52 +++++++++++++++++++++++++++++++++ libnm-core/nm-utils.h | 3 ++ libnm-core/tests/test-general.c | 21 +++++++++++++ libnm/libnm.ver | 1 + 4 files changed, 77 insertions(+) diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index e3c6b80bef..5e920de482 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -4120,3 +4120,55 @@ NM_BACKPORT_SYMBOL (libnm_1_0_6, gboolean, nm_utils_enum_from_str, (GType type, const char *str, int *out_value, char **err_token), (type, str, out_value, err_token)); +/** + * nm_utils_enum_get_values: + * @type: the %GType of the enum + * @from: the first element to be returned + * @to: the last element to be returned + * + * Returns the list of possible values for a given enum. + * + * Returns: a NULL-terminated dynamically-allocated array of static strings + * or %NULL on error + * + * Since: 1.2 + */ +const char **nm_utils_enum_get_values (GType type, gint from, gint to) +{ + GTypeClass *class; + GPtrArray *array; + gint i; + + class = g_type_class_ref (type); + array = g_ptr_array_new (); + + if (G_IS_ENUM_CLASS (class)) { + GEnumClass *enum_class = G_ENUM_CLASS (class); + GEnumValue *enum_value; + + for (i = 0; i < enum_class->n_values; i++) { + enum_value = &enum_class->values[i]; + if (enum_value->value >= from && enum_value->value <= to) + g_ptr_array_add (array, (gpointer) enum_value->value_nick); + } + } else if (G_IS_FLAGS_CLASS (class)) { + GFlagsClass *flags_class = G_FLAGS_CLASS (class); + GFlagsValue *flags_value; + + for (i = 0; i < flags_class->n_values; i++) { + flags_value = &flags_class->values[i]; + if (flags_value->value >= from && flags_value->value <= to) + g_ptr_array_add (array, (gpointer) flags_value->value_nick); + } + } else { + g_type_class_unref (class); + g_ptr_array_free (array, TRUE); + g_return_val_if_reached (NULL); + } + + g_type_class_unref (class); + g_ptr_array_add (array, NULL); + + return (const char **) g_ptr_array_free (array, FALSE); +} + diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index 4be58e09a1..407c14e2c4 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -203,6 +203,9 @@ char *nm_utils_enum_to_str (GType type, int value); NM_AVAILABLE_IN_1_2 gboolean nm_utils_enum_from_str (GType type, const char *str, int *out_value, char **err_token); +NM_AVAILABLE_IN_1_2 +const char **nm_utils_enum_get_values (GType type, gint from, gint to); + G_END_DECLS #endif /* __NM_UTILS_H__ */ diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index f4dec283ce..e8eb0bafb5 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -4740,6 +4740,21 @@ test_nm_utils_enum_to_str_do (GType type, int flags, const char *exp_str) g_free (str); } +static void +test_nm_utils_enum_get_values_do (GType type, int from, int to, const char *exp_str) +{ + const char **strv; + char *str; + + strv = nm_utils_enum_get_values (type, from, to); + g_assert (strv); + str = g_strjoinv (",", (char **) strv); + g_assert_cmpstr (str, ==, exp_str); + g_free (str); + g_free (strv); +} + + static void test_nm_utils_enum (void) { GType bool_enum = nm_test_general_bool_enum_get_type(); @@ -4783,6 +4798,12 @@ static void test_nm_utils_enum (void) test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE | NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL); test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white"); + + test_nm_utils_enum_get_values_do (bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown"); + test_nm_utils_enum_get_values_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, + NM_TEST_GENERAL_BOOL_ENUM_MAYBE, "yes,maybe"); + test_nm_utils_enum_get_values_do (meta_flags, 0, G_MAXINT, "none,foo,bar,baz"); + test_nm_utils_enum_get_values_do (color_flags, 0, G_MAXINT, "blue,red,green"); } /******************************************************************************/ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 865cc328df..81321f7af6 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -925,6 +925,7 @@ global: nm_utils_bond_mode_string_to_int; nm_utils_enum_from_str; nm_utils_enum_to_str; + nm_utils_enum_get_values; nm_utils_wifi_2ghz_freqs; nm_utils_wifi_5ghz_freqs; nm_vpn_editor_plugin_load_from_file; From ae8c7a8967c6f91aeeea75a37cd3d14bf0edb67d Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 1 Sep 2015 14:06:00 +0200 Subject: [PATCH 02/18] libnm-core: add NMSettingIPTunnel Add a generic NMSettingTunnel which describes properties of tunnels over IPv4 and IPv6 (GRE, SIT, IPIP, IPIP6, IP6GRE, etc.). Since those tunnel types all have similar properties it makes sense to have a single setting type for them. --- libnm-core/Makefile.libnm-core | 2 + libnm-core/nm-connection.c | 18 + libnm-core/nm-connection.h | 2 + libnm-core/nm-core-internal.h | 1 + libnm-core/nm-core-types.h | 1 + libnm-core/nm-dbus-interface.h | 32 +- libnm-core/nm-setting-ip-tunnel.c | 724 ++++++++++++++++++++++++++++++ libnm-core/nm-setting-ip-tunnel.h | 95 ++++ libnm/NetworkManager.h | 1 + libnm/libnm.ver | 13 + po/POTFILES.in | 1 + 11 files changed, 889 insertions(+), 1 deletion(-) create mode 100644 libnm-core/nm-setting-ip-tunnel.c create mode 100644 libnm-core/nm-setting-ip-tunnel.h diff --git a/libnm-core/Makefile.libnm-core b/libnm-core/Makefile.libnm-core index 867dd9045d..02c1d1021b 100644 --- a/libnm-core/Makefile.libnm-core +++ b/libnm-core/Makefile.libnm-core @@ -25,6 +25,7 @@ libnm_core_headers = \ $(core)/nm-setting-gsm.h \ $(core)/nm-setting-infiniband.h \ $(core)/nm-setting-ip-config.h \ + $(core)/nm-setting-ip-tunnel.h \ $(core)/nm-setting-ip4-config.h \ $(core)/nm-setting-ip6-config.h \ $(core)/nm-setting-olpc-mesh.h \ @@ -82,6 +83,7 @@ libnm_core_sources = \ $(core)/nm-setting-gsm.c \ $(core)/nm-setting-infiniband.c \ $(core)/nm-setting-ip-config.c \ + $(core)/nm-setting-ip-tunnel.c \ $(core)/nm-setting-ip4-config.c \ $(core)/nm-setting-ip6-config.c \ $(core)/nm-setting-olpc-mesh.c \ diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 94a897539a..0f599984c9 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1865,6 +1865,24 @@ nm_connection_get_setting_ip4_config (NMConnection *connection) return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); } +/** + * nm_connection_get_setting_ip_tunnel: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingIPTunnel the connection might contain. + * + * Returns: (transfer none): an #NMSettingIPTunnel if the connection contains one, otherwise %NULL + * + * Since: 1.2 + **/ +NMSettingIPTunnel * +nm_connection_get_setting_ip_tunnel (NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + return (NMSettingIPTunnel *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP_TUNNEL); +} + /** * nm_connection_get_setting_ip6_config: * @connection: the #NMConnection diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h index fc2117f61e..8896e59bab 100644 --- a/libnm-core/nm-connection.h +++ b/libnm-core/nm-connection.h @@ -202,6 +202,8 @@ NMSettingDcb * nm_connection_get_setting_dcb (NMConnec NMSettingGeneric * nm_connection_get_setting_generic (NMConnection *connection); NMSettingGsm * nm_connection_get_setting_gsm (NMConnection *connection); NMSettingInfiniband * nm_connection_get_setting_infiniband (NMConnection *connection); +NM_AVAILABLE_IN_1_2 +NMSettingIPTunnel * nm_connection_get_setting_ip_tunnel (NMConnection *connection); NMSettingIPConfig * nm_connection_get_setting_ip4_config (NMConnection *connection); NMSettingIPConfig * nm_connection_get_setting_ip6_config (NMConnection *connection); NMSettingOlpcMesh * nm_connection_get_setting_olpc_mesh (NMConnection *connection); diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index d1b0992900..c1eea777f2 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -49,6 +49,7 @@ #include "nm-setting-generic.h" #include "nm-setting-gsm.h" #include "nm-setting-infiniband.h" +#include "nm-setting-ip-tunnel.h" #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" #include "nm-setting-olpc-mesh.h" diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index 1355c92da6..29a34cc68d 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -42,6 +42,7 @@ typedef struct _NMSettingGeneric NMSettingGeneric; typedef struct _NMSettingGsm NMSettingGsm; typedef struct _NMSettingInfiniband NMSettingInfiniband; typedef struct _NMSettingIPConfig NMSettingIPConfig; +typedef struct _NMSettingIPTunnel NMSettingIPTunnel; typedef struct _NMSettingIP4Config NMSettingIP4Config; typedef struct _NMSettingIP6Config NMSettingIP6Config; typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh; diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index ddd6834c23..e81f081dff 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -67,7 +67,7 @@ #define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan" #define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" #define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre" - +#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel" #define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" #define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings" @@ -668,4 +668,34 @@ typedef enum /*< flags >*/ { #define NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE "nearest-non-tpmr-bridge" #define NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE "nearest-customer-bridge" +/** + * NMIPTunnelMode: + * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode + * @NM_IP_TUNNEL_MODE_IPIP: IP in IP tunnel + * @NM_IP_TUNNEL_MODE_GRE: GRE tunnel + * @NM_IP_TUNNEL_MODE_SIT: SIT tunnel + * @NM_IP_TUNNEL_MODE_ISATAP: ISATAP tunnel + * @NM_IP_TUNNEL_MODE_VTI: VTI tunnel + * @NM_IP_TUNNEL_MODE_IP6IP6: IPv6 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel + * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel + * + * The tunneling mode. + * + * Since: 1.2 + */ +typedef enum { + NM_IP_TUNNEL_MODE_UKNOWN = 0, + NM_IP_TUNNEL_MODE_IPIP = 1, + NM_IP_TUNNEL_MODE_GRE = 2, + NM_IP_TUNNEL_MODE_SIT = 3, + NM_IP_TUNNEL_MODE_ISATAP = 4, + NM_IP_TUNNEL_MODE_VTI = 5, + NM_IP_TUNNEL_MODE_IP6IP6 = 6, + NM_IP_TUNNEL_MODE_IPIP6 = 7, + NM_IP_TUNNEL_MODE_IP6GRE = 8, + NM_IP_TUNNEL_MODE_VTI6 = 9, +} NMIPTunnelMode; + #endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c new file mode 100644 index 0000000000..d561524950 --- /dev/null +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -0,0 +1,724 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#include "nm-setting-ip-tunnel.h" + +#include "config.h" + +#include "nm-setting-private.h" +#include "nm-macros-internal.h" +#include "nm-utils.h" + +/** + * SECTION:nm-setting-tunnel + * @short_description: Describes connection properties for IP tunnel devices + **/ + +G_DEFINE_TYPE_WITH_CODE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING, + _nm_register_setting (IP_TUNNEL, 1)) +NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP_TUNNEL) + +#define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate)) + +typedef struct { + char *parent; + NMIPTunnelMode mode; + char *local; + char *remote; + guint ttl; + guint tos; + gboolean path_mtu_discovery; + char *input_key; + char *output_key; + guint encapsulation_limit; + guint flow_label; +} NMSettingIPTunnelPrivate; + +enum { + PROP_0, + PROP_PARENT, + PROP_MODE, + PROP_LOCAL, + PROP_REMOTE, + PROP_TTL, + PROP_TOS, + PROP_PATH_MTU_DISCOVERY, + PROP_INPUT_KEY, + PROP_OUTPUT_KEY, + PROP_ENCAPSULATION_LIMIT, + PROP_FLOW_LABEL, + + LAST_PROP +}; + +/** + * nm_setting_ip_tunnel_get_parent: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:parent property of the setting + * + * Returns: the parent device + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_parent (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL); + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->parent; +} + +/** + * nm_setting_ip_tunnel_get_mode: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:mode property of the setting. + * + * Returns: the tunnel mode + * + * Since: 1.2 + **/ +NMIPTunnelMode +nm_setting_ip_tunnel_get_mode (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->mode; +} + +/** + * nm_setting_ip_tunnel_get_local: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:local property of the setting. + * + * Returns: the local endpoint + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_local (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->local; +} + +/** + * nm_setting_ip_tunnel_get_remote: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:remote property of the setting. + * + * Returns: the remote endpoint + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_remote (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->remote; +} + +/** + * nm_setting_ip_tunnel_get_ttl: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:ttl property of the setting. + * + * Returns: the Time-to-live value + * + * Since: 1.2 + **/ + +guint +nm_setting_ip_tunnel_get_ttl (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->ttl; +} + +/** + * nm_setting_ip_tunnel_get_tos: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:tos property of the setting. + * + * Returns: the TOS value + * + * Since: 1.2 + **/ +guint +nm_setting_ip_tunnel_get_tos (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->tos; +} + +/** + * nm_setting_ip_tunnel_get_path_mtu_discovery: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:path-mtu-discovery property of the setting. + * + * Returns: whether path MTU discovery is enabled + * + * Since: 1.2 + **/ +gboolean +nm_setting_ip_tunnel_get_path_mtu_discovery (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), TRUE); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->path_mtu_discovery; +} + +/** + * nm_setting_ip_tunnel_get_input_key: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:input-key property of the setting. + * + * Returns: the input key + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_input_key (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->input_key; +} + +/** + * nm_setting_ip_tunnel_get_output_key: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:output-key property of the setting. + * + * Returns: the output key + * + * Since: 1.2 + **/ +const char * +nm_setting_ip_tunnel_get_output_key (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->output_key; +} + +/** + * nm_setting_ip_tunnel_get_encapsulation_limit: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:encapsulation-limit property of the setting. + * + * Returns: the encapsulation limit value + * + * Since: 1.2 + **/ +guint +nm_setting_ip_tunnel_get_encapsulation_limit (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->encapsulation_limit; +} + +/** + * nm_setting_ip_tunnel_get_flow_label: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:flow-label property of the setting. + * + * Returns: the flow label value + * + * Since: 1.2 + **/ +guint +nm_setting_ip_tunnel_get_flow_label (NMSettingIPTunnel *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->flow_label; +} + +/*********************************************************************/ + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting); + int family; + + switch (priv->mode) { + case NM_IP_TUNNEL_MODE_IPIP: + case NM_IP_TUNNEL_MODE_SIT: + case NM_IP_TUNNEL_MODE_ISATAP: + case NM_IP_TUNNEL_MODE_GRE: + case NM_IP_TUNNEL_MODE_VTI: + family = AF_INET; + break; + case NM_IP_TUNNEL_MODE_IP6IP6: + case NM_IP_TUNNEL_MODE_IPIP6: + case NM_IP_TUNNEL_MODE_IP6GRE: + case NM_IP_TUNNEL_MODE_VTI6: + family = AF_INET6; + break; + default: + family = AF_UNSPEC; + } + + if (family == AF_UNSPEC) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%d' is not a valid tunnel mode"), + (int) priv->mode); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_MODE); + return FALSE; + } + + if ( priv->parent + && !nm_utils_iface_valid_name (priv->parent) + && !nm_utils_is_uuid (priv->parent)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_PARENT); + return FALSE; + } + + if (priv->local && !nm_utils_ipaddr_valid (family, priv->local)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IPv%c address"), + priv->local, + family == AF_INET ? '4' : '6'); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_LOCAL); + return FALSE; + } + + if (priv->remote && !nm_utils_ipaddr_valid (family, priv->remote)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IPv%c address"), + priv->remote, + family == AF_INET ? '4' : '6'); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_REMOTE); + return FALSE; + } + + if ( (priv->input_key && priv->input_key[0]) + || (priv->output_key && priv->output_key[0])) { + if ( priv->mode != NM_IP_TUNNEL_MODE_GRE + && priv->mode != NM_IP_TUNNEL_MODE_IP6GRE) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("tunnel keys can only be specified for GRE tunnels")); + return FALSE; + } + } + + if (priv->input_key && priv->input_key[0]) { + gint64 val; + + val = _nm_utils_ascii_str_to_int64 (priv->input_key, 10, 0, G_MAXUINT32, -1); + if (val == -1) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid tunnel key"), + priv->input_key); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_INPUT_KEY); + return FALSE; + } + } + + if (priv->output_key && priv->output_key[0]) { + gint64 val; + + val = _nm_utils_ascii_str_to_int64 (priv->output_key, 10, 0, G_MAXUINT32, -1); + if (val == -1) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid tunnel key"), + priv->output_key); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_OUTPUT_KEY); + return FALSE; + } + } + + if (!priv->path_mtu_discovery && priv->ttl != 0) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("a fixed TTL is allowed only when path MTU discovery is enabled")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_TTL); + return FALSE; + } + + return TRUE; +} + +/** + * nm_setting_ip_tunnel_new: + * + * Creates a new #NMSettingIPTunnel object with default values. + * + * Returns: (transfer full): the new empty #NMSettingIPTunnel object + * + * Since: 1.2 + **/ +NMSetting * +nm_setting_ip_tunnel_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP_TUNNEL, NULL); +} + +static void +nm_setting_ip_tunnel_init (NMSettingIPTunnel *setting) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingIPTunnel *setting = NM_SETTING_IP_TUNNEL (object); + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_PARENT: + g_free (priv->parent); + priv->parent = g_value_dup_string (value); + break; + case PROP_MODE: + priv->mode = g_value_get_uint (value); + break; + case PROP_LOCAL: + g_free (priv->local); + priv->local = g_value_dup_string (value); + break; + case PROP_REMOTE: + g_free (priv->remote); + priv->remote = g_value_dup_string (value); + break; + case PROP_TTL: + priv->ttl = g_value_get_uint (value); + break; + case PROP_TOS: + priv->tos = g_value_get_uint (value); + break; + case PROP_PATH_MTU_DISCOVERY: + priv->path_mtu_discovery = g_value_get_boolean (value); + break; + case PROP_INPUT_KEY: + g_free (priv->input_key); + priv->input_key = g_value_dup_string (value); + break; + case PROP_OUTPUT_KEY: + g_free (priv->output_key); + priv->output_key = g_value_dup_string (value); + break; + case PROP_ENCAPSULATION_LIMIT: + priv->encapsulation_limit = g_value_get_uint (value); + break; + case PROP_FLOW_LABEL: + priv->flow_label = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingIPTunnel *setting = NM_SETTING_IP_TUNNEL (object); + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string (value, priv->parent); + break; + case PROP_MODE: + g_value_set_uint (value, priv->mode); + break; + case PROP_LOCAL: + g_value_set_string (value, priv->local); + break; + case PROP_REMOTE: + g_value_set_string (value, priv->remote); + break; + case PROP_TTL: + g_value_set_uint (value, priv->ttl); + break; + case PROP_TOS: + g_value_set_uint (value, priv->tos); + break; + case PROP_PATH_MTU_DISCOVERY: + g_value_set_boolean (value, priv->path_mtu_discovery); + break; + case PROP_INPUT_KEY: + g_value_set_string (value, priv->input_key); + break; + case PROP_OUTPUT_KEY: + g_value_set_string (value, priv->output_key); + break; + case PROP_ENCAPSULATION_LIMIT: + g_value_set_uint (value, priv->encapsulation_limit); + break; + case PROP_FLOW_LABEL: + g_value_set_uint (value, priv->flow_label); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMSettingIPTunnel *setting = NM_SETTING_IP_TUNNEL (object); + NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting); + + g_free (priv->local); + g_free (priv->remote); + g_free (priv->input_key); + g_free (priv->output_key); + + G_OBJECT_CLASS (nm_setting_ip_tunnel_parent_class)->finalize (object); +} + +static void +nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingIPTunnelPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /** + * NMSettingIPTunnel:parent: + * + * If given, specifies the parent interface name or parent connection UUID + * the new device will be bound to so that tunneled packets will only be + * routed via that interface. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_string (NM_SETTING_IP_TUNNEL_PARENT, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:mode: + * + * The tunneling mode, for example %NM_IP_TUNNEL_MODE_IPIP or + * %NM_IP_TUNNEL_MODE_GRE. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_uint (NM_SETTING_IP_TUNNEL_MODE, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:local: + * + * The local endpoint of the tunnel; the value can be empty, otherwise it + * must contain an IPv4 or IPv6 address. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_SETTING_IP_TUNNEL_LOCAL, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:remote: + * + * The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 + * address. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_REMOTE, + g_param_spec_string (NM_SETTING_IP_TUNNEL_REMOTE, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:ttl + * + * The TTL to assign to tunneled packets. 0 is a special value meaning that + * packets inherit the TTL value. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uint (NM_SETTING_IP_TUNNEL_TTL, "", "", + 0, 255, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:tos + * + * The type of service (IPv4) or traffic class (IPv6) field to be set on + * tunneled packets. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uint (NM_SETTING_IP_TUNNEL_TOS, "", "", + 0, 255, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:path-mtu-discovery + * + * Whether to enable Path MTU Discovery on this tunnel. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_PATH_MTU_DISCOVERY, + g_param_spec_boolean (NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:input-key: + * + * The key used for tunnel input packets; the property is valid only for + * certain tunnel modes (GRE, IP6GRE). If empty, no key is used. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_INPUT_KEY, + g_param_spec_string (NM_SETTING_IP_TUNNEL_INPUT_KEY, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:output-key: + * + * The key used for tunnel output packets; the property is valid only for + * certain tunnel modes (GRE, IP6GRE). If empty, no key is used. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_OUTPUT_KEY, + g_param_spec_string (NM_SETTING_IP_TUNNEL_OUTPUT_KEY, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:encapsulation-limit: + * + * How many additional levels of encapsulation are permitted to be prepended + * to packets. This property applies only to IPv6 tunnels. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_ENCAPSULATION_LIMIT, + g_param_spec_uint (NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, "", "", + 0, 255, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingIPTunnel:flow-label: + * + * The flow label to assign to tunnel packets. This property applies only to + * IPv6 tunnels. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_FLOW_LABEL, + g_param_spec_uint (NM_SETTING_IP_TUNNEL_FLOW_LABEL, "", "", + 0, (1 << 20) - 1, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm-core/nm-setting-ip-tunnel.h b/libnm-core/nm-setting-ip-tunnel.h new file mode 100644 index 0000000000..a07bd50db0 --- /dev/null +++ b/libnm-core/nm-setting-ip-tunnel.h @@ -0,0 +1,95 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_IP_TUNNEL_H__ +#define __NM_SETTING_IP_TUNNEL_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_IP_TUNNEL (nm_setting_ip_tunnel_get_type ()) +#define NM_SETTING_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnel)) +#define NM_SETTING_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass)) +#define NM_IS_SETTING_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_IP_TUNNEL)) +#define NM_IS_SETTING_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_IP_TUNNEL)) +#define NM_SETTING_IP_TUNNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass)) + +#define NM_SETTING_IP_TUNNEL_SETTING_NAME "ip-tunnel" + +#define NM_SETTING_IP_TUNNEL_PARENT "parent" +#define NM_SETTING_IP_TUNNEL_MODE "mode" +#define NM_SETTING_IP_TUNNEL_LOCAL "local" +#define NM_SETTING_IP_TUNNEL_REMOTE "remote" +#define NM_SETTING_IP_TUNNEL_TTL "ttl" +#define NM_SETTING_IP_TUNNEL_TOS "tos" +#define NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY "path-mtu-discovery" +#define NM_SETTING_IP_TUNNEL_INPUT_KEY "input-key" +#define NM_SETTING_IP_TUNNEL_OUTPUT_KEY "output-key" +#define NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" +#define NM_SETTING_IP_TUNNEL_FLOW_LABEL "flow-label" + +struct _NMSettingIPTunnel { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingIPTunnelClass; + +NM_AVAILABLE_IN_1_2 +GType nm_setting_ip_tunnel_get_type (void); + +NM_AVAILABLE_IN_1_2 +NMSetting * nm_setting_ip_tunnel_new (void); + +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_parent (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +NMIPTunnelMode nm_setting_ip_tunnel_get_mode (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_local (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_remote (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_ttl (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_tos (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_ip_tunnel_get_path_mtu_discovery (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_input_key (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_ip_tunnel_get_output_key (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_encapsulation_limit (NMSettingIPTunnel *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_ip_tunnel_get_flow_label (NMSettingIPTunnel *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_IP_TUNNEL_H__ */ diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h index 95c92965e3..17e7a3523b 100644 --- a/libnm/NetworkManager.h +++ b/libnm/NetworkManager.h @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 81321f7af6..f5150d7277 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -858,6 +858,7 @@ libnm_1_0_6 { libnm_1_2_0 { global: nm_access_point_get_last_seen; + nm_connection_get_setting_ip_tunnel; nm_connection_verify_secrets; nm_device_ethernet_get_s390_subchannels; nm_device_get_lldp_neighbors; @@ -874,6 +875,7 @@ global: nm_device_tun_get_vnet_hdr; nm_device_wifi_request_scan_options; nm_device_wifi_request_scan_options_async; + nm_ip_tunnel_mode_get_type; nm_lldp_neighbor_get_attr_names; nm_lldp_neighbor_get_attr_string_value; nm_lldp_neighbor_get_attr_type; @@ -904,6 +906,17 @@ global: nm_setting_ip_config_has_dns_options; nm_setting_ip_config_remove_dns_option; nm_setting_ip_config_remove_dns_option_by_value; + nm_setting_ip_tunnel_get_input_key; + nm_setting_ip_tunnel_get_local; + nm_setting_ip_tunnel_get_mode; + nm_setting_ip_tunnel_get_output_key; + nm_setting_ip_tunnel_get_parent; + nm_setting_ip_tunnel_get_path_mtu_discovery; + nm_setting_ip_tunnel_get_remote; + nm_setting_ip_tunnel_get_tos; + nm_setting_ip_tunnel_get_type; + nm_setting_ip_tunnel_get_ttl; + nm_setting_ip_tunnel_new; nm_setting_mac_randomization_get_type; nm_setting_tun_get_group; nm_setting_tun_get_mode; diff --git a/po/POTFILES.in b/po/POTFILES.in index ca4b76ab1f..ba861b7eeb 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -65,6 +65,7 @@ libnm-core/nm-setting-infiniband.c libnm-core/nm-setting-ip-config.c libnm-core/nm-setting-ip4-config.c libnm-core/nm-setting-ip6-config.c +libnm-core/nm-setting-ip-tunnel.c libnm-core/nm-setting-olpc-mesh.c libnm-core/nm-setting-ppp.c libnm-core/nm-setting-pppoe.c From b614a5ec6174bd6dce1ea9593160dd7164fdbd57 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 1 Sep 2015 15:14:03 +0200 Subject: [PATCH 03/18] cli: add support for IP tunnel settings --- clients/cli/connections.c | 130 ++++++++++++++++++++++- clients/cli/nmcli-completion | 2 +- clients/cli/settings.c | 195 +++++++++++++++++++++++++++++++++++ 3 files changed, 325 insertions(+), 2 deletions(-) diff --git a/clients/cli/connections.c b/clients/cli/connections.c index bb07552f9c..659815a2f6 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -116,6 +116,7 @@ extern NmcOutputField nmc_fields_setting_team[]; extern NmcOutputField nmc_fields_setting_team_port[]; extern NmcOutputField nmc_fields_setting_dcb[]; extern NmcOutputField nmc_fields_setting_tun[]; +extern NmcOutputField nmc_fields_setting_ip_tunnel[]; /* Available settings for 'connection show ' - profile part */ static NmcOutputField nmc_fields_settings_names[] = { @@ -145,6 +146,7 @@ static NmcOutputField nmc_fields_settings_names[] = { SETTING_FIELD (NM_SETTING_TEAM_PORT_SETTING_NAME, nmc_fields_setting_team_port + 1), /* 23 */ SETTING_FIELD (NM_SETTING_DCB_SETTING_NAME, nmc_fields_setting_dcb + 1), /* 24 */ SETTING_FIELD (NM_SETTING_TUN_SETTING_NAME, nmc_fields_setting_tun + 1), /* 25 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_SETTING_NAME, nmc_fields_setting_ip_tunnel + 1), /* 26 */ {NULL, NULL, 0, NULL, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTINGS_NAMES_ALL_X NM_SETTING_CONNECTION_SETTING_NAME","\ @@ -171,7 +173,8 @@ static NmcOutputField nmc_fields_settings_names[] = { NM_SETTING_TEAM_SETTING_NAME","\ NM_SETTING_TEAM_PORT_SETTING_NAME"," \ NM_SETTING_DCB_SETTING_NAME"," \ - NM_SETTING_TUN_SETTING_NAME + NM_SETTING_TUN_SETTING_NAME"," \ + NM_SETTING_IP_TUNNEL_SETTING_NAME #define NMC_FIELDS_SETTINGS_NAMES_ALL NMC_FIELDS_SETTINGS_NAMES_ALL_X /* Active connection data */ @@ -2757,6 +2760,14 @@ static const NameItem nmc_tun_settings [] = { { NULL, NULL, NULL, FALSE } }; +static const NameItem nmc_ip_tunnel_settings [] = { + { NM_SETTING_CONNECTION_SETTING_NAME, NULL, NULL, TRUE }, + { NM_SETTING_IP_TUNNEL_SETTING_NAME, NULL, NULL, TRUE }, + { NM_SETTING_IP4_CONFIG_SETTING_NAME, NULL, NULL, FALSE }, + { NM_SETTING_IP6_CONFIG_SETTING_NAME, NULL, NULL, FALSE }, + { NULL, NULL, NULL, FALSE } +}; + /* Available connection types */ static const NameItem nmc_valid_connection_types[] = { { NM_SETTING_GENERIC_SETTING_NAME, NULL, nmc_generic_settings }, @@ -2779,6 +2790,7 @@ static const NameItem nmc_valid_connection_types[] = { { "team-slave", NULL, nmc_team_slave_settings }, { "bridge-slave", NULL, nmc_bridge_slave_settings }, { NM_SETTING_TUN_SETTING_NAME, NULL, nmc_tun_settings }, + { NM_SETTING_IP_TUNNEL_SETTING_NAME, NULL, nmc_ip_tunnel_settings }, { NULL, NULL, NULL } }; @@ -4383,6 +4395,31 @@ do_questionnaire_tun (char **user, char **group, } } +static void +do_questionnaire_ip_tunnel (char **local) +{ + gboolean once_more; + + /* Ask for optional 'ip-tunnel' arguments. */ + if (!want_provide_opt_args (_("IP Tunnel"), 1)) + return; + + if (!*local) { + do { + *local = nmc_readline (_("Local endpoint [none]: ")); + if (!*local) + break; + once_more = !nm_utils_ipaddr_valid (AF_INET, *local) + && !nm_utils_ipaddr_valid (AF_INET6, *local); + if (once_more) { + g_print (_("Error: 'local': '%s' is not valid; must be an IP address\n"), + *local); + g_free (*local); + } + } while (once_more); + } +} + static gboolean read_connection_properties (NMConnection *connection, int argc, @@ -4594,6 +4631,7 @@ complete_connection_by_type (NMConnection *connection, NMSettingOlpcMesh *s_olpc_mesh; NMSettingAdsl *s_adsl; NMSettingTun *s_tun; + NMSettingIPTunnel *s_ip_tunnel; const char *slave_type; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -5813,6 +5851,96 @@ cleanup_tun: g_free (multi_queue); if (!success) return FALSE; + + } else if (!strcmp (con_type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) { + /* Build up the settings required for 'ip-tunnel' */ + const char *mode_c = NULL, *local_c = NULL, *remote_c = NULL; + char *mode_ask = NULL, *remote_ask = NULL, *local = NULL; + gboolean success = FALSE; + NMIPTunnelMode mode_enum; + nmc_arg_t exp_args[] = { {"mode", TRUE, &mode_c, !ask}, + {"local", TRUE, &local_c, FALSE}, + {"remote", TRUE, &remote_c, !ask}, + {NULL} }; + + if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, error)) + return FALSE; + + if (!mode_c && ask) + mode_c = mode_ask = nmc_readline (_("Tunnel mode: ")); + if (!mode_c) { + g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'mode' is required.")); + goto cleanup_tunnel; + } + + if (!remote_c && ask) + remote_c = remote_ask = nmc_readline (_("Remote endpoint: ")); + if (!remote_c) { + g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'remote' is required.")); + goto cleanup_tunnel; + } + + if (!nm_utils_enum_from_str (nm_ip_tunnel_mode_get_type (), + mode_c, (int *) &mode_enum, NULL)) { + gs_free const char **values = NULL; + gs_free char *values_str = NULL; + + values = nm_utils_enum_get_values (nm_ip_tunnel_mode_get_type (), + NM_IP_TUNNEL_MODE_UKNOWN + 1, + G_MAXINT); + values_str = g_strjoinv (",", (char **) values); + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'mode': '%s' is not valid, use one of %s"), + mode_c, values_str); + goto cleanup_tunnel; + } + + if ( !nm_utils_ipaddr_valid (AF_INET, remote_c) + && !nm_utils_ipaddr_valid (AF_INET6, remote_c)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'remote': '%s' is not valid; must be an IP address"), + remote_c); + goto cleanup_tunnel; + } + + local = g_strdup (local_c); + if (ask) + do_questionnaire_ip_tunnel (&local); + + if ( local + && !nm_utils_ipaddr_valid (AF_INET, local) + && !nm_utils_ipaddr_valid (AF_INET6, local)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'local': '%s' is not valid; must be an IP address"), + local); + goto cleanup_tunnel; + } + + /* Add 'tunnel' setting */ + s_ip_tunnel = (NMSettingIPTunnel *) nm_setting_ip_tunnel_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip_tunnel)); + + /* Set 'tunnel' properties */ + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_MODE, mode_enum, NULL); + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_REMOTE, remote_c, NULL); + if (local) + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_LOCAL, local, NULL); + + /* Set default values for IPv6 tunnels */ + if (nm_utils_ipaddr_valid (AF_INET6, remote_c)) { + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_TOS, 64, NULL); + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, 4, NULL); + } + + success = TRUE; +cleanup_tunnel: + g_free (remote_ask); + g_free (mode_ask); + if (!success) + return FALSE; + } else if (!strcmp (con_type, NM_SETTING_GENERIC_SETTING_NAME)) { /* Add 'generic' setting */ s_generic = (NMSettingGeneric *) nm_setting_generic_new (); diff --git a/clients/cli/nmcli-completion b/clients/cli/nmcli-completion index 1827551b0c..2424fc6d7c 100644 --- a/clients/cli/nmcli-completion +++ b/clients/cli/nmcli-completion @@ -401,7 +401,7 @@ _nmcli_compl_ARGS() # user friendly. Only complete them, if the current word already starts with an "8". _nmcli_list "802-3-ethernet 802-11-wireless 802-11-olpc-mesh" else - _nmcli_list "ethernet wifi wimax gsm cdma infiniband bluetooth vpn olpc-mesh vlan bond bridge team pppoe adsl tun" + _nmcli_list "ethernet wifi wimax gsm cdma infiniband bluetooth vpn olpc-mesh vlan bond bridge team pppoe adsl tun ip-tunnel" fi return 0 fi diff --git a/clients/cli/settings.c b/clients/cli/settings.c index bf2cadc707..3e8c10f4c2 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -718,6 +718,36 @@ NmcOutputField nmc_fields_setting_tun[] = { NM_SETTING_TUN_MULTI_QUEUE #define NMC_FIELDS_SETTING_TUN_COMMON NMC_FIELDS_SETTING_TUN_ALL +/* Available fields for NM_SETTING_IP_TUNNEL_SETTING_NAME */ +NmcOutputField nmc_fields_setting_ip_tunnel[] = { + SETTING_FIELD ("name"), /* 0 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_MODE), /* 1 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_PARENT), /* 2 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_LOCAL), /* 3 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_REMOTE), /* 4 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_TTL), /* 5 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_TOS), /* 6 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY), /* 7 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_INPUT_KEY), /* 8 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_OUTPUT_KEY), /* 9 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT), /* 10 */ + SETTING_FIELD (NM_SETTING_IP_TUNNEL_FLOW_LABEL), /* 11 */ + {NULL, NULL, 0, NULL, FALSE, FALSE, 0} +}; +#define NMC_FIELDS_SETTING_IP_TUNNEL_ALL "name"","\ + NM_SETTING_IP_TUNNEL_MODE","\ + NM_SETTING_IP_TUNNEL_PARENT","\ + NM_SETTING_IP_TUNNEL_LOCAL","\ + NM_SETTING_IP_TUNNEL_REMOTE","\ + NM_SETTING_IP_TUNNEL_TTL","\ + NM_SETTING_IP_TUNNEL_TOS","\ + NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY","\ + NM_SETTING_IP_TUNNEL_INPUT_KEY","\ + NM_SETTING_IP_TUNNEL_OUTPUT_KEY","\ + NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT","\ + NM_SETTING_IP_TUNNEL_FLOW_LABEL +#define NMC_FIELDS_SETTING_IP_TUNNEL_COMMON NMC_FIELDS_SETTING_IP_TUNNEL_ALL + /*----------------------------------------------------------------------------*/ static char * wep_key_type_to_string (NMWepKeyType type) @@ -1310,6 +1340,17 @@ DEFINE_GETTER (nmc_property_tun_get_pi, NM_SETTING_TUN_PI); DEFINE_GETTER (nmc_property_tun_get_vnet_hdr, NM_SETTING_TUN_VNET_HDR); DEFINE_GETTER (nmc_property_tun_get_multi_queue, NM_SETTING_TUN_MULTI_QUEUE); +DEFINE_GETTER (nmc_property_ip_tunnel_get_parent, NM_SETTING_IP_TUNNEL_PARENT); +DEFINE_GETTER (nmc_property_ip_tunnel_get_local, NM_SETTING_IP_TUNNEL_LOCAL); +DEFINE_GETTER (nmc_property_ip_tunnel_get_remote, NM_SETTING_IP_TUNNEL_REMOTE); +DEFINE_GETTER (nmc_property_ip_tunnel_get_ttl, NM_SETTING_IP_TUNNEL_TTL); +DEFINE_GETTER (nmc_property_ip_tunnel_get_tos, NM_SETTING_IP_TUNNEL_TOS); +DEFINE_GETTER (nmc_property_ip_tunnel_get_path_mtu_discovery, NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY); +DEFINE_GETTER (nmc_property_ip_tunnel_get_input_key, NM_SETTING_IP_TUNNEL_INPUT_KEY); +DEFINE_GETTER (nmc_property_ip_tunnel_get_output_key, NM_SETTING_IP_TUNNEL_OUTPUT_KEY); +DEFINE_GETTER (nmc_property_ip_tunnel_get_encapsulation_limit, NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT); +DEFINE_GETTER (nmc_property_ip_tunnel_get_flow_label, NM_SETTING_IP_TUNNEL_FLOW_LABEL); + static char * nmc_property_ib_get_mtu (NMSetting *setting, NmcPropertyGetType get_type) { @@ -1665,6 +1706,44 @@ nmc_property_wired_set_wake_on_lan (NMSetting *setting, const char *prop, return TRUE; } +static char * +nmc_property_ip_tunnel_get_mode (NMSetting *setting, NmcPropertyGetType get_type) +{ + NMSettingIPTunnel *s_ip_tunnel = NM_SETTING_IP_TUNNEL (setting); + NMIPTunnelMode mode; + + mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); + return nm_utils_enum_to_str (nm_ip_tunnel_mode_get_type (), mode); +} + +static gboolean +nmc_property_ip_tunnel_set_mode (NMSetting *setting, const char *prop, + const char *val, GError **error) +{ + NMIPTunnelMode mode; + gboolean ret; + + ret = nm_utils_enum_from_str (nm_ip_tunnel_mode_get_type(), val, + (int *) &mode, NULL); + + if (!ret) { + gs_free const char **values = NULL; + gs_free char *values_str = NULL; + + values = nm_utils_enum_get_values (nm_ip_tunnel_mode_get_type (), + NM_IP_TUNNEL_MODE_UKNOWN + 1, + G_MAXINT); + values_str = g_strjoinv (",", (char **) values); + g_set_error (error, 1, 0, _("invalid mode '%s', use one of %s"), + val, values_str); + + return FALSE; + } + + g_object_set (setting, prop, mode, NULL); + return TRUE; +} + /* --- NM_SETTING_WIRELESS_SETTING_NAME property get functions --- */ DEFINE_GETTER (nmc_property_wireless_get_mode, NM_SETTING_WIRELESS_MODE) DEFINE_GETTER (nmc_property_wireless_get_band, NM_SETTING_WIRELESS_BAND) @@ -7073,6 +7152,85 @@ nmc_properties_init (void) NULL, NULL, NULL); + + /* Add editable properties for NM_SETTING_IP_TUNNEL_SETTING_NAME */ + nmc_add_prop_funcs (GLUE (IP_TUNNEL, MODE), + nmc_property_ip_tunnel_get_mode, + nmc_property_ip_tunnel_set_mode, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, PARENT), + nmc_property_ip_tunnel_get_parent, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, LOCAL), + nmc_property_ip_tunnel_get_local, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, REMOTE), + nmc_property_ip_tunnel_get_remote, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, TTL), + nmc_property_ip_tunnel_get_ttl, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, TOS), + nmc_property_ip_tunnel_get_tos, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, PATH_MTU_DISCOVERY), + nmc_property_ip_tunnel_get_path_mtu_discovery, + nmc_property_set_bool, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, INPUT_KEY), + nmc_property_ip_tunnel_get_input_key, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, OUTPUT_KEY), + nmc_property_ip_tunnel_get_output_key, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, ENCAPSULATION_LIMIT), + nmc_property_ip_tunnel_get_encapsulation_limit, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (IP_TUNNEL, FLOW_LABEL), + nmc_property_ip_tunnel_get_flow_label, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); } void @@ -8253,6 +8411,42 @@ setting_tun_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gboo return TRUE; } +static gboolean +setting_ip_tunnel_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets) +{ + NMSettingIPTunnel *s_ip_tunnel = NM_SETTING_IP_TUNNEL (setting); + NmcOutputField *tmpl, *arr; + size_t tmpl_len; + + g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (s_ip_tunnel), FALSE); + + tmpl = nmc_fields_setting_ip_tunnel; + tmpl_len = sizeof (nmc_fields_setting_ip_tunnel); + nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_IP_TUNNEL_ALL, + tmpl, FALSE, NULL, NULL); + arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES); + g_ptr_array_add (nmc->output_data, arr); + + arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX); + set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting))); + set_val_str (arr, 1, nmc_property_ip_tunnel_get_mode (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 2, nmc_property_ip_tunnel_get_parent (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 3, nmc_property_ip_tunnel_get_local (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 4, nmc_property_ip_tunnel_get_remote (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 5, nmc_property_ip_tunnel_get_ttl (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 6, nmc_property_ip_tunnel_get_tos (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 7, nmc_property_ip_tunnel_get_path_mtu_discovery (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 8, nmc_property_ip_tunnel_get_input_key (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 9, nmc_property_ip_tunnel_get_output_key (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 10, nmc_property_ip_tunnel_get_encapsulation_limit (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 11, nmc_property_ip_tunnel_get_flow_label (setting, NMC_PROPERTY_GET_PRETTY)); + g_ptr_array_add (nmc->output_data, arr); + + print_data (nmc); /* Print all data */ + + return TRUE; +} + typedef struct { const char *sname; gboolean (*func) (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets); @@ -8285,6 +8479,7 @@ static const SettingDetails detail_printers[] = { { NM_SETTING_TEAM_PORT_SETTING_NAME, setting_team_port_details }, { NM_SETTING_DCB_SETTING_NAME, setting_dcb_details }, { NM_SETTING_TUN_SETTING_NAME, setting_tun_details }, + { NM_SETTING_IP_TUNNEL_SETTING_NAME, setting_ip_tunnel_details }, { NULL }, }; From 91bf0efaa7dbfed84954192a449f6770d20105c1 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 1 Sep 2015 22:11:47 +0200 Subject: [PATCH 04/18] platform: add GRE links creation support --- src/platform/nm-linux-platform.c | 67 ++++++++++++++++++++++++++++++-- src/platform/nm-platform.c | 41 +++++++++++++++++++ src/platform/nm-platform.h | 10 +++++ 3 files changed, 114 insertions(+), 4 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index b79aa76767..27d04d1772 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -118,6 +118,8 @@ } \ } G_STMT_END +#define LOG_FMT_IP_TUNNEL "adding %s '%s' parent %u local %s remote %s" + /****************************************************************** * Forward declarations and enums ******************************************************************/ @@ -821,10 +823,10 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data) props = &obj->lnk_gre; props->parent_ifindex = tb[IFLA_GRE_LINK] ? nla_get_u32 (tb[IFLA_GRE_LINK]) : 0; - props->input_flags = tb[IFLA_GRE_IFLAGS] ? nla_get_u16 (tb[IFLA_GRE_IFLAGS]) : 0; - props->output_flags = tb[IFLA_GRE_OFLAGS] ? nla_get_u16 (tb[IFLA_GRE_OFLAGS]) : 0; - props->input_key = (props->input_flags & GRE_KEY) && tb[IFLA_GRE_IKEY] ? nla_get_u32 (tb[IFLA_GRE_IKEY]) : 0; - props->output_key = (props->output_flags & GRE_KEY) && tb[IFLA_GRE_OKEY] ? nla_get_u32 (tb[IFLA_GRE_OKEY]) : 0; + props->input_flags = tb[IFLA_GRE_IFLAGS] ? ntohs (nla_get_u16 (tb[IFLA_GRE_IFLAGS])) : 0; + props->output_flags = tb[IFLA_GRE_OFLAGS] ? ntohs (nla_get_u16 (tb[IFLA_GRE_OFLAGS])) : 0; + props->input_key = tb[IFLA_GRE_IKEY] ? ntohl (nla_get_u32 (tb[IFLA_GRE_IKEY])) : 0; + props->output_key = tb[IFLA_GRE_OKEY] ? ntohl (nla_get_u32 (tb[IFLA_GRE_OKEY])) : 0; props->local = tb[IFLA_GRE_LOCAL] ? nla_get_u32 (tb[IFLA_GRE_LOCAL]) : 0; props->remote = tb[IFLA_GRE_REMOTE] ? nla_get_u32 (tb[IFLA_GRE_REMOTE]) : 0; props->tos = tb[IFLA_GRE_TOS] ? nla_get_u8 (tb[IFLA_GRE_TOS]) : 0; @@ -4034,6 +4036,61 @@ nla_put_failure: g_return_val_if_reached (FALSE); } +static int +link_gre_add (NMPlatform *platform, + const char *name, + NMPlatformLnkGre *props, + NMPlatformLink *out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *info; + struct nlattr *data; + char buffer[INET_ADDRSTRLEN]; + + _LOGD (LOG_FMT_IP_TUNNEL, + "gre", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + NLM_F_CREATE, + 0, + name, + 0, + 0); + if (!nlmsg) + return FALSE; + + if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "gre"); + + if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (nlmsg, IFLA_GRE_LINK, props->parent_ifindex); + NLA_PUT_U32 (nlmsg, IFLA_GRE_LOCAL, props->local); + NLA_PUT_U32 (nlmsg, IFLA_GRE_REMOTE, props->remote); + NLA_PUT_U8 (nlmsg, IFLA_GRE_TTL, props->ttl); + NLA_PUT_U8 (nlmsg, IFLA_GRE_TOS, props->tos); + NLA_PUT_U8 (nlmsg, IFLA_GRE_PMTUDISC, !!props->path_mtu_discovery); + NLA_PUT_U32 (nlmsg, IFLA_GRE_IKEY, htonl (props->input_key)); + NLA_PUT_U32 (nlmsg, IFLA_GRE_OKEY, htonl (props->output_key)); + NLA_PUT_U32 (nlmsg, IFLA_GRE_IFLAGS, htons (props->input_flags)); + NLA_PUT_U32 (nlmsg, IFLA_GRE_OFLAGS, htons (props->output_flags)); + + nla_nest_end (nlmsg, data); + nla_nest_end (nlmsg, info); + + return do_add_link_with_lookup (platform, NM_LINK_TYPE_GRE, name, nlmsg, out_link); +nla_put_failure: + g_return_val_if_reached (FALSE); +} + static void _vlan_change_vlan_qos_mapping_create (gboolean is_ingress_map, gboolean reset_all, @@ -5487,6 +5544,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->mesh_set_channel = mesh_set_channel; platform_class->mesh_set_ssid = mesh_set_ssid; + platform_class->link_gre_add = link_gre_add; + platform_class->ip4_address_get = ip4_address_get; platform_class->ip6_address_get = ip6_address_get; platform_class->ip4_address_get_all = ip4_address_get_all; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index bb82ab0959..fb8924ef2a 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -71,6 +71,8 @@ G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OF } \ } G_STMT_END +#define LOG_FMT_IP_TUNNEL "adding %s '%s' parent %u local %s remote %s" + /*****************************************************************************/ #define NM_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PLATFORM, NMPlatformPrivate)) @@ -1709,6 +1711,45 @@ nm_platform_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, int to return nm_platform_link_vlan_change (self, ifindex, 0, 0, FALSE, NULL, 0, FALSE, &map, 1); } +/** + * nm_platform_link_gre_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create a software GRE device. + */ +NMPlatformError +nm_platform_link_gre_add (NMPlatform *self, + const char *name, + NMPlatformLnkGre *props, + NMPlatformLink *out_link) +{ + NMPlatformError plerr; + char buffer[INET_ADDRSTRLEN]; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_GRE, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD (LOG_FMT_IP_TUNNEL, + "gre", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + if (!klass->link_gre_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + NMPlatformError nm_platform_infiniband_partition_add (NMPlatform *self, int parent, int p_key, NMPlatformLink *out_link) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 00029b3aeb..432c29c150 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -63,6 +63,9 @@ typedef struct _NMPlatform NMPlatform; #define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */ +/* Redefine this in host's endianness */ +#define NM_GRE_KEY 0x2000 + typedef enum { /*< skip >*/ /* dummy value, to enforce that the enum type is signed and has a size @@ -524,6 +527,9 @@ typedef struct { const NMVlanQosMapping *egress_map, gsize n_egress_map); + gboolean (*link_gre_add) (NMPlatform *, const char *name, NMPlatformLnkGre *props, + NMPlatformLink *out_link); + gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key, NMPlatformLink *out_link); gboolean (*tun_add) (NMPlatform *platform, const char *name, gboolean tap, gint64 owner, gint64 group, gboolean pi, @@ -762,6 +768,10 @@ void nm_platform_ip4_address_set_addr (NMPlatformIP4Address *a const struct in6_addr *nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr); const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address); + +NMPlatformError nm_platform_link_gre_add (NMPlatform *self, const char *name, NMPlatformLnkGre *props, + NMPlatformLink *out_link); + const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen); GArray *nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex); GArray *nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex); From 0754280b9fa68131bf2d7c8d263045c4dabb9043 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 11 Nov 2015 18:41:48 +0100 Subject: [PATCH 05/18] platform: add SIT links support --- src/nm-types.h | 2 + src/platform/nm-linux-platform.c | 114 +++++++++++++++++++++++++++++++ src/platform/nm-platform.c | 98 ++++++++++++++++++++++++++ src/platform/nm-platform.h | 18 +++++ src/platform/nmp-object.c | 9 +++ src/platform/nmp-object.h | 7 ++ 6 files changed, 248 insertions(+) diff --git a/src/nm-types.h b/src/nm-types.h index 6dbd3b3b45..aa6a507a30 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -112,6 +112,7 @@ typedef enum { NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP, NM_LINK_TYPE_OPENVSWITCH, + NM_LINK_TYPE_SIT, NM_LINK_TYPE_TAP, NM_LINK_TYPE_TUN, NM_LINK_TYPE_VETH, @@ -136,6 +137,7 @@ typedef enum { NMP_OBJECT_TYPE_LNK_GRE, NMP_OBJECT_TYPE_LNK_INFINIBAND, NMP_OBJECT_TYPE_LNK_MACVLAN, + NMP_OBJECT_TYPE_LNK_SIT, NMP_OBJECT_TYPE_LNK_VLAN, NMP_OBJECT_TYPE_LNK_VXLAN, diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 27d04d1772..f8e713ad96 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -86,6 +86,19 @@ #define IFLA_MACVLAN_FLAGS 2 #define __IFLA_MACVLAN_MAX 3 +#define IFLA_IPTUN_LINK 1 +#define IFLA_IPTUN_LOCAL 2 +#define IFLA_IPTUN_REMOTE 3 +#define IFLA_IPTUN_TTL 4 +#define IFLA_IPTUN_TOS 5 +#define IFLA_IPTUN_FLAGS 8 +#define IFLA_IPTUN_PROTO 9 +#define IFLA_IPTUN_PMTUDISC 10 +#define __IFLA_IPTUN_MAX 19 +#ifndef IFLA_IPTUN_MAX +#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) +#endif + #ifndef MACVLAN_FLAG_NOPROMISC #define MACVLAN_FLAG_NOPROMISC 1 #endif @@ -320,6 +333,7 @@ static const LinkDesc linktypes[] = { { NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL }, { NM_LINK_TYPE_MACVTAP, "macvtap", "macvtap", NULL }, { NM_LINK_TYPE_OPENVSWITCH, "openvswitch", "openvswitch", NULL }, + { NM_LINK_TYPE_SIT, "sit", "sit", NULL }, { NM_LINK_TYPE_TAP, "tap", NULL, NULL }, { NM_LINK_TYPE_TUN, "tun", NULL, NULL }, { NM_LINK_TYPE_VETH, "veth", "veth", NULL }, @@ -613,6 +627,8 @@ _linktype_get_type (NMPlatform *platform, return NM_LINK_TYPE_LOOPBACK; else if (arptype == ARPHRD_INFINIBAND) return NM_LINK_TYPE_INFINIBAND; + else if (arptype == ARPHRD_SIT) + return NM_LINK_TYPE_SIT; if (ifname) { gs_free char *driver = NULL; @@ -950,6 +966,48 @@ _parse_lnk_macvlan (const char *kind, struct nlattr *info_data) /*****************************************************************************/ +static NMPObject * +_parse_lnk_sit (const char *kind, struct nlattr *info_data) +{ + static struct nla_policy policy[IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 }, + [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 }, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, + [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, + [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, + [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, + }; + struct nlattr *tb[IFLA_IPTUN_MAX + 1]; + int err; + NMPObject *obj; + NMPlatformLnkSit *props; + + if (!info_data || g_strcmp0 (kind, "sit")) + return NULL; + + err = nla_parse_nested (tb, IFLA_IPTUN_MAX, info_data, policy); + if (err < 0) + return NULL; + + obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_SIT, NULL); + props = &obj->lnk_sit; + + props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32 (tb[IFLA_IPTUN_LINK]) : 0; + props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32 (tb[IFLA_IPTUN_LOCAL]) : 0; + props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32 (tb[IFLA_IPTUN_REMOTE]) : 0; + props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8 (tb[IFLA_IPTUN_TOS]) : 0; + props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8 (tb[IFLA_IPTUN_TTL]) : 0; + props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8 (tb[IFLA_IPTUN_PMTUDISC]); + props->flags = tb[IFLA_IPTUN_FLAGS] ? nla_get_u16 (tb[IFLA_IPTUN_FLAGS]) : 0; + props->proto = tb[IFLA_IPTUN_PROTO] ? nla_get_u8 (tb[IFLA_IPTUN_PROTO]) : 0; + + return obj; +} + +/*****************************************************************************/ + static gboolean _vlan_qos_mapping_from_nla (struct nlattr *nlattr, const NMVlanQosMapping **out_map, @@ -1330,6 +1388,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case NM_LINK_TYPE_MACVLAN: lnk_data = _parse_lnk_macvlan (nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_SIT: + lnk_data = _parse_lnk_sit (nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_VLAN: lnk_data = _parse_lnk_vlan (nl_info_kind, nl_info_data); break; @@ -2738,6 +2799,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP case NM_LINK_TYPE_GRE: case NM_LINK_TYPE_INFINIBAND: case NM_LINK_TYPE_MACVLAN: + case NM_LINK_TYPE_SIT: case NM_LINK_TYPE_VLAN: case NM_LINK_TYPE_VXLAN: delayed_action_schedule (platform, @@ -4091,6 +4153,57 @@ nla_put_failure: g_return_val_if_reached (FALSE); } +static int +link_sit_add (NMPlatform *platform, + const char *name, + NMPlatformLnkSit *props, + NMPlatformLink *out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *info; + struct nlattr *data; + char buffer[INET_ADDRSTRLEN]; + + _LOGD (LOG_FMT_IP_TUNNEL, + "sit", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + NLM_F_CREATE, + 0, + name, + 0, + 0); + if (!nlmsg) + return FALSE; + + if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "sit"); + + if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LINK, props->parent_ifindex); + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LOCAL, props->local); + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_REMOTE, props->remote); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TOS, props->tos); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); + + nla_nest_end (nlmsg, data); + nla_nest_end (nlmsg, info); + + return do_add_link_with_lookup (platform, NM_LINK_TYPE_SIT, name, nlmsg, out_link); +nla_put_failure: + g_return_val_if_reached (FALSE); +} + static void _vlan_change_vlan_qos_mapping_create (gboolean is_ingress_map, gboolean reset_all, @@ -5545,6 +5658,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->mesh_set_ssid = mesh_set_ssid; platform_class->link_gre_add = link_gre_add; + platform_class->link_sit_add = link_sit_add; platform_class->ip4_address_get = ip4_address_get; platform_class->ip6_address_get = ip6_address_get; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index fb8924ef2a..dc0b156371 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1435,6 +1435,12 @@ nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatfor return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVLAN, out_link); } +const NMPlatformLnkSit * +nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_SIT, out_link); +} + const NMPlatformLnkVlan * nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -1847,6 +1853,45 @@ nm_platform_infiniband_get_properties (NMPlatform *self, return TRUE; } +/** + * nm_platform_sit_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create a software SIT device. + */ +NMPlatformError +nm_platform_link_sit_add (NMPlatform *self, + const char *name, + NMPlatformLnkSit *props, + NMPlatformLink *out_link) +{ + NMPlatformError plerr; + char buffer[INET_ADDRSTRLEN]; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_SIT, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD (LOG_FMT_IP_TUNNEL, + "sit", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + if (!klass->link_sit_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + gboolean nm_platform_veth_get_properties (NMPlatform *self, int ifindex, int *out_peer_ifindex) { @@ -2860,6 +2905,44 @@ nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, g return buf; } +const char * +nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_flags[30]; + char str_proto[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "sit" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "%s" /* flags */ + "%s" /* proto */ + "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc", + lnk->flags ? nm_sprintf_buf (str_flags, " flags 0x%x", lnk->flags) : "", + lnk->proto ? nm_sprintf_buf (str_proto, " proto 0x%x", lnk->proto) : ""); + return buf; +} + const char * nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len) { @@ -3410,6 +3493,21 @@ nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkM return 0; } +int +nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD (a, b, local); + _CMP_FIELD (a, b, remote); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD (a, b, tos); + _CMP_FIELD_BOOL (a, b, path_mtu_discovery); + _CMP_FIELD (a, b, flags); + _CMP_FIELD (a, b, proto); + return 0; +} + int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 432c29c150..e39845145c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -383,6 +383,17 @@ typedef struct { gboolean no_promisc; } NMPlatformLnkMacvlan; +typedef struct { + int parent_ifindex; + in_addr_t local; + in_addr_t remote; + guint8 ttl; + guint8 tos; + gboolean path_mtu_discovery; + guint16 flags; + guint8 proto; +} NMPlatformLnkSit; + typedef struct { /* rtnl_link_vlan_get_id(), IFLA_VLAN_ID */ guint16 id; @@ -529,6 +540,8 @@ typedef struct { gboolean (*link_gre_add) (NMPlatform *, const char *name, NMPlatformLnkGre *props, NMPlatformLink *out_link); + gboolean (*link_sit_add) (NMPlatform *, const char *name, NMPlatformLnkSit *props, + NMPlatformLink *out_link); gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key, NMPlatformLink *out_link); @@ -720,6 +733,7 @@ const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLink const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkVlan *nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkVxlan *nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); @@ -771,6 +785,8 @@ const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int i NMPlatformError nm_platform_link_gre_add (NMPlatform *self, const char *name, NMPlatformLnkGre *props, NMPlatformLink *out_link); +NMPlatformError nm_platform_link_sit_add (NMPlatform *self, const char *name, NMPlatformLnkSit *props, + NMPlatformLink *out_link); const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen); GArray *nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex); @@ -814,6 +830,7 @@ const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, g const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len); const char *nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len); +const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len); const char *nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len); const char *nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len); const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len); @@ -831,6 +848,7 @@ int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b); int nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); int nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b); int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b); +int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b); int nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b); int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index ef467f4241..8ef2f9ab7a 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -2054,6 +2054,15 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_macvlan_to_string, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp, }, + [NMP_OBJECT_TYPE_LNK_SIT - 1] = { + .obj_type = NMP_OBJECT_TYPE_LNK_SIT, + .sizeof_data = sizeof (NMPObjectLnkSit), + .sizeof_public = sizeof (NMPlatformLnkSit), + .obj_type_name = "sit", + .lnk_link_type = NM_LINK_TYPE_SIT, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_sit_to_string, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_sit_cmp, + }, [NMP_OBJECT_TYPE_LNK_VLAN - 1] = { .obj_type = NMP_OBJECT_TYPE_LNK_VLAN, .sizeof_data = sizeof (NMPObjectLnkVlan), diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 971bd37eca..61e82a580a 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -173,6 +173,10 @@ typedef struct { NMPlatformLnkMacvlan _public; } NMPObjectLnkMacvlan; +typedef struct { + NMPlatformLnkSit _public; +} NMPObjectLnkSit; + typedef struct { NMPlatformLnkVlan _public; @@ -221,6 +225,9 @@ struct _NMPObject { NMPlatformLnkMacvlan lnk_macvlan; NMPObjectLnkMacvlan _lnk_macvlan; + NMPlatformLnkSit lnk_sit; + NMPObjectLnkSit _lnk_sit; + NMPlatformLnkVlan lnk_vlan; NMPObjectLnkVlan _lnk_vlan; From 30e648f981d9beadf54f0194e194bb7581afadb0 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Fri, 27 Nov 2015 14:01:56 +0100 Subject: [PATCH 06/18] platform: add IPIP links support --- src/nm-types.h | 2 + src/platform/nm-linux-platform.c | 94 ++++++++++++++++++++++++++++++++ src/platform/nm-platform.c | 90 ++++++++++++++++++++++++++++++ src/platform/nm-platform.h | 16 ++++++ src/platform/nmp-object.c | 9 +++ src/platform/nmp-object.h | 7 +++ 6 files changed, 218 insertions(+) diff --git a/src/nm-types.h b/src/nm-types.h index aa6a507a30..9926e813e5 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -108,6 +108,7 @@ typedef enum { NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_IFB, + NM_LINK_TYPE_IPIP, NM_LINK_TYPE_LOOPBACK, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP, @@ -136,6 +137,7 @@ typedef enum { NMP_OBJECT_TYPE_LNK_GRE, NMP_OBJECT_TYPE_LNK_INFINIBAND, + NMP_OBJECT_TYPE_LNK_IPIP, NMP_OBJECT_TYPE_LNK_MACVLAN, NMP_OBJECT_TYPE_LNK_SIT, NMP_OBJECT_TYPE_LNK_VLAN, diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index f8e713ad96..9fcfb4618c 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -329,6 +329,7 @@ static const LinkDesc linktypes[] = { { NM_LINK_TYPE_GRE, "gre", "gre", NULL }, { NM_LINK_TYPE_GRETAP, "gretap", "gretap", NULL }, { NM_LINK_TYPE_IFB, "ifb", "ifb", NULL }, + { NM_LINK_TYPE_IPIP, "ipip", "ipip", NULL }, { NM_LINK_TYPE_LOOPBACK, "loopback", NULL, NULL }, { NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL }, { NM_LINK_TYPE_MACVTAP, "macvtap", "macvtap", NULL }, @@ -914,6 +915,44 @@ _parse_lnk_infiniband (const char *kind, struct nlattr *info_data) /*****************************************************************************/ +static NMPObject * +_parse_lnk_ipip (const char *kind, struct nlattr *info_data) +{ + static struct nla_policy policy[IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 }, + [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 }, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, + [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, + }; + struct nlattr *tb[IFLA_IPTUN_MAX + 1]; + int err; + NMPObject *obj; + NMPlatformLnkIpIp *props; + + if (!info_data || g_strcmp0 (kind, "ipip")) + return NULL; + + err = nla_parse_nested (tb, IFLA_IPTUN_MAX, info_data, policy); + if (err < 0) + return NULL; + + obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_IPIP, NULL); + props = &obj->lnk_ipip; + + props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32 (tb[IFLA_IPTUN_LINK]) : 0; + props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32 (tb[IFLA_IPTUN_LOCAL]) : 0; + props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32 (tb[IFLA_IPTUN_REMOTE]) : 0; + props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8 (tb[IFLA_IPTUN_TOS]) : 0; + props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8 (tb[IFLA_IPTUN_TTL]) : 0; + props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8 (tb[IFLA_IPTUN_PMTUDISC]); + + return obj; +} + +/*****************************************************************************/ + static NMPObject * _parse_lnk_macvlan (const char *kind, struct nlattr *info_data) { @@ -1385,6 +1424,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case NM_LINK_TYPE_INFINIBAND: lnk_data = _parse_lnk_infiniband (nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_IPIP: + lnk_data = _parse_lnk_ipip (nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_MACVLAN: lnk_data = _parse_lnk_macvlan (nl_info_kind, nl_info_data); break; @@ -4153,6 +4195,57 @@ nla_put_failure: g_return_val_if_reached (FALSE); } +static int +link_ipip_add (NMPlatform *platform, + const char *name, + NMPlatformLnkIpIp *props, + NMPlatformLink *out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *info; + struct nlattr *data; + char buffer[INET_ADDRSTRLEN]; + + _LOGD (LOG_FMT_IP_TUNNEL, + "ipip", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + NLM_F_CREATE, + 0, + name, + 0, + 0); + if (!nlmsg) + return FALSE; + + if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "ipip"); + + if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LINK, props->parent_ifindex); + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LOCAL, props->local); + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_REMOTE, props->remote); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TOS, props->tos); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); + + nla_nest_end (nlmsg, data); + nla_nest_end (nlmsg, info); + + return do_add_link_with_lookup (platform, NM_LINK_TYPE_IPIP, name, nlmsg, out_link); +nla_put_failure: + g_return_val_if_reached (FALSE); +} + static int link_sit_add (NMPlatform *platform, const char *name, @@ -5658,6 +5751,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->mesh_set_ssid = mesh_set_ssid; platform_class->link_gre_add = link_gre_add; + platform_class->link_ipip_add = link_ipip_add; platform_class->link_sit_add = link_sit_add; platform_class->ip4_address_get = ip4_address_get; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index dc0b156371..0b86e08387 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1429,6 +1429,12 @@ nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlat return _link_get_lnk (self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link); } +const NMPlatformLnkIpIp * +nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IPIP, out_link); +} + const NMPlatformLnkMacvlan * nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -1853,6 +1859,45 @@ nm_platform_infiniband_get_properties (NMPlatform *self, return TRUE; } +/** + * nm_platform_ipip_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create an IPIP tunnel. + */ +NMPlatformError +nm_platform_link_ipip_add (NMPlatform *self, + const char *name, + NMPlatformLnkIpIp *props, + NMPlatformLink *out_link) +{ + NMPlatformError plerr; + char buffer[INET_ADDRSTRLEN]; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_IPIP, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD (LOG_FMT_IP_TUNNEL, + "ipip", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + if (!klass->link_ipip_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + /** * nm_platform_sit_add: * @self: platform instance @@ -2891,6 +2936,38 @@ nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char * return buf; } +const char * +nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "ipip" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc"); + return buf; +} + const char * nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len) { @@ -3484,6 +3561,19 @@ nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatfo return 0; } +int +nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD (a, b, local); + _CMP_FIELD (a, b, remote); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD (a, b, tos); + _CMP_FIELD_BOOL (a, b, path_mtu_discovery); + return 0; +} + int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index e39845145c..60f0500572 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -378,6 +378,15 @@ typedef struct { const char *mode; } NMPlatformLnkInfiniband; +typedef struct { + int parent_ifindex; + in_addr_t local; + in_addr_t remote; + guint8 ttl; + guint8 tos; + gboolean path_mtu_discovery; +} NMPlatformLnkIpIp; + typedef struct { const char *mode; gboolean no_promisc; @@ -540,6 +549,8 @@ typedef struct { gboolean (*link_gre_add) (NMPlatform *, const char *name, NMPlatformLnkGre *props, NMPlatformLink *out_link); + gboolean (*link_ipip_add) (NMPlatform *, const char *name, NMPlatformLnkIpIp *props, + NMPlatformLink *out_link); gboolean (*link_sit_add) (NMPlatform *, const char *name, NMPlatformLnkSit *props, NMPlatformLink *out_link); @@ -732,6 +743,7 @@ char *nm_platform_slave_get_option (NMPlatform *self, int ifindex, const char *o const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link); const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkVlan *nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); @@ -785,6 +797,8 @@ const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int i NMPlatformError nm_platform_link_gre_add (NMPlatform *self, const char *name, NMPlatformLnkGre *props, NMPlatformLink *out_link); +NMPlatformError nm_platform_link_ipip_add (NMPlatform *self, const char *name, NMPlatformLnkIpIp *props, + NMPlatformLink *out_link); NMPlatformError nm_platform_link_sit_add (NMPlatform *self, const char *name, NMPlatformLnkSit *props, NMPlatformLink *out_link); @@ -829,6 +843,7 @@ gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6 const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len); const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len); const char *nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); +const char *nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len); const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len); const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len); const char *nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len); @@ -847,6 +862,7 @@ const char *nm_platform_vlan_qos_mapping_to_string (const char *name, int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b); int nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); int nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b); +int nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b); int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b); int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 8ef2f9ab7a..da40c8b6a8 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -2045,6 +2045,15 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_infiniband_to_string, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_infiniband_cmp, }, + [NMP_OBJECT_TYPE_LNK_IPIP - 1] = { + .obj_type = NMP_OBJECT_TYPE_LNK_IPIP, + .sizeof_data = sizeof (NMPObjectLnkIpIp), + .sizeof_public = sizeof (NMPlatformLnkIpIp), + .obj_type_name = "ipip", + .lnk_link_type = NM_LINK_TYPE_IPIP, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ipip_to_string, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ipip_cmp, + }, [NMP_OBJECT_TYPE_LNK_MACVLAN - 1] = { .obj_type = NMP_OBJECT_TYPE_LNK_MACVLAN, .sizeof_data = sizeof (NMPObjectLnkMacvlan), diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 61e82a580a..07bd7e5e85 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -169,6 +169,10 @@ typedef struct { NMPlatformLnkInfiniband _public; } NMPObjectLnkInfiniband; +typedef struct { + NMPlatformLnkIpIp _public; +} NMPObjectLnkIpIp; + typedef struct { NMPlatformLnkMacvlan _public; } NMPObjectLnkMacvlan; @@ -222,6 +226,9 @@ struct _NMPObject { NMPlatformLnkInfiniband lnk_infiniband; NMPObjectLnkInfiniband _lnk_infiniband; + NMPlatformLnkIpIp lnk_ipip; + NMPObjectLnkIpIp _lnk_ipip; + NMPlatformLnkMacvlan lnk_macvlan; NMPObjectLnkMacvlan _lnk_macvlan; From 32f6e1ef2e60f25d8b82b16a53b14dc2a6fbd376 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Fri, 27 Nov 2015 22:22:25 +0100 Subject: [PATCH 07/18] platform: add IP6TNL links support --- src/nm-types.h | 2 + src/platform/nm-linux-platform.c | 128 +++++++++++++++++++++++++++++++ src/platform/nm-platform.c | 99 ++++++++++++++++++++++++ src/platform/nm-platform.h | 19 +++++ src/platform/nmp-object.c | 9 +++ src/platform/nmp-object.h | 7 ++ 6 files changed, 264 insertions(+) diff --git a/src/nm-types.h b/src/nm-types.h index 9926e813e5..16ae6fa7b4 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -108,6 +108,7 @@ typedef enum { NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_IFB, + NM_LINK_TYPE_IP6TNL, NM_LINK_TYPE_IPIP, NM_LINK_TYPE_LOOPBACK, NM_LINK_TYPE_MACVLAN, @@ -137,6 +138,7 @@ typedef enum { NMP_OBJECT_TYPE_LNK_GRE, NMP_OBJECT_TYPE_LNK_INFINIBAND, + NMP_OBJECT_TYPE_LNK_IP6TNL, NMP_OBJECT_TYPE_LNK_IPIP, NMP_OBJECT_TYPE_LNK_MACVLAN, NMP_OBJECT_TYPE_LNK_SIT, diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 9fcfb4618c..354641fee8 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -91,6 +91,8 @@ #define IFLA_IPTUN_REMOTE 3 #define IFLA_IPTUN_TTL 4 #define IFLA_IPTUN_TOS 5 +#define IFLA_IPTUN_ENCAP_LIMIT 6 +#define IFLA_IPTUN_FLOWINFO 7 #define IFLA_IPTUN_FLAGS 8 #define IFLA_IPTUN_PROTO 9 #define IFLA_IPTUN_PMTUDISC 10 @@ -103,6 +105,10 @@ #define MACVLAN_FLAG_NOPROMISC 1 #endif +#define IP6_FLOWINFO_TCLASS_MASK 0x0FF00000 +#define IP6_FLOWINFO_TCLASS_SHIFT 20 +#define IP6_FLOWINFO_FLOWLABEL_MASK 0x000FFFFF + /*********************************************************************************************/ #define _NMLOG_PREFIX_NAME "platform-linux" @@ -329,6 +335,7 @@ static const LinkDesc linktypes[] = { { NM_LINK_TYPE_GRE, "gre", "gre", NULL }, { NM_LINK_TYPE_GRETAP, "gretap", "gretap", NULL }, { NM_LINK_TYPE_IFB, "ifb", "ifb", NULL }, + { NM_LINK_TYPE_IP6TNL, "ip6tnl", "ip6tnl", NULL }, { NM_LINK_TYPE_IPIP, "ipip", "ipip", NULL }, { NM_LINK_TYPE_LOOPBACK, "loopback", NULL, NULL }, { NM_LINK_TYPE_MACVLAN, "macvlan", "macvlan", NULL }, @@ -630,6 +637,8 @@ _linktype_get_type (NMPlatform *platform, return NM_LINK_TYPE_INFINIBAND; else if (arptype == ARPHRD_SIT) return NM_LINK_TYPE_SIT; + else if (arptype == ARPHRD_TUNNEL6) + return NM_LINK_TYPE_IP6TNL; if (ifname) { gs_free char *driver = NULL; @@ -915,6 +924,59 @@ _parse_lnk_infiniband (const char *kind, struct nlattr *info_data) /*****************************************************************************/ +static NMPObject * +_parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data) +{ + static struct nla_policy policy[IFLA_IPTUN_MAX + 1] = { + [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NLA_UNSPEC, + .minlen = sizeof (struct in6_addr)}, + [IFLA_IPTUN_REMOTE] = { .type = NLA_UNSPEC, + .minlen = sizeof (struct in6_addr)}, + [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, + [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, + }; + struct nlattr *tb[IFLA_IPTUN_MAX + 1]; + int err; + NMPObject *obj; + NMPlatformLnkIp6Tnl *props; + guint32 flowinfo; + + if (!info_data || g_strcmp0 (kind, "ip6tnl")) + return NULL; + + err = nla_parse_nested (tb, IFLA_IPTUN_MAX, info_data, policy); + if (err < 0) + return NULL; + + obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_IP6TNL, NULL); + props = &obj->lnk_ip6tnl; + + if (tb[IFLA_IPTUN_LINK]) + props->parent_ifindex = nla_get_u32 (tb[IFLA_IPTUN_LINK]); + if (tb[IFLA_IPTUN_LOCAL]) + memcpy (&props->local, nla_data (tb[IFLA_IPTUN_LOCAL]), sizeof (props->local)); + if (tb[IFLA_IPTUN_REMOTE]) + memcpy (&props->remote, nla_data (tb[IFLA_IPTUN_REMOTE]), sizeof (props->remote)); + if (tb[IFLA_IPTUN_TTL]) + props->ttl = nla_get_u8 (tb[IFLA_IPTUN_TTL]); + if (tb[IFLA_IPTUN_ENCAP_LIMIT]) + props->encap_limit = nla_get_u8 (tb[IFLA_IPTUN_ENCAP_LIMIT]); + if (tb[IFLA_IPTUN_FLOWINFO]) { + flowinfo = ntohl (nla_get_u32 (tb[IFLA_IPTUN_FLOWINFO])); + props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; + props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; + } + if (tb[IFLA_IPTUN_PROTO]) + props->proto = nla_get_u8 (tb[IFLA_IPTUN_PROTO]); + + return obj; +} + +/*****************************************************************************/ + static NMPObject * _parse_lnk_ipip (const char *kind, struct nlattr *info_data) { @@ -1424,6 +1486,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case NM_LINK_TYPE_INFINIBAND: lnk_data = _parse_lnk_infiniband (nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_IP6TNL: + lnk_data = _parse_lnk_ip6tnl (nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_IPIP: lnk_data = _parse_lnk_ipip (nl_info_kind, nl_info_data); break; @@ -2839,6 +2904,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP * For example https://bugzilla.redhat.com/show_bug.cgi?id=1284001 */ switch (new->link.type) { case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_IP6TNL: case NM_LINK_TYPE_INFINIBAND: case NM_LINK_TYPE_MACVLAN: case NM_LINK_TYPE_SIT: @@ -4195,6 +4261,67 @@ nla_put_failure: g_return_val_if_reached (FALSE); } +static int +link_ip6tnl_add (NMPlatform *platform, + const char *name, + NMPlatformLnkIp6Tnl *props, + NMPlatformLink *out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *info; + struct nlattr *data; + char buffer[INET_ADDRSTRLEN]; + guint32 flowinfo; + + _LOGD (LOG_FMT_IP_TUNNEL, + "ip6tnl", + name, + props->parent_ifindex, + nm_utils_inet6_ntop (&props->local, NULL), + nm_utils_inet6_ntop (&props->remote, buffer)); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + NLM_F_CREATE, + 0, + name, + 0, + 0); + if (!nlmsg) + return FALSE; + + if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "ip6tnl"); + + if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_LINK, props->parent_ifindex); + + if (memcmp (&props->local, &in6addr_any, sizeof (in6addr_any))) + NLA_PUT (nlmsg, IFLA_IPTUN_LOCAL, sizeof (props->local), &props->local); + if (memcmp (&props->remote, &in6addr_any, sizeof (in6addr_any))) + NLA_PUT (nlmsg, IFLA_IPTUN_REMOTE, sizeof (props->remote), &props->remote); + + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_ENCAP_LIMIT, props->encap_limit); + + flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; + flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) + & IP6_FLOWINFO_TCLASS_MASK; + NLA_PUT_U32 (nlmsg, IFLA_IPTUN_FLOWINFO, htonl (flowinfo)); + NLA_PUT_U8 (nlmsg, IFLA_IPTUN_PROTO, props->proto); + + nla_nest_end (nlmsg, data); + nla_nest_end (nlmsg, info); + + return do_add_link_with_lookup (platform, NM_LINK_TYPE_IP6TNL, name, nlmsg, out_link); +nla_put_failure: + g_return_val_if_reached (FALSE); +} + static int link_ipip_add (NMPlatform *platform, const char *name, @@ -5751,6 +5878,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->mesh_set_ssid = mesh_set_ssid; platform_class->link_gre_add = link_gre_add; + platform_class->link_ip6tnl_add = link_ip6tnl_add; platform_class->link_ipip_add = link_ipip_add; platform_class->link_sit_add = link_sit_add; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 0b86e08387..959f6dfae3 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1429,6 +1429,12 @@ nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlat return _link_get_lnk (self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link); } +const NMPlatformLnkIp6Tnl * +nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6TNL, out_link); +} + const NMPlatformLnkIpIp * nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -1859,6 +1865,45 @@ nm_platform_infiniband_get_properties (NMPlatform *self, return TRUE; } +/** + * nm_platform_ip6tnl_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create an IPv6 tunnel. + */ +NMPlatformError +nm_platform_link_ip6tnl_add (NMPlatform *self, + const char *name, + NMPlatformLnkIp6Tnl *props, + NMPlatformLink *out_link) +{ + NMPlatformError plerr; + char buffer[INET6_ADDRSTRLEN]; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_IP6TNL, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD (LOG_FMT_IP_TUNNEL, + "ip6tnl", + name, + props->parent_ifindex, + nm_utils_inet6_ntop (&props->local, NULL), + nm_utils_inet6_ntop (&props->remote, buffer)); + + if (!klass->link_ip6tnl_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + /** * nm_platform_ipip_add: * @self: platform instance @@ -2936,6 +2981,45 @@ nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char * return buf; } +const char * +nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tclass[30]; + char str_flow[30]; + char str_encap[30]; + char str_proto[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "ip6tnl" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tclass */ + "%s" /* encap limit */ + "%s" /* flow label */ + "%s" /* proto */ + "", + nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet6_ntop (&lnk->remote, str_remote1)), + nm_sprintf_buf (str_local, " local %s", nm_utils_inet6_ntop (&lnk->local, str_local1)), + lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tclass == 1 ? " tclass inherit" : nm_sprintf_buf (str_tclass, " tclass 0x%x", lnk->tclass), + nm_sprintf_buf (str_encap, " encap-limit %u", lnk->encap_limit), + nm_sprintf_buf (str_flow, " flow-label 0x05%x", lnk->flow_label), + nm_sprintf_buf (str_proto, " proto %u", lnk->proto)); + return buf; +} + const char * nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len) { @@ -3561,6 +3645,21 @@ nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatfo return 0; } +int +nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD_MEMCMP (a, b, local); + _CMP_FIELD_MEMCMP (a, b, remote); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD (a, b, tclass); + _CMP_FIELD (a, b, encap_limit); + _CMP_FIELD (a, b, flow_label); + _CMP_FIELD (a, b, proto); + return 0; +} + int nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 60f0500572..5eb042cf78 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -378,6 +378,17 @@ typedef struct { const char *mode; } NMPlatformLnkInfiniband; +typedef struct { + int parent_ifindex; + struct in6_addr local; + struct in6_addr remote; + guint8 ttl; + guint8 tclass; + guint8 encap_limit; + guint flow_label; + guint8 proto; +} NMPlatformLnkIp6Tnl; + typedef struct { int parent_ifindex; in_addr_t local; @@ -549,6 +560,8 @@ typedef struct { gboolean (*link_gre_add) (NMPlatform *, const char *name, NMPlatformLnkGre *props, NMPlatformLink *out_link); + gboolean (*link_ip6tnl_add) (NMPlatform *, const char *name, NMPlatformLnkIp6Tnl *props, + NMPlatformLink *out_link); gboolean (*link_ipip_add) (NMPlatform *, const char *name, NMPlatformLnkIpIp *props, NMPlatformLink *out_link); gboolean (*link_sit_add) (NMPlatform *, const char *name, NMPlatformLnkSit *props, @@ -742,6 +755,8 @@ char *nm_platform_slave_get_option (NMPlatform *self, int ifindex, const char *o const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link); const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); @@ -797,6 +812,8 @@ const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int i NMPlatformError nm_platform_link_gre_add (NMPlatform *self, const char *name, NMPlatformLnkGre *props, NMPlatformLink *out_link); +NMPlatformError nm_platform_link_ip6tnl_add (NMPlatform *self, const char *name, NMPlatformLnkIp6Tnl *props, + NMPlatformLink *out_link); NMPlatformError nm_platform_link_ipip_add (NMPlatform *self, const char *name, NMPlatformLnkIpIp *props, NMPlatformLink *out_link); NMPlatformError nm_platform_link_sit_add (NMPlatform *self, const char *name, NMPlatformLnkSit *props, @@ -843,6 +860,7 @@ gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6 const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len); const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len); const char *nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); +const char *nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len); const char *nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len); const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len); const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len); @@ -862,6 +880,7 @@ const char *nm_platform_vlan_qos_mapping_to_string (const char *name, int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b); int nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); int nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b); +int nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b); int nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b); int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b); int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index da40c8b6a8..cb605c28f4 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -2045,6 +2045,15 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_infiniband_to_string, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_infiniband_cmp, }, + [NMP_OBJECT_TYPE_LNK_IP6TNL - 1] = { + .obj_type = NMP_OBJECT_TYPE_LNK_IP6TNL, + .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), + .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), + .obj_type_name = "ip6tnl", + .lnk_link_type = NM_LINK_TYPE_IP6TNL, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, + }, [NMP_OBJECT_TYPE_LNK_IPIP - 1] = { .obj_type = NMP_OBJECT_TYPE_LNK_IPIP, .sizeof_data = sizeof (NMPObjectLnkIpIp), diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 07bd7e5e85..38224acd30 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -169,6 +169,10 @@ typedef struct { NMPlatformLnkInfiniband _public; } NMPObjectLnkInfiniband; +typedef struct { + NMPlatformLnkIp6Tnl _public; +} NMPObjectLnkIp6Tnl; + typedef struct { NMPlatformLnkIpIp _public; } NMPObjectLnkIpIp; @@ -229,6 +233,9 @@ struct _NMPObject { NMPlatformLnkIpIp lnk_ipip; NMPObjectLnkIpIp _lnk_ipip; + NMPlatformLnkIp6Tnl lnk_ip6tnl; + NMPObjectLnkIp6Tnl _lnk_ip6tnl; + NMPlatformLnkMacvlan lnk_macvlan; NMPObjectLnkMacvlan _lnk_macvlan; From 0d606a187b31b7e8e836a4cb2ed92cbc023b3373 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 19 Nov 2015 17:27:41 +0100 Subject: [PATCH 08/18] platform/tests: test GRE links also using platform code --- src/platform/tests/test-common.c | 30 ++++++++++++++++++++++++++++++ src/platform/tests/test-common.h | 4 ++++ src/platform/tests/test-link.c | 20 ++++++++++++++------ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 6f46546c46..1c1a22babb 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -670,6 +670,36 @@ _ip_address_add (gboolean external_command, } while (TRUE); } +gboolean +nmtstp_link_gre_add (gboolean external_command, const char *name, NMPlatformLnkGre *lnk) +{ + gboolean success; + char buffer[INET_ADDRSTRLEN]; + + external_command = nmtstp_run_command_check_external (external_command); + + if (external_command) { + gs_free char *dev = NULL; + + if (lnk->parent_ifindex) + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + + success = !nmtstp_run_command ("ip tunnel add %s mode gre %s local %s remote %s ttl %u tos %02x %s", + name, + dev ? dev : "", + nm_utils_inet4_ntop (lnk->local, NULL), + nm_utils_inet4_ntop (lnk->remote, buffer), + lnk->ttl, + lnk->tos, + lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); + if (success) + nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_GRE, 100); + } else + success = nm_platform_link_gre_add (NM_PLATFORM_GET, name, lnk, NULL) == NM_PLATFORM_ERROR_SUCCESS; + + return success; +} + void nmtstp_ip4_address_add (gboolean external_command, int ifindex, diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index ed7dd67fa1..536d14b1d1 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -135,6 +135,10 @@ void nmtstp_link_set_updown (gboolean external_command, int ifindex, gboolean up); +gboolean nmtstp_link_gre_add (gboolean external_command, + const char *name, + NMPlatformLnkGre *lnk); + void init_tests (int *argc, char ***argv); void setup_tests (void); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 8a29df2d15..15ed1031da 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -659,26 +659,34 @@ test_software_detect (gconstpointer user_data) const NMPlatformLink *plink; const NMPObject *lnk; guint i_step; - int exit_code; + const gint EX = -1; nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME); ifindex_parent = nmtstp_assert_wait_for_link (PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; switch (test_data->link_type) { case NM_LINK_TYPE_GRE: { + NMPlatformLnkGre lnk_gre = { }; gboolean gracefully_skip = FALSE; + inet_pton (AF_INET, "192.168.233.204", &lnk_gre.local); + inet_pton (AF_INET, "172.168.10.25", &lnk_gre.remote); + lnk_gre.parent_ifindex = ifindex_parent; + lnk_gre.ttl = 174; + lnk_gre.tos = 37; + lnk_gre.path_mtu_discovery = TRUE; + if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "gre0")) { /* Seems that the ip_gre module is not loaded... try to load it. */ gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip_gre", NULL) != 0; } - exit_code = nmtstp_run_command ("ip tunnel add %s mode gre remote 172.168.10.25 local 192.168.233.204 ttl 174", DEVICE_NAME); - if (exit_code != 0) { + + if (!nmtstp_link_gre_add (EX, DEVICE_NAME, &lnk_gre)) { if (gracefully_skip) { g_test_skip ("Cannot create gre tunnel because of missing ip_gre module (modprobe ip_gre)"); goto out_delete_parent; } - g_error ("Failed adding GRE tunnel: exit code %d", exit_code); + g_error ("Failed adding GRE tunnel"); } break; } @@ -741,7 +749,7 @@ test_software_detect (gconstpointer user_data) const NMPlatformLnkGre *plnk = &lnk->lnk_gre; g_assert (plnk == nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, 0); + g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); g_assert_cmpint (plnk->input_flags, ==, 0); g_assert_cmpint (plnk->output_flags, ==, 0); g_assert_cmpint (plnk->input_key, ==, 0); @@ -749,7 +757,7 @@ test_software_detect (gconstpointer user_data) nmtst_assert_ip4_address (plnk->local, "192.168.233.204"); nmtst_assert_ip4_address (plnk->remote, "172.168.10.25"); g_assert_cmpint (plnk->ttl, ==, 174); - g_assert_cmpint (plnk->tos, ==, 0); + g_assert_cmpint (plnk->tos, ==, 37); g_assert_cmpint (plnk->path_mtu_discovery, ==, TRUE); break; } From 3063f40e9a45a63d91e611a23abd13b6da346ab3 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 19 Nov 2015 17:52:43 +0100 Subject: [PATCH 09/18] platform/tests: test SIT links --- src/platform/tests/test-common.c | 30 +++++++++++++++++++++++++ src/platform/tests/test-common.h | 3 +++ src/platform/tests/test-link.c | 38 ++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 1c1a22babb..c6b24720d2 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -700,6 +700,36 @@ nmtstp_link_gre_add (gboolean external_command, const char *name, NMPlatformLnkG return success; } +gboolean +nmtstp_link_sit_add (gboolean external_command, const char *name, NMPlatformLnkSit *lnk) +{ + gboolean success; + char buffer[INET_ADDRSTRLEN]; + + external_command = nmtstp_run_command_check_external (external_command); + + if (external_command) { + gs_free char *dev = NULL; + + if (lnk->parent_ifindex) + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + + success = !nmtstp_run_command ("ip tunnel add %s mode sit %s local %s remote %s ttl %u tos %02x %s", + name, + dev, + nm_utils_inet4_ntop (lnk->local, NULL), + nm_utils_inet4_ntop (lnk->remote, buffer), + lnk->ttl, + lnk->tos, + lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); + if (success) + nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_SIT, 100); + } else + success = nm_platform_link_sit_add (NM_PLATFORM_GET, name, lnk, NULL) == NM_PLATFORM_ERROR_SUCCESS; + + return success; +} + void nmtstp_ip4_address_add (gboolean external_command, int ifindex, diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 536d14b1d1..4120a7f138 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -138,6 +138,9 @@ void nmtstp_link_set_updown (gboolean external_command, gboolean nmtstp_link_gre_add (gboolean external_command, const char *name, NMPlatformLnkGre *lnk); +gboolean nmtstp_link_sit_add (gboolean external_command, + const char *name, + NMPlatformLnkSit *lnk); void init_tests (int *argc, char ***argv); void setup_tests (void); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 15ed1031da..25004b74bb 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -693,6 +693,31 @@ test_software_detect (gconstpointer user_data) case NM_LINK_TYPE_MACVLAN: nmtstp_run_command_check ("ip link add name %s link %s type macvlan", DEVICE_NAME, PARENT_NAME); break; + case NM_LINK_TYPE_SIT: { + NMPlatformLnkSit lnk_sit = { }; + gboolean gracefully_skip = FALSE; + + inet_pton (AF_INET, "192.168.200.1", &lnk_sit.local); + inet_pton (AF_INET, "172.25.100.14", &lnk_sit.remote); + lnk_sit.parent_ifindex = ifindex_parent; + lnk_sit.ttl = 0; + lnk_sit.tos = 31; + lnk_sit.path_mtu_discovery = FALSE; + + if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "sit0")) { + /* Seems that the sit module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe (NULL, TRUE, "sit", NULL) != 0; + } + + if (!nmtstp_link_sit_add (EX, DEVICE_NAME, &lnk_sit)) { + if (gracefully_skip) { + g_test_skip ("Cannot create sit tunnel because of missing sit module (modprobe sit)"); + goto out_delete_parent; + } + g_error ("Failed adding SIT tunnel"); + } + break; + } case NM_LINK_TYPE_VLAN: nmtstp_run_command_check ("ip link add name %s link %s type vlan id 1242", DEVICE_NAME, PARENT_NAME); break; @@ -769,6 +794,18 @@ test_software_detect (gconstpointer user_data) g_assert_cmpstr (plnk->mode, ==, "vepa"); break; } + case NM_LINK_TYPE_SIT: { + const NMPlatformLnkSit *plnk = &lnk->lnk_sit; + + g_assert (plnk == nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip4_address (plnk->local, "192.168.200.1"); + nmtst_assert_ip4_address (plnk->remote, "172.25.100.14"); + g_assert_cmpint (plnk->ttl, ==, 0); + g_assert_cmpint (plnk->tos, ==, 31); + g_assert_cmpint (plnk->path_mtu_discovery, ==, FALSE); + break; + } case NM_LINK_TYPE_VLAN: { const NMPlatformLnkVlan *plnk = &lnk->lnk_vlan; @@ -1588,6 +1625,7 @@ setup_tests (void) test_software_detect_add ("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0); test_software_detect_add ("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0); + test_software_detect_add ("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0); test_software_detect_add ("/link/software/detect/vlan", NM_LINK_TYPE_VLAN, 0); test_software_detect_add ("/link/software/detect/vxlan/0", NM_LINK_TYPE_VXLAN, 0); test_software_detect_add ("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1); From 133724d95805142e29c6d34a7bc201368e7a9d05 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sun, 29 Nov 2015 18:42:52 +0100 Subject: [PATCH 10/18] platform/tests: test IPIP links --- src/platform/tests/test-common.c | 30 ++++++++++++++++++++++++++++++ src/platform/tests/test-common.h | 3 +++ src/platform/tests/test-link.c | 26 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index c6b24720d2..8856b11a85 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -700,6 +700,36 @@ nmtstp_link_gre_add (gboolean external_command, const char *name, NMPlatformLnkG return success; } +gboolean +nmtstp_link_ipip_add (gboolean external_command, const char *name, NMPlatformLnkIpIp *lnk) +{ + gboolean success; + char buffer[INET_ADDRSTRLEN]; + + external_command = nmtstp_run_command_check_external (external_command); + + if (external_command) { + gs_free char *dev = NULL; + + if (lnk->parent_ifindex) + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + + success = !nmtstp_run_command ("ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s", + name, + dev, + nm_utils_inet4_ntop (lnk->local, NULL), + nm_utils_inet4_ntop (lnk->remote, buffer), + lnk->ttl, + lnk->tos, + lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); + if (success) + nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_IPIP, 100); + } else + success = nm_platform_link_ipip_add (NM_PLATFORM_GET, name, lnk, NULL) == NM_PLATFORM_ERROR_SUCCESS; + + return success; +} + gboolean nmtstp_link_sit_add (gboolean external_command, const char *name, NMPlatformLnkSit *lnk) { diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 4120a7f138..a3897f2d58 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -138,6 +138,9 @@ void nmtstp_link_set_updown (gboolean external_command, gboolean nmtstp_link_gre_add (gboolean external_command, const char *name, NMPlatformLnkGre *lnk); +gboolean nmtstp_link_ipip_add (gboolean external_command, + const char *name, + NMPlatformLnkIpIp *lnk); gboolean nmtstp_link_sit_add (gboolean external_command, const char *name, NMPlatformLnkSit *lnk); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 25004b74bb..cee9d0a61c 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -690,6 +690,19 @@ test_software_detect (gconstpointer user_data) } break; } + case NM_LINK_TYPE_IPIP: { + NMPlatformLnkIpIp lnk_ipip = { }; + + inet_pton (AF_INET, "1.2.3.4", &lnk_ipip.local); + inet_pton (AF_INET, "5.6.7.8", &lnk_ipip.remote); + lnk_ipip.parent_ifindex = ifindex_parent; + lnk_ipip.tos = 32; + lnk_ipip.path_mtu_discovery = FALSE; + + if (!nmtstp_link_ipip_add (EX, DEVICE_NAME, &lnk_ipip)) + g_error ("Failed adding IPIP tunnel"); + break; + } case NM_LINK_TYPE_MACVLAN: nmtstp_run_command_check ("ip link add name %s link %s type macvlan", DEVICE_NAME, PARENT_NAME); break; @@ -786,6 +799,18 @@ test_software_detect (gconstpointer user_data) g_assert_cmpint (plnk->path_mtu_discovery, ==, TRUE); break; } + case NM_LINK_TYPE_IPIP: { + const NMPlatformLnkIpIp *plnk = &lnk->lnk_ipip; + + g_assert (plnk == nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip4_address (plnk->local, "1.2.3.4"); + nmtst_assert_ip4_address (plnk->remote, "5.6.7.8"); + g_assert_cmpint (plnk->ttl, ==, 0); + g_assert_cmpint (plnk->tos, ==, 32); + g_assert_cmpint (plnk->path_mtu_discovery, ==, FALSE); + break; + } case NM_LINK_TYPE_MACVLAN: { const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan; @@ -1624,6 +1649,7 @@ setup_tests (void) g_test_add_func ("/link/external", test_external); test_software_detect_add ("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0); + test_software_detect_add ("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0); test_software_detect_add ("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0); test_software_detect_add ("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0); test_software_detect_add ("/link/software/detect/vlan", NM_LINK_TYPE_VLAN, 0); From 1a3448b43bb122243b7f9730e2ed7d62ab0a4c1e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Nov 2015 18:49:01 +0100 Subject: [PATCH 11/18] platform/tests: test IP6TNL links --- src/platform/tests/test-common.c | 44 ++++++++++++++++++++++++++++++++ src/platform/tests/test-common.h | 3 +++ src/platform/tests/test-link.c | 30 ++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 8856b11a85..595096d2fb 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -700,6 +700,50 @@ nmtstp_link_gre_add (gboolean external_command, const char *name, NMPlatformLnkG return success; } +gboolean +nmtstp_link_ip6tnl_add (gboolean external_command, const char *name, NMPlatformLnkIp6Tnl *lnk) +{ + gboolean success; + char buffer[INET6_ADDRSTRLEN]; + + external_command = nmtstp_run_command_check_external (external_command); + + if (external_command) { + gs_free char *dev = NULL; + const char *mode; + + if (lnk->parent_ifindex) + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + + switch (lnk->proto) { + case IPPROTO_IPIP: + mode = "ipip6"; + break; + case IPPROTO_IPV6: + mode = "ip6ip6"; + break; + default: + g_assert (FALSE); + } + + success = !nmtstp_run_command ("ip -6 tunnel add %s mode %s %s local %s remote %s ttl %u tclass %02x encaplimit %u flowlabel %x", + name, + mode, + dev, + nm_utils_inet6_ntop (&lnk->local, NULL), + nm_utils_inet6_ntop (&lnk->remote, buffer), + lnk->ttl, + lnk->tclass, + lnk->encap_limit, + lnk->flow_label); + if (success) + nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_IP6TNL, 100); + } else + success = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, name, lnk, NULL) == NM_PLATFORM_ERROR_SUCCESS; + + return success; +} + gboolean nmtstp_link_ipip_add (gboolean external_command, const char *name, NMPlatformLnkIpIp *lnk) { diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index a3897f2d58..6140f26406 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -138,6 +138,9 @@ void nmtstp_link_set_updown (gboolean external_command, gboolean nmtstp_link_gre_add (gboolean external_command, const char *name, NMPlatformLnkGre *lnk); +gboolean nmtstp_link_ip6tnl_add (gboolean external_command, + const char *name, + NMPlatformLnkIp6Tnl *lnk); gboolean nmtstp_link_ipip_add (gboolean external_command, const char *name, NMPlatformLnkIpIp *lnk); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index cee9d0a61c..047dfe1cf7 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -703,6 +703,21 @@ test_software_detect (gconstpointer user_data) g_error ("Failed adding IPIP tunnel"); break; } + case NM_LINK_TYPE_IP6TNL: { + NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; + + inet_pton (AF_INET6, "fd01::15", &lnk_ip6tnl.local); + inet_pton (AF_INET6, "fd01::16", &lnk_ip6tnl.remote); + lnk_ip6tnl.parent_ifindex = ifindex_parent; + lnk_ip6tnl.tclass = 20; + lnk_ip6tnl.encap_limit = 6; + lnk_ip6tnl.flow_label = 1337; + lnk_ip6tnl.proto = IPPROTO_IPV6; + + if (!nmtstp_link_ip6tnl_add (EX, DEVICE_NAME, &lnk_ip6tnl)) + g_error ("Failed adding IPv6 tunnel"); + break; + } case NM_LINK_TYPE_MACVLAN: nmtstp_run_command_check ("ip link add name %s link %s type macvlan", DEVICE_NAME, PARENT_NAME); break; @@ -799,6 +814,20 @@ test_software_detect (gconstpointer user_data) g_assert_cmpint (plnk->path_mtu_discovery, ==, TRUE); break; } + case NM_LINK_TYPE_IP6TNL: { + const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; + + g_assert (plnk == nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip6_address (&plnk->local, "fd01::15"); + nmtst_assert_ip6_address (&plnk->remote, "fd01::16"); + g_assert_cmpint (plnk->ttl, ==, 0); + g_assert_cmpint (plnk->tclass, ==, 20); + g_assert_cmpint (plnk->encap_limit, ==, 6); + g_assert_cmpint (plnk->flow_label, ==, 1337); + g_assert_cmpint (plnk->proto, ==, IPPROTO_IPV6); + break; + } case NM_LINK_TYPE_IPIP: { const NMPlatformLnkIpIp *plnk = &lnk->lnk_ipip; @@ -1649,6 +1678,7 @@ setup_tests (void) g_test_add_func ("/link/external", test_external); test_software_detect_add ("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0); + test_software_detect_add ("/link/software/detect/ip6tnl", NM_LINK_TYPE_IP6TNL, 0); test_software_detect_add ("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0); test_software_detect_add ("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0); test_software_detect_add ("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0); From 570fdce93f44a51dbd84bbfe098913141c94b789 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Fri, 30 Oct 2015 15:14:23 +0100 Subject: [PATCH 12/18] device: add NMDeviceIPTunnel The new object type represents tunnels over IPv4 and IPv6. We have a single setting type (NMSettingIPTunnel) for tunnels and it can't be shared among different device factories. So we define also a single device type for all tunnels. This new object will also represent GRE tunnels, which before were instantiated as NMDeviceGre and had a ".Device.Gre" D-Bus interface. This commit introduces a change in behavior. --- introspection/Makefile.am | 3 + introspection/nm-device-ip-tunnel.xml | 71 +++ libnm-core/nm-connection.c | 3 +- libnm-core/nm-dbus-interface.h | 1 + po/POTFILES.in | 1 + src/Makefile.am | 2 + src/devices/nm-device-gre.c | 1 - src/devices/nm-device-ip-tunnel.c | 762 ++++++++++++++++++++++++++ src/devices/nm-device-ip-tunnel.h | 58 ++ src/devices/nm-device.c | 2 + src/tests/Makefile.am | 2 +- 11 files changed, 903 insertions(+), 3 deletions(-) create mode 100644 introspection/nm-device-ip-tunnel.xml create mode 100644 src/devices/nm-device-ip-tunnel.c create mode 100644 src/devices/nm-device-ip-tunnel.h diff --git a/introspection/Makefile.am b/introspection/Makefile.am index c8a70cffc7..c3721fc44d 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -35,6 +35,8 @@ nodist_libnmdbus_la_SOURCES = \ nmdbus-device-gre.h \ nmdbus-device-infiniband.c \ nmdbus-device-infiniband.h \ + nmdbus-device-ip-tunnel.c \ + nmdbus-device-ip-tunnel.h \ nmdbus-device-macvlan.c \ nmdbus-device-macvlan.h \ nmdbus-device-modem.c \ @@ -110,6 +112,7 @@ EXTRA_DIST = \ nm-device-generic.xml \ nm-device-gre.xml \ nm-device-infiniband.xml \ + nm-device-ip-tunnel.xml \ nm-device-macvlan.xml \ nm-device-modem.xml \ nm-device-olpc-mesh.xml \ diff --git a/introspection/nm-device-ip-tunnel.xml b/introspection/nm-device-ip-tunnel.xml new file mode 100644 index 0000000000..db5335b2a5 --- /dev/null +++ b/introspection/nm-device-ip-tunnel.xml @@ -0,0 +1,71 @@ + + + + + + + + The tunneling mode. + + + + + + The object path of the parent device. + + + + + + The local endpoint of the tunnel. + + + + + + The remote endpoint of the tunnel. + + + + + + The TTL assigned to tunneled packets. 0 is a special value + meaning that packets inherit the TTL value + + + + + + The type of service (IPv4) or traffic class (IPv6) assigned to + tunneled packets. + + + + + + Whether path MTU discovery is enabled on this tunnel. + + + + + + The key used for incoming packets. + + + + + + The key used for outgoing packets. + + + + + + + A dictionary mapping property names to variant boxed values + + + + + + diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 0f599984c9..e801f2fd47 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1595,7 +1595,8 @@ nm_connection_is_virtual (NMConnection *connection) || !strcmp (type, NM_SETTING_TEAM_SETTING_NAME) || !strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME) || !strcmp (type, NM_SETTING_VLAN_SETTING_NAME) - || !strcmp (type, NM_SETTING_TUN_SETTING_NAME)) + || !strcmp (type, NM_SETTING_TUN_SETTING_NAME) + || !strcmp (type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) return TRUE; if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) { diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index e81f081dff..f901028f9b 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -173,6 +173,7 @@ typedef enum { NM_DEVICE_TYPE_GENERIC = 14, NM_DEVICE_TYPE_TEAM = 15, NM_DEVICE_TYPE_TUN = 16, + NM_DEVICE_TYPE_IP_TUNNEL = 17, } NMDeviceType; /** diff --git a/po/POTFILES.in b/po/POTFILES.in index ba861b7eeb..c0f79bf786 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -149,6 +149,7 @@ src/devices/nm-device-bridge.c src/devices/nm-device-ethernet.c src/devices/nm-device-ethernet-utils.c src/devices/nm-device-infiniband.c +src/devices/nm-device-ip-tunnel.c src/devices/nm-device-tun.c src/devices/nm-device-vlan.c src/devices/team/nm-device-team.c diff --git a/src/Makefile.am b/src/Makefile.am index 89681f1970..b7c773ea4b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -206,6 +206,7 @@ nm_device_sources = \ devices/nm-device-ethernet.c \ devices/nm-device-gre.c \ devices/nm-device-infiniband.c \ + devices/nm-device-ip-tunnel.c \ devices/nm-device-macvlan.c \ devices/nm-device-tun.c \ devices/nm-device-veth.c \ @@ -219,6 +220,7 @@ nm_device_headers = \ devices/nm-device-ethernet.h \ devices/nm-device-gre.h \ devices/nm-device-infiniband.h \ + devices/nm-device-ip-tunnel.h \ devices/nm-device-macvlan.h \ devices/nm-device-tun.h \ devices/nm-device-veth.h \ diff --git a/src/devices/nm-device-gre.c b/src/devices/nm-device-gre.c index 9b9ffc9be1..3bb1ed787d 100644 --- a/src/devices/nm-device-gre.c +++ b/src/devices/nm-device-gre.c @@ -262,7 +262,6 @@ nm_device_gre_class_init (NMDeviceGreClass *klass) } /*************************************************************/ - #define NM_TYPE_GRE_FACTORY (nm_gre_factory_get_type ()) #define NM_GRE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GRE_FACTORY, NMGreFactory)) diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c new file mode 100644 index 0000000000..4d338ecbf3 --- /dev/null +++ b/src/devices/nm-device-ip-tunnel.c @@ -0,0 +1,762 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "nm-device-ip-tunnel.h" +#include "nm-device-private.h" +#include "nm-default.h" +#include "nm-manager.h" +#include "nm-platform.h" +#include "nm-device-factory.h" +#include "nm-core-internal.h" +#include "nm-connection-provider.h" +#include "nm-activation-request.h" + +#include "nmdbus-device-ip-tunnel.h" + +#include "nm-device-logging.h" +_LOG_DECLARE_SELF(NMDeviceIPTunnel); + +G_DEFINE_TYPE (NMDeviceIPTunnel, nm_device_ip_tunnel, NM_TYPE_DEVICE) + +#define NM_DEVICE_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelPrivate)) + +typedef struct { + NMIPTunnelMode mode; + NMDevice *parent; + int parent_ifindex; + char *local; + char *remote; + guint8 ttl; + guint8 tos; + gboolean path_mtu_discovery; + int addr_family; + char *input_key; + char *output_key; +} NMDeviceIPTunnelPrivate; + +enum { + PROP_0, + PROP_MODE, + PROP_PARENT, + PROP_LOCAL, + PROP_REMOTE, + PROP_TTL, + PROP_TOS, + PROP_PATH_MTU_DISCOVERY, + PROP_INPUT_KEY, + PROP_OUTPUT_KEY, + + LAST_PROP +}; + +/**************************************************************/ + +static gboolean +address_equal_pp (int family, const char *a, const char *b) +{ + char buffer1[sizeof (struct in6_addr)] = { }; + char buffer2[sizeof (struct in6_addr)] = { }; + + g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + + if (a) + inet_pton (family, a, buffer1); + if (b) + inet_pton (family, b, buffer2); + + return !memcmp (buffer1, buffer2, + family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr)); +} + +static gboolean +address_equal_pn (int family, const char *a, const void *b) +{ + char buffer1[sizeof (struct in6_addr)] = { }; + + g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + + if (a) + inet_pton (family, a, buffer1); + + return !memcmp (buffer1, b, + family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr)); + +} + +static void +update_properties (NMDevice *device) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + GObject *object = G_OBJECT (device); + NMDevice *parent; + int parent_ifindex; + in_addr_t local4, remote4; + struct in6_addr local6, remote6; + guint8 ttl, tos; + gboolean pmtud; + char *key; + + if (priv->mode == NM_IP_TUNNEL_MODE_GRE) { + const NMPlatformLnkGre *lnk; + + lnk = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "gre"); + return; + } + + parent_ifindex = lnk->parent_ifindex; + local4 = lnk->local; + remote4 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tos; + pmtud = lnk->path_mtu_discovery; + + if (NM_FLAGS_HAS (lnk->input_flags, NM_GRE_KEY)) { + key = g_strdup_printf ("%u", lnk->input_key); + if (g_strcmp0 (priv->input_key, key)) { + g_free (priv->input_key); + priv->input_key = key; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); + } else + g_free (key); + } else { + if (priv->input_key) { + g_clear_pointer (&priv->input_key, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); + } + } + + if (NM_FLAGS_HAS (lnk->output_flags, NM_GRE_KEY)) { + key = g_strdup_printf ("%u", lnk->output_key); + if (g_strcmp0 (priv->output_key, key)) { + g_free (priv->output_key); + priv->output_key = key; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); + } else + g_free (key); + } else { + if (priv->output_key) { + g_clear_pointer (&priv->output_key, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); + } + } + } else + g_return_if_reached (); + + if (priv->parent_ifindex != parent_ifindex) { + g_clear_object (&priv->parent); + priv->parent_ifindex = parent_ifindex; + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + if (parent) + priv->parent = g_object_ref (parent); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_PARENT); + } + + if (priv->addr_family == AF_INET) { + if (!address_equal_pn (AF_INET, priv->local, &local4)) { + g_clear_pointer (&priv->local, g_free); + if (local4) + priv->local = g_strdup (nm_utils_inet4_ntop (local4, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); + } + + if (!address_equal_pn (AF_INET, priv->remote, &remote4)) { + g_clear_pointer (&priv->remote, g_free); + if (remote4) + priv->remote = g_strdup (nm_utils_inet4_ntop (remote4, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); + } + } else { + if (!address_equal_pn (AF_INET6, priv->local, &local6)) { + g_clear_pointer (&priv->local, g_free); + if (memcmp (&local6, &in6addr_any, sizeof (in6addr_any))) + priv->local = g_strdup (nm_utils_inet6_ntop (&local6, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); + } + + if (!address_equal_pn (AF_INET6, priv->remote, &remote6)) { + g_clear_pointer (&priv->remote, g_free); + if (memcmp (&remote6, &in6addr_any, sizeof (in6addr_any))) + priv->remote = g_strdup (nm_utils_inet6_ntop (&remote6, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); + } + } + + if (priv->ttl != ttl) { + priv->ttl = ttl; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_TTL); + } + + if (priv->tos != tos) { + priv->tos = tos; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_TOS); + } + + if (priv->path_mtu_discovery != pmtud) { + priv->path_mtu_discovery = pmtud; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY); + } +} + +static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->link_changed (device, info); + update_properties (device); +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingIPTunnel *s_ip_tunnel; + + nm_utils_complete_generic (connection, + NM_SETTING_IP_TUNNEL_SETTING_NAME, + existing_connections, + NULL, + _("IP tunnel connection"), + NULL, + TRUE); + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + if (!s_ip_tunnel) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'tunnel' setting is required."); + return FALSE; + } + + return TRUE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + NMSettingIPTunnel *s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + NMDevice *parent = NULL; + const char *setting_parent, *new_parent; + + if (!s_ip_tunnel) { + s_ip_tunnel = (NMSettingIPTunnel *) nm_setting_ip_tunnel_new (); + nm_connection_add_setting (connection, (NMSetting *) s_ip_tunnel); + } + + update_properties (device); + + if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_MODE, priv->mode, NULL); + + if (priv->parent_ifindex > 0) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); + + /* Update parent in the connection; default to parent's interface name */ + if (parent) { + new_parent = nm_device_get_iface (parent); + setting_parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel); + 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_ip_tunnel, NM_SETTING_IP_TUNNEL_PARENT, new_parent, NULL); + } else + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_PARENT, NULL, NULL); + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_local (s_ip_tunnel), + priv->local)) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_LOCAL, priv->local, NULL); + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_remote (s_ip_tunnel), + priv->remote)) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_REMOTE, priv->remote, NULL); + + if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_TTL, priv->ttl, NULL); + + if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_TOS, priv->tos, NULL); + + if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, + priv->path_mtu_discovery, + NULL); + } + + if (priv->mode == NM_IP_TUNNEL_MODE_GRE || priv->mode == NM_IP_TUNNEL_MODE_IP6GRE) { + if (g_strcmp0 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), priv->input_key)) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_INPUT_KEY, + priv->input_key, + NULL); + } + if (g_strcmp0 (nm_setting_ip_tunnel_get_output_key (s_ip_tunnel), priv->output_key)) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_OUTPUT_KEY, + priv->output_key, + NULL); + } + } +} + +static gboolean +realize (NMDevice *self, NMPlatformLink *plink, GError **error) +{ + update_properties (self); + return TRUE; +} + +static gboolean +match_parent (NMDevice *dev_parent, const char *setting_parent) +{ + g_return_val_if_fail (setting_parent, FALSE); + + if (!dev_parent) + return FALSE; + + if (nm_utils_is_uuid (setting_parent)) { + NMActRequest *parent_req; + NMConnection *parent_connection; + + /* If the parent is a UUID, the connection matches if our parent + * device has that connection activated. + */ + parent_req = nm_device_get_act_request (dev_parent); + if (!parent_req) + return FALSE; + + parent_connection = nm_active_connection_get_applied_connection (NM_ACTIVE_CONNECTION (parent_req)); + if (!parent_connection) + return FALSE; + + if (g_strcmp0 (setting_parent, nm_connection_get_uuid (parent_connection)) != 0) + return FALSE; + } else { + /* interface name */ + if (g_strcmp0 (setting_parent, nm_device_get_ip_iface (dev_parent)) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + NMSettingIPTunnel *s_ip_tunnel; + const char *parent; + + if (!NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + if (!s_ip_tunnel) + return FALSE; + + update_properties (device); + + /* Check parent interface; could be an interface name or a UUID */ + parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel); + if (parent) { + if (!match_parent (priv->parent, parent)) + return FALSE; + } + + if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) + return FALSE; + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_local (s_ip_tunnel), + priv->local)) + return FALSE; + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_remote (s_ip_tunnel), + priv->remote)) + return FALSE; + + if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl) + return FALSE; + + if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) + return FALSE; + + if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) + return FALSE; + + return TRUE; +} + +static NMIPTunnelMode +platform_link_to_tunnel_mode (const NMPlatformLink *link) +{ + switch (link->type) { + case NM_LINK_TYPE_GRE: + return NM_IP_TUNNEL_MODE_GRE; + default: + g_return_val_if_reached (NM_IP_TUNNEL_MODE_UKNOWN); + } +} + +/**************************************************************/ + +static void +nm_device_ip_tunnel_init (NMDeviceIPTunnel *self) +{ +} + +static void +constructed (GObject *object) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + + priv->addr_family = AF_INET; /* at the moment we support only IPv4 tunnels */ + + G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->constructed (object); +} + +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + NMPlatformLink *out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface (device); + NMSettingIPTunnel *s_ip_tunnel; + NMPlatformError plerr; + NMPlatformLnkGre lnk_gre = { }; + const char *str; + gint64 val; + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + g_assert (s_ip_tunnel); + g_assert (out_plink); + + switch (nm_setting_ip_tunnel_get_mode (s_ip_tunnel)) { + case NM_IP_TUNNEL_MODE_GRE: + if (parent) + lnk_gre.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET, str, &lnk_gre.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET, str, &lnk_gre.remote); + + lnk_gre.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_gre.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_gre.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); + + val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + -1); + if (val != -1) { + lnk_gre.input_key = val; + lnk_gre.input_flags = NM_GRE_KEY; + } + + val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_output_key (s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + -1); + if (val != -1) { + lnk_gre.output_key = val; + lnk_gre.output_flags = NM_GRE_KEY; + } + + plerr = nm_platform_link_gre_add (NM_PLATFORM_GET, iface, &lnk_gre, 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 GRE interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; + default: + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create IP tunnel interface '%s' for '%s': mode %d not supported", + iface, + nm_connection_get_id (connection), + (int) nm_setting_ip_tunnel_get_mode (s_ip_tunnel)); + return FALSE; + } + + return TRUE; +} + +static void +setup (NMDevice *device, NMPlatformLink *plink) +{ + NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->setup (device, plink); + + update_properties (device); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + NMDevice *parent; + + switch (prop_id) { + case PROP_MODE: + g_value_set_uint (value, priv->mode); + break; + case PROP_PARENT: + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); + nm_utils_g_value_set_object_path (value, parent); + break; + case PROP_LOCAL: + g_value_set_string (value, priv->local); + break; + case PROP_REMOTE: + g_value_set_string (value, priv->remote); + break; + case PROP_TTL: + g_value_set_uchar (value, priv->ttl); + break; + case PROP_TOS: + g_value_set_uchar (value, priv->tos); + break; + case PROP_PATH_MTU_DISCOVERY: + g_value_set_boolean (value, priv->path_mtu_discovery); + break; + case PROP_INPUT_KEY: + g_value_set_string (value, priv->input_key); + break; + case PROP_OUTPUT_KEY: + g_value_set_string (value, priv->output_key); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_MODE: + priv->mode = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceIPTunnelPrivate)); + + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + + device_class->link_changed = link_changed; + device_class->complete_connection = complete_connection; + device_class->update_connection = update_connection; + device_class->check_connection_compatible = check_connection_compatible; + device_class->create_and_realize = create_and_realize; + device_class->realize = realize; + device_class->setup = setup; + + device_class->connection_type = NM_SETTING_IP_TUNNEL_SETTING_NAME; + + /* properties */ + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_uint (NM_DEVICE_IP_TUNNEL_MODE, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /* properties */ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_PARENT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_LOCAL, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_REMOTE, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_REMOTE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_TTL, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_TOS, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_PATH_MTU_DISCOVERY, + g_param_spec_boolean (NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_INPUT_KEY, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_INPUT_KEY, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_OUTPUT_KEY, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_OUTPUT_KEY, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_IPTUNNEL_SKELETON, + NULL); +} +/*************************************************************/ + +#define NM_TYPE_IP_TUNNEL_FACTORY (nm_ip_tunnel_factory_get_type ()) +#define NM_IP_TUNNEL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP_TUNNEL_FACTORY, NMIPTunnelFactory)) + +static NMDevice * +create_device (NMDeviceFactory *factory, + const char *iface, + NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) +{ + NMSettingIPTunnel *s_ip_tunnel; + NMIPTunnelMode mode; + + if (connection) { + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); + } else + mode = platform_link_to_tunnel_mode (plink); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_IP_TUNNEL, + NM_DEVICE_IFACE, iface, + NM_DEVICE_TYPE_DESC, "IPTunnel", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_IP_TUNNEL, + NM_DEVICE_IP_TUNNEL_MODE, mode, + NULL); +} + +static const char * +get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingIPTunnel *s_ip_tunnel; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_IP_TUNNEL_SETTING_NAME), NULL); + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + g_assert (s_ip_tunnel); + + return nm_setting_ip_tunnel_get_parent (s_ip_tunnel); +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + const char *ifname; + NMSettingIPTunnel *s_ip_tunnel; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_IP_TUNNEL_SETTING_NAME), NULL); + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + g_assert (s_ip_tunnel); + + if (nm_setting_ip_tunnel_get_parent (s_ip_tunnel) && !parent_iface) + return NULL; + + ifname = nm_connection_get_interface_name (connection); + + return g_strdup (ifname); +} + +NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), + factory_iface->create_device = create_device; + factory_iface->get_connection_parent = get_connection_parent; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; +) diff --git a/src/devices/nm-device-ip-tunnel.h b/src/devices/nm-device-ip-tunnel.h new file mode 100644 index 0000000000..fdd92f3c6c --- /dev/null +++ b/src/devices/nm-device-ip-tunnel.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_DEVICE_IP_TUNNEL_H__ +#define __NETWORKMANAGER_DEVICE_IP_TUNNEL_H__ + +#include "nm-core-types.h" +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_IP_TUNNEL (nm_device_ip_tunnel_get_type ()) +#define NM_DEVICE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnel)) +#define NM_DEVICE_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelClass)) +#define NM_IS_DEVICE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_IP_TUNNEL)) +#define NM_IS_DEVICE_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_IP_TUNNEL)) +#define NM_DEVICE_IP_TUNNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelClass)) + +#define NM_DEVICE_IP_TUNNEL_MODE "mode" +#define NM_DEVICE_IP_TUNNEL_PARENT "parent" +#define NM_DEVICE_IP_TUNNEL_LOCAL "local" +#define NM_DEVICE_IP_TUNNEL_REMOTE "remote" +#define NM_DEVICE_IP_TUNNEL_TTL "ttl" +#define NM_DEVICE_IP_TUNNEL_TOS "tos" +#define NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY "path-mtu-discovery" +#define NM_DEVICE_IP_TUNNEL_INPUT_KEY "input-key" +#define NM_DEVICE_IP_TUNNEL_OUTPUT_KEY "output-key" + +typedef struct { + NMDevice parent; +} NMDeviceIPTunnel; + +typedef struct { + NMDeviceClass parent; +} NMDeviceIPTunnelClass; + +GType nm_device_ip_tunnel_get_type (void); + +G_END_DECLS + +#endif /* NM_DEVICE_IP_TUNNEL_H */ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 6a78ed4b1a..459d4ac664 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -760,6 +760,8 @@ nm_device_get_priority (NMDevice *self) return 600; case NM_DEVICE_TYPE_OLPC_MESH: return 650; + case NM_DEVICE_TYPE_IP_TUNNEL: + return 675; case NM_DEVICE_TYPE_MODEM: return 700; case NM_DEVICE_TYPE_BT: diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 219e0270ba..2278e5a028 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -150,7 +150,7 @@ TESTS = \ if ENABLE_TESTS check-local: - @for t in bond bridge ethernet gre infiniband macvlan tun veth vlan vxlan; do \ + @for t in bond bridge ethernet gre infiniband ip_tunnel macvlan tun veth vlan vxlan; do \ # Ensure the device subclass factory registration constructors exist \ # which could inadvertently break if src/Makefile.am gets changed \ if ! LC_ALL=C nm $(top_builddir)/src/NetworkManager | LC_ALL=C grep -q "register_device_factory_internal_$$t" ; then \ From 3dfeec75e56df17777afda85435cd5d11c95abc9 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 12 Nov 2015 17:28:51 +0100 Subject: [PATCH 13/18] device: remove NMDeviceGre As per previous commit, GRE tunnels are now represented as generic IP tunnel devices. --- introspection/Makefile.am | 3 - introspection/nm-device-gre.xml | 81 --------- src/Makefile.am | 2 - src/devices/nm-device-gre.c | 286 -------------------------------- src/devices/nm-device-gre.h | 53 ------ src/tests/Makefile.am | 2 +- 6 files changed, 1 insertion(+), 426 deletions(-) delete mode 100644 introspection/nm-device-gre.xml delete mode 100644 src/devices/nm-device-gre.c delete mode 100644 src/devices/nm-device-gre.h diff --git a/introspection/Makefile.am b/introspection/Makefile.am index c3721fc44d..735921d373 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -31,8 +31,6 @@ nodist_libnmdbus_la_SOURCES = \ nmdbus-device.h \ nmdbus-device-generic.c \ nmdbus-device-generic.h \ - nmdbus-device-gre.c \ - nmdbus-device-gre.h \ nmdbus-device-infiniband.c \ nmdbus-device-infiniband.h \ nmdbus-device-ip-tunnel.c \ @@ -110,7 +108,6 @@ EXTRA_DIST = \ nm-device-bt.xml \ nm-device-ethernet.xml \ nm-device-generic.xml \ - nm-device-gre.xml \ nm-device-infiniband.xml \ nm-device-ip-tunnel.xml \ nm-device-macvlan.xml \ diff --git a/introspection/nm-device-gre.xml b/introspection/nm-device-gre.xml deleted file mode 100644 index ae418aab55..0000000000 --- a/introspection/nm-device-gre.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - The object path of the parent device. - - - - - - The expected set of GRE flags for incoming packets. (The - values are specified by the GRE specification. On Linux, they - are defined in <linux/if_tunnel.h>. Eg, GRE_KEY for the - 'Key Present' bit.) - - - - - - The set of GRE flags to use for outgoing packets. (The - values are specified by the GRE specification. On Linux, they - are defined in <linux/if_tunnel.h>. Eg, GRE_KEY for the - 'Key Present' bit.) - - - - - - Expected input key (if the "Key Present" bit is set in the input flags). - - - - - - Output key (if the "Key Present" bit is set in the output flags). - - - - - - The local end of the tunnel. - - - - - - The remote end of the tunnel. - - - - - - The value to use in the IP TTL field for tunnel packets. - - - - - - The value to use in the IP ToS field for tunnel packets. - - - - - - Whether path MTU discovery is performed. - - - - - - - A dictionary mapping property names to variant boxed values - - - - - - diff --git a/src/Makefile.am b/src/Makefile.am index b7c773ea4b..e4b2cb090c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -204,7 +204,6 @@ nm_device_sources = \ devices/nm-device-bond.c \ devices/nm-device-bridge.c \ devices/nm-device-ethernet.c \ - devices/nm-device-gre.c \ devices/nm-device-infiniband.c \ devices/nm-device-ip-tunnel.c \ devices/nm-device-macvlan.c \ @@ -218,7 +217,6 @@ nm_device_headers = \ devices/nm-device-bond.h \ devices/nm-device-bridge.h \ devices/nm-device-ethernet.h \ - devices/nm-device-gre.h \ devices/nm-device-infiniband.h \ devices/nm-device-ip-tunnel.h \ devices/nm-device-macvlan.h \ diff --git a/src/devices/nm-device-gre.c b/src/devices/nm-device-gre.c deleted file mode 100644 index 3bb1ed787d..0000000000 --- a/src/devices/nm-device-gre.c +++ /dev/null @@ -1,286 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. - */ - -#include "config.h" - -#include -#include - -#include "nm-device-gre.h" -#include "nm-device-private.h" -#include "nm-default.h" -#include "nm-manager.h" -#include "nm-platform.h" -#include "nm-device-factory.h" -#include "nm-core-internal.h" - -#include "nmdbus-device-gre.h" - -#include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceGre); - -G_DEFINE_TYPE (NMDeviceGre, nm_device_gre, NM_TYPE_DEVICE_GENERIC) - -#define NM_DEVICE_GRE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GRE, NMDeviceGrePrivate)) - -typedef struct { - NMPlatformLnkGre props; -} NMDeviceGrePrivate; - -enum { - PROP_0, - PROP_PARENT, - PROP_INPUT_FLAGS, - PROP_OUTPUT_FLAGS, - PROP_INPUT_KEY, - PROP_OUTPUT_KEY, - PROP_LOCAL, - PROP_REMOTE, - PROP_TTL, - PROP_TOS, - PROP_PATH_MTU_DISCOVERY, - - LAST_PROP -}; - -/**************************************************************/ - -static void -update_properties (NMDevice *device) -{ - NMDeviceGre *self = NM_DEVICE_GRE (device); - NMDeviceGrePrivate *priv = NM_DEVICE_GRE_GET_PRIVATE (self); - GObject *object = G_OBJECT (device); - const NMPlatformLnkGre *props; - - props = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); - if (!props) { - _LOGW (LOGD_HW, "could not read gre properties"); - return; - } - - g_object_freeze_notify (object); - - if (priv->props.parent_ifindex != props->parent_ifindex) - g_object_notify (object, NM_DEVICE_GRE_PARENT); - if (priv->props.input_flags != props->input_flags) - g_object_notify (object, NM_DEVICE_GRE_INPUT_FLAGS); - if (priv->props.output_flags != props->output_flags) - g_object_notify (object, NM_DEVICE_GRE_OUTPUT_FLAGS); - if (priv->props.input_key != props->input_key) - g_object_notify (object, NM_DEVICE_GRE_INPUT_KEY); - if (priv->props.output_key != props->output_key) - g_object_notify (object, NM_DEVICE_GRE_OUTPUT_KEY); - if (priv->props.local != props->local) - g_object_notify (object, NM_DEVICE_GRE_LOCAL); - if (priv->props.remote != props->remote) - g_object_notify (object, NM_DEVICE_GRE_REMOTE); - if (priv->props.ttl != props->ttl) - g_object_notify (object, NM_DEVICE_GRE_TTL); - if (priv->props.tos != props->tos) - g_object_notify (object, NM_DEVICE_GRE_TOS); - if (priv->props.path_mtu_discovery != props->path_mtu_discovery) - g_object_notify (object, NM_DEVICE_GRE_PATH_MTU_DISCOVERY); - - priv->props = *props; - - g_object_thaw_notify (object); -} - -static void -link_changed (NMDevice *device, NMPlatformLink *info) -{ - NM_DEVICE_CLASS (nm_device_gre_parent_class)->link_changed (device, info); - update_properties (device); -} - -/**************************************************************/ - -static void -nm_device_gre_init (NMDeviceGre *self) -{ -} - -static void -constructed (GObject *object) -{ - update_properties (NM_DEVICE (object)); - - G_OBJECT_CLASS (nm_device_gre_parent_class)->constructed (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceGrePrivate *priv = NM_DEVICE_GRE_GET_PRIVATE (object); - char buf[INET_ADDRSTRLEN]; - NMDevice *parent; - - switch (prop_id) { - case PROP_PARENT: - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); - nm_utils_g_value_set_object_path (value, parent); - break; - case PROP_INPUT_FLAGS: - g_value_set_uint (value, priv->props.input_flags); - break; - case PROP_OUTPUT_FLAGS: - g_value_set_uint (value, priv->props.output_flags); - break; - case PROP_INPUT_KEY: - g_value_set_uint (value, priv->props.input_key); - break; - case PROP_OUTPUT_KEY: - g_value_set_uint (value, priv->props.output_key); - break; - case PROP_LOCAL: - g_value_set_string (value, inet_ntop (AF_INET, &priv->props.local, buf, sizeof (buf))); - break; - case PROP_REMOTE: - g_value_set_string (value, inet_ntop (AF_INET, &priv->props.remote, buf, sizeof (buf))); - break; - case PROP_TTL: - g_value_set_uchar (value, priv->props.ttl); - break; - case PROP_TOS: - g_value_set_uchar (value, priv->props.tos); - break; - case PROP_PATH_MTU_DISCOVERY: - g_value_set_boolean (value, priv->props.path_mtu_discovery); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_gre_class_init (NMDeviceGreClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (klass, sizeof (NMDeviceGrePrivate)); - - object_class->constructed = constructed; - object_class->get_property = get_property; - - device_class->link_changed = link_changed; - - /* properties */ - g_object_class_install_property - (object_class, PROP_PARENT, - g_param_spec_string (NM_DEVICE_GRE_PARENT, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INPUT_FLAGS, - g_param_spec_uint (NM_DEVICE_GRE_INPUT_FLAGS, "", "", - 0, G_MAXUINT16, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_OUTPUT_FLAGS, - g_param_spec_uint (NM_DEVICE_GRE_OUTPUT_FLAGS, "", "", - 0, G_MAXUINT16, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INPUT_KEY, - g_param_spec_uint (NM_DEVICE_GRE_INPUT_KEY, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_OUTPUT_KEY, - g_param_spec_uint (NM_DEVICE_GRE_OUTPUT_KEY, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_LOCAL, - g_param_spec_string (NM_DEVICE_GRE_LOCAL, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_REMOTE, - g_param_spec_string (NM_DEVICE_GRE_REMOTE, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_TTL, - g_param_spec_uchar (NM_DEVICE_GRE_TTL, "", "", - 0, 255, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_TOS, - g_param_spec_uchar (NM_DEVICE_GRE_TOS, "", "", - 0, 255, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_PATH_MTU_DISCOVERY, - g_param_spec_boolean (NM_DEVICE_GRE_PATH_MTU_DISCOVERY, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), - NMDBUS_TYPE_DEVICE_GRE_SKELETON, - NULL); -} - -/*************************************************************/ -#define NM_TYPE_GRE_FACTORY (nm_gre_factory_get_type ()) -#define NM_GRE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GRE_FACTORY, NMGreFactory)) - -static NMDevice * -create_device (NMDeviceFactory *factory, - const char *iface, - NMPlatformLink *plink, - NMConnection *connection, - gboolean *out_ignore) -{ - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GRE, - NM_DEVICE_IFACE, iface, - NM_DEVICE_TYPE_DESC, "Gre", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, - NULL); -} - -NM_DEVICE_FACTORY_DEFINE_INTERNAL (GRE, Gre, gre, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP), - factory_iface->create_device = create_device; - ) - diff --git a/src/devices/nm-device-gre.h b/src/devices/nm-device-gre.h deleted file mode 100644 index 7e2d105c4b..0000000000 --- a/src/devices/nm-device-gre.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_DEVICE_GRE_H__ -#define __NETWORKMANAGER_DEVICE_GRE_H__ - -#include "nm-device-generic.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_GRE (nm_device_gre_get_type ()) -#define NM_DEVICE_GRE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GRE, NMDeviceGre)) -#define NM_DEVICE_GRE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GRE, NMDeviceGreClass)) -#define NM_IS_DEVICE_GRE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GRE)) -#define NM_IS_DEVICE_GRE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GRE)) -#define NM_DEVICE_GRE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GRE, NMDeviceGreClass)) - -#define NM_DEVICE_GRE_PARENT "parent" -#define NM_DEVICE_GRE_INPUT_FLAGS "input-flags" -#define NM_DEVICE_GRE_OUTPUT_FLAGS "output-flags" -#define NM_DEVICE_GRE_INPUT_KEY "input-key" -#define NM_DEVICE_GRE_OUTPUT_KEY "output-key" -#define NM_DEVICE_GRE_LOCAL "local" -#define NM_DEVICE_GRE_REMOTE "remote" -#define NM_DEVICE_GRE_TTL "ttl" -#define NM_DEVICE_GRE_TOS "tos" -#define NM_DEVICE_GRE_PATH_MTU_DISCOVERY "path-mtu-discovery" - -typedef NMDeviceGeneric NMDeviceGre; -typedef NMDeviceGenericClass NMDeviceGreClass; - -GType nm_device_gre_get_type (void); - -G_END_DECLS - -#endif /* NM_DEVICE_GRE_H */ diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 2278e5a028..18fce10088 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -150,7 +150,7 @@ TESTS = \ if ENABLE_TESTS check-local: - @for t in bond bridge ethernet gre infiniband ip_tunnel macvlan tun veth vlan vxlan; do \ + @for t in bond bridge ethernet infiniband ip_tunnel macvlan tun veth vlan vxlan; do \ # Ensure the device subclass factory registration constructors exist \ # which could inadvertently break if src/Makefile.am gets changed \ if ! LC_ALL=C nm $(top_builddir)/src/NetworkManager | LC_ALL=C grep -q "register_device_factory_internal_$$t" ; then \ From d1b389bfa83ccfe2930c0f3c7b40fca9198ecc3b Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Nov 2015 20:20:15 +0100 Subject: [PATCH 14/18] device/ip-tunnel: add support for SIT tunnels --- src/devices/nm-device-ip-tunnel.c | 46 ++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 4d338ecbf3..a47e1baf46 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -167,6 +167,21 @@ update_properties (NMDevice *device) g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); } } + } else if (priv->mode == NM_IP_TUNNEL_MODE_SIT) { + const NMPlatformLnkSit *lnk; + + lnk = nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "sit"); + return; + } + + parent_ifindex = lnk->parent_ifindex; + local4 = lnk->local; + remote4 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tos; + pmtud = lnk->path_mtu_discovery; } else g_return_if_reached (); @@ -434,6 +449,8 @@ platform_link_to_tunnel_mode (const NMPlatformLink *link) switch (link->type) { case NM_LINK_TYPE_GRE: return NM_IP_TUNNEL_MODE_GRE; + case NM_LINK_TYPE_SIT: + return NM_IP_TUNNEL_MODE_SIT; default: g_return_val_if_reached (NM_IP_TUNNEL_MODE_UKNOWN); } @@ -467,6 +484,7 @@ create_and_realize (NMDevice *device, NMSettingIPTunnel *s_ip_tunnel; NMPlatformError plerr; NMPlatformLnkGre lnk_gre = { }; + NMPlatformLnkSit lnk_sit = { }; const char *str; gint64 val; @@ -521,6 +539,32 @@ create_and_realize (NMDevice *device, return FALSE; } break; + case NM_IP_TUNNEL_MODE_SIT: + if (parent) + lnk_sit.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET, str, &lnk_sit.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET, str, &lnk_sit.remote); + + lnk_sit.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_sit.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); + + plerr = nm_platform_link_sit_add (NM_PLATFORM_GET, iface, &lnk_sit, 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 SIT interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; default: g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IP tunnel interface '%s' for '%s': mode %d not supported", @@ -754,7 +798,7 @@ get_virtual_iface_name (NMDeviceFactory *factory, } NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE) + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_SIT) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; From 8d2aa135344b04ff79c94defdb27e8bdecb004ff Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Nov 2015 20:26:20 +0100 Subject: [PATCH 15/18] device/ip-tunnel: add support for IPIP tunnels --- src/devices/nm-device-ip-tunnel.c | 46 ++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index a47e1baf46..faaf2149d7 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -176,6 +176,21 @@ update_properties (NMDevice *device) return; } + parent_ifindex = lnk->parent_ifindex; + local4 = lnk->local; + remote4 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tos; + pmtud = lnk->path_mtu_discovery; + } else if (priv->mode == NM_IP_TUNNEL_MODE_IPIP) { + const NMPlatformLnkIpIp *lnk; + + lnk = nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "ipip"); + return; + } + parent_ifindex = lnk->parent_ifindex; local4 = lnk->local; remote4 = lnk->remote; @@ -449,6 +464,8 @@ platform_link_to_tunnel_mode (const NMPlatformLink *link) switch (link->type) { case NM_LINK_TYPE_GRE: return NM_IP_TUNNEL_MODE_GRE; + case NM_LINK_TYPE_IPIP: + return NM_IP_TUNNEL_MODE_IPIP; case NM_LINK_TYPE_SIT: return NM_IP_TUNNEL_MODE_SIT; default: @@ -485,6 +502,7 @@ create_and_realize (NMDevice *device, NMPlatformError plerr; NMPlatformLnkGre lnk_gre = { }; NMPlatformLnkSit lnk_sit = { }; + NMPlatformLnkIpIp lnk_ipip = { }; const char *str; gint64 val; @@ -565,6 +583,32 @@ create_and_realize (NMDevice *device, return FALSE; } break; + case NM_IP_TUNNEL_MODE_IPIP: + if (parent) + lnk_ipip.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET, str, &lnk_ipip.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET, str, &lnk_ipip.remote); + + lnk_ipip.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_ipip.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); + + plerr = nm_platform_link_ipip_add (NM_PLATFORM_GET, iface, &lnk_ipip, 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 IPIP interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; default: g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IP tunnel interface '%s' for '%s': mode %d not supported", @@ -798,7 +842,7 @@ get_virtual_iface_name (NMDeviceFactory *factory, } NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_SIT) + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_SIT, NM_LINK_TYPE_IPIP) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; From 8361fbf010b8fd6cd78ec944af1f3f96f8e67c78 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Nov 2015 21:22:13 +0100 Subject: [PATCH 16/18] device/ip-tunnel: add support for IP6TNL tunnels --- introspection/nm-device-ip-tunnel.xml | 15 +++ src/devices/nm-device-ip-tunnel.c | 131 +++++++++++++++++++++++++- src/devices/nm-device-ip-tunnel.h | 2 + 3 files changed, 143 insertions(+), 5 deletions(-) diff --git a/introspection/nm-device-ip-tunnel.xml b/introspection/nm-device-ip-tunnel.xml index db5335b2a5..fcb42ce275 100644 --- a/introspection/nm-device-ip-tunnel.xml +++ b/introspection/nm-device-ip-tunnel.xml @@ -59,6 +59,21 @@ + + + How many additional levels of encapsulation are permitted to + be prepended to packets. This property applies only to IPv6 + tunnels. + + + + + + The flow label to assign to tunnel packets. This property + applies only to IPv6 tunnels. + + + diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index faaf2149d7..746fb170d0 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -57,6 +57,8 @@ typedef struct { int addr_family; char *input_key; char *output_key; + guint8 encap_limit; + guint32 flow_label; } NMDeviceIPTunnelPrivate; enum { @@ -70,6 +72,8 @@ enum { PROP_PATH_MTU_DISCOVERY, PROP_INPUT_KEY, PROP_OUTPUT_KEY, + PROP_ENCAPSULATION_LIMIT, + PROP_FLOW_LABEL, LAST_PROP }; @@ -118,8 +122,9 @@ update_properties (NMDevice *device) int parent_ifindex; in_addr_t local4, remote4; struct in6_addr local6, remote6; - guint8 ttl, tos; - gboolean pmtud; + guint8 ttl = 0, tos = 0, encap_limit = 0; + gboolean pmtud = FALSE; + guint32 flow_label = 0; char *key; if (priv->mode == NM_IP_TUNNEL_MODE_GRE) { @@ -197,6 +202,23 @@ update_properties (NMDevice *device) ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; + } else if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6 + || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) { + const NMPlatformLnkIp6Tnl *lnk; + + lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "ip6tnl"); + return; + } + + parent_ifindex = lnk->parent_ifindex; + local6 = lnk->local; + remote6 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tclass; + encap_limit = lnk->encap_limit; + flow_label = lnk->flow_label; } else g_return_if_reached (); @@ -253,6 +275,16 @@ update_properties (NMDevice *device) priv->path_mtu_discovery = pmtud; g_object_notify (object, NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY); } + + if (priv->encap_limit != encap_limit) { + priv->encap_limit = encap_limit; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT); + } + + if (priv->flow_label != flow_label) { + priv->flow_label = flow_label; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_FLOW_LABEL); + } } static void @@ -352,6 +384,20 @@ update_connection (NMDevice *device, NMConnection *connection) NULL); } + if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, + priv->encap_limit, + NULL); + } + + if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_FLOW_LABEL, + priv->flow_label, + NULL); + } + if (priv->mode == NM_IP_TUNNEL_MODE_GRE || priv->mode == NM_IP_TUNNEL_MODE_IP6GRE) { if (g_strcmp0 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), priv->input_key)) { g_object_set (G_OBJECT (s_ip_tunnel), @@ -452,8 +498,16 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) return FALSE; - if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) - return FALSE; + if (priv->addr_family == AF_INET) { + if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) + return FALSE; + } else { + if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit) + return FALSE; + + if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label) + return FALSE; + } return TRUE; } @@ -461,9 +515,19 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) static NMIPTunnelMode platform_link_to_tunnel_mode (const NMPlatformLink *link) { + const NMPlatformLnkIp6Tnl *lnk; + switch (link->type) { case NM_LINK_TYPE_GRE: return NM_IP_TUNNEL_MODE_GRE; + case NM_LINK_TYPE_IP6TNL: + lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, link->ifindex, NULL); + if (lnk->proto == IPPROTO_IPIP) + return NM_IP_TUNNEL_MODE_IPIP6; + else if (lnk->proto == IPPROTO_IPV6) + return NM_IP_TUNNEL_MODE_IP6IP6; + else + return NM_IP_TUNNEL_MODE_UKNOWN; case NM_LINK_TYPE_IPIP: return NM_IP_TUNNEL_MODE_IPIP; case NM_LINK_TYPE_SIT: @@ -485,7 +549,11 @@ constructed (GObject *object) { NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); - priv->addr_family = AF_INET; /* at the moment we support only IPv4 tunnels */ + if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6 + || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) + priv->addr_family = AF_INET6; + else + priv->addr_family = AF_INET; G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->constructed (object); } @@ -503,6 +571,7 @@ create_and_realize (NMDevice *device, NMPlatformLnkGre lnk_gre = { }; NMPlatformLnkSit lnk_sit = { }; NMPlatformLnkIpIp lnk_ipip = { }; + NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; const char *str; gint64 val; @@ -609,6 +678,35 @@ create_and_realize (NMDevice *device, return FALSE; } break; + case NM_IP_TUNNEL_MODE_IPIP6: + case NM_IP_TUNNEL_MODE_IP6IP6: + if (parent) + lnk_ip6tnl.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET6, str, &lnk_ip6tnl.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET6, str, &lnk_ip6tnl.remote); + + lnk_ip6tnl.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_ip6tnl.tclass = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_ip6tnl.encap_limit = nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel); + lnk_ip6tnl.flow_label = nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel); + lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6; + + plerr = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, iface, &lnk_ip6tnl, 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 IPIP interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; default: g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create IP tunnel interface '%s' for '%s': mode %d not supported", @@ -665,6 +763,12 @@ get_property (GObject *object, guint prop_id, case PROP_OUTPUT_KEY: g_value_set_string (value, priv->output_key); break; + case PROP_ENCAPSULATION_LIMIT: + g_value_set_uchar (value, priv->encap_limit); + break; + case PROP_FLOW_LABEL: + g_value_set_uint (value, priv->flow_label); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -774,6 +878,20 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_ENCAPSULATION_LIMIT, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_FLOW_LABEL, + g_param_spec_uint (NM_DEVICE_IP_TUNNEL_FLOW_LABEL, "", "", + 0, (1 << 20) - 1, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_IPTUNNEL_SKELETON, NULL); @@ -799,6 +917,9 @@ create_device (NMDeviceFactory *factory, } else mode = platform_link_to_tunnel_mode (plink); + if (mode == NM_IP_TUNNEL_MODE_UKNOWN) + return NULL; + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_IP_TUNNEL, NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "IPTunnel", diff --git a/src/devices/nm-device-ip-tunnel.h b/src/devices/nm-device-ip-tunnel.h index fdd92f3c6c..11cb5bce3b 100644 --- a/src/devices/nm-device-ip-tunnel.h +++ b/src/devices/nm-device-ip-tunnel.h @@ -42,6 +42,8 @@ G_BEGIN_DECLS #define NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY "path-mtu-discovery" #define NM_DEVICE_IP_TUNNEL_INPUT_KEY "input-key" #define NM_DEVICE_IP_TUNNEL_OUTPUT_KEY "output-key" +#define NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" +#define NM_DEVICE_IP_TUNNEL_FLOW_LABEL "flow-label" typedef struct { NMDevice parent; From e2da055f900e147a871fac37f2b755ab83d0265e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 12 Nov 2015 17:46:39 +0100 Subject: [PATCH 17/18] libnm: add NMDeviceIPTunnel --- libnm/Makefile.am | 2 + libnm/libnm.ver | 12 + libnm/nm-device-ip-tunnel.c | 544 ++++++++++++++++++++++++++++++++++++ libnm/nm-device-ip-tunnel.h | 90 ++++++ libnm/nm-device.c | 3 + libnm/nm-types.h | 1 + po/POTFILES.in | 1 + 7 files changed, 653 insertions(+) create mode 100644 libnm/nm-device-ip-tunnel.c create mode 100644 libnm/nm-device-ip-tunnel.h diff --git a/libnm/Makefile.am b/libnm/Makefile.am index bf921abd89..4ce9655554 100644 --- a/libnm/Makefile.am +++ b/libnm/Makefile.am @@ -38,6 +38,7 @@ libnminclude_hfiles = \ nm-device-ethernet.h \ nm-device-generic.h \ nm-device-infiniband.h \ + nm-device-ip-tunnel.h \ nm-device-modem.h \ nm-device-olpc-mesh.h \ nm-device-team.h \ @@ -90,6 +91,7 @@ libnm_la_csources = \ nm-device-ethernet.c \ nm-device-generic.c \ nm-device-infiniband.c \ + nm-device-ip-tunnel.c \ nm-device-modem.c \ nm-device-olpc-mesh.c \ nm-device-team.c \ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index f5150d7277..dbd95922e9 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -863,6 +863,18 @@ global: nm_device_ethernet_get_s390_subchannels; nm_device_get_lldp_neighbors; nm_device_get_metered; + nm_device_ip_tunnel_get_encapsulation_limit; + nm_device_ip_tunnel_get_flow_label; + nm_device_ip_tunnel_get_input_key; + nm_device_ip_tunnel_get_local; + nm_device_ip_tunnel_get_mode; + nm_device_ip_tunnel_get_output_key; + nm_device_ip_tunnel_get_parent; + nm_device_ip_tunnel_get_path_mtu_discovery; + nm_device_ip_tunnel_get_remote; + nm_device_ip_tunnel_get_tos; + nm_device_ip_tunnel_get_ttl; + nm_device_ip_tunnel_get_type; nm_device_get_nm_plugin_missing; nm_device_set_managed; nm_device_tun_get_group; diff --git a/libnm/nm-device-ip-tunnel.c b/libnm/nm-device-ip-tunnel.c new file mode 100644 index 0000000000..ad107155b8 --- /dev/null +++ b/libnm/nm-device-ip-tunnel.c @@ -0,0 +1,544 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include +#include +#include + +#include "nm-default.h" +#include "nm-device-ip-tunnel.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-core-internal.h" + +G_DEFINE_TYPE (NMDeviceIPTunnel, nm_device_ip_tunnel, NM_TYPE_DEVICE) + +#define NM_DEVICE_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelPrivate)) + +typedef struct { + NMIPTunnelMode mode; + NMDevice *parent; + char *local; + char *remote; + guint8 ttl; + guint8 tos; + gboolean path_mtu_discovery; + char *input_key; + char *output_key; + guint8 encap_limit; + guint32 flow_label; +} NMDeviceIPTunnelPrivate; + +enum { + PROP_0, + PROP_MODE, + PROP_PARENT, + PROP_LOCAL, + PROP_REMOTE, + PROP_TTL, + PROP_TOS, + PROP_PATH_MTU_DISCOVERY, + PROP_INPUT_KEY, + PROP_OUTPUT_KEY, + PROP_ENCAPSULATION_LIMIT, + PROP_FLOW_LABEL, + + LAST_PROP +}; + +/** + * nm_device_ip_tunnel_get_mode: + * @device: a #NMDeviceIPTunnel + * + * Returns: the tunneling mode + * + * Since: 1.2 + **/ +NMIPTunnelMode +nm_device_ip_tunnel_get_mode (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), 0); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->mode; +} + +/** + * nm_device_ip_tunnel_get_parent: + * @device: a #NMDeviceIPTunnel + * + * Returns: (transfer none): the device's parent device + * + * Since: 1.2 + **/ +NMDevice * +nm_device_ip_tunnel_get_parent (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), NULL); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->parent; +} + +/** + * nm_device_ip_tunnel_get_local: + * @device: a #NMDeviceIPTunnel + * + * Returns: the local endpoint of the tunnel + * + * Since: 1.2 + **/ +const char * +nm_device_ip_tunnel_get_local (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), NULL); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->local; +} + +/** + * nm_device_ip_tunnel_get_remote: + * @device: a #NMDeviceIPTunnel + * + * Returns: the remote endpoint of the tunnel + * + * Since: 1.2 + **/ +const char * +nm_device_ip_tunnel_get_remote (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), NULL); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->remote; +} + +/** + * nm_device_ip_tunnel_get_ttl: + * @device: a #NMDeviceIPTunnel + * + * Returns: the TTL assigned to tunneled packets + * + * Since: 1.2 + **/ +guint8 +nm_device_ip_tunnel_get_ttl (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), 0); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->ttl; +} + +/** + * nm_device_ip_tunnel_get_tos: + * @device: a #NMDeviceIPTunnel + * + * Returns: type of service (IPv4) or traffic class (IPv6) assigned + * to tunneled packets. + * + * Since: 1.2 + **/ +guint8 +nm_device_ip_tunnel_get_tos (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), 0); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->tos; +} + +/** + * nm_device_ip_tunnel_get_path_mtu_discovery: + * @device: a #NMDeviceIPTunnel + * + * Returns: whether path MTU discovery is enabled + * + * Since: 1.2 + **/ +gboolean +nm_device_ip_tunnel_get_path_mtu_discovery (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), TRUE); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->path_mtu_discovery; +} + +/** + * nm_device_ip_tunnel_get_input_key: + * @device: a #NMDeviceIPTunnel + * + * Returns: the key used for incoming packets + * + * Since: 1.2 + **/ +const char * +nm_device_ip_tunnel_get_input_key (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), NULL); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->input_key; +} + +/** + * nm_device_ip_tunnel_get_output_key: + * @device: a #NMDeviceIPTunnel + * + * Returns: the key used for outgoing packets + * + * Since: 1.2 + **/ +const char * +nm_device_ip_tunnel_get_output_key (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), NULL); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->output_key; +} + +/** + * nm_device_ip_tunnel_get_encapsulation_limit: + * @device: a #NMDeviceIPTunnel + * + * Returns: the maximum permitted encapsulation level + * + * Since: 1.2 + **/ +guint8 +nm_device_ip_tunnel_get_encapsulation_limit (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), 0); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->encap_limit; +} + +/** + * nm_device_ip_tunnel_get_flow_label: + * @device: a #NMDeviceIPTunnel + * + * Returns: the flow label assigned to tunnel packets + * + * Since: 1.2 + **/ +guint +nm_device_ip_tunnel_get_flow_label (NMDeviceIPTunnel *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), 0); + + return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->flow_label; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_IP_TUNNEL_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not an IP tunnel connection.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_IP_TUNNEL; +} + +/***********************************************************/ + +static void +nm_device_ip_tunnel_init (NMDeviceIPTunnel *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_IP_TUNNEL); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_IP_TUNNEL_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, + { NM_DEVICE_IP_TUNNEL_MODE, &priv->mode }, + { NM_DEVICE_IP_TUNNEL_LOCAL, &priv->local }, + { NM_DEVICE_IP_TUNNEL_REMOTE, &priv->remote }, + { NM_DEVICE_IP_TUNNEL_TTL, &priv->ttl }, + { NM_DEVICE_IP_TUNNEL_TOS, &priv->tos }, + { NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY, &priv->path_mtu_discovery }, + { NM_DEVICE_IP_TUNNEL_INPUT_KEY, &priv->input_key }, + { NM_DEVICE_IP_TUNNEL_OUTPUT_KEY, &priv->output_key }, + { NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT, &priv->encap_limit }, + { NM_DEVICE_IP_TUNNEL_FLOW_LABEL, &priv->flow_label }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL, + property_info); +} + +static void +finalize (GObject *object) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + + g_free (priv->local); + g_free (priv->remote); + g_free (priv->input_key); + g_free (priv->output_key); + g_clear_object (&priv->parent); + + G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceIPTunnel *device = NM_DEVICE_IP_TUNNEL (object); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_object (value, nm_device_ip_tunnel_get_parent (device)); + break; + case PROP_MODE: + g_value_set_uint (value, nm_device_ip_tunnel_get_mode (device)); + break; + case PROP_LOCAL: + g_value_set_string (value, nm_device_ip_tunnel_get_local (device)); + break; + case PROP_REMOTE: + g_value_set_string (value, nm_device_ip_tunnel_get_remote (device)); + break; + case PROP_TTL: + g_value_set_uint (value, nm_device_ip_tunnel_get_ttl (device)); + break; + case PROP_TOS: + g_value_set_uint (value, nm_device_ip_tunnel_get_tos (device)); + break; + case PROP_PATH_MTU_DISCOVERY: + g_value_set_boolean (value, nm_device_ip_tunnel_get_path_mtu_discovery (device)); + break; + case PROP_INPUT_KEY: + g_value_set_string (value, nm_device_ip_tunnel_get_input_key (device)); + break; + case PROP_OUTPUT_KEY: + g_value_set_string (value, nm_device_ip_tunnel_get_output_key (device)); + break; + case PROP_ENCAPSULATION_LIMIT: + g_value_set_uint (value, nm_device_ip_tunnel_get_encapsulation_limit (device)); + break; + case PROP_FLOW_LABEL: + g_value_set_uint (value, nm_device_ip_tunnel_get_flow_label (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *bond_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (bond_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bond_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (bond_class); + + g_type_class_add_private (bond_class, sizeof (NMDeviceIPTunnelPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL); + + /* virtual methods */ + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + + /* properties */ + + /** + * NMDeviceIPTunnel:mode: + * + * The tunneling mode of the device. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_uint (NM_DEVICE_IP_TUNNEL_MODE, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:parent: + * + * The devices's parent device. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_object (NM_DEVICE_IP_TUNNEL_PARENT, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:local: + * + * The local endpoint of the tunnel. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_LOCAL, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:remote: + * + * The remote endpoint of the tunnel. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_REMOTE, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_REMOTE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:ttl: + * + * The TTL assigned to tunneled packets. 0 is a special value + * meaning that packets inherit the TTL value + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_TTL, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:tos: + * + * The type of service (IPv4) or traffic class (IPv6) assigned to + * tunneled packets. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_TOS, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:path-mtu-discovery: + * + * Whether path MTU discovery is enabled on this tunnel. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_PATH_MTU_DISCOVERY, + g_param_spec_boolean (NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:parent: + * + * The key used for tunneled input packets, if applicable. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_INPUT_KEY, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_INPUT_KEY, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:output-key: + * + * The key used for tunneled output packets, if applicable. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_OUTPUT_KEY, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_OUTPUT_KEY, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:encapsulation-limit: + * + * How many additional levels of encapsulation are permitted to + * be prepended to packets. This property applies only to IPv6 + * tunnels. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_ENCAPSULATION_LIMIT, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceIPTunnel:flow-label: + * + * The flow label to assign to tunnel packets. This property + * applies only to IPv6 tunnels. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_FLOW_LABEL, + g_param_spec_uint (NM_DEVICE_IP_TUNNEL_FLOW_LABEL, "", "", + 0, (1 << 20) - 1, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-ip-tunnel.h b/libnm/nm-device-ip-tunnel.h new file mode 100644 index 0000000000..820eab16dc --- /dev/null +++ b/libnm/nm-device-ip-tunnel.h @@ -0,0 +1,90 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_IP_TUNNEL_H__ +#define __NM_DEVICE_IP_TUNNEL_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_IP_TUNNEL (nm_device_ip_tunnel_get_type ()) +#define NM_DEVICE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnel)) +#define NM_DEVICE_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelClass)) +#define NM_IS_DEVICE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_IP_TUNNEL)) +#define NM_IS_DEVICE_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_IP_TUNNEL)) +#define NM_DEVICE_IP_TUNNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelClass)) + +#define NM_DEVICE_IP_TUNNEL_MODE "mode" +#define NM_DEVICE_IP_TUNNEL_PARENT "parent" +#define NM_DEVICE_IP_TUNNEL_LOCAL "local" +#define NM_DEVICE_IP_TUNNEL_REMOTE "remote" +#define NM_DEVICE_IP_TUNNEL_TTL "ttl" +#define NM_DEVICE_IP_TUNNEL_TOS "tos" +#define NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY "path-mtu-discovery" +#define NM_DEVICE_IP_TUNNEL_INPUT_KEY "input-key" +#define NM_DEVICE_IP_TUNNEL_OUTPUT_KEY "output-key" +#define NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" +#define NM_DEVICE_IP_TUNNEL_FLOW_LABEL "flow-label" + +struct _NMDeviceIPTunnel { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceIPTunnelClass; + +NM_AVAILABLE_IN_1_2 +GType nm_device_ip_tunnel_get_type (void); + +NM_AVAILABLE_IN_1_2 +NMDevice * nm_device_ip_tunnel_get_parent (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +NMIPTunnelMode nm_device_ip_tunnel_get_mode (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +const char * nm_device_ip_tunnel_get_local (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +const char * nm_device_ip_tunnel_get_remote (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +guint8 nm_device_ip_tunnel_get_ttl (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +guint8 nm_device_ip_tunnel_get_tos (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +gboolean nm_device_ip_tunnel_get_path_mtu_discovery (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +const char * nm_device_ip_tunnel_get_input_key (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +const char * nm_device_ip_tunnel_get_output_key (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +guint8 nm_device_ip_tunnel_get_encapsulation_limit (NMDeviceIPTunnel *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_ip_tunnel_get_flow_label (NMDeviceIPTunnel *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_IP_TUNNEL_H__ */ diff --git a/libnm/nm-device.c b/libnm/nm-device.c index e6e5126f51..3ca08c55ce 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -41,6 +41,7 @@ #include "nm-device-bridge.h" #include "nm-device-vlan.h" #include "nm-device-generic.h" +#include "nm-device-ip-tunnel.h" #include "nm-device.h" #include "nm-device-private.h" #include "nm-dhcp4-config.h" @@ -365,6 +366,8 @@ _nm_device_gtype_from_dtype (NMDeviceType dtype) return NM_TYPE_DEVICE_GENERIC; case NM_DEVICE_TYPE_TUN: return NM_TYPE_DEVICE_TUN; + case NM_DEVICE_TYPE_IP_TUNNEL: + return NM_TYPE_DEVICE_IP_TUNNEL; default: g_warning ("Unknown device type %d", dtype); return G_TYPE_INVALID; diff --git a/libnm/nm-types.h b/libnm/nm-types.h index 334e4a17b7..f69deffaec 100644 --- a/libnm/nm-types.h +++ b/libnm/nm-types.h @@ -37,6 +37,7 @@ typedef struct _NMDeviceBt NMDeviceBt; typedef struct _NMDeviceEthernet NMDeviceEthernet; typedef struct _NMDeviceGeneric NMDeviceGeneric; typedef struct _NMDeviceInfiniband NMDeviceInfiniband; +typedef struct _NMDeviceIPTunnel NMDeviceIPTunnel; typedef struct _NMDeviceModem NMDeviceModem; typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh; typedef struct _NMDeviceTeam NMDeviceTeam; diff --git a/po/POTFILES.in b/po/POTFILES.in index c0f79bf786..a451d8dd00 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -120,6 +120,7 @@ libnm/nm-device-ethernet.c libnm/nm-device-generic.c libnm/nm-device-tun.c libnm/nm-device-infiniband.c +libnm/nm-device-ip-tunnel.c libnm/nm-device-modem.c libnm/nm-device-olpc-mesh.c libnm/nm-device-team.c From 818f7f57243feb31ac9089d1f787e70ff9dc63a6 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 30 Nov 2015 22:03:43 +0100 Subject: [PATCH 18/18] libnm-glib: add support for IP tunnel devices as generic ones --- libnm-glib/nm-device.c | 1 + libnm-util/NetworkManager.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index aac94fb1dc..ce76432107 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -321,6 +321,7 @@ _nm_device_gtype_from_dtype (NMDeviceType dtype) return NM_TYPE_DEVICE_VLAN; case NM_DEVICE_TYPE_GENERIC: case NM_DEVICE_TYPE_TUN: + case NM_DEVICE_TYPE_IP_TUNNEL: return NM_TYPE_DEVICE_GENERIC; default: g_warning ("Unknown device type %d", dtype); diff --git a/libnm-util/NetworkManager.h b/libnm-util/NetworkManager.h index 71862c42eb..8101082b77 100644 --- a/libnm-util/NetworkManager.h +++ b/libnm-util/NetworkManager.h @@ -152,6 +152,7 @@ typedef enum { * @NM_DEVICE_TYPE_BRIDGE: a bridge master interface * @NM_DEVICE_TYPE_TEAM: a team master interface * @NM_DEVICE_TYPE_TUN: a TUN/TAP interface + * @NM_DEVICE_TYPE_IP_TUNNEL: an IP tunnel interface * * #NMDeviceType values indicate the type of hardware represented by * an #NMDevice. @@ -176,6 +177,7 @@ typedef enum { NM_DEVICE_TYPE_GENERIC = 14, NM_DEVICE_TYPE_TEAM = 15, NM_DEVICE_TYPE_TUN = 16, + NM_DEVICE_TYPE_IP_TUNNEL = 17, } NMDeviceType; /**