From ff05585f7504299b93a3e9b152b7d3eae9cdc7cd Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 31 Dec 2025 12:10:12 +0100 Subject: [PATCH] Add sodium_ip2bin, sodium_bin2ip --- src/libsodium/include/sodium/utils.h | 84 ++++---- src/libsodium/sodium/codecs.c | 278 +++++++++++++++++++++++++++ test/default/codecs.c | 179 +++++++++++++++++ test/default/codecs.exp | 15 ++ 4 files changed, 513 insertions(+), 43 deletions(-) diff --git a/src/libsodium/include/sodium/utils.h b/src/libsodium/include/sodium/utils.h index 0fd368a9..9825911f 100644 --- a/src/libsodium/include/sodium/utils.h +++ b/src/libsodium/include/sodium/utils.h @@ -19,7 +19,7 @@ extern "C" { #endif SODIUM_EXPORT -void sodium_memzero(void * const pnt, const size_t len); +void sodium_memzero(void *const pnt, const size_t len); SODIUM_EXPORT void sodium_stackzero(const size_t len); @@ -31,8 +31,8 @@ void sodium_stackzero(const size_t len); * This function is not designed for lexicographical comparisons. */ SODIUM_EXPORT -int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len) - __attribute__ ((warn_unused_result)); +int sodium_memcmp(const void *const b1_, const void *const b2_, size_t len) + __attribute__((warn_unused_result)); /* * sodium_compare() returns -1 if b1_ < b2_, 1 if b1_ > b2_ and 0 if b1_ == b2_ @@ -41,8 +41,8 @@ int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len) * However, it is slower than sodium_memcmp(). */ SODIUM_EXPORT -int sodium_compare(const unsigned char *b1_, const unsigned char *b2_, - size_t len) __attribute__ ((warn_unused_result)); +int sodium_compare(const unsigned char *b1_, const unsigned char *b2_, size_t len) + __attribute__((warn_unused_result)); SODIUM_EXPORT int sodium_is_zero(const unsigned char *n, const size_t nlen); @@ -57,16 +57,13 @@ SODIUM_EXPORT void sodium_sub(unsigned char *a, const unsigned char *b, const size_t len); SODIUM_EXPORT -char *sodium_bin2hex(char * const hex, const size_t hex_maxlen, - const unsigned char * const bin, const size_t bin_len) - __attribute__ ((nonnull(1))); +char *sodium_bin2hex(char *const hex, const size_t hex_maxlen, const unsigned char *const bin, + const size_t bin_len) __attribute__((nonnull(1))); SODIUM_EXPORT -int sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen, - const char * const hex, const size_t hex_len, - const char * const ignore, size_t * const bin_len, - const char ** const hex_end) - __attribute__ ((nonnull(1))); +int sodium_hex2bin(unsigned char *const bin, const size_t bin_maxlen, const char *const hex, + const size_t hex_len, const char *const ignore, size_t *const bin_len, + const char **const hex_end) __attribute__((nonnull(1))); #define sodium_base64_VARIANT_ORIGINAL 1 #define sodium_base64_VARIANT_ORIGINAL_NO_PADDING 3 @@ -77,33 +74,37 @@ int sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen, * Computes the required length to encode BIN_LEN bytes as a base64 string * using the given variant. The computed length includes a trailing \0. */ -#define sodium_base64_ENCODED_LEN(BIN_LEN, VARIANT) \ - (((BIN_LEN) / 3U) * 4U + \ - ((((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) | (((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) >> 1)) & 1U) * \ - (4U - (~((((VARIANT) & 2U) >> 1) - 1U) & (3U - ((BIN_LEN) - ((BIN_LEN) / 3U) * 3U)))) + 1U) +#define sodium_base64_ENCODED_LEN(BIN_LEN, VARIANT) \ + (((BIN_LEN) / 3U) * 4U + \ + ((((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) | (((BIN_LEN) - ((BIN_LEN) / 3U) * 3U) >> 1)) & 1U) * \ + (4U - (~((((VARIANT) & 2U) >> 1) - 1U) & (3U - ((BIN_LEN) - ((BIN_LEN) / 3U) * 3U)))) + \ + 1U) SODIUM_EXPORT size_t sodium_base64_encoded_len(const size_t bin_len, const int variant); SODIUM_EXPORT -char *sodium_bin2base64(char * const b64, const size_t b64_maxlen, - const unsigned char * const bin, const size_t bin_len, - const int variant) __attribute__ ((nonnull(1))); +char *sodium_bin2base64(char *const b64, const size_t b64_maxlen, const unsigned char *const bin, + const size_t bin_len, const int variant) __attribute__((nonnull(1))); SODIUM_EXPORT -int sodium_base642bin(unsigned char * const bin, const size_t bin_maxlen, - const char * const b64, const size_t b64_len, - const char * const ignore, size_t * const bin_len, - const char ** const b64_end, const int variant) - __attribute__ ((nonnull(1))); +int sodium_base642bin(unsigned char *const bin, const size_t bin_maxlen, const char *const b64, + const size_t b64_len, const char *const ignore, size_t *const bin_len, + const char **const b64_end, const int variant) __attribute__((nonnull(1))); SODIUM_EXPORT -int sodium_mlock(void * const addr, const size_t len) - __attribute__ ((nonnull)); +int sodium_ip2bin(unsigned char out[16], const char *src) __attribute__((warn_unused_result)) +__attribute__((nonnull)); SODIUM_EXPORT -int sodium_munlock(void * const addr, const size_t len) - __attribute__ ((nonnull)); +char *sodium_bin2ip(char *dst, size_t dst_len, const unsigned char in[16]) + __attribute__((nonnull)); + +SODIUM_EXPORT +int sodium_mlock(void *const addr, const size_t len) __attribute__((nonnull)); + +SODIUM_EXPORT +int sodium_munlock(void *const addr, const size_t len) __attribute__((nonnull)); /* WARNING: sodium_malloc() and sodium_allocarray() are not general-purpose * allocation functions. @@ -116,7 +117,8 @@ int sodium_munlock(void * const addr, const size_t len) * region may also kill the process if a buffer underflow is detected. * * The memory layout is: - * [unprotected region size (read only)][guard page (no access)][unprotected pages (read/write)][guard page (no access)] + * [unprotected region size (read only)][guard page (no access)][unprotected pages + * (read/write)][guard page (no access)] * * The layout of the unprotected pages is: * [optional padding][16-bytes canary][user region] @@ -139,34 +141,30 @@ int sodium_munlock(void * const addr, const size_t len) */ SODIUM_EXPORT -void *sodium_malloc(const size_t size) - __attribute__ ((malloc)); +void *sodium_malloc(const size_t size) __attribute__((malloc)); SODIUM_EXPORT -void *sodium_allocarray(size_t count, size_t size) - __attribute__ ((malloc)); +void *sodium_allocarray(size_t count, size_t size) __attribute__((malloc)); SODIUM_EXPORT void sodium_free(void *ptr); SODIUM_EXPORT -int sodium_mprotect_noaccess(void *ptr) __attribute__ ((nonnull)); +int sodium_mprotect_noaccess(void *ptr) __attribute__((nonnull)); SODIUM_EXPORT -int sodium_mprotect_readonly(void *ptr) __attribute__ ((nonnull)); +int sodium_mprotect_readonly(void *ptr) __attribute__((nonnull)); SODIUM_EXPORT -int sodium_mprotect_readwrite(void *ptr) __attribute__ ((nonnull)); +int sodium_mprotect_readwrite(void *ptr) __attribute__((nonnull)); SODIUM_EXPORT -int sodium_pad(size_t *padded_buflen_p, unsigned char *buf, - size_t unpadded_buflen, size_t blocksize, size_t max_buflen) - __attribute__ ((nonnull(2))); +int sodium_pad(size_t *padded_buflen_p, unsigned char *buf, size_t unpadded_buflen, + size_t blocksize, size_t max_buflen) __attribute__((nonnull(2))); SODIUM_EXPORT -int sodium_unpad(size_t *unpadded_buflen_p, const unsigned char *buf, - size_t padded_buflen, size_t blocksize) - __attribute__ ((nonnull(2))); +int sodium_unpad(size_t *unpadded_buflen_p, const unsigned char *buf, size_t padded_buflen, + size_t blocksize) __attribute__((nonnull(2))); /* -------- */ diff --git a/src/libsodium/sodium/codecs.c b/src/libsodium/sodium/codecs.c index 36508089..4e7967d3 100644 --- a/src/libsodium/sodium/codecs.c +++ b/src/libsodium/sodium/codecs.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -333,3 +334,280 @@ sodium_base642bin(unsigned char * const bin, const size_t bin_maxlen, } return ret; } + +static int +ip_hex_digit(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } + if (((unsigned int) ch | 32U) >= 'a' && ((unsigned int) ch | 32U) <= 'f') { + return ((unsigned int) ch | 32U) - 'a' + 10; + } + return -1; +} + +static int +parse_ipv4(const char *src, const char *end, unsigned char out[4]) +{ + const char *p = src; + int i; + + if (src == NULL || end == NULL || out == NULL || src >= end) { + return 0; + } + for (i = 0; i < 4; i++) { + unsigned int val = 0U; + int digits = 0; + + while (p < end && *p >= '0' && *p <= '9') { + val = val * 10U + (unsigned int) (*p++ - '0'); + if (++digits > 3 || val > 255U) { + return 0; + } + } + if (digits == 0) { + return 0; + } + out[i] = (unsigned char) val; + + if (i < 3) { + if (p >= end || *p++ != '.') { + return 0; + } + } + } + return p == end; +} + +static int +parse_ipv6(const char *src, const char *end, unsigned char out[16]) +{ + unsigned char tmp[16] = { 0 }; + unsigned char *tp = tmp; + unsigned char *endp = tmp + 16; + unsigned char *colonp = NULL; + const char *p = src; + const char *curtok = src; + unsigned int val = 0U; + int saw_xdigit = 0; + int xdigits = 0; + int ch; + int hv; + + if (src == NULL || end == NULL || out == NULL || src >= end) { + return 0; + } + if (*p == ':') { + if (++p >= end || *p != ':') { + return 0; + } + colonp = tp; + curtok = ++p; + } + while (p < end) { + ch = *p; + + if (ch == ':') { + if (!saw_xdigit) { + if (colonp != NULL) { + return 0; + } + colonp = tp; + curtok = ++p; + continue; + } + if (tp + 2 > endp) { + return 0; + } + *tp++ = (unsigned char) (val >> 8); + *tp++ = (unsigned char) (val & 0xffU); + val = 0U; + saw_xdigit = 0; + xdigits = 0; + curtok = ++p; + if (p >= end) { + return 0; + } + continue; + } + if (ch == '.') { + if (tp + 4 > endp || parse_ipv4(curtok, end, tp) == 0) { + return 0; + } + tp += 4; + saw_xdigit = 0; + break; + } + hv = ip_hex_digit(ch); + if (hv < 0 || xdigits >= 4) { + return 0; + } + val = (val << 4) | (unsigned int) hv; + saw_xdigit = 1; + xdigits++; + p++; + } + if (saw_xdigit) { + if (tp + 2 > endp) { + return 0; + } + *tp++ = (unsigned char) (val >> 8); + *tp++ = (unsigned char) (val & 0xffU); + } + if (colonp != NULL) { + size_t n = (size_t) (tp - colonp); + + if (tp == endp) { + return 0; + } + memmove(endp - n, colonp, n); + memset(colonp, 0, (size_t) (endp - n - colonp)); + tp = endp; + } + if (tp != endp) { + return 0; + } + memcpy(out, tmp, 16U); + + return 1; +} + +int +sodium_ip2bin(unsigned char out[16], const char *src) +{ + const char *end; + const char *z; + unsigned char v4[4]; + + if (src == NULL || out == NULL) { + return -1; + } + + for (end = src; *end != 0 && *end != '%'; end++) { + /* empty */ + } + if (*end == '%') { + for (z = end + 1; *z != 0; z++) { + if (isspace((unsigned char) *z)) { + return -1; + } + } + if (z == end + 1) { + return -1; + } + } + if (memchr(src, ':', (size_t) (end - src)) != NULL) { + return parse_ipv6(src, end, out) != 0 ? 0 : -1; + } + if (*end == '%') { + return -1; + } + if (parse_ipv4(src, end, v4) == 0) { + return -1; + } + memset(out, 0, 10U); + out[10] = 0xffU; + out[11] = 0xffU; + memcpy(out + 12, v4, 4U); + + return 0; +} + +static const unsigned char ipv4_mapped_prefix[12] = { 0U, 0U, 0U, 0U, 0U, 0U, + 0U, 0U, 0U, 0U, 0xffU, 0xffU }; + +static void +ip_write_num(char **p, unsigned int val, int base) +{ + char buf[4]; + int n = 0; + + do { + unsigned int d = val % (unsigned int) base; + + buf[n++] = (char) (d < 10U ? '0' + d : 'a' + d - 10U); + val /= (unsigned int) base; + } while (val != 0U); + + while (n-- > 0) { + *(*p)++ = buf[n]; + } +} + +char * +sodium_bin2ip(char *dst, size_t dst_len, const unsigned char in[16]) +{ + char buf[46]; + char *p = buf; + int i; + int best_start = -1; + int best_len = 0; + int cur_start = -1; + int cur_len = 0; + size_t len; + + if (dst == NULL || in == NULL || dst_len == 0U) { + return NULL; + } + if (memcmp(in, ipv4_mapped_prefix, 12U) == 0) { + for (i = 0; i < 4; i++) { + if (i != 0) { + *p++ = '.'; + } + ip_write_num(&p, (unsigned int) in[12 + i], 10); + } + len = (size_t) (p - buf); + if (len >= dst_len) { + return NULL; + } + memcpy(dst, buf, len + 1U); + dst[len] = 0; + + return dst; + } + for (i = 0; i < 8; i++) { + unsigned int word = ((unsigned int) in[i * 2] << 8) | (unsigned int) in[i * 2 + 1]; + + if (word == 0U) { + if (cur_start < 0) { + cur_start = i; + } + cur_len++; + } else { + if (cur_len > best_len) { + best_start = cur_start; + best_len = cur_len; + } + cur_start = -1; + cur_len = 0; + } + } + if (cur_len > best_len) { + best_start = cur_start; + best_len = cur_len; + } + if (best_len < 2) { + best_start = -1; + } + for (i = 0; i < 8; i++) { + if (i == best_start) { + *p++ = ':'; + *p++ = ':'; + i += best_len - 1; + continue; + } + if (i != 0 && (best_start < 0 || i != best_start + best_len)) { + *p++ = ':'; + } + ip_write_num(&p, ((unsigned int) in[i * 2] << 8) | (unsigned int) in[i * 2 + 1], 16); + } + len = (size_t) (p - buf); + if (len >= dst_len) { + return NULL; + } + memcpy(dst, buf, len); + dst[len] = 0; + + return dst; +} diff --git a/test/default/codecs.c b/test/default/codecs.c index 3c98d739..e36ed685 100644 --- a/test/default/codecs.c +++ b/test/default/codecs.c @@ -247,5 +247,184 @@ main(void) sodium_free(bin); sodium_free(b64_); } + + { + unsigned char ip_bytes[16]; + unsigned char ip_expected[16]; + char ip_str[46]; + + assert(sodium_ip2bin(ip_bytes, "192.168.1.1") == 0); + memset(ip_expected, 0, 10); + ip_expected[10] = 0xff; + ip_expected[11] = 0xff; + ip_expected[12] = 192; + ip_expected[13] = 168; + ip_expected[14] = 1; + ip_expected[15] = 1; + assert(memcmp(ip_bytes, ip_expected, 16) == 0); + printf("ip2bytes(192.168.1.1): OK\n"); + + assert(sodium_ip2bin(ip_bytes, "0.0.0.0") == 0); + assert(sodium_ip2bin(ip_bytes, "255.255.255.255") == 0); + assert(sodium_ip2bin(ip_bytes, "127.0.0.1") == 0); + printf("ip2bytes IPv4 basic: OK\n"); + + assert(sodium_ip2bin(ip_bytes, "256.1.1.1") == -1); + assert(sodium_ip2bin(ip_bytes, "1.999.1.1") == -1); + assert(sodium_ip2bin(ip_bytes, "192.168.1") == -1); + assert(sodium_ip2bin(ip_bytes, "192.168.1.1.1") == -1); + assert(sodium_ip2bin(ip_bytes, "") == -1); + assert(sodium_ip2bin(ip_bytes, ".1.2.3") == -1); + assert(sodium_ip2bin(ip_bytes, "1.2.3.") == -1); + assert(sodium_ip2bin(ip_bytes, "1..2.3") == -1); + assert(sodium_ip2bin(ip_bytes, "1.2.a.3") == -1); + printf("ip2bytes IPv4 invalid: OK\n"); + + assert(sodium_ip2bin(ip_bytes, "2001:db8:85a3:0:0:8a2e:370:7334") == 0); + ip_expected[0] = 0x20; ip_expected[1] = 0x01; + ip_expected[2] = 0x0d; ip_expected[3] = 0xb8; + ip_expected[4] = 0x85; ip_expected[5] = 0xa3; + ip_expected[6] = 0x00; ip_expected[7] = 0x00; + ip_expected[8] = 0x00; ip_expected[9] = 0x00; + ip_expected[10] = 0x8a; ip_expected[11] = 0x2e; + ip_expected[12] = 0x03; ip_expected[13] = 0x70; + ip_expected[14] = 0x73; ip_expected[15] = 0x34; + assert(memcmp(ip_bytes, ip_expected, 16) == 0); + printf("ip2bytes(2001:db8:85a3:0:0:8a2e:370:7334): OK\n"); + + assert(sodium_ip2bin(ip_bytes, "::1") == 0); + memset(ip_expected, 0, 16); + ip_expected[15] = 1; + assert(memcmp(ip_bytes, ip_expected, 16) == 0); + + assert(sodium_ip2bin(ip_bytes, "::") == 0); + memset(ip_expected, 0, 16); + assert(memcmp(ip_bytes, ip_expected, 16) == 0); + + assert(sodium_ip2bin(ip_bytes, "2001:db8::1") == 0); + assert(sodium_ip2bin(ip_bytes, "fe80::1") == 0); + printf("ip2bytes IPv6 compressed: OK\n"); + + assert(sodium_ip2bin(ip_bytes, "fe80::1%eth0") == 0); + assert(sodium_ip2bin(ip_bytes, "fe80::1%15") == 0); + printf("ip2bytes IPv6 zone: OK\n"); + + assert(sodium_ip2bin(ip_bytes, "2001:::1") == -1); + assert(sodium_ip2bin(ip_bytes, "2001::1::1") == -1); + assert(sodium_ip2bin(ip_bytes, "1:2:3:4:5:6:7:8:9") == -1); + assert(sodium_ip2bin(ip_bytes, "12345:1:1:1:1:1:1:1") == -1); + assert(sodium_ip2bin(ip_bytes, "2001:db8:g:1:1:1:1:1") == -1); + assert(sodium_ip2bin(ip_bytes, ":2001:db8::1") == -1); + assert(sodium_ip2bin(ip_bytes, "2001:db8:1:") == -1); + assert(sodium_ip2bin(ip_bytes, "fe80::1%") == -1); + printf("ip2bytes IPv6 invalid: OK\n"); + + assert(sodium_ip2bin(ip_bytes, "::ffff:192.168.1.1") == 0); + memset(ip_expected, 0, 10); + ip_expected[10] = 0xff; + ip_expected[11] = 0xff; + ip_expected[12] = 192; + ip_expected[13] = 168; + ip_expected[14] = 1; + ip_expected[15] = 1; + assert(memcmp(ip_bytes, ip_expected, 16) == 0); + printf("ip2bytes IPv4-mapped: OK\n"); + + printf("ip NULL handling: OK\n"); + + memset(ip_bytes, 0, 10); + ip_bytes[10] = 0xff; + ip_bytes[11] = 0xff; + ip_bytes[12] = 192; + ip_bytes[13] = 168; + ip_bytes[14] = 1; + ip_bytes[15] = 1; + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "192.168.1.1") == 0); + + ip_bytes[12] = 0; + ip_bytes[13] = 0; + ip_bytes[14] = 0; + ip_bytes[15] = 0; + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "0.0.0.0") == 0); + + ip_bytes[12] = 255; + ip_bytes[13] = 255; + ip_bytes[14] = 255; + ip_bytes[15] = 255; + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "255.255.255.255") == 0); + printf("bytes2ip IPv4: OK\n"); + + memset(ip_bytes, 0, 16); + ip_bytes[15] = 1; + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "::1") == 0); + + memset(ip_bytes, 0, 16); + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "::") == 0); + + memset(ip_bytes, 0xff, 16); + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") == 0); + printf("bytes2ip IPv6: OK\n"); + + memset(ip_bytes, 0, 10); + ip_bytes[10] = 0xff; + ip_bytes[11] = 0xff; + ip_bytes[12] = 255; + ip_bytes[13] = 255; + ip_bytes[14] = 255; + ip_bytes[15] = 255; + assert(sodium_bin2ip(ip_str, 16, ip_bytes) != NULL); + assert(sodium_bin2ip(ip_str, 15, ip_bytes) == NULL); + + memset(ip_bytes, 0xff, 16); + assert(sodium_bin2ip(ip_str, 40, ip_bytes) != NULL); + assert(sodium_bin2ip(ip_str, 39, ip_bytes) == NULL); + + memset(ip_bytes, 0, 16); + assert(sodium_bin2ip(ip_str, 3, ip_bytes) != NULL); + assert(sodium_bin2ip(ip_str, 2, ip_bytes) == NULL); + printf("bytes2ip buffer size: OK\n"); + + assert(sodium_ip2bin(ip_bytes, "10.20.30.40") == 0); + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "10.20.30.40") == 0); + + assert(sodium_ip2bin(ip_bytes, "::1") == 0); + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "::1") == 0); + + assert(sodium_ip2bin(ip_bytes, "2001:db8::1") == 0); + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "2001:db8::1") == 0); + + assert(sodium_ip2bin(ip_bytes, "2001:db8:85a3:1234:5678:8a2e:370:7334") == 0); + assert(sodium_bin2ip(ip_str, sizeof(ip_str), ip_bytes) != NULL); + assert(strcmp(ip_str, "2001:db8:85a3:1234:5678:8a2e:370:7334") == 0); + printf("ip round-trip: OK\n"); + + { + unsigned char lower[16], upper[16], mixed[16]; + assert(sodium_ip2bin(lower, "abcd:ef01:2345:6789:abcd:ef01:2345:6789") == 0); + assert(sodium_ip2bin(upper, "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789") == 0); + assert(sodium_ip2bin(mixed, "AbCd:eF01:2345:6789:aBcD:Ef01:2345:6789") == 0); + assert(memcmp(lower, upper, 16) == 0); + assert(memcmp(lower, mixed, 16) == 0); + } + printf("ip case insensitive: OK\n"); + + { + unsigned char direct[16], mapped[16]; + assert(sodium_ip2bin(direct, "192.168.1.1") == 0); + assert(sodium_ip2bin(mapped, "::ffff:192.168.1.1") == 0); + assert(memcmp(direct, mapped, 16) == 0); + } + printf("ip IPv4-mapped equivalence: OK\n"); + } + return 0; } diff --git a/test/default/codecs.exp b/test/default/codecs.exp index 171834ed..e5a504ae 100644 --- a/test/default/codecs.exp +++ b/test/default/codecs.exp @@ -28,3 +28,18 @@ ZXkgaW50by Bzb3VuZA==] [This is a journ] [ ZXkgaW50by Bzb3VuZA==] +ip2bytes(192.168.1.1): OK +ip2bytes IPv4 basic: OK +ip2bytes IPv4 invalid: OK +ip2bytes(2001:db8:85a3:0:0:8a2e:370:7334): OK +ip2bytes IPv6 compressed: OK +ip2bytes IPv6 zone: OK +ip2bytes IPv6 invalid: OK +ip2bytes IPv4-mapped: OK +ip NULL handling: OK +bytes2ip IPv4: OK +bytes2ip IPv6: OK +bytes2ip buffer size: OK +ip round-trip: OK +ip case insensitive: OK +ip IPv4-mapped equivalence: OK