diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2015-10-30 15:14:23 +0100 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2015-11-12 17:23:52 +0100 |
commit | a1bf40193e0741e14056c936c2d9fae7e718d93d (patch) | |
tree | 8e22cc4daeecaa97289dfc9d8919d9295f737bab | |
parent | 162d5216ea66e39f0ee7dc8a898a87f89a773153 (diff) | |
download | NetworkManager-a1bf40193e0741e14056c936c2d9fae7e718d93d.tar.gz |
device: add NMDeviceIPTunnel
-rw-r--r-- | introspection/Makefile.am | 3 | ||||
-rw-r--r-- | introspection/nm-device-ip-tunnel.xml | 57 | ||||
-rw-r--r-- | libnm-core/nm-connection.c | 3 | ||||
-rw-r--r-- | libnm-core/nm-dbus-interface.h | 1 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/devices/nm-device-gre.c | 3 | ||||
-rw-r--r-- | src/devices/nm-device-ip-tunnel.c | 577 | ||||
-rw-r--r-- | src/devices/nm-device-ip-tunnel.h | 58 | ||||
-rw-r--r-- | src/devices/nm-device.c | 2 | ||||
-rw-r--r-- | src/tests/Makefile.am | 2 |
11 files changed, 706 insertions, 3 deletions
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..438f2732b1 --- /dev/null +++ b/introspection/nm-device-ip-tunnel.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <interface name="org.freedesktop.NetworkManager.Device.IPTunnel"> + + <property name="Parent" type="o" access="read"> + <tp:docstring> + The object path of the parent device. + </tp:docstring> + </property> + + <property name="Local" type="s" access="read"> + <tp:docstring> + The local end of the tunnel. + </tp:docstring> + </property> + + <property name="Remote" type="s" access="read"> + <tp:docstring> + The remote end of the tunnel. + </tp:docstring> + </property> + + <property name="Ttl" type="y" access="read"> + <tp:docstring> + The value to use in the IP TTL field for tunnel packets. + </tp:docstring> + </property> + + <property name="Tos" type="y" access="read"> + <tp:docstring> + The value to use in the IP ToS field for tunnel packets. + </tp:docstring> + </property> + + <property name="InputKey" type="s" access="read"> + <tp:docstring> + The key used for incoming packets. + </tp:docstring> + </property> + + <property name="OutputKey" type="s" access="read"> + <tp:docstring> + The key used for outgoing packets. + </tp:docstring> + </property> + + <signal name="PropertiesChanged"> + <arg name="properties" type="a{sv}" tp:type="String_Variant_Map"> + <tp:docstring> + A dictionary mapping property names to variant boxed values + </tp:docstring> + </arg> + </signal> + + </interface> +</node> diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index fb0d4da129..eb19917254 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1566,7 +1566,8 @@ nm_connection_is_virtual (NMConnection *connection) if ( !strcmp (type, NM_SETTING_BOND_SETTING_NAME) || !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_VLAN_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 30871c3c86..b418842a2f 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -171,6 +171,7 @@ typedef enum { NM_DEVICE_TYPE_BRIDGE = 13, NM_DEVICE_TYPE_GENERIC = 14, NM_DEVICE_TYPE_TEAM = 15, + NM_DEVICE_TYPE_IP_TUNNEL = 16, } NMDeviceType; /** diff --git a/po/POTFILES.in b/po/POTFILES.in index 20e67fa8f9..73cc4329f3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -147,6 +147,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-vlan.c src/devices/team/nm-device-team.c src/devices/wifi/nm-device-olpc-mesh.c diff --git a/src/Makefile.am b/src/Makefile.am index 0c96c4510d..6fb30b6851 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -186,6 +186,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 \ @@ -199,6 +200,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..895eaed5f4 100644 --- a/src/devices/nm-device-gre.c +++ b/src/devices/nm-device-gre.c @@ -262,7 +262,7 @@ nm_device_gre_class_init (NMDeviceGreClass *klass) } /*************************************************************/ - +#if 0 #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)) @@ -284,4 +284,5 @@ 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; ) +#endif diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c new file mode 100644 index 0000000000..2ec83d2d47 --- /dev/null +++ b/src/devices/nm-device-ip-tunnel.c @@ -0,0 +1,577 @@ +/* -*- 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 <string.h> +#include <netinet/in.h> +#include <linux/if.h> +#include <linux/ip.h> +#include <linux/if_tunnel.h> + +#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 "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; + 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 +}; + +/**************************************************************/ + +struct { + NMLinkType platform_type; + NMIPTunnelMode setting_mode; + int family; +} tunnel_types[] = { + { NM_LINK_TYPE_GRE, NM_IP_TUNNEL_MODE_GRE, AF_INET }, +}; + +static int +platform_type_to_setting_mode (NMLinkType type) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (tunnel_types); i++) { + if (tunnel_types[i].platform_type == type) + return tunnel_types[i].setting_mode; + } + + return -1; +} + +static int +setting_mode_to_family (NMIPTunnelMode mode) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (tunnel_types); i++) { + if (tunnel_types[i].setting_mode == mode) + return tunnel_types[i].family; + } + + return AF_UNSPEC; +} + +static gboolean +string_address_equal (NMIPTunnelMode mode, const char *a, const char *b) +{ + char buffer1[sizeof (struct in6_addr)] = { }; + char buffer2[sizeof (struct in6_addr)] = { }; + int family; + + family = setting_mode_to_family (mode); + + 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 void +update_properties (NMDevice *device) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + + nm_log_err (LOGD_DEVICE, "IP-Tunnel %s, mode %d", nm_device_get_iface (device), priv->mode); + + 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 gre properties"); + return; + } + + priv->parent_ifindex = lnk->parent_ifindex; + + g_clear_pointer (&priv->local, g_free); + if (lnk->local) + priv->local = g_strdup (nm_utils_inet4_ntop (lnk->local, NULL)); + + g_clear_pointer (&priv->remote, g_free); + if (lnk->remote) + priv->remote = g_strdup (nm_utils_inet4_ntop (lnk->remote, NULL)); + + priv->ttl = lnk->ttl; + priv->tos = lnk->tos; + priv->path_mtu_discovery = lnk->path_mtu_discovery; + + g_clear_pointer (&priv->input_key, g_free); + if (NM_FLAGS_HAS (lnk->input_flags, GRE_KEY)) + priv->input_key = g_strdup_printf ("%u", ntohl (lnk->input_key)); + + g_clear_pointer (&priv->output_key, g_free); + if (NM_FLAGS_HAS (lnk->output_flags, GRE_KEY)) + priv->output_key = g_strdup_printf ("%u", ntohl (lnk->output_key)); + } +} + +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); + + 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 (!string_address_equal (priv->mode, + 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 (!string_address_equal (priv->mode, + 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); +} + +static gboolean +realize (NMDevice *self, NMPlatformLink *plink, GError **error) +{ + update_properties (self); + 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; + + if (!NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + update_properties (device); + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + if (!s_ip_tunnel) + return FALSE; + + if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) + return FALSE; + + if (!string_address_equal (priv->mode, + nm_setting_ip_tunnel_get_local (s_ip_tunnel), + priv->local)) + return FALSE; + + if (!string_address_equal (priv->mode, + 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 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 = setting_mode_to_family (priv->mode); + + 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: + 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 = htonl (val); + lnk_gre.input_flags = 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 = htonl (val); + lnk_gre.output_flags = GRE_KEY; + } + + plerr = nm_platform_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_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; + int val; + + if (connection) { + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); + } else { + g_return_val_if_fail (plink, NULL); + val = platform_type_to_setting_mode (plink->type); + + if (val > 0) + mode = val; + else + mode = 0; + } + + nm_log_err (LOGD_DEVICE, "IP-Tunnel %s, mode %d", iface, mode); + + 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); +} + +NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE /*, NM_LINK_TYPE_GRETAP */) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), + factory_iface->create_device = create_device; + ) 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 1d28dd4835..a10963cb9e 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -758,6 +758,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..3ad626a913 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 ip_tunnel infiniband 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 \ |