From b02aeaf2f3e0127d9ffa8fb1d960c5cf4014eb1f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 19 Aug 2022 13:26:14 +0200 Subject: [PATCH] glib-aux: fix various nm_ip_addr_*() functions for unaligned addresses Most of our nm_ip_addr_*() functions take an opaque pointer, that can be either in_addr_t, struct in6_addr or NMIPAddr. They also tend to support that their argument pointer is not aligned. The reason is not very strong, except that usually it's simple to support and it allows the caller to use those low-level functions for pointers of unknown alignment (e.g. from a package on the network). Fix a few cases for that. --- src/libnm-glib-aux/nm-inet-utils.c | 38 +++++++++++++++---------- src/libnm-glib-aux/nm-inet-utils.h | 45 +++++++++++++++--------------- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/libnm-glib-aux/nm-inet-utils.c b/src/libnm-glib-aux/nm-inet-utils.c index f8b287d086..3e5fe4496a 100644 --- a/src/libnm-glib-aux/nm-inet-utils.c +++ b/src/libnm-glib-aux/nm-inet-utils.c @@ -138,20 +138,22 @@ nm_ip4_addr_get_default_prefix(in_addr_t ip) gboolean nm_ip_addr_is_site_local(int addr_family, const void *address) { - in_addr_t addr4; + NMIPAddr a; + + nm_ip_addr_set(addr_family, &a, address); switch (addr_family) { case AF_INET: /* RFC1918 private addresses * 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */ - addr4 = ntohl(*((const in_addr_t *) address)); - return (addr4 & 0xff000000) == 0x0a000000 || (addr4 & 0xfff00000) == 0xac100000 - || (addr4 & 0xffff0000) == 0xc0a80000; + return (a.addr4 & htonl(0xff000000)) == htonl(0x0a000000) + || (a.addr4 & htonl(0xfff00000)) == htonl(0xac100000) + || (a.addr4 & htonl(0xffff0000)) == htonl(0xc0a80000); case AF_INET6: /* IN6_IS_ADDR_SITELOCAL() is for deprecated fec0::/10 addresses (see rfc3879, 4.). - * Note that for unique local IPv6 addresses (ULA, fc00::/7) this returns false, - * which may or may not be a bug. */ - return IN6_IS_ADDR_SITELOCAL(address); + * Note that for unique local IPv6 addresses (ULA, fc00::/7) this returns false. + * This may or may not be a bug of this function. */ + return IN6_IS_ADDR_SITELOCAL(&a.addr6); default: g_return_val_if_reached(FALSE); } @@ -169,25 +171,33 @@ nm_ip6_addr_is_ula(const struct in6_addr *address) gconstpointer nm_ip_addr_clear_host_address(int family, gpointer dst, gconstpointer src, guint32 plen) { + NMIPAddr a; + NMIPAddr a2; + g_return_val_if_fail(dst, NULL); + if (!src) { + /* allow "self-assignment", by specifying %NULL as source. */ + src = dst; + } + + nm_ip_addr_set(family, &a, src); + switch (family) { case AF_INET: g_return_val_if_fail(plen <= 32, NULL); - if (!src) { - /* allow "self-assignment", by specifying %NULL as source. */ - src = dst; - } - - *((guint32 *) dst) = nm_ip4_addr_clear_host_address(*((guint32 *) src), plen); + a2.addr4 = nm_ip4_addr_clear_host_address(a.addr4, plen); break; case AF_INET6: - nm_ip6_addr_clear_host_address(dst, src, plen); + nm_ip6_addr_clear_host_address(&a2.addr6, &a.addr6, plen); break; default: g_return_val_if_reached(NULL); } + + nm_ip_addr_set(family, dst, &a2); + return dst; } diff --git a/src/libnm-glib-aux/nm-inet-utils.h b/src/libnm-glib-aux/nm-inet-utils.h index 6530f4222f..d9246d459b 100644 --- a/src/libnm-glib-aux/nm-inet-utils.h +++ b/src/libnm-glib-aux/nm-inet-utils.h @@ -50,23 +50,6 @@ nm_ip_addr_equal(int addr_family, gconstpointer a, gconstpointer b) return nm_ip_addr_cmp(addr_family, a, b) == 0; } -static inline gboolean -nm_ip_addr_is_null(int addr_family, gconstpointer addr) -{ - nm_assert(addr); - - if (NM_IS_IPv4(addr_family)) { - in_addr_t t; - - /* also for in_addr_t type (AF_INET), we accept that the pointer might - * be unaligned. */ - memcpy(&t, addr, sizeof(t)); - return t == 0; - } - - return IN6_IS_ADDR_UNSPECIFIED((const struct in6_addr *) addr); -} - static inline void nm_ip_addr_set(int addr_family, gpointer dst, gconstpointer src) { @@ -84,6 +67,19 @@ nm_ip_addr_set(int addr_family, gpointer dst, gconstpointer src) * uninitalized bytes. Avoid that by using nm_ip_addr_init() instead. */ } +static inline gboolean +nm_ip_addr_is_null(int addr_family, gconstpointer addr) +{ + NMIPAddr a; + + nm_ip_addr_set(addr_family, &a, addr); + + if (NM_IS_IPv4(addr_family)) + return a.addr4 == 0; + + return IN6_IS_ADDR_UNSPECIFIED(&a.addr6); +} + static inline NMIPAddr nm_ip_addr_init(int addr_family, gconstpointer src) { @@ -201,15 +197,18 @@ nm_ip6_addr_same_prefix(const struct in6_addr *addr_a, const struct in6_addr *ad static inline int nm_ip_addr_same_prefix_cmp(int addr_family, gconstpointer addr_a, gconstpointer addr_b, guint8 plen) { + NMIPAddr a; + NMIPAddr b; + NM_CMP_SELF(addr_a, addr_b); - if (NM_IS_IPv4(addr_family)) { - return nm_ip4_addr_same_prefix_cmp(*((const in_addr_t *) addr_a), - *((const in_addr_t *) addr_b), - plen); - } + nm_ip_addr_set(addr_family, &a, addr_a); + nm_ip_addr_set(addr_family, &b, addr_b); - return nm_ip6_addr_same_prefix_cmp(addr_a, addr_b, plen); + if (NM_IS_IPv4(addr_family)) + return nm_ip4_addr_same_prefix_cmp(a.addr4, b.addr4, plen); + + return nm_ip6_addr_same_prefix_cmp(&a.addr6, &b.addr6, plen); } static inline gboolean