From 0c40bce3140666658d51de7217e3d9eade2aa4d7 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sat, 30 Apr 2016 16:43:10 +0200 Subject: [PATCH] core-utils: add conversions of ipv6 tokens From/to strings and interface identifiers. --- libnm-core/nm-core-internal.h | 4 ++ libnm-core/nm-utils.c | 34 +++++++++++++++++ src/nm-core-utils.c | 72 +++++++++++++++++++++++++++++++++++ src/nm-core-utils.h | 18 ++++++--- 4 files changed, 122 insertions(+), 6 deletions(-) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 2041a1d3a1..a09ee26c48 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -296,4 +296,8 @@ typedef enum { NMBondOptionType _nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name); +/***********************************************************/ + +gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr); + #endif diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 81676e9f1f..7a87dc18c4 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -3565,6 +3565,40 @@ nm_utils_ipaddr_valid (int family, const char *ip) return inet_pton (family, ip, buf) == 1; } +/** + * nm_utils_iinet6_is_token: + * @in6addr: the AF_INET6 address structure + * + * Checks if only the bottom 64bits of the address are set. + * + * Return value: %TRUE or %FALSE + */ +gboolean +_nm_utils_inet6_is_token (const struct in6_addr *in6addr) +{ + if ( in6addr->s6_addr[0] + || in6addr->s6_addr[1] + || in6addr->s6_addr[2] + || in6addr->s6_addr[3] + || in6addr->s6_addr[4] + || in6addr->s6_addr[5] + || in6addr->s6_addr[6] + || in6addr->s6_addr[7]) + return FALSE; + + if ( in6addr->s6_addr[8] + || in6addr->s6_addr[9] + || in6addr->s6_addr[10] + || in6addr->s6_addr[11] + || in6addr->s6_addr[12] + || in6addr->s6_addr[13] + || in6addr->s6_addr[14] + || in6addr->s6_addr[15]) + return TRUE; + + return FALSE; +} + /** * nm_utils_check_virtual_device_compatibility: * @virtual_type: a virtual connection type diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 5d6c74c57a..276dc1c406 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -2866,6 +2866,19 @@ nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, } return FALSE; } + +/*****************************************************************************/ + +/** + * nm_utils_ipv6_addr_set_interface_identifier: + * @addr: output token encoded as %in6_addr + * @iid: %NMUtilsIPv6IfaceId interface identifier + * + * Converts the %NMUtilsIPv6IfaceId to an %in6_addr (suitable for use + * with Linux platform). This only copies the lower 8 bytes, ignoring + * the /64 network prefix which is expected to be all-zero for a valid + * token. + */ void nm_utils_ipv6_addr_set_interface_identifier (struct in6_addr *addr, const NMUtilsIPv6IfaceId iid) @@ -2873,6 +2886,14 @@ nm_utils_ipv6_addr_set_interface_identifier (struct in6_addr *addr, memcpy (addr->s6_addr + 8, &iid.id_u8, 8); } +/** + * nm_utils_ipv6_interface_identifier_get_from_addr: + * @iid: output %NMUtilsIPv6IfaceId interface identifier set from the token + * @addr: token encoded as %in6_addr + * + * Converts the %in6_addr encoded token (as used by Linux platform) to + * the interface identifier. + */ void nm_utils_ipv6_interface_identifier_get_from_addr (NMUtilsIPv6IfaceId *iid, const struct in6_addr *addr) @@ -2880,6 +2901,57 @@ nm_utils_ipv6_interface_identifier_get_from_addr (NMUtilsIPv6IfaceId *iid, memcpy (iid, addr->s6_addr + 8, 8); } +/** + * nm_utils_ipv6_interface_identifier_get_from_token: + * @iid: output %NMUtilsIPv6IfaceId interface identifier set from the token + * @token: token encoded as string + * + * Converts the %in6_addr encoded token (as used in ip6 settings) to + * the interface identifier. + * + * Returns: %TRUE if the @token is a valid token, %FALSE otherwise + */ +gboolean +nm_utils_ipv6_interface_identifier_get_from_token (NMUtilsIPv6IfaceId *iid, + const char *token) +{ + struct in6_addr i6_token; + + g_return_val_if_fail (token, FALSE); + + if (!inet_pton (AF_INET6, token, &i6_token)) + return FALSE; + + if (!_nm_utils_inet6_is_token (&i6_token)) + return FALSE; + + nm_utils_ipv6_interface_identifier_get_from_addr (iid, &i6_token); + return TRUE; +} + +/** + * nm_utils_inet6_interface_identifier_to_token: + * @iid: %NMUtilsIPv6IfaceId interface identifier + * @buf: the destination buffer or %NULL + * + * Converts the interface identifier to a string token. + * If the destination buffer it set, set it is used to store the + * resulting token, otherwise an internal static buffer is used. + * The buffer needs to be %NM_UTILS_INET_ADDRSTRLEN characters long. + * + * Returns: a statically allocated array. Do not g_free(). + */ +const char * +nm_utils_inet6_interface_identifier_to_token (NMUtilsIPv6IfaceId iid, char *buf) +{ + struct in6_addr i6_token = { .s6_addr = { 0, } }; + + nm_utils_ipv6_addr_set_interface_identifier (&i6_token, iid); + return nm_utils_inet6_ntop (&i6_token, buf); +} + +/*****************************************************************************/ + static gboolean _set_stable_privacy (struct in6_addr *addr, const char *ifname, diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 8b54113cb3..a203a8ef71 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -335,24 +335,30 @@ struct _NMUtilsIPv6IfaceId { #define NM_UTILS_IPV6_IFACE_ID_INIT { { .id = 0 } } +void nm_utils_ipv6_addr_set_interface_identifier (struct in6_addr *addr, + const NMUtilsIPv6IfaceId iid); + +void nm_utils_ipv6_interface_identifier_get_from_addr (NMUtilsIPv6IfaceId *iid, + const struct in6_addr *addr); + +gboolean nm_utils_ipv6_interface_identifier_get_from_token (NMUtilsIPv6IfaceId *iid, + const char *token); + +const char *nm_utils_inet6_interface_identifier_to_token (NMUtilsIPv6IfaceId iid, + char *buf); + gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, const guint8 *hwaddr, guint len, guint dev_id, NMUtilsIPv6IfaceId *out_iid); -void nm_utils_ipv6_addr_set_interface_identifier (struct in6_addr *addr, - const NMUtilsIPv6IfaceId iid); - gboolean nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr, const char *ifname, const char *uuid, guint dad_counter, GError **error); -void nm_utils_ipv6_interface_identifier_get_from_addr (NMUtilsIPv6IfaceId *iid, - const struct in6_addr *addr); - void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len); void nm_utils_setpgid (gpointer unused);