mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-06 20:10:17 +01:00
platform: merge: branch 'lr/ipv6-tokens' (rh #1104689)
This adds support for tokenised identifier use as specified in
draft-chown-6man-tokenised-ipv6-identifiers-02 Internet Draft,
enabled if there's a support for tokenised identifiers in libnl.
https://bugzilla.redhat.com/show_bug.cgi?id=1104689
https://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02
(cherry picked from commit 5f50c0480a)
This commit is contained in:
commit
8d91bf5769
9 changed files with 150 additions and 10 deletions
|
|
@ -428,6 +428,13 @@ else
|
|||
AC_DEFINE(HAVE_KERNEL_INET6_ADDR_GEN_MODE, 0, [Define if the kernel has IN6_ADDR_GEN_MODE_*])
|
||||
fi
|
||||
|
||||
# IPv6 tokenized identifiers support in libnl
|
||||
AC_CHECK_LIB([nl-route-3], [rtnl_link_inet6_get_token],
|
||||
ac_have_ipv6_token="1",
|
||||
ac_have_ipv6_token="0")
|
||||
AC_DEFINE_UNQUOTED(HAVE_LIBNL_INET6_TOKEN,
|
||||
$ac_have_ipv6_token, [Define if libnl has rtnl_link_inet6_get_token()])
|
||||
|
||||
# uuid library
|
||||
PKG_CHECK_MODULES(UUID, uuid)
|
||||
AC_SUBST(UUID_CFLAGS)
|
||||
|
|
|
|||
|
|
@ -192,12 +192,12 @@ gboolean nm_utils_is_specific_hostname (const char *name);
|
|||
* and should not normally be treated as a %guint64, but this is done for
|
||||
* convenience of validity checking and initialization.
|
||||
*/
|
||||
typedef struct {
|
||||
struct _NMUtilsIPv6IfaceId {
|
||||
union {
|
||||
guint64 id;
|
||||
guint8 id_u8[8];
|
||||
};
|
||||
} NMUtilsIPv6IfaceId;
|
||||
};
|
||||
|
||||
#define NM_UTILS_IPV6_IFACE_ID_INIT { .id = 0 }
|
||||
|
||||
|
|
|
|||
|
|
@ -1239,6 +1239,7 @@ device_link_changed (NMDevice *self, NMPlatformLink *info)
|
|||
{
|
||||
NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMUtilsIPv6IfaceId token_iid;
|
||||
gboolean ip_ifname_changed = FALSE;
|
||||
|
||||
if (info->udi && g_strcmp0 (info->udi, priv->udi)) {
|
||||
|
|
@ -1285,6 +1286,12 @@ device_link_changed (NMDevice *self, NMPlatformLink *info)
|
|||
nm_device_enslave_slave (priv->master, self, NULL);
|
||||
}
|
||||
|
||||
if (priv->rdisc && nm_platform_link_get_ipv6_token (priv->ifindex, &token_iid)) {
|
||||
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
|
||||
if (nm_rdisc_set_iid (priv->rdisc, token_iid))
|
||||
nm_rdisc_start (priv->rdisc);
|
||||
}
|
||||
|
||||
if (klass->link_changed)
|
||||
klass->link_changed (self, info);
|
||||
|
||||
|
|
@ -4282,11 +4289,12 @@ addrconf6_start_with_link_ready (NMDevice *self)
|
|||
|
||||
g_assert (priv->rdisc);
|
||||
|
||||
if (!nm_device_get_ip_iface_identifier (self, &iid)) {
|
||||
if (nm_platform_link_get_ipv6_token (priv->ifindex, &iid)) {
|
||||
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
|
||||
} else if (!nm_device_get_ip_iface_identifier (self, &iid)) {
|
||||
_LOGW (LOGD_IP6, "failed to get interface identifier; IPv6 cannot continue");
|
||||
return FALSE;
|
||||
}
|
||||
nm_rdisc_set_iid (priv->rdisc, iid);
|
||||
|
||||
/* Apply any manual configuration before starting RA */
|
||||
if (!ip6_config_merge_and_apply (self, TRUE, NULL))
|
||||
|
|
@ -4305,6 +4313,8 @@ addrconf6_start_with_link_ready (NMDevice *self)
|
|||
NM_RDISC_RA_TIMEOUT,
|
||||
G_CALLBACK (rdisc_ra_timeout),
|
||||
self);
|
||||
|
||||
nm_rdisc_set_iid (priv->rdisc, iid);
|
||||
nm_rdisc_start (priv->rdisc);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,4 +113,7 @@ typedef struct _NMSecretAgent NMSecretAgent;
|
|||
typedef struct _NMSettings NMSettings;
|
||||
typedef struct _NMSettingsConnection NMSettingsConnection;
|
||||
|
||||
/* utils */
|
||||
typedef struct _NMUtilsIPv6IfaceId NMUtilsIPv6IfaceId;
|
||||
|
||||
#endif /* NM_TYPES_H */
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@
|
|||
#include <netlink/route/route.h>
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
|
||||
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE || HAVE_LIBNL_INET6_TOKEN
|
||||
#include <netlink/route/link/inet6.h>
|
||||
#if HAVE_KERNEL_INET6_ADDR_GEN_MODE
|
||||
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE && HAVE_KERNEL_INET6_ADDR_GEN_MODE
|
||||
#include <linux/if_link.h>
|
||||
#else
|
||||
#define IN6_ADDR_GEN_MODE_EUI64 0
|
||||
|
|
@ -1905,6 +1905,37 @@ nm_nl_object_diff (ObjectType type, struct nl_object *_a, struct nl_object *_b)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#if HAVE_LIBNL_INET6_TOKEN
|
||||
/* libnl ignores PROTINFO changes in object without AF assigned */
|
||||
if (type == OBJECT_TYPE_LINK) {
|
||||
struct rtnl_addr *a = (struct rtnl_addr *) _a;
|
||||
struct rtnl_addr *b = (struct rtnl_addr *) _b;
|
||||
auto_nl_addr struct nl_addr *token_a = NULL;
|
||||
auto_nl_addr struct nl_addr *token_b = NULL;
|
||||
|
||||
if (rtnl_link_inet6_get_token ((struct rtnl_link *) a, &token_a) != 0)
|
||||
token_a = NULL;
|
||||
if (rtnl_link_inet6_get_token ((struct rtnl_link *) b, &token_b) != 0)
|
||||
token_b = NULL;
|
||||
|
||||
if (token_a && token_b) {
|
||||
if (nl_addr_get_family (token_a) == AF_INET6 &&
|
||||
nl_addr_get_family (token_b) == AF_INET6 &&
|
||||
nl_addr_get_len (token_a) == sizeof (struct in6_addr) &&
|
||||
nl_addr_get_len (token_b) == sizeof (struct in6_addr) &&
|
||||
memcmp (nl_addr_get_binary_addr (token_a),
|
||||
nl_addr_get_binary_addr (token_b),
|
||||
sizeof (struct in6_addr))) {
|
||||
/* Token changed */
|
||||
return TRUE;
|
||||
}
|
||||
} else if (token_a != token_b) {
|
||||
/* Token added or removed (?). */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS) {
|
||||
struct rtnl_addr *a = (struct rtnl_addr *) _a;
|
||||
struct rtnl_addr *b = (struct rtnl_addr *) _b;
|
||||
|
|
@ -2488,6 +2519,38 @@ link_set_noarp (NMPlatform *platform, int ifindex)
|
|||
return link_change_flags (platform, ifindex, IFF_NOARP, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_get_ipv6_token (NMPlatform *platform, int ifindex, NMUtilsIPv6IfaceId *iid)
|
||||
{
|
||||
#if HAVE_LIBNL_INET6_TOKEN
|
||||
auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex);
|
||||
struct nl_addr *nladdr;
|
||||
struct in6_addr *addr;
|
||||
|
||||
if (rtnllink &&
|
||||
(rtnl_link_inet6_get_token (rtnllink, &nladdr)) == 0) {
|
||||
if (nl_addr_get_family (nladdr) != AF_INET6 ||
|
||||
nl_addr_get_len (nladdr) != sizeof (struct in6_addr)) {
|
||||
nl_addr_put (nladdr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
addr = nl_addr_get_binary_addr (nladdr);
|
||||
iid->id_u8[7] = addr->s6_addr[15];
|
||||
iid->id_u8[6] = addr->s6_addr[14];
|
||||
iid->id_u8[5] = addr->s6_addr[13];
|
||||
iid->id_u8[4] = addr->s6_addr[12];
|
||||
iid->id_u8[3] = addr->s6_addr[11];
|
||||
iid->id_u8[2] = addr->s6_addr[10];
|
||||
iid->id_u8[1] = addr->s6_addr[9];
|
||||
iid->id_u8[0] = addr->s6_addr[8];
|
||||
nl_addr_put (nladdr);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_get_user_ipv6ll_enabled (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
|
|
@ -4572,6 +4635,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
|
|||
platform_class->link_is_connected = link_is_connected;
|
||||
platform_class->link_uses_arp = link_uses_arp;
|
||||
|
||||
platform_class->link_get_ipv6_token = link_get_ipv6_token;
|
||||
|
||||
platform_class->link_get_user_ipv6ll_enabled = link_get_user_ipv6ll_enabled;
|
||||
platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled;
|
||||
|
||||
|
|
|
|||
|
|
@ -779,6 +779,31 @@ nm_platform_link_uses_arp (int ifindex)
|
|||
return klass->link_uses_arp (platform, ifindex);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_link_get_ipv6_token:
|
||||
* @ifindex: Interface index
|
||||
* @iid: Tokenized interface identifier
|
||||
*
|
||||
* Returns IPv6 tokenized interface identifier. If the platform or OS doesn't
|
||||
* support IPv6 tokenized interface identifiers, or the token is not set
|
||||
* this call will fail and return %FALSE.
|
||||
*
|
||||
* Returns: %TRUE a tokenized identifier was available
|
||||
*/
|
||||
gboolean
|
||||
nm_platform_link_get_ipv6_token (int ifindex, NMUtilsIPv6IfaceId *iid)
|
||||
{
|
||||
reset_error ();
|
||||
|
||||
g_return_val_if_fail (ifindex >= 0, FALSE);
|
||||
g_return_val_if_fail (iid, FALSE);
|
||||
|
||||
if (klass->link_get_ipv6_token)
|
||||
return klass->link_get_ipv6_token (platform, ifindex, iid);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nm_platform_link_get_user_ip6vll_enabled:
|
||||
* @ifindex: Interface index
|
||||
|
|
|
|||
|
|
@ -379,6 +379,8 @@ typedef struct {
|
|||
gboolean (*link_is_connected) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_uses_arp) (NMPlatform *, int ifindex);
|
||||
|
||||
gboolean (*link_get_ipv6_token) (NMPlatform *, int ifindex, NMUtilsIPv6IfaceId *iid);
|
||||
|
||||
gboolean (*link_get_user_ipv6ll_enabled) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled);
|
||||
|
||||
|
|
@ -528,6 +530,8 @@ gboolean nm_platform_link_is_up (int ifindex);
|
|||
gboolean nm_platform_link_is_connected (int ifindex);
|
||||
gboolean nm_platform_link_uses_arp (int ifindex);
|
||||
|
||||
gboolean nm_platform_link_get_ipv6_token (int ifindex, NMUtilsIPv6IfaceId *iid);
|
||||
|
||||
gboolean nm_platform_link_get_user_ipv6ll_enabled (int ifindex);
|
||||
gboolean nm_platform_link_set_user_ipv6ll_enabled (int ifindex, gboolean enabled);
|
||||
|
||||
|
|
|
|||
|
|
@ -241,12 +241,38 @@ clear_rs_timeout (NMRDisc *rdisc)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
/**
|
||||
* nm_rdisc_set_iid:
|
||||
* @rdisc: the #NMRDisc
|
||||
* @iid: the new interface ID
|
||||
*
|
||||
* Sets the "Modified EUI-64" interface ID to be used when generating
|
||||
* IPv6 addresses using received prefixes. Identifiers are either generated
|
||||
* from the hardware addresses or manually set by the operator with
|
||||
* "ip token" command.
|
||||
*
|
||||
* Upon token change (or initial setting) all addresses generated using
|
||||
* the old identifier are removed. The caller should ensure the addresses
|
||||
* will be reset by soliciting router advertisements.
|
||||
*
|
||||
* Returns: %TRUE if the token was changed, %FALSE otherwise.
|
||||
**/
|
||||
gboolean
|
||||
nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid)
|
||||
{
|
||||
g_return_if_fail (NM_IS_RDISC (rdisc));
|
||||
g_return_val_if_fail (NM_IS_RDISC (rdisc), FALSE);
|
||||
|
||||
rdisc->iid = iid;
|
||||
if (rdisc->iid.id != iid.id) {
|
||||
rdisc->iid = iid;
|
||||
if (rdisc->addresses->len) {
|
||||
debug ("(%s) IPv6 interface identifier changed, flushing addresses", rdisc->ifname);
|
||||
g_array_remove_range (rdisc->addresses, 0, rdisc->addresses->len);
|
||||
g_signal_emit_by_name (rdisc, NM_RDISC_CONFIG_CHANGED, NM_RDISC_CONFIG_ADDRESSES);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ typedef struct {
|
|||
|
||||
GType nm_rdisc_get_type (void);
|
||||
|
||||
void nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid);
|
||||
gboolean nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid);
|
||||
void nm_rdisc_start (NMRDisc *rdisc);
|
||||
|
||||
#endif /* __NETWORKMANAGER_RDISC_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue