diff options
Diffstat (limited to 'src/libnm-glib-aux/nm-shared-utils.c')
| -rw-r--r-- | src/libnm-glib-aux/nm-shared-utils.c | 675 |
1 files changed, 53 insertions, 622 deletions
diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index aca7d708..702a63e9 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -3,6 +3,8 @@ * Copyright (C) 2016 Red Hat, Inc. */ +#define NM_WANT_NM_ARRAY_FIND_BSEARCH_INLINE + #include "libnm-glib-aux/nm-default-glib-i18n-lib.h" #include "nm-shared-utils.h" @@ -35,111 +37,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)); @@ -158,6 +55,7 @@ nm_ether_addr_from_string(NMEtherAddr *addr, const char *str) return addr; } + /*****************************************************************************/ /** @@ -184,37 +82,6 @@ _nm_utils_inet6_is_token(const struct in6_addr *in6addr) } /** - * 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) -{ - 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) -{ - 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 @@ -244,7 +111,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 +128,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 +848,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 +903,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 @@ -2587,15 +2130,16 @@ nm_strv_cleanup(char **strv, gboolean strip_whitespace, gboolean skip_empty, gbo /*****************************************************************************/ GPtrArray * -_nm_g_ptr_array_copy(GPtrArray *array, - GCopyFunc func, - gpointer user_data, - GDestroyNotify element_free_func) +nm_g_ptr_array_new_clone(GPtrArray *array, + GCopyFunc func, + gpointer user_data, + GDestroyNotify element_free_func) { GPtrArray *new_array; guint i; g_return_val_if_fail(array, NULL); + nm_assert((!!func) == (!!element_free_func)); new_array = g_ptr_array_new_full(array->len, element_free_func); for (i = 0; i < array->len; i++) { @@ -3522,12 +3066,12 @@ nm_utils_named_value_list_find(const NMUtilsNamedValue *arr, #endif if (sorted) { - return nm_utils_array_find_binary_search(arr, - sizeof(NMUtilsNamedValue), - len, - &name, - nm_strcmp_p_with_data, - NULL); + return nm_array_find_bsearch(arr, + len, + sizeof(NMUtilsNamedValue), + &name, + nm_strcmp_p_with_data, + NULL); } for (i = 0; i < len; i++) { if (nm_streq(arr[i].name, name)) @@ -4215,17 +3759,19 @@ nm_utils_ptrarray_is_sorted(gconstpointer *list, } gssize -nm_utils_ptrarray_find_binary_search(gconstpointer *list, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data) -{ - gssize imin, imax, imid; +nm_ptrarray_find_bsearch(gconstpointer *list, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data) +{ + gssize imax; + gssize imid; + gssize imin; int cmp; - g_return_val_if_fail(list || !len, ~((gssize) 0)); - g_return_val_if_fail(cmpfcn, ~((gssize) 0)); + nm_assert(list || len == 0); + nm_assert(cmpfcn); imin = 0; if (len > 0) { @@ -4252,19 +3798,24 @@ nm_utils_ptrarray_find_binary_search(gconstpointer *list, } gssize -nm_utils_ptrarray_find_binary_search_range(gconstpointer *list, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data, - gssize *out_idx_first, - gssize *out_idx_last) -{ - gssize imin, imax, imid, i2min, i2max, i2mid; +nm_ptrarray_find_bsearch_range(gconstpointer *list, + gsize len, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data, + gssize *out_idx_first, + gssize *out_idx_last) +{ + gssize imax; + gssize imid; + gssize imin; + gssize i2max; + gssize i2mid; + gssize i2min; int cmp; - g_return_val_if_fail(list || !len, ~((gssize) 0)); - g_return_val_if_fail(cmpfcn, ~((gssize) 0)); + nm_assert(list || len == 0); + nm_assert(cmpfcn); imin = 0; if (len > 0) { @@ -4333,10 +3884,10 @@ nm_utils_ptrarray_find_binary_search_range(gconstpointer *list, /*****************************************************************************/ /** - * nm_utils_array_find_binary_search: + * nm_array_find_bsearch: * @list: the list to search. It must be sorted according to @cmpfcn ordering. - * @elem_size: the size in bytes of each element in the list * @len: the number of elements in @list + * @elem_size: the size in bytes of each element in the list * @needle: the value that is searched * @cmpfcn: the compare function. The elements @list are passed as first * argument to @cmpfcn, while @needle is passed as second. Usually, the @@ -4357,42 +3908,14 @@ nm_utils_ptrarray_find_binary_search_range(gconstpointer *list, * position where it should be. */ gssize -nm_utils_array_find_binary_search(gconstpointer list, - gsize elem_size, - gsize len, - gconstpointer needle, - GCompareDataFunc cmpfcn, - gpointer user_data) -{ - gssize imin, imax, imid; - int cmp; - - g_return_val_if_fail(list || !len, ~((gssize) 0)); - g_return_val_if_fail(cmpfcn, ~((gssize) 0)); - g_return_val_if_fail(elem_size > 0, ~((gssize) 0)); - - imin = 0; - if (len == 0) - return ~imin; - - imax = len - 1; - - while (imin <= imax) { - imid = imin + (imax - imin) / 2; - - cmp = cmpfcn(&((const char *) list)[elem_size * imid], needle, user_data); - if (cmp == 0) - return imid; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - } - - /* return the inverse of @imin. This is a negative number, but - * also is ~imin the position where the value should be inserted. */ - return ~imin; +nm_array_find_bsearch(gconstpointer list, + gsize len, + gsize elem_size, + gconstpointer needle, + GCompareDataFunc cmpfcn, + gpointer user_data) +{ + return nm_array_find_bsearch_inline(list, len, elem_size, needle, cmpfcn, user_data); } /*****************************************************************************/ @@ -6370,98 +5893,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/" |