diff options
Diffstat (limited to 'src/core/devices/nm-device-ip-tunnel.c')
| -rw-r--r-- | src/core/devices/nm-device-ip-tunnel.c | 277 |
1 files changed, 199 insertions, 78 deletions
diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c index 02680dd7..5e5ba632 100644 --- a/src/core/devices/nm-device-ip-tunnel.c +++ b/src/core/devices/nm-device-ip-tunnel.c @@ -39,6 +39,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceIPTunnel, PROP_OUTPUT_KEY, PROP_ENCAPSULATION_LIMIT, PROP_FLOW_LABEL, + PROP_FWMARK, PROP_FLAGS, ); typedef struct { @@ -53,6 +54,7 @@ typedef struct { char *output_key; guint8 encap_limit; guint32 flow_label; + guint32 fwmark; NMIPTunnelFlags flags; } NMDeviceIPTunnelPrivate; @@ -107,12 +109,12 @@ address_equal_pp(int addr_family, const char *a, const char *b) nm_assert_addr_family(addr_family); if (a) { - if (!nm_utils_parse_inaddr_bin(addr_family, a, NULL, &addr_a_val)) + if (!nm_inet_parse_bin(addr_family, a, NULL, &addr_a_val)) nm_assert_not_reached(); addr_a = &addr_a_val; } if (b) { - if (!nm_utils_parse_inaddr_bin(addr_family, b, NULL, &addr_b_val)) + if (!nm_inet_parse_bin(addr_family, b, NULL, &addr_b_val)) nm_assert_not_reached(); addr_b = &addr_b_val; } @@ -125,7 +127,7 @@ address_set(int addr_family, char **p_addr, const NMIPAddr *addr_new) { nm_assert_addr_family(addr_family); nm_assert(p_addr); - nm_assert(!*p_addr || nm_utils_ipaddr_is_normalized(addr_family, *p_addr)); + nm_assert(!*p_addr || nm_inet_is_normalized(addr_family, *p_addr)); if (!addr_new || nm_ip_addr_is_null(addr_family, addr_new)) { if (nm_clear_g_free(p_addr)) @@ -136,7 +138,7 @@ address_set(int addr_family, char **p_addr, const NMIPAddr *addr_new) if (*p_addr) { NMIPAddr addr_val; - if (!nm_utils_parse_inaddr_bin(addr_family, *p_addr, NULL, &addr_val)) + if (!nm_inet_parse_bin(addr_family, *p_addr, NULL, &addr_val)) nm_assert_not_reached(); if (nm_ip_addr_equal(addr_family, &addr_val, addr_new)) @@ -145,7 +147,7 @@ address_set(int addr_family, char **p_addr, const NMIPAddr *addr_new) g_free(*p_addr); } - *p_addr = nm_utils_inet_ntop_dup(addr_family, addr_new); + *p_addr = nm_inet_ntop_dup(addr_family, addr_new); return TRUE; } @@ -162,8 +164,10 @@ update_properties_from_ifindex(NMDevice *device, int ifindex) guint8 encap_limit = 0; gboolean pmtud = FALSE; guint32 flow_label = 0; + guint32 fwmark = 0; NMIPTunnelFlags flags = NM_IP_TUNNEL_FLAG_NONE; - char *key; + gs_free char *input_key = NULL; + gs_free char *output_key = NULL; if (ifindex <= 0) { clear: @@ -207,35 +211,10 @@ clear: 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; - _notify(self, PROP_INPUT_KEY); - } else - g_free(key); - } else { - if (priv->input_key) { - nm_clear_g_free(&priv->input_key); - _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) { - nm_clear_g_free(&priv->output_key); - _notify(self, PROP_OUTPUT_KEY); - } - } + if (NM_FLAGS_HAS(lnk->input_flags, NM_GRE_KEY)) + input_key = g_strdup_printf("%u", lnk->input_key); + if (NM_FLAGS_HAS(lnk->output_flags, NM_GRE_KEY)) + output_key = g_strdup_printf("%u", lnk->output_key); } else if (priv->mode == NM_IP_TUNNEL_MODE_SIT) { const NMPlatformLnkSit *lnk; @@ -296,36 +275,45 @@ clear: 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) { - nm_clear_g_free(&priv->input_key); - _notify(self, PROP_INPUT_KEY); - } - } + if (NM_FLAGS_HAS(lnk->input_flags, NM_GRE_KEY)) + input_key = g_strdup_printf("%u", lnk->input_key); + if (NM_FLAGS_HAS(lnk->output_flags, NM_GRE_KEY)) + output_key = g_strdup_printf("%u", lnk->output_key); + } + } else if (priv->mode == NM_IP_TUNNEL_MODE_VTI) { + const NMPlatformLnkVti *lnk; - 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) { - nm_clear_g_free(&priv->output_key); - _notify(self, PROP_OUTPUT_KEY); - } - } + lnk = nm_platform_link_get_lnk_vti(nm_device_get_platform(device), ifindex, NULL); + if (!lnk) { + _LOGW(LOGD_PLATFORM, "could not read %s properties", "vti"); + goto clear; + } + + parent_ifindex = lnk->parent_ifindex; + local.addr4 = lnk->local; + remote.addr4 = lnk->remote; + fwmark = lnk->fwmark; + if (lnk->ikey) + input_key = g_strdup_printf("%u", lnk->ikey); + if (lnk->okey) + input_key = g_strdup_printf("%u", lnk->okey); + } else if (priv->mode == NM_IP_TUNNEL_MODE_VTI6) { + const NMPlatformLnkVti6 *lnk; + + lnk = nm_platform_link_get_lnk_vti6(nm_device_get_platform(device), ifindex, NULL); + if (!lnk) { + _LOGW(LOGD_PLATFORM, "could not read %s properties", "vti6"); + goto clear; } + + parent_ifindex = lnk->parent_ifindex; + local.addr6 = lnk->local; + remote.addr6 = lnk->remote; + fwmark = lnk->fwmark; + if (lnk->ikey) + input_key = g_strdup_printf("%u", lnk->ikey); + if (lnk->okey) + input_key = g_strdup_printf("%u", lnk->okey); } else g_return_if_reached(); @@ -337,7 +325,6 @@ clear: _notify(self, PROP_REMOTE); out: - if (priv->ttl != ttl) { priv->ttl = ttl; _notify(self, PROP_TTL); @@ -363,6 +350,23 @@ out: _notify(self, PROP_FLOW_LABEL); } + if (!nm_streq0(priv->input_key, input_key)) { + g_free(priv->input_key); + priv->input_key = g_steal_pointer(&input_key); + _notify(self, PROP_INPUT_KEY); + } + + if (!nm_streq0(priv->output_key, output_key)) { + g_free(priv->output_key); + priv->output_key = g_steal_pointer(&output_key); + _notify(self, PROP_OUTPUT_KEY); + } + + if (priv->fwmark != fwmark) { + priv->fwmark = fwmark; + _notify(self, PROP_FWMARK); + } + if (priv->flags != flags) { priv->flags = flags; _notify(self, PROP_FLAGS); @@ -467,11 +471,17 @@ update_connection(NMDevice *device, NMConnection *connection) NULL); } + if (nm_setting_ip_tunnel_get_fwmark(s_ip_tunnel) != priv->fwmark) { + g_object_set(G_OBJECT(s_ip_tunnel), NM_SETTING_IP_TUNNEL_FWMARK, priv->fwmark, NULL); + } + 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_IP6GRETAP)) { + NM_IP_TUNNEL_MODE_IP6GRETAP, + NM_IP_TUNNEL_MODE_VTI, + NM_IP_TUNNEL_MODE_VTI6)) { 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, @@ -493,6 +503,7 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL(device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); NMSettingIPTunnel *s_ip_tunnel; + NMIPTunnelMode mode; const char *parent; if (!NM_DEVICE_CLASS(nm_device_ip_tunnel_parent_class) @@ -500,8 +511,9 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * return FALSE; s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection); + mode = nm_setting_ip_tunnel_get_mode(s_ip_tunnel); - if (nm_setting_ip_tunnel_get_mode(s_ip_tunnel) != priv->mode) { + if (mode != priv->mode) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "incompatible IP tunnel mode"); @@ -536,14 +548,16 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * return FALSE; } - if (nm_setting_ip_tunnel_get_ttl(s_ip_tunnel) != priv->ttl) { + if (!NM_IN_SET(mode, NM_IP_TUNNEL_MODE_VTI, NM_IP_TUNNEL_MODE_VTI6) + && nm_setting_ip_tunnel_get_ttl(s_ip_tunnel) != priv->ttl) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "TTL of IP tunnel mismatches"); return FALSE; } - if (nm_setting_ip_tunnel_get_tos(s_ip_tunnel) != priv->tos) { + if (!NM_IN_SET(mode, NM_IP_TUNNEL_MODE_VTI, NM_IP_TUNNEL_MODE_VTI6) + && nm_setting_ip_tunnel_get_tos(s_ip_tunnel) != priv->tos) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "TOS of IP tunnel mismatches"); @@ -551,11 +565,14 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } if (priv->addr_family == AF_INET) { - if (nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel) - != priv->path_mtu_discovery) { - nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "MTU discovery setting of IP tunnel mismatches"); + if (!NM_IN_SET(mode, NM_IP_TUNNEL_MODE_VTI, NM_IP_TUNNEL_MODE_VTI6) + && nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel) + != priv->path_mtu_discovery) { + nm_utils_error_set(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "MTU discovery setting of IP tunnel mismatches: %d vs %d", + nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel), + priv->path_mtu_discovery); return FALSE; } } else { @@ -605,6 +622,10 @@ platform_link_to_tunnel_mode(const NMPlatformLink *link) return NM_IP_TUNNEL_MODE_IPIP; case NM_LINK_TYPE_SIT: return NM_IP_TUNNEL_MODE_SIT; + case NM_LINK_TYPE_VTI: + return NM_IP_TUNNEL_MODE_VTI; + case NM_LINK_TYPE_VTI6: + return NM_IP_TUNNEL_MODE_VTI6; default: g_return_val_if_reached(NM_IP_TUNNEL_MODE_UNKNOWN); } @@ -630,7 +651,9 @@ tunnel_mode_to_link_type(NMIPTunnelMode tunnel_mode) case NM_IP_TUNNEL_MODE_SIT: return NM_LINK_TYPE_SIT; case NM_IP_TUNNEL_MODE_VTI: + return NM_LINK_TYPE_VTI; case NM_IP_TUNNEL_MODE_VTI6: + return NM_LINK_TYPE_VTI6; case NM_IP_TUNNEL_MODE_ISATAP: return NM_LINK_TYPE_UNKNOWN; case NM_IP_TUNNEL_MODE_UNKNOWN: @@ -654,6 +677,8 @@ create_and_realize(NMDevice *device, NMPlatformLnkSit lnk_sit = {}; NMPlatformLnkIpIp lnk_ipip = {}; NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; + NMPlatformLnkVti lnk_vti = {}; + NMPlatformLnkVti6 lnk_vti6 = {}; const char *str; gint64 val; NMIPTunnelMode mode; @@ -871,6 +896,81 @@ create_and_realize(NMDevice *device, return FALSE; } break; + case NM_IP_TUNNEL_MODE_VTI: + if (parent) + lnk_vti.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_vti.local); + + str = nm_setting_ip_tunnel_get_remote(s_ip_tunnel); + nm_assert(str); + inet_pton(AF_INET, str, &lnk_vti.remote); + + lnk_vti.ikey = _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_input_key(s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + 0); + lnk_vti.okey = + _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_output_key(s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + 0); + lnk_vti.fwmark = nm_setting_ip_tunnel_get_fwmark(s_ip_tunnel); + + r = nm_platform_link_vti_add(nm_device_get_platform(device), iface, &lnk_vti, out_plink); + if (r < 0) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create VTI interface '%s' for '%s': %s", + iface, + nm_connection_get_id(connection), + nm_strerror(r)); + return FALSE; + } + break; + case NM_IP_TUNNEL_MODE_VTI6: + if (parent) + lnk_vti6.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_vti6.local); + + str = nm_setting_ip_tunnel_get_remote(s_ip_tunnel); + nm_assert(str); + inet_pton(AF_INET6, str, &lnk_vti6.remote); + + lnk_vti6.ikey = + _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_input_key(s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + 0); + lnk_vti6.okey = + _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_output_key(s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + 0); + lnk_vti6.fwmark = nm_setting_ip_tunnel_get_fwmark(s_ip_tunnel); + + r = nm_platform_link_vti6_add(nm_device_get_platform(device), iface, &lnk_vti6, out_plink); + if (r < 0) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create VTI6 interface '%s' for '%s': %s", + iface, + nm_connection_get_id(connection), + nm_strerror(r)); + return FALSE; + } + break; default: g_set_error(error, NM_DEVICE_ERROR, @@ -986,6 +1086,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) case PROP_FLAGS: g_value_set_uint(value, priv->flags); break; + case PROP_FWMARK: + g_value_set_uint(value, priv->fwmark); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -1021,7 +1124,8 @@ constructed(GObject *object) NM_IP_TUNNEL_MODE_IPIP6, NM_IP_TUNNEL_MODE_IP6IP6, NM_IP_TUNNEL_MODE_IP6GRE, - NM_IP_TUNNEL_MODE_IP6GRETAP)) + NM_IP_TUNNEL_MODE_IP6GRETAP, + NM_IP_TUNNEL_MODE_VTI6)) priv->addr_family = AF_INET6; else priv->addr_family = AF_INET; @@ -1070,6 +1174,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_ip_tunnel = { NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("FlowLabel", "u", NM_DEVICE_IP_TUNNEL_FLOW_LABEL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("FwMark", + "u", + NM_DEVICE_IP_TUNNEL_FWMARK), NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Flags", "u", NM_DEVICE_IP_TUNNEL_FLAGS), ), ), @@ -1097,7 +1204,9 @@ nm_device_ip_tunnel_class_init(NMDeviceIPTunnelClass *klass) NM_LINK_TYPE_IP6GRE, NM_LINK_TYPE_IP6GRETAP, NM_LINK_TYPE_IPIP, - NM_LINK_TYPE_SIT); + NM_LINK_TYPE_SIT, + NM_LINK_TYPE_VTI, + NM_LINK_TYPE_VTI6); device_class->act_stage1_prepare = act_stage1_prepare; device_class->link_changed = link_changed; @@ -1192,14 +1301,24 @@ nm_device_ip_tunnel_class_init(NMDeviceIPTunnelClass *klass) 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_FWMARK] = g_param_spec_uint(NM_DEVICE_IP_TUNNEL_FWMARK, + "", + "", + 0, + G_MAXUINT32, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); } /*****************************************************************************/ #define NM_TYPE_IP_TUNNEL_DEVICE_FACTORY (nm_ip_tunnel_device_factory_get_type()) -#define NM_IP_TUNNEL_DEVICE_FACTORY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IP_TUNNEL_DEVICE_FACTORY, NMIPTunnelDeviceFactory)) +#define NM_IP_TUNNEL_DEVICE_FACTORY(obj) \ + (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), \ + NM_TYPE_IP_TUNNEL_DEVICE_FACTORY, \ + NMIPTunnelDeviceFactory)) static NMDevice * create_device(NMDeviceFactory *factory, @@ -1282,7 +1401,9 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL( NM_LINK_TYPE_IPIP, NM_LINK_TYPE_IP6TNL, NM_LINK_TYPE_IP6GRE, - NM_LINK_TYPE_IP6GRETAP) + NM_LINK_TYPE_IP6GRETAP, + NM_LINK_TYPE_VTI, + NM_LINK_TYPE_VTI6) 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; |