ip-tunnel: add support for ip6gre and ip6gretap tunnel connections

This commit is contained in:
Beniamino Galvani 2018-06-26 15:05:15 +02:00
parent f9199c7fb5
commit 3f9f9f7fa2
3 changed files with 126 additions and 24 deletions

View file

@ -809,17 +809,18 @@ typedef enum /*< flags >*/ {
/**
* 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
* @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel
* @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
* @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel
* @NM_IP_TUNNEL_MODE_IP6GRETAP: IPv6 GRETAP tunnel
*
* The tunneling mode.
*
@ -837,6 +838,7 @@ typedef enum {
NM_IP_TUNNEL_MODE_IP6GRE = 8,
NM_IP_TUNNEL_MODE_VTI6 = 9,
NM_IP_TUNNEL_MODE_GRETAP = 10,
NM_IP_TUNNEL_MODE_IP6GRETAP = 11,
} NMIPTunnelMode;
/**

View file

@ -326,6 +326,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
case NM_IP_TUNNEL_MODE_IPIP6:
case NM_IP_TUNNEL_MODE_IP6GRE:
case NM_IP_TUNNEL_MODE_VTI6:
case NM_IP_TUNNEL_MODE_IP6GRETAP:
family = AF_INET6;
break;
case NM_IP_TUNNEL_MODE_UNKNOWN:
@ -391,7 +392,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
if (!NM_IN_SET (priv->mode,
NM_IP_TUNNEL_MODE_GRE,
NM_IP_TUNNEL_MODE_GRETAP,
NM_IP_TUNNEL_MODE_IP6GRE)) {
NM_IP_TUNNEL_MODE_IP6GRE,
NM_IP_TUNNEL_MODE_IP6GRETAP)) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,

View file

@ -257,11 +257,21 @@ clear:
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) {
} else if (NM_IN_SET (priv->mode,
NM_IP_TUNNEL_MODE_IPIP6,
NM_IP_TUNNEL_MODE_IP6IP6,
NM_IP_TUNNEL_MODE_IP6GRE,
NM_IP_TUNNEL_MODE_IP6GRETAP)) {
const NMPlatformLnkIp6Tnl *lnk;
NMPlatform *plat = nm_device_get_platform (device);
if (priv->mode == NM_IP_TUNNEL_MODE_IP6GRE)
lnk = nm_platform_link_get_lnk_ip6gre (plat, ifindex, NULL);
else if (priv->mode == NM_IP_TUNNEL_MODE_IP6GRETAP)
lnk = nm_platform_link_get_lnk_ip6gretap (plat, ifindex, NULL);
else
lnk = nm_platform_link_get_lnk_ip6tnl (plat, ifindex, NULL);
lnk = nm_platform_link_get_lnk_ip6tnl (nm_device_get_platform (device), ifindex, NULL);
if (!lnk) {
_LOGW (LOGD_PLATFORM, "could not read %s properties", "ip6tnl");
goto clear;
@ -275,6 +285,40 @@ clear:
encap_limit = lnk->encap_limit;
flow_label = lnk->flow_label;
flags = ip6tnl_flags_plat_to_setting (lnk->flags);
if (NM_IN_SET (priv->mode,
NM_IP_TUNNEL_MODE_IP6GRE,
NM_IP_TUNNEL_MODE_IP6GRETAP)) {
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;
_notify (self, PROP_INPUT_KEY);
} else
g_free (key);
} else {
if (priv->input_key) {
g_clear_pointer (&priv->input_key, g_free);
_notify (self, PROP_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;
_notify (self, PROP_OUTPUT_KEY);
} else
g_free (key);
} else {
if (priv->output_key) {
g_clear_pointer (&priv->output_key, g_free);
_notify (self, PROP_OUTPUT_KEY);
}
}
}
} else
g_return_if_reached ();
@ -462,7 +506,8 @@ update_connection (NMDevice *device, NMConnection *connection)
if (NM_IN_SET (priv->mode,
NM_IP_TUNNEL_MODE_GRE,
NM_IP_TUNNEL_MODE_GRETAP,
NM_IP_TUNNEL_MODE_IP6GRE)) {
NM_IP_TUNNEL_MODE_IP6GRE,
NM_IP_TUNNEL_MODE_IP6GRETAP)) {
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,
@ -552,6 +597,10 @@ platform_link_to_tunnel_mode (const NMPlatformLink *link)
return NM_IP_TUNNEL_MODE_IP6IP6;
}
return NM_IP_TUNNEL_MODE_UNKNOWN;
case NM_LINK_TYPE_IP6GRE:
return NM_IP_TUNNEL_MODE_IP6GRE;
case NM_LINK_TYPE_IP6GRETAP:
return NM_IP_TUNNEL_MODE_IP6GRETAP;
case NM_LINK_TYPE_IPIP:
return NM_IP_TUNNEL_MODE_IPIP;
case NM_LINK_TYPE_SIT:
@ -572,12 +621,15 @@ tunnel_mode_to_link_type (NMIPTunnelMode tunnel_mode)
case NM_IP_TUNNEL_MODE_IPIP6:
case NM_IP_TUNNEL_MODE_IP6IP6:
return NM_LINK_TYPE_IP6TNL;
case NM_IP_TUNNEL_MODE_IP6GRE:
return NM_LINK_TYPE_IP6GRE;
case NM_IP_TUNNEL_MODE_IP6GRETAP:
return NM_LINK_TYPE_IP6GRETAP;
case NM_IP_TUNNEL_MODE_IPIP:
return NM_LINK_TYPE_IPIP;
case NM_IP_TUNNEL_MODE_SIT:
return NM_LINK_TYPE_SIT;
case NM_IP_TUNNEL_MODE_VTI:
case NM_IP_TUNNEL_MODE_IP6GRE:
case NM_IP_TUNNEL_MODE_VTI6:
case NM_IP_TUNNEL_MODE_ISATAP:
return NM_LINK_TYPE_UNKNOWN;
@ -605,11 +657,13 @@ create_and_realize (NMDevice *device,
NMPlatformLnkIp6Tnl lnk_ip6tnl = { };
const char *str;
gint64 val;
NMIPTunnelMode mode;
s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection);
g_assert (s_ip_tunnel);
switch (nm_setting_ip_tunnel_get_mode (s_ip_tunnel)) {
mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel);
switch (mode) {
case NM_IP_TUNNEL_MODE_GRETAP:
lnk_gre.is_tap = TRUE;
/* fall-through */
@ -713,6 +767,8 @@ create_and_realize (NMDevice *device,
break;
case NM_IP_TUNNEL_MODE_IPIP6:
case NM_IP_TUNNEL_MODE_IP6IP6:
case NM_IP_TUNNEL_MODE_IP6GRE:
case NM_IP_TUNNEL_MODE_IP6GRETAP:
if (parent)
lnk_ip6tnl.parent_ifindex = nm_device_get_ifindex (parent);
@ -728,13 +784,44 @@ create_and_realize (NMDevice *device,
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;
lnk_ip6tnl.flags = ip6tnl_flags_setting_to_plat (nm_setting_ip_tunnel_get_flags (s_ip_tunnel));
plerr = nm_platform_link_ip6tnl_add (nm_device_get_platform (device), iface, &lnk_ip6tnl, out_plink);
if (NM_IN_SET (mode, NM_IP_TUNNEL_MODE_IP6GRE, NM_IP_TUNNEL_MODE_IP6GRETAP)) {
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_ip6tnl.input_key = val;
lnk_ip6tnl.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_ip6tnl.output_key = val;
lnk_ip6tnl.output_flags = NM_GRE_KEY;
}
lnk_ip6tnl.is_gre = TRUE;
lnk_ip6tnl.is_tap = (mode == NM_IP_TUNNEL_MODE_IP6GRETAP);
plerr = nm_platform_link_ip6gre_add (nm_device_get_platform (device),
iface, &lnk_ip6tnl, out_plink);
} else {
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_device_get_platform (device),
iface, &lnk_ip6tnl, out_plink);
}
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create IPIP interface '%s' for '%s': %s",
"Failed to create IPv6 tunnel interface '%s' for '%s': %s",
iface,
nm_connection_get_id (connection),
nm_platform_error_to_string_a (plerr));
@ -877,8 +964,11 @@ constructed (GObject *object)
{
NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE ((NMDeviceIPTunnel *) object);
if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6
|| priv->mode == NM_IP_TUNNEL_MODE_IP6IP6)
if (NM_IN_SET (priv->mode,
NM_IP_TUNNEL_MODE_IPIP6,
NM_IP_TUNNEL_MODE_IP6IP6,
NM_IP_TUNNEL_MODE_IP6GRE,
NM_IP_TUNNEL_MODE_IP6GRETAP))
priv->addr_family = AF_INET6;
else
priv->addr_family = AF_INET;
@ -953,6 +1043,8 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
NM_LINK_TYPE_GRE,
NM_LINK_TYPE_GRETAP,
NM_LINK_TYPE_IP6TNL,
NM_LINK_TYPE_IP6GRE,
NM_LINK_TYPE_IP6GRETAP,
NM_LINK_TYPE_IPIP,
NM_LINK_TYPE_SIT);
@ -1098,7 +1190,13 @@ get_connection_iface (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_GRETAP, NM_LINK_TYPE_SIT, NM_LINK_TYPE_IPIP)
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE,
NM_LINK_TYPE_GRETAP,
NM_LINK_TYPE_SIT,
NM_LINK_TYPE_IPIP,
NM_LINK_TYPE_IP6TNL,
NM_LINK_TYPE_IP6GRE,
NM_LINK_TYPE_IP6GRETAP)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME),
factory_class->create_device = create_device;
factory_class->get_connection_parent = get_connection_parent;