summaryrefslogtreecommitdiff
path: root/src/libnm-glib-aux
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-glib-aux')
-rw-r--r--src/libnm-glib-aux/meson.build1
-rw-r--r--src/libnm-glib-aux/nm-default-glib.h1
-rw-r--r--src/libnm-glib-aux/nm-inet-utils.c529
-rw-r--r--src/libnm-glib-aux/nm-inet-utils.h359
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.c525
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.h364
-rw-r--r--src/libnm-glib-aux/nm-test-utils.h10
-rw-r--r--src/libnm-glib-aux/tests/test-shared-general.c53
8 files changed, 934 insertions, 908 deletions
diff --git a/src/libnm-glib-aux/meson.build b/src/libnm-glib-aux/meson.build
index 4f13fd0b17..d5e88e6b7a 100644
--- a/src/libnm-glib-aux/meson.build
+++ b/src/libnm-glib-aux/meson.build
@@ -8,6 +8,7 @@ libnm_glib_aux = static_library(
'nm-enum-utils.c',
'nm-errno.c',
'nm-hash-utils.c',
+ 'nm-inet-utils.c',
'nm-io-utils.c',
'nm-json-aux.c',
'nm-keyfile-aux.c',
diff --git a/src/libnm-glib-aux/nm-default-glib.h b/src/libnm-glib-aux/nm-default-glib.h
index f39e16cc5b..18460de8ff 100644
--- a/src/libnm-glib-aux/nm-default-glib.h
+++ b/src/libnm-glib-aux/nm-default-glib.h
@@ -67,6 +67,7 @@
#include "libnm-glib-aux/nm-shared-utils.h"
#include "libnm-glib-aux/nm-errno.h"
#include "libnm-glib-aux/nm-hash-utils.h"
+#include "libnm-glib-aux/nm-inet-utils.h"
/*****************************************************************************/
diff --git a/src/libnm-glib-aux/nm-inet-utils.c b/src/libnm-glib-aux/nm-inet-utils.c
new file mode 100644
index 0000000000..2ede87baf9
--- /dev/null
+++ b/src/libnm-glib-aux/nm-inet-utils.c
@@ -0,0 +1,529 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
+
+#include "nm-inet-utils.h"
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*****************************************************************************/
+
+const NMIPAddr nm_ip_addr_zero = {};
+
+/* We use _nm_alignas(NMIPAddr) to ensure that fields for in_addr_t and
+ * struct in6_addr have all the same alignment. Ensure that this is suitable. */
+G_STATIC_ASSERT(_nm_alignof(in_addr_t) <= _nm_alignof(NMIPAddr));
+G_STATIC_ASSERT(_nm_alignof(struct in_addr) <= _nm_alignof(NMIPAddr));
+G_STATIC_ASSERT(_nm_alignof(struct in6_addr) <= _nm_alignof(NMIPAddr));
+G_STATIC_ASSERT(_nm_alignof(NMEtherAddr) <= _nm_alignof(NMIPAddr));
+
+int
+nm_ip_addr_cmp_for_sort(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ /* This is a compare function that can be used for sorting IP addresses.
+ * Essentially, it calls memcmp(). @user_data must be GINT_TO_POINTER(addr_family).
+ * @a and @b must be either pointers to in_addr_t, struct in6_addr or NMIPAddr. */
+ return nm_ip_addr_cmp(GPOINTER_TO_INT(user_data), a, b);
+}
+
+/* this initializes a struct in_addr/in6_addr and allows for untrusted
+ * arguments (like unsuitable @addr_family or @src_len). It's almost safe
+ * in the sense that it verifies input arguments strictly. Also, it
+ * uses memcpy() to access @src, so alignment is not an issue.
+ *
+ * Only potential pitfalls:
+ *
+ * - it allows for @addr_family to be AF_UNSPEC. If that is the case (and the
+ * caller allows for that), the caller MUST provide @out_addr_family.
+ * - when setting @dst to an IPv4 address, the trailing bytes are not touched.
+ * Meaning, if @dst is an NMIPAddr union, only the first bytes will be set.
+ * If that matter to you, clear @dst before. */
+gboolean
+nm_ip_addr_set_from_untrusted(int addr_family,
+ gpointer dst,
+ gconstpointer src,
+ gsize src_len,
+ int *out_addr_family)
+{
+ nm_assert(dst);
+
+ switch (addr_family) {
+ case AF_UNSPEC:
+ if (!out_addr_family) {
+ /* when the callers allow undefined @addr_family, they must provide
+ * an @out_addr_family argument. */
+ nm_assert_not_reached();
+ return FALSE;
+ }
+ switch (src_len) {
+ case sizeof(struct in_addr):
+ addr_family = AF_INET;
+ break;
+ case sizeof(struct in6_addr):
+ addr_family = AF_INET6;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case AF_INET:
+ if (src_len != sizeof(struct in_addr))
+ return FALSE;
+ break;
+ case AF_INET6:
+ if (src_len != sizeof(struct in6_addr))
+ return FALSE;
+ break;
+ default:
+ /* when the callers allow undefined @addr_family, they must provide
+ * an @out_addr_family argument. */
+ nm_assert(out_addr_family);
+ return FALSE;
+ }
+
+ nm_assert(src);
+
+ memcpy(dst, src, src_len);
+ NM_SET_OUT(out_addr_family, addr_family);
+ return TRUE;
+}
+
+gboolean
+nm_ip_addr_set_from_variant(int addr_family, gpointer dst, GVariant *variant, int *out_addr_family)
+{
+ gconstpointer bytes;
+ gsize len;
+
+ g_return_val_if_fail(dst, FALSE);
+ g_return_val_if_fail(variant, FALSE);
+
+ /* This function always expects IP addressea a byte arrays ("ay"). Note that
+ * several NetworkManager API uses "u" (32 bit unsigned intergers) for IPv4 addresses.
+ * So this function won't work in those cases.
+ *
+ * Btw, using "u" for IPv4 address messes badly with the endianness (host
+ * vs network byte order). Don't do that.
+ */
+ g_return_val_if_fail(g_variant_is_of_type(variant, G_VARIANT_TYPE("ay")), FALSE);
+
+ bytes = g_variant_get_fixed_array(variant, &len, sizeof(guint8));
+
+ return nm_ip_addr_set_from_untrusted(addr_family, dst, bytes, len, out_addr_family);
+}
+
+/*****************************************************************************/
+
+guint32
+nm_ip4_addr_get_default_prefix0(in_addr_t ip)
+{
+ /* The function is originally from ipcalc.c of Red Hat's initscripts. */
+ switch (ntohl(ip) >> 24) {
+ case 0 ... 127:
+ return 8; /* Class A */
+ case 128 ... 191:
+ return 16; /* Class B */
+ case 192 ... 223:
+ return 24; /* Class C */
+ }
+ return 0;
+}
+
+guint32
+nm_ip4_addr_get_default_prefix(in_addr_t ip)
+{
+ return nm_ip4_addr_get_default_prefix0(ip) ?: 24;
+}
+
+gboolean
+nm_ip_addr_is_site_local(int addr_family, const void *address)
+{
+ 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 */
+ 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.
+ * 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);
+ }
+}
+
+gboolean
+nm_ip6_addr_is_ula(const struct in6_addr *address)
+{
+ /* Unique local IPv6 address (ULA) fc00::/7 */
+ return (address->s6_addr32[0] & htonl(0xfe000000u)) == htonl(0xfc000000u);
+}
+
+/*****************************************************************************/
+
+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);
+
+ a2.addr4 = nm_ip4_addr_clear_host_address(a.addr4, plen);
+ break;
+ case AF_INET6:
+ 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;
+}
+
+/* nm_ip6_addr_clear_host_address:
+ * @dst: destination output buffer, will contain the network part of the @src address
+ * @src: source ip6 address. If NULL, this does an in-place update of @dst.
+ * Also, @src and @dst are allowed to be the same pointers.
+ * @plen: prefix length of network
+ *
+ * Note: this function is self assignment safe, to update @src inplace, set both
+ * @dst and @src to the same destination or set @src NULL.
+ */
+const struct in6_addr *
+nm_ip6_addr_clear_host_address(struct in6_addr *dst, const struct in6_addr *src, guint32 plen)
+{
+ g_return_val_if_fail(plen <= 128, NULL);
+ g_return_val_if_fail(dst, NULL);
+
+ if (!src)
+ src = dst;
+
+ if (plen < 128) {
+ guint nbytes = plen / 8;
+ guint nbits = plen % 8;
+
+ if (nbytes && dst != src)
+ memcpy(dst, src, nbytes);
+ if (nbits) {
+ dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
+ nbytes++;
+ }
+ if (nbytes <= 15)
+ memset(&dst->s6_addr[nbytes], 0, 16 - nbytes);
+ } else if (src != dst)
+ *dst = *src;
+
+ return dst;
+}
+
+int
+nm_ip6_addr_same_prefix_cmp(const struct in6_addr *addr_a,
+ const struct in6_addr *addr_b,
+ guint32 plen)
+{
+ int nbytes;
+ guint8 va, vb, m;
+
+ if (plen >= 128) {
+ nm_assert(plen == 128);
+ NM_CMP_DIRECT_MEMCMP(addr_a, addr_b, sizeof(struct in6_addr));
+ } else {
+ nbytes = plen / 8;
+ if (nbytes)
+ NM_CMP_DIRECT_MEMCMP(addr_a, addr_b, nbytes);
+
+ plen = plen % 8;
+ if (plen != 0) {
+ m = ~((1 << (8 - plen)) - 1);
+ va = ((((const guint8 *) addr_a))[nbytes]) & m;
+ vb = ((((const guint8 *) addr_b))[nbytes]) & m;
+ NM_CMP_DIRECT(va, vb);
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+_parse_legacy_addr4(const char *text, in_addr_t *out_addr, GError **error)
+{
+ gs_free char *s_free = NULL;
+ struct in_addr a1;
+ guint8 bin[sizeof(a1)];
+ char *s;
+ int i;
+
+ if (inet_aton(text, &a1) != 1) {
+ g_set_error_literal(error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_INVALID_ARGUMENT,
+ "address invalid according to inet_aton()");
+ return FALSE;
+ }
+
+ /* OK, inet_aton() accepted the format. That's good, because we want
+ * to accept IPv4 addresses in octal format, like 255.255.000.000.
+ * That's what "legacy" means here. inet_pton() doesn't accept those.
+ *
+ * But inet_aton() also ignores trailing garbage and formats with fewer than
+ * 4 digits. That is just too crazy and we don't do that. Perform additional checks
+ * and reject some forms that inet_aton() accepted.
+ *
+ * Note that we still should (of course) accept everything that inet_pton()
+ * accepts. However this code never gets called if inet_pton() succeeds
+ * (see below, aside the assertion code). */
+
+ if (NM_STRCHAR_ANY(text, ch, (!(ch >= '0' && ch <= '9') && !NM_IN_SET(ch, '.', 'x')))) {
+ /* We only accepts '.', digits, and 'x' for "0x". */
+ g_set_error_literal(error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_INVALID_ARGUMENT,
+ "contains an invalid character");
+ return FALSE;
+ }
+
+ s = nm_memdup_maybe_a(300, text, strlen(text) + 1, &s_free);
+
+ for (i = 0; i < G_N_ELEMENTS(bin); i++) {
+ char *current_token = s;
+ gint32 v;
+
+ s = strchr(s, '.');
+ if (s) {
+ s[0] = '\0';
+ s++;
+ }
+
+ if ((i == G_N_ELEMENTS(bin) - 1) != (s == NULL)) {
+ /* Exactly for the last digit, we expect to have no more following token.
+ * But this isn't the case. Abort. */
+ g_set_error(error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_INVALID_ARGUMENT,
+ "wrong number of tokens (index %d, token '%s')",
+ i,
+ s);
+ return FALSE;
+ }
+
+ v = _nm_utils_ascii_str_to_int64(current_token, 0, 0, 0xFF, -1);
+ if (v == -1) {
+ int errsv = errno;
+
+ /* we do accept octal and hex (even with leading "0x"). But something
+ * about this token is wrong. */
+ g_set_error(error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_INVALID_ARGUMENT,
+ "invalid token '%s': %s (%d)",
+ current_token,
+ nm_strerror_native(errsv),
+ errsv);
+ return FALSE;
+ }
+
+ bin[i] = v;
+ }
+
+ if (memcmp(bin, &a1, sizeof(bin)) != 0) {
+ /* our parsing did not agree with what inet_aton() gave. Something
+ * is wrong. Abort. */
+ g_set_error(
+ error,
+ NM_UTILS_ERROR,
+ NM_UTILS_ERROR_INVALID_ARGUMENT,
+ "inet_aton() result 0x%08x differs from computed value 0x%02hhx%02hhx%02hhx%02hhx",
+ a1.s_addr,
+ bin[0],
+ bin[1],
+ bin[2],
+ bin[3]);
+ return FALSE;
+ }
+
+ *out_addr = a1.s_addr;
+ return TRUE;
+}
+
+gboolean
+nm_inet_parse_bin_full(int addr_family,
+ gboolean accept_legacy,
+ const char *text,
+ int *out_addr_family,
+ gpointer out_addr)
+{
+ NMIPAddr addrbin;
+
+ g_return_val_if_fail(text, FALSE);
+
+ if (addr_family == AF_UNSPEC) {
+ g_return_val_if_fail(!out_addr || out_addr_family, FALSE);
+ addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
+ } else
+ g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
+
+ if (inet_pton(addr_family, text, &addrbin) != 1) {
+ if (accept_legacy && addr_family == AF_INET
+ && _parse_legacy_addr4(text, &addrbin.addr4, NULL)) {
+ /* The address is in some legacy format which inet_aton() accepts, but not inet_pton().
+ * Most likely octal digits (leading zeros). We accept the address. */
+ } else
+ return FALSE;
+ }
+
+#if NM_MORE_ASSERTS > 10
+ if (addr_family == AF_INET) {
+ NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER
+ gs_free_error GError *error = NULL;
+ in_addr_t a;
+
+ /* The legacy parser should accept everything that inet_pton() accepts too. Meaning,
+ * it should strictly parse *more* formats. And of course, parse it the same way. */
+ if (!_parse_legacy_addr4(text, &a, &error)) {
+ char buf[INET_ADDRSTRLEN];
+
+ g_error("unexpected assertion failure: could parse \"%s\" as %s, but not accepted by "
+ "legacy parser: %s",
+ text,
+ nm_inet4_ntop(addrbin.addr4, buf),
+ error->message);
+ }
+ nm_assert(addrbin.addr4 == a);
+ NM_PRAGMA_WARNING_REENABLE
+ }
+#endif
+
+ NM_SET_OUT(out_addr_family, addr_family);
+ if (out_addr)
+ nm_ip_addr_set(addr_family, out_addr, &addrbin);
+ return TRUE;
+}
+
+gboolean
+nm_inet_parse_str(int addr_family, const char *text, char **out_addr)
+{
+ NMIPAddr addrbin;
+
+ if (!nm_inet_parse_bin(addr_family, text, &addr_family, &addrbin))
+ return FALSE;
+
+ NM_SET_OUT(out_addr, nm_inet_ntop_dup(addr_family, &addrbin));
+ return TRUE;
+}
+
+gboolean
+nm_inet_parse_with_prefix_bin(int addr_family,
+ const char *text,
+ int *out_addr_family,
+ gpointer out_addr,
+ int *out_prefix)
+{
+ gs_free char *addrstr_free = NULL;
+ int prefix = -1;
+ const char *slash;
+ const char *addrstr;
+ NMIPAddr addrbin;
+
+ g_return_val_if_fail(text, FALSE);
+
+ if (addr_family == AF_UNSPEC) {
+ g_return_val_if_fail(!out_addr || out_addr_family, FALSE);
+ addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
+ } else
+ g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
+
+ slash = strchr(text, '/');
+ if (slash)
+ addrstr = nm_strndup_a(300, text, slash - text, &addrstr_free);
+ else
+ addrstr = text;
+
+ if (inet_pton(addr_family, addrstr, &addrbin) != 1)
+ return FALSE;
+
+ if (slash) {
+ /* For IPv4, `ip addr add` supports the prefix-length as a netmask. We don't
+ * do that. */
+ prefix =
+ _nm_utils_ascii_str_to_int64(&slash[1], 10, 0, addr_family == AF_INET ? 32 : 128, -1);
+ if (prefix == -1)
+ return FALSE;
+ }
+
+ NM_SET_OUT(out_addr_family, addr_family);
+ if (out_addr)
+ nm_ip_addr_set(addr_family, out_addr, &addrbin);
+ NM_SET_OUT(out_prefix, prefix);
+ return TRUE;
+}
+
+gboolean
+nm_inet_parse_with_prefix_str(int addr_family, const char *text, char **out_addr, int *out_prefix)
+{
+ NMIPAddr addrbin;
+
+ if (!nm_inet_parse_with_prefix_bin(addr_family, text, &addr_family, &addrbin, out_prefix))
+ return FALSE;
+
+ NM_SET_OUT(out_addr, nm_inet_ntop_dup(addr_family, &addrbin));
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+gboolean
+nm_inet_is_valid(int addr_family, const char *str_addr)
+{
+ nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
+
+ return str_addr && nm_inet_parse_bin(addr_family, str_addr, NULL, NULL);
+}
+
+gboolean
+nm_inet_is_normalized(int addr_family, const char *str_addr)
+{
+ NMIPAddr addr;
+ char sbuf[NM_INET_ADDRSTRLEN];
+
+ nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
+
+ if (!str_addr)
+ return FALSE;
+
+ if (!nm_inet_parse_bin(addr_family, str_addr, &addr_family, &addr))
+ return FALSE;
+
+ nm_inet_ntop(addr_family, &addr, sbuf);
+ return nm_streq(sbuf, str_addr);
+}
+
+/*****************************************************************************/
+
+NM_UTILS_ENUM2STR_DEFINE(nm_icmpv6_router_pref_to_string,
+ NMIcmpv6RouterPref,
+ NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_LOW, "low"),
+ NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_MEDIUM, "medium"),
+ NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_HIGH, "high"),
+ NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_INVALID, "invalid"), );
diff --git a/src/libnm-glib-aux/nm-inet-utils.h b/src/libnm-glib-aux/nm-inet-utils.h
new file mode 100644
index 0000000000..d9246d459b
--- /dev/null
+++ b/src/libnm-glib-aux/nm-inet-utils.h
@@ -0,0 +1,359 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef __NM_INET_UTILS_H__
+#define __NM_INET_UTILS_H__
+
+typedef struct _NMIPAddr {
+ union {
+ guint8 addr_ptr[sizeof(struct in6_addr)];
+ in_addr_t addr4;
+ struct in_addr addr4_struct;
+ struct in6_addr addr6;
+
+ /* NMIPAddr is really a union for IP addresses.
+ * However, as ethernet addresses fit in here nicely, use
+ * it also for an ethernet MAC address. */
+ guint8 ether_addr_octet[6 /*ETH_ALEN*/];
+ NMEtherAddr ether_addr;
+
+ guint8 array[sizeof(struct in6_addr)];
+ };
+} NMIPAddr;
+
+#define NM_IP_ADDR_INIT \
+ { \
+ .array = { 0 } \
+ }
+
+extern const NMIPAddr nm_ip_addr_zero;
+
+/* This doesn't really belong here, but since it's convenient to re-use nm_ip_addr_zero.ether_addr
+ * for NMEtherAddr, it is. */
+#define nm_ether_addr_zero (nm_ip_addr_zero.ether_addr)
+
+static inline int
+nm_ip_addr_cmp(int addr_family, gconstpointer a, gconstpointer b)
+{
+ /* Note that @a and @b are not required to be full NMIPAddr unions.
+ * Depending on @addr_family, they can also be only in_addr_t or
+ * struct in6_addr. */
+ NM_CMP_SELF(a, b);
+ NM_CMP_DIRECT_MEMCMP(a, b, nm_utils_addr_family_to_size(addr_family));
+ return 0;
+}
+
+int nm_ip_addr_cmp_for_sort(gconstpointer a, gconstpointer b, gpointer user_data);
+
+static inline gboolean
+nm_ip_addr_equal(int addr_family, gconstpointer a, gconstpointer b)
+{
+ return nm_ip_addr_cmp(addr_family, a, b) == 0;
+}
+
+static inline void
+nm_ip_addr_set(int addr_family, gpointer dst, gconstpointer src)
+{
+ nm_assert(dst);
+ nm_assert(src);
+
+ /* this MUST use memcpy() to support unaligned src/dst pointers. */
+ memcpy(dst, src, nm_utils_addr_family_to_size(addr_family));
+
+ /* Note that @dst is not necessarily a NMIPAddr, it could also be just
+ * an in_addr_t/struct in6_addr. We thus can only set the bytes that
+ * we know are present based on the address family.
+ *
+ * Using this function to initialize an NMIPAddr union (for IPv4) leaves
+ * 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)
+{
+ NMIPAddr a;
+
+ nm_assert_addr_family(addr_family);
+ nm_assert(src);
+
+ G_STATIC_ASSERT_EXPR(sizeof(NMIPAddr) == sizeof(struct in6_addr));
+
+ /* this MUST use memcpy() to support unaligned src/dst pointers. */
+
+ if (NM_IS_IPv4(addr_family)) {
+ memcpy(&a, src, sizeof(in_addr_t));
+
+ /* ensure all bytes of the union are initialized. If only to make
+ * valgrind happy. */
+ memset(&a.array[sizeof(in_addr_t)], 0, sizeof(a) - sizeof(in_addr_t));
+ } else
+ memcpy(&a, src, sizeof(struct in6_addr));
+
+ return a;
+}
+
+gboolean nm_ip_addr_set_from_untrusted(int addr_family,
+ gpointer dst,
+ gconstpointer src,
+ gsize src_len,
+ int *out_addr_family);
+
+gboolean
+nm_ip_addr_set_from_variant(int addr_family, gpointer dst, GVariant *variant, int *out_addr_family);
+
+static inline gconstpointer
+nm_ip_addr_from_packed_array(int addr_family, gconstpointer ipaddr_arr, gsize idx)
+{
+ return NM_IS_IPv4(addr_family)
+ ? ((gconstpointer) & (((const struct in_addr *) ipaddr_arr)[idx]))
+ : ((gconstpointer) & (((const struct in6_addr *) ipaddr_arr)[idx]));
+}
+
+/*****************************************************************************/
+
+static inline guint32
+nm_ip4_addr_netmask_to_prefix(in_addr_t subnetmask)
+{
+ G_STATIC_ASSERT_EXPR(__SIZEOF_INT__ == 4);
+ G_STATIC_ASSERT_EXPR(sizeof(int) == 4);
+ G_STATIC_ASSERT_EXPR(sizeof(guint) == 4);
+ G_STATIC_ASSERT_EXPR(sizeof(subnetmask) == 4);
+
+ return ((subnetmask != 0u) ? (guint32) (32 - __builtin_ctz(ntohl(subnetmask))) : 0u);
+}
+
+/**
+ * nm_ip4_addr_netmask_from_prefix:
+ * @prefix: a CIDR prefix
+ *
+ * Returns: the netmask represented by the prefix, in network byte order
+ **/
+static inline in_addr_t
+nm_ip4_addr_netmask_from_prefix(guint32 prefix)
+{
+ nm_assert(prefix <= 32);
+ return prefix < 32 ? ~htonl(0xFFFFFFFFu >> prefix) : 0xFFFFFFFFu;
+}
+
+guint32 nm_ip4_addr_get_default_prefix0(in_addr_t ip);
+guint32 nm_ip4_addr_get_default_prefix(in_addr_t ip);
+
+gconstpointer
+nm_ip_addr_clear_host_address(int family, gpointer dst, gconstpointer src, guint32 plen);
+
+/* nm_ip4_addr_clear_host_address:
+ * @addr: source ip6 address
+ * @plen: prefix length of network
+ *
+ * returns: the input address, with the host address set to 0.
+ */
+static inline in_addr_t
+nm_ip4_addr_clear_host_address(in_addr_t addr, guint32 plen)
+{
+ return addr & nm_ip4_addr_netmask_from_prefix(plen);
+}
+
+const struct in6_addr *
+nm_ip6_addr_clear_host_address(struct in6_addr *dst, const struct in6_addr *src, guint32 plen);
+
+/*****************************************************************************/
+
+static inline int
+nm_ip4_addr_same_prefix_cmp(in_addr_t addr_a, in_addr_t addr_b, guint32 plen)
+{
+ NM_CMP_DIRECT(htonl(nm_ip4_addr_clear_host_address(addr_a, plen)),
+ htonl(nm_ip4_addr_clear_host_address(addr_b, plen)));
+ return 0;
+}
+
+int nm_ip6_addr_same_prefix_cmp(const struct in6_addr *addr_a,
+ const struct in6_addr *addr_b,
+ guint32 plen);
+
+static inline gboolean
+nm_ip4_addr_same_prefix(in_addr_t addr_a, in_addr_t addr_b, guint32 plen)
+{
+ return nm_ip4_addr_same_prefix_cmp(addr_a, addr_b, plen) == 0;
+}
+
+static inline gboolean
+nm_ip6_addr_same_prefix(const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
+{
+ return nm_ip6_addr_same_prefix_cmp(addr_a, addr_b, plen) == 0;
+}
+
+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);
+
+ nm_ip_addr_set(addr_family, &a, addr_a);
+ nm_ip_addr_set(addr_family, &b, addr_b);
+
+ 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
+nm_ip_addr_same_prefix(int addr_family, gconstpointer addr_a, gconstpointer addr_b, guint8 plen)
+{
+ return nm_ip_addr_same_prefix_cmp(addr_family, addr_a, addr_b, plen) == 0;
+}
+
+#define NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX(a, b, plen) \
+ NM_CMP_RETURN(nm_ip4_addr_same_prefix_cmp((a), (b), (plen)))
+
+#define NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(a, b, plen) \
+ NM_CMP_RETURN(nm_ip6_addr_same_prefix_cmp((a), (b), (plen)))
+
+/*****************************************************************************/
+
+gboolean nm_ip_addr_is_site_local(int addr_family, const void *address);
+gboolean nm_ip6_addr_is_ula(const struct in6_addr *address);
+
+/*****************************************************************************/
+
+#define NM_IPV4LL_NETWORK ((in_addr_t) htonl(0xA9FE0000lu))
+#define NM_IPV4LL_NETMASK ((in_addr_t) htonl(0xFFFF0000lu))
+
+static inline gboolean
+nm_ip4_addr_is_loopback(in_addr_t addr)
+{
+ /* There is also IN_LOOPBACK() in <linux/in.h>, but there the
+ * argument is in host order not `in_addr_t`. */
+ return (addr & htonl(0xFF000000u)) == htonl(0x7F000000u);
+}
+
+static inline gboolean
+nm_ip4_addr_is_link_local(in_addr_t addr)
+{
+ return (addr & NM_IPV4LL_NETMASK) == NM_IPV4LL_NETWORK;
+}
+
+static inline gboolean
+nm_ip4_addr_is_zeronet(in_addr_t network)
+{
+ /* Same as ipv4_is_zeronet() from kernel's include/linux/in.h. */
+ return (network & htonl(0xFF000000u)) == htonl(0x00000000u);
+}
+
+/*****************************************************************************/
+
+#define NM_INET_ADDRSTRLEN INET6_ADDRSTRLEN
+
+/* Forward declare function so we don't have to drag in <arpa/inet.h>. */
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
+
+static inline const char *
+nm_inet_ntop(int addr_family, gconstpointer addr, char *dst)
+{
+ const char *s;
+
+ nm_assert_addr_family(addr_family);
+ nm_assert(addr);
+ nm_assert(dst);
+
+ s = inet_ntop(addr_family,
+ addr,
+ dst,
+ addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN);
+ nm_assert(s);
+ return s;
+}
+
+static inline const char *
+nm_inet4_ntop(in_addr_t addr, char dst[static INET_ADDRSTRLEN])
+{
+ return nm_inet_ntop(AF_INET, &addr, dst);
+}
+
+static inline const char *
+nm_inet6_ntop(const struct in6_addr *addr, char dst[static INET6_ADDRSTRLEN])
+{
+ return nm_inet_ntop(AF_INET6, addr, dst);
+}
+
+static inline char *
+nm_inet_ntop_dup(int addr_family, gconstpointer addr)
+{
+ char buf[NM_INET_ADDRSTRLEN];
+
+ return g_strdup(nm_inet_ntop(addr_family, addr, buf));
+}
+
+static inline char *
+nm_inet4_ntop_dup(in_addr_t addr)
+{
+ return nm_inet_ntop_dup(AF_INET, &addr);
+}
+
+static inline char *
+nm_inet6_ntop_dup(const struct in6_addr *addr)
+{
+ return nm_inet_ntop_dup(AF_INET6, addr);
+}
+
+/*****************************************************************************/
+
+gboolean nm_inet_parse_bin_full(int addr_family,
+ gboolean accept_legacy,
+ const char *text,
+ int *out_addr_family,
+ gpointer out_addr);
+static inline gboolean
+nm_inet_parse_bin(int addr_family, const char *text, int *out_addr_family, gpointer out_addr)
+{
+ return nm_inet_parse_bin_full(addr_family, FALSE, text, out_addr_family, out_addr);
+}
+
+gboolean nm_inet_parse_str(int addr_family, const char *text, char **out_addr);
+
+gboolean nm_inet_parse_with_prefix_bin(int addr_family,
+ const char *text,
+ int *out_addr_family,
+ gpointer out_addr,
+ int *out_prefix);
+
+gboolean
+nm_inet_parse_with_prefix_str(int addr_family, const char *text, char **out_addr, int *out_prefix);
+
+/*****************************************************************************/
+
+gboolean nm_inet_is_valid(int addr_family, const char *str_addr);
+
+gboolean nm_inet_is_normalized(int addr_family, const char *str_addr);
+
+/*****************************************************************************/
+
+/* this enum is compatible with ICMPV6_ROUTER_PREF_* (from <linux/icmpv6.h>,
+ * the values for netlink attribute RTA_PREF) and "enum ndp_route_preference"
+ * from <ndp.h>. */
+typedef enum _nm_packed {
+ NM_ICMPV6_ROUTER_PREF_MEDIUM = 0x0, /* ICMPV6_ROUTER_PREF_MEDIUM */
+ NM_ICMPV6_ROUTER_PREF_LOW = 0x3, /* ICMPV6_ROUTER_PREF_LOW */
+ NM_ICMPV6_ROUTER_PREF_HIGH = 0x1, /* ICMPV6_ROUTER_PREF_HIGH */
+ NM_ICMPV6_ROUTER_PREF_INVALID = 0x2, /* ICMPV6_ROUTER_PREF_INVALID */
+} NMIcmpv6RouterPref;
+
+const char *nm_icmpv6_router_pref_to_string(NMIcmpv6RouterPref pref, char *buf, gsize len);
+
+/*****************************************************************************/
+
+#endif /* __NM_INET_UTILS_H__ */
diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c
index 624f9a3e97..524f0c31b1 100644
--- a/src/libnm-glib-aux/nm-shared-utils.c
+++ b/src/libnm-glib-aux/nm-shared-utils.c
@@ -35,111 +35,6 @@ const void *const _NM_PTRARRAY_EMPTY[1] = {NULL};
/*****************************************************************************/
-const NMIPAddr nm_ip_addr_zero = {};
-
-/* We use _nm_alignas(NMIPAddr) to ensure that fields for in_addr_t and
- * struct in6_addr have all the same alignment. Ensure that this is suitable. */
-G_STATIC_ASSERT(_nm_alignof(in_addr_t) <= _nm_alignof(NMIPAddr));
-G_STATIC_ASSERT(_nm_alignof(struct in_addr) <= _nm_alignof(NMIPAddr));
-G_STATIC_ASSERT(_nm_alignof(struct in6_addr) <= _nm_alignof(NMIPAddr));
-G_STATIC_ASSERT(_nm_alignof(NMEtherAddr) <= _nm_alignof(NMIPAddr));
-
-int
-nm_ip_addr_cmp_for_sort(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- /* This is a compare function that can be used for sorting IP addresses.
- * Essentially, it calls memcmp(). @user_data must be GINT_TO_POINTER(addr_family).
- * @a and @b must be either pointers to in_addr_t, struct in6_addr or NMIPAddr. */
- return nm_ip_addr_cmp(GPOINTER_TO_INT(user_data), a, b);
-}
-
-/* this initializes a struct in_addr/in6_addr and allows for untrusted
- * arguments (like unsuitable @addr_family or @src_len). It's almost safe
- * in the sense that it verifies input arguments strictly. Also, it
- * uses memcpy() to access @src, so alignment is not an issue.
- *
- * Only potential pitfalls:
- *
- * - it allows for @addr_family to be AF_UNSPEC. If that is the case (and the
- * caller allows for that), the caller MUST provide @out_addr_family.
- * - when setting @dst to an IPv4 address, the trailing bytes are not touched.
- * Meaning, if @dst is an NMIPAddr union, only the first bytes will be set.
- * If that matter to you, clear @dst before. */
-gboolean
-nm_ip_addr_set_from_untrusted(int addr_family,
- gpointer dst,
- gconstpointer src,
- gsize src_len,
- int *out_addr_family)
-{
- nm_assert(dst);
-
- switch (addr_family) {
- case AF_UNSPEC:
- if (!out_addr_family) {
- /* when the callers allow undefined @addr_family, they must provide
- * an @out_addr_family argument. */
- nm_assert_not_reached();
- return FALSE;
- }
- switch (src_len) {
- case sizeof(struct in_addr):
- addr_family = AF_INET;
- break;
- case sizeof(struct in6_addr):
- addr_family = AF_INET6;
- break;
- default:
- return FALSE;
- }
- break;
- case AF_INET:
- if (src_len != sizeof(struct in_addr))
- return FALSE;
- break;
- case AF_INET6:
- if (src_len != sizeof(struct in6_addr))
- return FALSE;
- break;
- default:
- /* when the callers allow undefined @addr_family, they must provide
- * an @out_addr_family argument. */
- nm_assert(out_addr_family);
- return FALSE;
- }
-
- nm_assert(src);
-
- memcpy(dst, src, src_len);
- NM_SET_OUT(out_addr_family, addr_family);
- return TRUE;
-}
-
-gboolean
-nm_ip_addr_set_from_variant(int addr_family, gpointer dst, GVariant *variant, int *out_addr_family)
-{
- gconstpointer bytes;
- gsize len;
-
- g_return_val_if_fail(dst, FALSE);
- g_return_val_if_fail(variant, FALSE);
-
- /* This function always expects IP addressea a byte arrays ("ay"). Note that
- * several NetworkManager API uses "u" (32 bit unsigned intergers) for IPv4 addresses.
- * So this function won't work in those cases.
- *
- * Btw, using "u" for IPv4 address messes badly with the endianness (host
- * vs network byte order). Don't do that.
- */
- g_return_val_if_fail(g_variant_is_of_type(variant, G_VARIANT_TYPE("ay")), FALSE);
-
- bytes = g_variant_get_fixed_array(variant, &len, sizeof(guint8));
-
- return nm_ip_addr_set_from_untrusted(addr_family, dst, bytes, len, out_addr_family);
-}
-
-/*****************************************************************************/
-
G_STATIC_ASSERT(ETH_ALEN == sizeof(struct ether_addr));
G_STATIC_ASSERT(ETH_ALEN == 6);
G_STATIC_ASSERT(ETH_ALEN == sizeof(NMEtherAddr));
@@ -244,7 +139,7 @@ nm_utils_ipv6_interface_identifier_get_from_token(NMUtilsIPv6IfaceId *iid, const
/**
* nm_utils_inet6_interface_identifier_to_token:
* @iid: %NMUtilsIPv6IfaceId interface identifier
- * @buf: the destination buffer of at least %NM_UTILS_INET_ADDRSTRLEN
+ * @buf: the destination buffer of at least %NM_INET_ADDRSTRLEN
* bytes.
*
* Converts the interface identifier to a string token.
@@ -261,7 +156,7 @@ nm_utils_inet6_interface_identifier_to_token(const NMUtilsIPv6IfaceId *iid,
nm_assert(buf);
nm_utils_ipv6_addr_set_interface_identifier(&i6_token, iid);
- return _nm_utils_inet6_ntop(&i6_token, buf);
+ return nm_inet6_ntop(&i6_token, buf);
}
/*****************************************************************************/
@@ -981,293 +876,6 @@ nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs,
/*****************************************************************************/
-guint32
-_nm_utils_ip4_get_default_prefix0(in_addr_t ip)
-{
- /* The function is originally from ipcalc.c of Red Hat's initscripts. */
- switch (ntohl(ip) >> 24) {
- case 0 ... 127:
- return 8; /* Class A */
- case 128 ... 191:
- return 16; /* Class B */
- case 192 ... 223:
- return 24; /* Class C */
- }
- return 0;
-}
-
-guint32
-_nm_utils_ip4_get_default_prefix(in_addr_t ip)
-{
- return _nm_utils_ip4_get_default_prefix0(ip) ?: 24;
-}
-
-gboolean
-nm_utils_ip_is_site_local(int addr_family, const void *address)
-{
- in_addr_t addr4;
-
- 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;
- 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);
- default:
- g_return_val_if_reached(FALSE);
- }
-}
-
-gboolean
-nm_utils_ip6_is_ula(const struct in6_addr *address)
-{
- /* Unique local IPv6 address (ULA) fc00::/7 */
- return (address->s6_addr32[0] & htonl(0xfe000000u)) == htonl(0xfc000000u);
-}
-
-/*****************************************************************************/
-
-static gboolean
-_parse_legacy_addr4(const char *text, in_addr_t *out_addr, GError **error)
-{
- gs_free char *s_free = NULL;
- struct in_addr a1;
- guint8 bin[sizeof(a1)];
- char *s;
- int i;
-
- if (inet_aton(text, &a1) != 1) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "address invalid according to inet_aton()");
- return FALSE;
- }
-
- /* OK, inet_aton() accepted the format. That's good, because we want
- * to accept IPv4 addresses in octal format, like 255.255.000.000.
- * That's what "legacy" means here. inet_pton() doesn't accept those.
- *
- * But inet_aton() also ignores trailing garbage and formats with fewer than
- * 4 digits. That is just too crazy and we don't do that. Perform additional checks
- * and reject some forms that inet_aton() accepted.
- *
- * Note that we still should (of course) accept everything that inet_pton()
- * accepts. However this code never gets called if inet_pton() succeeds
- * (see below, aside the assertion code). */
-
- if (NM_STRCHAR_ANY(text, ch, (!(ch >= '0' && ch <= '9') && !NM_IN_SET(ch, '.', 'x')))) {
- /* We only accepts '.', digits, and 'x' for "0x". */
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "contains an invalid character");
- return FALSE;
- }
-
- s = nm_memdup_maybe_a(300, text, strlen(text) + 1, &s_free);
-
- for (i = 0; i < G_N_ELEMENTS(bin); i++) {
- char *current_token = s;
- gint32 v;
-
- s = strchr(s, '.');
- if (s) {
- s[0] = '\0';
- s++;
- }
-
- if ((i == G_N_ELEMENTS(bin) - 1) != (s == NULL)) {
- /* Exactly for the last digit, we expect to have no more following token.
- * But this isn't the case. Abort. */
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "wrong number of tokens (index %d, token '%s')",
- i,
- s);
- return FALSE;
- }
-
- v = _nm_utils_ascii_str_to_int64(current_token, 0, 0, 0xFF, -1);
- if (v == -1) {
- int errsv = errno;
-
- /* we do accept octal and hex (even with leading "0x"). But something
- * about this token is wrong. */
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "invalid token '%s': %s (%d)",
- current_token,
- nm_strerror_native(errsv),
- errsv);
- return FALSE;
- }
-
- bin[i] = v;
- }
-
- if (memcmp(bin, &a1, sizeof(bin)) != 0) {
- /* our parsing did not agree with what inet_aton() gave. Something
- * is wrong. Abort. */
- g_set_error(
- error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "inet_aton() result 0x%08x differs from computed value 0x%02hhx%02hhx%02hhx%02hhx",
- a1.s_addr,
- bin[0],
- bin[1],
- bin[2],
- bin[3]);
- return FALSE;
- }
-
- *out_addr = a1.s_addr;
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_bin_full(int addr_family,
- gboolean accept_legacy,
- const char *text,
- int *out_addr_family,
- gpointer out_addr)
-{
- NMIPAddr addrbin;
-
- g_return_val_if_fail(text, FALSE);
-
- if (addr_family == AF_UNSPEC) {
- g_return_val_if_fail(!out_addr || out_addr_family, FALSE);
- addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
- } else
- g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
-
- if (inet_pton(addr_family, text, &addrbin) != 1) {
- if (accept_legacy && addr_family == AF_INET
- && _parse_legacy_addr4(text, &addrbin.addr4, NULL)) {
- /* The address is in some legacy format which inet_aton() accepts, but not inet_pton().
- * Most likely octal digits (leading zeros). We accept the address. */
- } else
- return FALSE;
- }
-
-#if NM_MORE_ASSERTS > 10
- if (addr_family == AF_INET) {
- NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER
- gs_free_error GError *error = NULL;
- in_addr_t a;
-
- /* The legacy parser should accept everything that inet_pton() accepts too. Meaning,
- * it should strictly parse *more* formats. And of course, parse it the same way. */
- if (!_parse_legacy_addr4(text, &a, &error)) {
- char buf[INET_ADDRSTRLEN];
-
- g_error("unexpected assertion failure: could parse \"%s\" as %s, but not accepted by "
- "legacy parser: %s",
- text,
- _nm_utils_inet4_ntop(addrbin.addr4, buf),
- error->message);
- }
- nm_assert(addrbin.addr4 == a);
- NM_PRAGMA_WARNING_REENABLE
- }
-#endif
-
- NM_SET_OUT(out_addr_family, addr_family);
- if (out_addr)
- nm_ip_addr_set(addr_family, out_addr, &addrbin);
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr(int addr_family, const char *text, char **out_addr)
-{
- NMIPAddr addrbin;
- char addrstr_buf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
-
- g_return_val_if_fail(text, FALSE);
-
- if (addr_family == AF_UNSPEC)
- addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
- else
- g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
-
- if (inet_pton(addr_family, text, &addrbin) != 1)
- return FALSE;
-
- NM_SET_OUT(out_addr,
- g_strdup(inet_ntop(addr_family, &addrbin, addrstr_buf, sizeof(addrstr_buf))));
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_prefix_bin(int addr_family,
- const char *text,
- int *out_addr_family,
- gpointer out_addr,
- int *out_prefix)
-{
- gs_free char *addrstr_free = NULL;
- int prefix = -1;
- const char *slash;
- const char *addrstr;
- NMIPAddr addrbin;
-
- g_return_val_if_fail(text, FALSE);
-
- if (addr_family == AF_UNSPEC) {
- g_return_val_if_fail(!out_addr || out_addr_family, FALSE);
- addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
- } else
- g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
-
- slash = strchr(text, '/');
- if (slash)
- addrstr = nm_strndup_a(300, text, slash - text, &addrstr_free);
- else
- addrstr = text;
-
- if (inet_pton(addr_family, addrstr, &addrbin) != 1)
- return FALSE;
-
- if (slash) {
- /* For IPv4, `ip addr add` supports the prefix-length as a netmask. We don't
- * do that. */
- prefix =
- _nm_utils_ascii_str_to_int64(&slash[1], 10, 0, addr_family == AF_INET ? 32 : 128, -1);
- if (prefix == -1)
- return FALSE;
- }
-
- NM_SET_OUT(out_addr_family, addr_family);
- if (out_addr)
- nm_ip_addr_set(addr_family, out_addr, &addrbin);
- NM_SET_OUT(out_prefix, prefix);
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_prefix(int addr_family, const char *text, char **out_addr, int *out_prefix)
-{
- NMIPAddr addrbin;
- char addrstr_buf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
-
- if (!nm_utils_parse_inaddr_prefix_bin(addr_family, text, &addr_family, &addrbin, out_prefix))
- return FALSE;
- NM_SET_OUT(out_addr,
- g_strdup(inet_ntop(addr_family, &addrbin, addrstr_buf, sizeof(addrstr_buf))));
- return TRUE;
-}
-
gboolean
nm_utils_parse_next_line(const char **inout_ptr,
gsize *inout_len,
@@ -1323,43 +931,6 @@ done:
/*****************************************************************************/
-gboolean
-nm_utils_ipaddr_is_valid(int addr_family, const char *str_addr)
-{
- nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
-
- return str_addr && nm_utils_parse_inaddr_bin(addr_family, str_addr, NULL, NULL);
-}
-
-gboolean
-nm_utils_ipaddr_is_normalized(int addr_family, const char *str_addr)
-{
- NMIPAddr addr;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
-
- if (!str_addr)
- return FALSE;
-
- if (!nm_utils_parse_inaddr_bin(addr_family, str_addr, &addr_family, &addr))
- return FALSE;
-
- nm_utils_inet_ntop(addr_family, &addr, sbuf);
- return nm_streq(sbuf, str_addr);
-}
-
-/*****************************************************************************/
-
-NM_UTILS_ENUM2STR_DEFINE(nm_icmpv6_router_pref_to_string,
- NMIcmpv6RouterPref,
- NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_LOW, "low"),
- NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_MEDIUM, "medium"),
- NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_HIGH, "high"),
- NM_UTILS_ENUM2STR(NM_ICMPV6_ROUTER_PREF_INVALID, "invalid"), );
-
-/*****************************************************************************/
-
/**
* nm_g_ascii_strtoll()
* @nptr: the string to parse
@@ -6359,98 +5930,6 @@ _nm_utils_ssid_to_string_gbytes(GBytes *ssid)
/*****************************************************************************/
-gconstpointer
-nm_utils_ipx_address_clear_host_address(int family, gpointer dst, gconstpointer src, guint32 plen)
-{
- g_return_val_if_fail(dst, NULL);
-
- 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_utils_ip4_address_clear_host_address(*((guint32 *) src), plen);
- break;
- case AF_INET6:
- nm_utils_ip6_address_clear_host_address(dst, src, plen);
- break;
- default:
- g_return_val_if_reached(NULL);
- }
- return dst;
-}
-
-/* nm_utils_ip6_address_clear_host_address:
- * @dst: destination output buffer, will contain the network part of the @src address
- * @src: source ip6 address. If NULL, this does an in-place update of @dst.
- * Also, @src and @dst are allowed to be the same pointers.
- * @plen: prefix length of network
- *
- * Note: this function is self assignment safe, to update @src inplace, set both
- * @dst and @src to the same destination or set @src NULL.
- */
-const struct in6_addr *
-nm_utils_ip6_address_clear_host_address(struct in6_addr *dst,
- const struct in6_addr *src,
- guint32 plen)
-{
- g_return_val_if_fail(plen <= 128, NULL);
- g_return_val_if_fail(dst, NULL);
-
- if (!src)
- src = dst;
-
- if (plen < 128) {
- guint nbytes = plen / 8;
- guint nbits = plen % 8;
-
- if (nbytes && dst != src)
- memcpy(dst, src, nbytes);
- if (nbits) {
- dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
- nbytes++;
- }
- if (nbytes <= 15)
- memset(&dst->s6_addr[nbytes], 0, 16 - nbytes);
- } else if (src != dst)
- *dst = *src;
-
- return dst;
-}
-
-int
-nm_utils_ip6_address_same_prefix_cmp(const struct in6_addr *addr_a,
- const struct in6_addr *addr_b,
- guint32 plen)
-{
- int nbytes;
- guint8 va, vb, m;
-
- if (plen >= 128) {
- nm_assert(plen == 128);
- NM_CMP_DIRECT_MEMCMP(addr_a, addr_b, sizeof(struct in6_addr));
- } else {
- nbytes = plen / 8;
- if (nbytes)
- NM_CMP_DIRECT_MEMCMP(addr_a, addr_b, nbytes);
-
- plen = plen % 8;
- if (plen != 0) {
- m = ~((1 << (8 - plen)) - 1);
- va = ((((const guint8 *) addr_a))[nbytes]) & m;
- vb = ((((const guint8 *) addr_b))[nbytes]) & m;
- NM_CMP_DIRECT(va, vb);
- }
- }
- return 0;
-}
-
-/*****************************************************************************/
-
#define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/"
#define IPV4_PROPERTY_DIR "/proc/sys/net/ipv4/conf/"
diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h
index 3d8eaced07..892d0d3012 100644
--- a/src/libnm-glib-aux/nm-shared-utils.h
+++ b/src/libnm-glib-aux/nm-shared-utils.h
@@ -214,128 +214,6 @@ nm_ether_addr_equal(const NMEtherAddr *a, const NMEtherAddr *b)
/*****************************************************************************/
-typedef struct {
- union {
- guint8 addr_ptr[sizeof(struct in6_addr)];
- in_addr_t addr4;
- struct in_addr addr4_struct;
- struct in6_addr addr6;
-
- /* NMIPAddr is really a union for IP addresses.
- * However, as ethernet addresses fit in here nicely, use
- * it also for an ethernet MAC address. */
- guint8 ether_addr_octet[6 /*ETH_ALEN*/];
- NMEtherAddr ether_addr;
-
- guint8 array[sizeof(struct in6_addr)];
- };
-} NMIPAddr;
-
-#define NM_IP_ADDR_INIT \
- { \
- .array = { 0 } \
- }
-
-extern const NMIPAddr nm_ip_addr_zero;
-
-#define nm_ether_addr_zero (nm_ip_addr_zero.ether_addr)
-
-static inline int
-nm_ip_addr_cmp(int addr_family, gconstpointer a, gconstpointer b)
-{
- /* Note that @a and @b are not required to be full NMIPAddr unions.
- * Depending on @addr_family, they can also be only in_addr_t or
- * struct in6_addr. */
- NM_CMP_SELF(a, b);
- NM_CMP_DIRECT_MEMCMP(a, b, nm_utils_addr_family_to_size(addr_family));
- return 0;
-}
-
-int nm_ip_addr_cmp_for_sort(gconstpointer a, gconstpointer b, gpointer user_data);
-
-static inline gboolean
-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)
-{
- nm_assert(dst);
- nm_assert(src);
-
- /* this MUST use memcpy() to support unaligned src/dst pointers. */
- memcpy(dst, src, nm_utils_addr_family_to_size(addr_family));
-
- /* Note that @dst is not necessarily a NMIPAddr, it could also be just
- * an in_addr_t/struct in6_addr. We thus can only set the bytes that
- * we know are present based on the address family.
- *
- * Using this function to initialize an NMIPAddr union (for IPv4) leaves
- * uninitalized bytes. Avoid that by using nm_ip_addr_init() instead. */
-}
-
-static inline NMIPAddr
-nm_ip_addr_init(int addr_family, gconstpointer src)
-{
- NMIPAddr a;
-
- nm_assert_addr_family(addr_family);
- nm_assert(src);
-
- G_STATIC_ASSERT_EXPR(sizeof(NMIPAddr) == sizeof(struct in6_addr));
-
- /* this MUST use memcpy() to support unaligned src/dst pointers. */
-
- if (NM_IS_IPv4(addr_family)) {
- memcpy(&a, src, sizeof(in_addr_t));
-
- /* ensure all bytes of the union are initialized. If only to make
- * valgrind happy. */
- memset(&a.array[sizeof(in_addr_t)], 0, sizeof(a) - sizeof(in_addr_t));
- } else
- memcpy(&a, src, sizeof(struct in6_addr));
-
- return a;
-}
-
-gboolean nm_ip_addr_set_from_untrusted(int addr_family,
- gpointer dst,
- gconstpointer src,
- gsize src_len,
- int *out_addr_family);
-
-gboolean
-nm_ip_addr_set_from_variant(int addr_family, gpointer dst, GVariant *variant, int *out_addr_family);
-
-static inline gconstpointer
-nm_ip_addr_from_packed_array(int addr_family, gconstpointer ipaddr_arr, gsize idx)
-{
- return NM_IS_IPv4(addr_family)
- ? ((gconstpointer) & (((const struct in_addr *) ipaddr_arr)[idx]))
- : ((gconstpointer) & (((const struct in6_addr *) ipaddr_arr)[idx]));
-}
-
-/*****************************************************************************/
-
struct ether_addr;
static inline int
@@ -397,219 +275,6 @@ gboolean nm_utils_get_ipv6_interface_identifier(NMLinkType link_type,
/*****************************************************************************/
-static inline guint32
-_nm_utils_ip4_netmask_to_prefix(in_addr_t subnetmask)
-{
- G_STATIC_ASSERT_EXPR(__SIZEOF_INT__ == 4);
- G_STATIC_ASSERT_EXPR(sizeof(int) == 4);
- G_STATIC_ASSERT_EXPR(sizeof(guint) == 4);
- G_STATIC_ASSERT_EXPR(sizeof(subnetmask) == 4);
-
- return ((subnetmask != 0u) ? (guint32) (32 - __builtin_ctz(ntohl(subnetmask))) : 0u);
-}
-
-/**
- * _nm_utils_ip4_prefix_to_netmask:
- * @prefix: a CIDR prefix
- *
- * Returns: the netmask represented by the prefix, in network byte order
- **/
-static inline in_addr_t
-_nm_utils_ip4_prefix_to_netmask(guint32 prefix)
-{
- nm_assert(prefix <= 32);
- return prefix < 32 ? ~htonl(0xFFFFFFFFu >> prefix) : 0xFFFFFFFFu;
-}
-
-guint32 _nm_utils_ip4_get_default_prefix0(in_addr_t ip);
-guint32 _nm_utils_ip4_get_default_prefix(in_addr_t ip);
-
-gconstpointer
-nm_utils_ipx_address_clear_host_address(int family, gpointer dst, gconstpointer src, guint32 plen);
-
-/* nm_utils_ip4_address_clear_host_address:
- * @addr: source ip6 address
- * @plen: prefix length of network
- *
- * returns: the input address, with the host address set to 0.
- */
-static inline in_addr_t
-nm_utils_ip4_address_clear_host_address(in_addr_t addr, guint32 plen)
-{
- return addr & _nm_utils_ip4_prefix_to_netmask(plen);
-}
-
-const struct in6_addr *nm_utils_ip6_address_clear_host_address(struct in6_addr *dst,
- const struct in6_addr *src,
- guint32 plen);
-
-static inline int
-nm_utils_ip4_address_same_prefix_cmp(in_addr_t addr_a, in_addr_t addr_b, guint32 plen)
-{
- NM_CMP_DIRECT(htonl(nm_utils_ip4_address_clear_host_address(addr_a, plen)),
- htonl(nm_utils_ip4_address_clear_host_address(addr_b, plen)));
- return 0;
-}
-
-int nm_utils_ip6_address_same_prefix_cmp(const struct in6_addr *addr_a,
- const struct in6_addr *addr_b,
- guint32 plen);
-
-static inline gboolean
-nm_utils_ip4_address_same_prefix(in_addr_t addr_a, in_addr_t addr_b, guint32 plen)
-{
- return nm_utils_ip4_address_same_prefix_cmp(addr_a, addr_b, plen) == 0;
-}
-
-static inline gboolean
-nm_utils_ip6_address_same_prefix(const struct in6_addr *addr_a,
- const struct in6_addr *addr_b,
- guint8 plen)
-{
- return nm_utils_ip6_address_same_prefix_cmp(addr_a, addr_b, plen) == 0;
-}
-
-static inline int
-nm_utils_ip_address_same_prefix_cmp(int addr_family,
- gconstpointer addr_a,
- gconstpointer addr_b,
- guint8 plen)
-{
- NM_CMP_SELF(addr_a, addr_b);
-
- if (NM_IS_IPv4(addr_family)) {
- return nm_utils_ip4_address_same_prefix_cmp(*((const in_addr_t *) addr_a),
- *((const in_addr_t *) addr_b),
- plen);
- }
-
- return nm_utils_ip6_address_same_prefix_cmp(addr_a, addr_b, plen);
-}
-
-static inline gboolean
-nm_utils_ip_address_same_prefix(int addr_family,
- gconstpointer addr_a,
- gconstpointer addr_b,
- guint8 plen)
-{
- return nm_utils_ip_address_same_prefix_cmp(addr_family, addr_a, addr_b, plen) == 0;
-}
-
-#define NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a, b, plen) \
- NM_CMP_RETURN(nm_utils_ip4_address_same_prefix_cmp((a), (b), (plen)))
-
-#define NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(a, b, plen) \
- NM_CMP_RETURN(nm_utils_ip6_address_same_prefix_cmp((a), (b), (plen)))
-
-/*****************************************************************************/
-
-gboolean nm_utils_ip_is_site_local(int addr_family, const void *address);
-gboolean nm_utils_ip6_is_ula(const struct in6_addr *address);
-
-/*****************************************************************************/
-
-#define NM_IPV4LL_NETWORK ((in_addr_t) htonl(0xA9FE0000lu))
-#define NM_IPV4LL_NETMASK ((in_addr_t) htonl(0xFFFF0000lu))
-
-static inline gboolean
-nm_utils_ip4_address_is_loopback(in_addr_t addr)
-{
- /* There is also IN_LOOPBACK() in <linux/in.h>, but there the
- * argument is in host order not `in_addr_t`. */
- return (addr & htonl(0xFF000000u)) == htonl(0x7F000000u);
-}
-
-static inline gboolean
-nm_utils_ip4_address_is_link_local(in_addr_t addr)
-{
- return (addr & NM_IPV4LL_NETMASK) == NM_IPV4LL_NETWORK;
-}
-
-static inline gboolean
-nm_utils_ip4_address_is_zeronet(in_addr_t network)
-{
- /* Same as ipv4_is_zeronet() from kernel's include/linux/in.h. */
- return (network & htonl(0xFF000000u)) == htonl(0x00000000u);
-}
-
-/*****************************************************************************/
-
-#define NM_UTILS_INET_ADDRSTRLEN INET6_ADDRSTRLEN
-
-/* Forward declare function so we don't have to drag in <arpa/inet.h>. */
-const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
-
-static inline const char *
-nm_utils_inet_ntop(int addr_family, gconstpointer addr, char *dst)
-{
- const char *s;
-
- nm_assert_addr_family(addr_family);
- nm_assert(addr);
- nm_assert(dst);
-
- s = inet_ntop(addr_family,
- addr,
- dst,
- addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN);
- nm_assert(s);
- return s;
-}
-
-static inline const char *
-_nm_utils_inet4_ntop(in_addr_t addr, char dst[static INET_ADDRSTRLEN])
-{
- return nm_utils_inet_ntop(AF_INET, &addr, dst);
-}
-
-static inline const char *
-_nm_utils_inet6_ntop(const struct in6_addr *addr, char dst[static INET6_ADDRSTRLEN])
-{
- return nm_utils_inet_ntop(AF_INET6, addr, dst);
-}
-
-static inline char *
-nm_utils_inet_ntop_dup(int addr_family, gconstpointer addr)
-{
- char buf[NM_UTILS_INET_ADDRSTRLEN];
-
- return g_strdup(nm_utils_inet_ntop(addr_family, addr, buf));
-}
-
-static inline char *
-nm_utils_inet4_ntop_dup(in_addr_t addr)
-{
- return nm_utils_inet_ntop_dup(AF_INET, &addr);
-}
-
-static inline char *
-nm_utils_inet6_ntop_dup(const struct in6_addr *addr)
-{
- return nm_utils_inet_ntop_dup(AF_INET6, addr);
-}
-
-/*****************************************************************************/
-
-gboolean nm_utils_ipaddr_is_valid(int addr_family, const char *str_addr);
-
-gboolean nm_utils_ipaddr_is_normalized(int addr_family, const char *str_addr);
-
-/*****************************************************************************/
-
-/* this enum is compatible with ICMPV6_ROUTER_PREF_* (from <linux/icmpv6.h>,
- * the values for netlink attribute RTA_PREF) and "enum ndp_route_preference"
- * from <ndp.h>. */
-typedef enum _nm_packed {
- NM_ICMPV6_ROUTER_PREF_MEDIUM = 0x0, /* ICMPV6_ROUTER_PREF_MEDIUM */
- NM_ICMPV6_ROUTER_PREF_LOW = 0x3, /* ICMPV6_ROUTER_PREF_LOW */
- NM_ICMPV6_ROUTER_PREF_HIGH = 0x1, /* ICMPV6_ROUTER_PREF_HIGH */
- NM_ICMPV6_ROUTER_PREF_INVALID = 0x2, /* ICMPV6_ROUTER_PREF_INVALID */
-} NMIcmpv6RouterPref;
-
-const char *nm_icmpv6_router_pref_to_string(NMIcmpv6RouterPref pref, char *buf, gsize len);
-
-/*****************************************************************************/
-
gboolean nm_utils_memeqzero(gconstpointer data, gsize length);
/*****************************************************************************/
@@ -1042,31 +707,6 @@ nm_utils_escaped_tokens_options_escape_val(const char *val, char **out_to_free)
/*****************************************************************************/
-gboolean nm_utils_parse_inaddr_bin_full(int addr_family,
- gboolean accept_legacy,
- const char *text,
- int *out_addr_family,
- gpointer out_addr);
-static inline gboolean
-nm_utils_parse_inaddr_bin(int addr_family,
- const char *text,
- int *out_addr_family,
- gpointer out_addr)
-{
- return nm_utils_parse_inaddr_bin_full(addr_family, FALSE, text, out_addr_family, out_addr);
-}
-
-gboolean nm_utils_parse_inaddr(int addr_family, const char *text, char **out_addr);
-
-gboolean nm_utils_parse_inaddr_prefix_bin(int addr_family,
- const char *text,
- int *out_addr_family,
- gpointer out_addr,
- int *out_prefix);
-
-gboolean
-nm_utils_parse_inaddr_prefix(int addr_family, const char *text, char **out_addr, int *out_prefix);
-
gboolean nm_utils_parse_next_line(const char **inout_ptr,
gsize *inout_len,
const char **out_line,
@@ -1658,6 +1298,10 @@ nm_g_variant_new_au(const guint32 *data, gsize len)
return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, data, len, sizeof(guint32));
}
+struct _NMIPAddr;
+
+extern const struct _NMIPAddr nm_ip_addr_zero;
+
static inline GVariant *
nm_g_variant_new_ay_inaddr(int addr_family, gconstpointer addr)
{
diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h
index 83702070b8..fd2ddf86fb 100644
--- a/src/libnm-glib-aux/nm-test-utils.h
+++ b/src/libnm-glib-aux/nm-test-utils.h
@@ -1944,9 +1944,9 @@ nmtst_setting_ip_config_add_address(NMSettingIPConfig *s_ip, const char *address
g_assert(s_ip);
- if (nm_utils_ipaddr_is_valid(AF_INET, address))
+ if (nm_inet_is_valid(AF_INET, address))
family = AF_INET;
- else if (nm_utils_ipaddr_is_valid(AF_INET6, address))
+ else if (nm_inet_is_valid(AF_INET6, address))
family = AF_INET6;
else
g_assert_not_reached();
@@ -1969,9 +1969,9 @@ nmtst_setting_ip_config_add_route(NMSettingIPConfig *s_ip,
g_assert(s_ip);
- if (nm_utils_ipaddr_is_valid(AF_INET, dest))
+ if (nm_inet_is_valid(AF_INET, dest))
family = AF_INET;
- else if (nm_utils_ipaddr_is_valid(AF_INET6, dest))
+ else if (nm_inet_is_valid(AF_INET6, dest))
family = AF_INET6;
else
g_assert_not_reached();
@@ -2913,7 +2913,7 @@ nmtst_ip_address_new(int addr_family, const char *str)
GError *error = NULL;
NMIPAddress *a;
- if (!nm_utils_parse_inaddr_prefix_bin(addr_family, str, &addr_family, &addr, &plen))
+ if (!nm_inet_parse_with_prefix_bin(addr_family, str, &addr_family, &addr, &plen))
g_assert_not_reached();
if (plen == -1)
diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c
index 7d36d64a8c..e6e57c5218 100644
--- a/src/libnm-glib-aux/tests/test-shared-general.c
+++ b/src/libnm-glib-aux/tests/test-shared-general.c
@@ -251,37 +251,37 @@ test_nm_strndup_a(void)
/*****************************************************************************/
static void
-test_nm_utils_ip4_address_is_loopback(void)
+test_nm_ip4_addr_is_loopback(void)
{
- g_assert(nm_utils_ip4_address_is_loopback(nmtst_inet4_from_string("127.0.0.0")));
- g_assert(nm_utils_ip4_address_is_loopback(nmtst_inet4_from_string("127.0.0.1")));
- g_assert(nm_utils_ip4_address_is_loopback(nmtst_inet4_from_string("127.5.0.1")));
- g_assert(!nm_utils_ip4_address_is_loopback(nmtst_inet4_from_string("126.5.0.1")));
- g_assert(!nm_utils_ip4_address_is_loopback(nmtst_inet4_from_string("128.5.0.1")));
- g_assert(!nm_utils_ip4_address_is_loopback(nmtst_inet4_from_string("129.5.0.1")));
+ g_assert(nm_ip4_addr_is_loopback(nmtst_inet4_from_string("127.0.0.0")));
+ g_assert(nm_ip4_addr_is_loopback(nmtst_inet4_from_string("127.0.0.1")));
+ g_assert(nm_ip4_addr_is_loopback(nmtst_inet4_from_string("127.5.0.1")));
+ g_assert(!nm_ip4_addr_is_loopback(nmtst_inet4_from_string("126.5.0.1")));
+ g_assert(!nm_ip4_addr_is_loopback(nmtst_inet4_from_string("128.5.0.1")));
+ g_assert(!nm_ip4_addr_is_loopback(nmtst_inet4_from_string("129.5.0.1")));
}
/*****************************************************************************/
static void
-test_nm_utils_ip4_prefix_to_netmask(void)
+test_nm_ip4_addr_netmask_from_prefix(void)
{
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(0), ==, nmtst_inet4_from_string("0.0.0.0"));
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(1), ==, nmtst_inet4_from_string("128.0.0.0"));
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(2), ==, nmtst_inet4_from_string("192.0.0.0"));
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(16),
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(0), ==, nmtst_inet4_from_string("0.0.0.0"));
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(1), ==, nmtst_inet4_from_string("128.0.0.0"));
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(2), ==, nmtst_inet4_from_string("192.0.0.0"));
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(16),
==,
nmtst_inet4_from_string("255.255.0.0"));
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(24),
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(24),
==,
nmtst_inet4_from_string("255.255.255.0"));
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(30),
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(30),
==,
nmtst_inet4_from_string("255.255.255.252"));
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(31),
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(31),
==,
nmtst_inet4_from_string("255.255.255.254"));
- g_assert_cmpint(_nm_utils_ip4_prefix_to_netmask(32),
+ g_assert_cmpint(nm_ip4_addr_netmask_from_prefix(32),
==,
nmtst_inet4_from_string("255.255.255.255"));
}
@@ -2201,6 +2201,19 @@ test_hostname_is_valid(void)
/*****************************************************************************/
+static void
+test_inet_utils(void)
+{
+ g_assert(nm_ip_addr_is_site_local(AF_INET, nmtst_inet_from_string(AF_INET, "172.16.0.1")));
+ g_assert(nm_ip_addr_is_site_local(AF_INET, nmtst_inet_from_string(AF_INET, "172.17.0.1")));
+ g_assert(nm_ip_addr_is_site_local(AF_INET, nmtst_inet_from_string(AF_INET, "192.168.7.5")));
+ g_assert(!nm_ip_addr_is_site_local(AF_INET, nmtst_inet_from_string(AF_INET, "192.0.7.5")));
+ g_assert(nm_ip_addr_is_site_local(AF_INET6, nmtst_inet_from_string(AF_INET6, "fec0::")));
+ g_assert(!nm_ip_addr_is_site_local(AF_INET6, nmtst_inet_from_string(AF_INET6, "fc00::")));
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE();
int
@@ -2215,10 +2228,9 @@ main(int argc, char **argv)
g_test_add_func("/general/test_nm_make_strv", test_make_strv);
g_test_add_func("/general/test_nm_strdup_int", test_nm_strdup_int);
g_test_add_func("/general/test_nm_strndup_a", test_nm_strndup_a);
- g_test_add_func("/general/test_nm_utils_ip4_address_is_loopback",
- test_nm_utils_ip4_address_is_loopback);
- g_test_add_func("/general/test_nm_utils_ip4_prefix_to_netmask",
- test_nm_utils_ip4_prefix_to_netmask);
+ g_test_add_func("/general/test_nm_ip4_addr_is_loopback", test_nm_ip4_addr_is_loopback);
+ g_test_add_func("/general/test_nm_ip4_addr_netmask_from_prefix",
+ test_nm_ip4_addr_netmask_from_prefix);
g_test_add_func("/general/test_unaligned", test_unaligned);
g_test_add_func("/general/test_strv_cmp", test_strv_cmp);
g_test_add_func("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy);
@@ -2246,6 +2258,7 @@ main(int argc, char **argv)
g_test_add_func("/general/test_path_startswith", test_path_startswith);
g_test_add_func("/general/test_path_simplify", test_path_simplify);
g_test_add_func("/general/test_hostname_is_valid", test_hostname_is_valid);
+ g_test_add_func("/general/test_inet_utils", test_inet_utils);
return g_test_run();
}