diff options
Diffstat (limited to 'src/devices/nm-device-ip-tunnel.c')
| -rw-r--r-- | src/devices/nm-device-ip-tunnel.c | 191 |
1 files changed, 115 insertions, 76 deletions
diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 0becb5e5..0a33c82e 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -67,7 +67,7 @@ struct _NMDeviceIPTunnelClass { G_DEFINE_TYPE (NMDeviceIPTunnel, nm_device_ip_tunnel, NM_TYPE_DEVICE) -#define NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceIPTunnel, NM_IS_DEVICE_IP_TUNNEL) +#define NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceIPTunnel, NM_IS_DEVICE_IP_TUNNEL, NMDevice) /*****************************************************************************/ @@ -96,35 +96,63 @@ ip6tnl_flags_plat_to_setting (guint32 flags) /*****************************************************************************/ static gboolean -address_equal_pp (int family, const char *a, const char *b) +address_equal_pp (int addr_family, const char *a, const char *b) { - char buffer1[sizeof (struct in6_addr)] = { }; - char buffer2[sizeof (struct in6_addr)] = { }; + const NMIPAddr *addr_a = &nm_ip_addr_zero; + const NMIPAddr *addr_b = &nm_ip_addr_zero; + NMIPAddr addr_a_val; + NMIPAddr addr_b_val; - g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + nm_assert_addr_family (addr_family); - if (a) - inet_pton (family, a, buffer1); - if (b) - inet_pton (family, b, buffer2); + if (a) { + if (!nm_utils_parse_inaddr_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)) + nm_assert_not_reached (); + addr_b = &addr_b_val; + } - return !memcmp (buffer1, buffer2, - family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr)); + return nm_ip_addr_equal (addr_family, addr_a, addr_b); } static gboolean -address_equal_pn (int family, const char *a, const void *b) +address_set (int addr_family, + char **p_addr, + const NMIPAddr *addr_new) { - char buffer1[sizeof (struct in6_addr)] = { }; + nm_assert_addr_family (addr_family); + nm_assert (p_addr); + nm_assert ( !*p_addr + || nm_utils_ipaddr_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)) + return TRUE; + return FALSE; + } - g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + if (*p_addr) { + NMIPAddr addr_val; - if (a) - inet_pton (family, a, buffer1); + if (!nm_utils_parse_inaddr_bin (addr_family, + *p_addr, + NULL, + &addr_val)) + nm_assert_not_reached (); - return !memcmp (buffer1, b, - family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr)); + if (nm_ip_addr_equal (addr_family, &addr_val, addr_new)) + return FALSE; + + g_free (*p_addr); + } + *p_addr = nm_utils_inet_ntop_dup (addr_family, addr_new); + return TRUE; } static void @@ -133,10 +161,8 @@ update_properties_from_ifindex (NMDevice *device, int ifindex) NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); int parent_ifindex = 0; - in_addr_t local4 = 0; - in_addr_t remote4 = 0; - struct in6_addr local6 = IN6ADDR_ANY_INIT; - struct in6_addr remote6 = IN6ADDR_ANY_INIT; + NMIPAddr local = NM_IP_ADDR_INIT; + NMIPAddr remote = NM_IP_ADDR_INIT; guint8 ttl = 0; guint8 tos = 0; guint8 encap_limit = 0; @@ -149,19 +175,19 @@ update_properties_from_ifindex (NMDevice *device, int ifindex) clear: nm_device_parent_set_ifindex (device, 0); if (priv->local) { - g_clear_pointer (&priv->local, g_free); + nm_clear_g_free (&priv->local); _notify (self, PROP_LOCAL); } if (priv->remote) { - g_clear_pointer (&priv->remote, g_free); + nm_clear_g_free (&priv->remote); _notify (self, PROP_REMOTE); } if (priv->input_key) { - g_clear_pointer (&priv->input_key, g_free); + nm_clear_g_free (&priv->input_key); _notify (self, PROP_INPUT_KEY); } if (priv->output_key) { - g_clear_pointer (&priv->output_key, g_free); + nm_clear_g_free (&priv->output_key); _notify (self, PROP_OUTPUT_KEY); } @@ -181,8 +207,8 @@ clear: } parent_ifindex = lnk->parent_ifindex; - local4 = lnk->local; - remote4 = lnk->remote; + local.addr4 = lnk->local; + remote.addr4 = lnk->remote; ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; @@ -197,7 +223,7 @@ clear: g_free (key); } else { if (priv->input_key) { - g_clear_pointer (&priv->input_key, g_free); + nm_clear_g_free (&priv->input_key); _notify (self, PROP_INPUT_KEY); } } @@ -212,7 +238,7 @@ clear: g_free (key); } else { if (priv->output_key) { - g_clear_pointer (&priv->output_key, g_free); + nm_clear_g_free (&priv->output_key); _notify (self, PROP_OUTPUT_KEY); } } @@ -226,8 +252,8 @@ clear: } parent_ifindex = lnk->parent_ifindex; - local4 = lnk->local; - remote4 = lnk->remote; + local.addr4 = lnk->local; + remote.addr4 = lnk->remote; ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; @@ -241,8 +267,8 @@ clear: } parent_ifindex = lnk->parent_ifindex; - local4 = lnk->local; - remote4 = lnk->remote; + local.addr4 = lnk->local; + remote.addr4 = lnk->remote; ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; @@ -267,8 +293,8 @@ clear: } parent_ifindex = lnk->parent_ifindex; - local6 = lnk->local; - remote6 = lnk->remote; + local.addr6 = lnk->local; + remote.addr6 = lnk->remote; ttl = lnk->ttl; tos = lnk->tclass; encap_limit = lnk->encap_limit; @@ -288,7 +314,7 @@ clear: g_free (key); } else { if (priv->input_key) { - g_clear_pointer (&priv->input_key, g_free); + nm_clear_g_free (&priv->input_key); _notify (self, PROP_INPUT_KEY); } } @@ -303,7 +329,7 @@ clear: g_free (key); } else { if (priv->output_key) { - g_clear_pointer (&priv->output_key, g_free); + nm_clear_g_free (&priv->output_key); _notify (self, PROP_OUTPUT_KEY); } } @@ -313,35 +339,10 @@ clear: nm_device_parent_set_ifindex (device, parent_ifindex); - 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 = nm_utils_inet4_ntop_dup (local4); - _notify (self, PROP_LOCAL); - } - - if (!address_equal_pn (AF_INET, priv->remote, &remote4)) { - g_clear_pointer (&priv->remote, g_free); - if (remote4) - priv->remote = nm_utils_inet4_ntop_dup (remote4); - _notify (self, PROP_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 = nm_utils_inet6_ntop_dup (&local6); - _notify (self, PROP_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 = nm_utils_inet6_ntop_dup (&remote6); - _notify (self, PROP_REMOTE); - } - } + if (address_set (priv->addr_family, &priv->local, &local)) + _notify (self, PROP_LOCAL); + if (address_set (priv->addr_family, &priv->remote, &remote)) + _notify (self, PROP_REMOTE); out: @@ -657,11 +658,44 @@ create_and_realize (NMDevice *device, gint64 val; NMIPTunnelMode mode; int r; + gs_free char *hwaddr = NULL; + guint8 mac_address[ETH_ALEN]; + gboolean mac_address_valid = FALSE; s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); - g_assert (s_ip_tunnel); + nm_assert (NM_IS_SETTING_IP_TUNNEL (s_ip_tunnel)); mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); + + if ( nm_device_hw_addr_get_cloned (device, + connection, + FALSE, + &hwaddr, + NULL, + NULL) + && hwaddr) { + /* FIXME: we set the MAC address when creating the interface, while the + * NMDevice is still unrealized. As we afterwards realize the device, it + * forgets the parameters for the cloned MAC address, and in stage 1 + * it might create a different MAC address. That should be fixed by + * better handling device realization. */ + if (!nm_utils_hwaddr_aton (hwaddr, mac_address, ETH_ALEN)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Invalid hardware address '%s'", + hwaddr); + g_return_val_if_reached (FALSE); + } + + if (NM_IN_SET (mode, NM_IP_TUNNEL_MODE_GRE)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Invalid hardware address '%s' for tunnel type", + hwaddr); + return FALSE; + } + + mac_address_valid = TRUE; + } + switch (mode) { case NM_IP_TUNNEL_MODE_GRETAP: lnk_gre.is_tap = TRUE; @@ -702,7 +736,12 @@ create_and_realize (NMDevice *device, lnk_gre.output_flags = NM_GRE_KEY; } - r = nm_platform_link_gre_add (nm_device_get_platform (device), iface, &lnk_gre, out_plink); + r = nm_platform_link_gre_add (nm_device_get_platform (device), + iface, + mac_address_valid ? mac_address : NULL, + mac_address_valid ? ETH_ALEN : 0, + &lnk_gre, + out_plink); if (r < 0) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create GRE interface '%s' for '%s': %s", @@ -896,7 +935,7 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE ((NMDeviceIPTunnel *) object); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); switch (prop_id) { case PROP_MODE: @@ -942,7 +981,7 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE ((NMDeviceIPTunnel *) object); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); switch (prop_id) { case PROP_MODE: @@ -963,7 +1002,7 @@ nm_device_ip_tunnel_init (NMDeviceIPTunnel *self) static void constructed (GObject *object) { - NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE ((NMDeviceIPTunnel *) object); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); if (NM_IN_SET (priv->mode, NM_IP_TUNNEL_MODE_IPIP6, @@ -983,10 +1022,10 @@ dispose (GObject *object) NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (object); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); - g_clear_pointer (&priv->local, g_free); - g_clear_pointer (&priv->remote, g_free); - g_clear_pointer (&priv->input_key, g_free); - g_clear_pointer (&priv->output_key, g_free); + nm_clear_g_free (&priv->local); + nm_clear_g_free (&priv->remote); + nm_clear_g_free (&priv->input_key); + nm_clear_g_free (&priv->output_key); G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->dispose (object); } |