summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-10-30 15:14:23 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2015-11-12 17:23:52 +0100
commita1bf40193e0741e14056c936c2d9fae7e718d93d (patch)
tree8e22cc4daeecaa97289dfc9d8919d9295f737bab
parent162d5216ea66e39f0ee7dc8a898a87f89a773153 (diff)
downloadNetworkManager-a1bf40193e0741e14056c936c2d9fae7e718d93d.tar.gz
device: add NMDeviceIPTunnel
-rw-r--r--introspection/Makefile.am3
-rw-r--r--introspection/nm-device-ip-tunnel.xml57
-rw-r--r--libnm-core/nm-connection.c3
-rw-r--r--libnm-core/nm-dbus-interface.h1
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/devices/nm-device-gre.c3
-rw-r--r--src/devices/nm-device-ip-tunnel.c577
-rw-r--r--src/devices/nm-device-ip-tunnel.h58
-rw-r--r--src/devices/nm-device.c2
-rw-r--r--src/tests/Makefile.am2
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 \