| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// Unittests for inet_ntop. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "hdr/errno_macros.h" |
| #include "hdr/sys_socket_macros.h" |
| #include "hdr/types/struct_in6_addr.h" |
| #include "hdr/types/struct_in_addr.h" |
| #include "src/__support/endian_internal.h" |
| #include "src/arpa/inet/inet_ntop.h" |
| #include "test/UnitTest/ErrnoCheckingTest.h" |
| #include "test/UnitTest/Test.h" |
| |
| using LlvmLibcInetNtopTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; |
| |
| TEST_F(LlvmLibcInetNtopTest, InvalidFamily) { |
| char buf[64]; |
| struct in_addr addr = {0}; |
| ASSERT_EQ(static_cast<const char *>(nullptr), |
| LIBC_NAMESPACE::inet_ntop(AF_INET + AF_INET6 + 1, &addr, buf, |
| sizeof(buf))); |
| ASSERT_ERRNO_EQ(EAFNOSUPPORT); |
| } |
| |
| static void *ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { |
| static struct in_addr addr; |
| addr.s_addr = LIBC_NAMESPACE::Endian::to_big_endian( |
| static_cast<uint32_t>(a) << 24 | static_cast<uint32_t>(b) << 16 | |
| static_cast<uint32_t>(c) << 8 | static_cast<uint32_t>(d)); |
| return &addr; |
| } |
| |
| static void *ipv6(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e, |
| uint16_t f, uint16_t g, uint16_t h) { |
| static struct in6_addr addr; |
| addr.s6_addr16[0] = LIBC_NAMESPACE::Endian::to_big_endian(a); |
| addr.s6_addr16[1] = LIBC_NAMESPACE::Endian::to_big_endian(b); |
| addr.s6_addr16[2] = LIBC_NAMESPACE::Endian::to_big_endian(c); |
| addr.s6_addr16[3] = LIBC_NAMESPACE::Endian::to_big_endian(d); |
| addr.s6_addr16[4] = LIBC_NAMESPACE::Endian::to_big_endian(e); |
| addr.s6_addr16[5] = LIBC_NAMESPACE::Endian::to_big_endian(f); |
| addr.s6_addr16[6] = LIBC_NAMESPACE::Endian::to_big_endian(g); |
| addr.s6_addr16[7] = LIBC_NAMESPACE::Endian::to_big_endian(h); |
| return &addr; |
| } |
| |
| TEST_F(LlvmLibcInetNtopTest, IPv4Tests) { |
| char buf[16]; |
| |
| EXPECT_STREQ("127.0.0.1", LIBC_NAMESPACE::inet_ntop( |
| AF_INET, ipv4(127, 0, 0, 1), buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Test buffer too small (needs 10 bytes including null terminator) |
| EXPECT_EQ(static_cast<const char *>(nullptr), |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(127, 0, 0, 1), buf, 9)); |
| ASSERT_ERRNO_EQ(ENOSPC); |
| |
| EXPECT_STREQ("127.0.0.1", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(127, 0, 0, 1), buf, 10)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("255.255.255.255", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(255, 255, 255, 255), buf, |
| sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Test buffer too small (needs 16 bytes) |
| EXPECT_EQ( |
| static_cast<const char *>(nullptr), |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(255, 255, 255, 255), buf, 15)); |
| ASSERT_ERRNO_EQ(ENOSPC); |
| |
| // Boundary conditions for the number of digits. |
| EXPECT_STREQ("0.0.0.0", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 0), buf, 10)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("0.0.0.1", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 1), buf, 10)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("0.0.0.9", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 9), buf, 10)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("0.0.0.10", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 10), buf, 11)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("0.0.0.11", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 11), buf, 11)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("0.0.0.99", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 99), buf, 11)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("0.0.0.100", |
| LIBC_NAMESPACE::inet_ntop(AF_INET, ipv4(0, 0, 0, 100), buf, 12)); |
| ASSERT_ERRNO_SUCCESS(); |
| } |
| |
| TEST_F(LlvmLibcInetNtopTest, IPv6Tests) { |
| char buf[64]; |
| |
| // No compression |
| EXPECT_STREQ("1:2:3:4:5:6:7:8", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(1, 2, 3, 4, 5, 6, 7, 8), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Compression, fully compressed. |
| EXPECT_STREQ(static_cast<const char *>(nullptr), |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 0), |
| buf, 2)); |
| ASSERT_ERRNO_EQ(ENOSPC); |
| |
| EXPECT_STREQ("::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 0), buf, 3)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Leading block of zeroes. |
| EXPECT_STREQ("::1", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 1), buf, 4)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_EQ(static_cast<const char *>(nullptr), |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 1), |
| buf, 3)); |
| ASSERT_ERRNO_EQ(ENOSPC); |
| |
| EXPECT_STREQ("::1:2:3", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 1, 2, 3), buf, 8)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Trailing block of zeroes. |
| EXPECT_STREQ("1::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(1, 0, 0, 0, 0, 0, 0, 0), buf, 4)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("1:2::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(1, 2, 0, 0, 0, 0, 0, 0), buf, 6)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Middle of string. |
| EXPECT_STREQ("2001:db8::1", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, |
| ipv6(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("2001:db8:0:1::1", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, |
| ipv6(0x2001, 0x0db8, 0, 1, 0, 0, 0, 1), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Longer block wins. |
| EXPECT_STREQ("2001:0:0:1::1", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0x2001, 0, 0, 1, 0, 0, 0, 1), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("0:0:1:1::", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 1, 1, 0, 0, 0, 0), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // In case of ties, the first block wins. |
| EXPECT_STREQ("::1:0:0:1:0:0", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 0, 1, 0, 0, 1, 0, 0), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // A single zero is not compressed, no matter it's position. |
| EXPECT_STREQ("0:1:1:1:1:1:1:1", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(0, 1, 1, 1, 1, 1, 1, 1), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("1:0:1:1:1:1:1:1", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(1, 0, 1, 1, 1, 1, 1, 1), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("1:1:1:1:1:1:1:0", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, ipv6(1, 1, 1, 1, 1, 1, 1, 0), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // V4 mapped addresses. |
| EXPECT_STREQ("::ffff:192.168.0.1", |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0xffff, 0xc0a8, 1), buf, 19)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("::192.168.0.1", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0xc0a8, 1), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // If only the last component is set, we don't v4-map. |
| EXPECT_STREQ("::dead", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0, 0xdead), buf, |
| sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // But we do for the penultimate. |
| EXPECT_STREQ("::10.13.0.0", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0, 0x0a0d, 0), |
| buf, sizeof(buf))); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Edge cases for numbers of digits. |
| EXPECT_STREQ("0:1::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 1, 0, 0, 0, 0, 0, 0), buf, 6)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("1:1::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(1, 1, 0, 0, 0, 0, 0, 0), buf, 6)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("2:1::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(2, 1, 0, 0, 0, 0, 0, 0), buf, 6)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("4:1::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(4, 1, 0, 0, 0, 0, 0, 0), buf, 6)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("8:1::", LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(8, 1, 0, 0, 0, 0, 0, 0), buf, 6)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("10:1::", |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0x10, 1, 0, 0, 0, 0, 0, 0), buf, 7)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("ff:1::", |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0xff, 1, 0, 0, 0, 0, 0, 0), buf, 7)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("100:1::", |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0x100, 1, 0, 0, 0, 0, 0, 0), buf, 8)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("fff:1::", |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0xfff, 1, 0, 0, 0, 0, 0, 0), buf, 8)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_STREQ("1000:1::", |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0x1000, 1, 0, 0, 0, 0, 0, 0), buf, 9)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| // Maximum length address. |
| EXPECT_STREQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, |
| ipv6(0xffff, 0xffff, 0xffff, 0xffff, |
| 0xffff, 0xffff, 0xffff, 0xffff), |
| buf, 40)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_EQ(static_cast<const char *>(nullptr), |
| LIBC_NAMESPACE::inet_ntop(AF_INET6, |
| ipv6(0xffff, 0xffff, 0xffff, 0xffff, |
| 0xffff, 0xffff, 0xffff, 0xffff), |
| buf, 39)); |
| ASSERT_ERRNO_EQ(ENOSPC); |
| |
| // IPv4-mapped max length |
| EXPECT_STREQ( |
| "::ffff:255.255.255.255", |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff), buf, 23)); |
| ASSERT_ERRNO_SUCCESS(); |
| |
| EXPECT_EQ( |
| static_cast<const char *>(nullptr), |
| LIBC_NAMESPACE::inet_ntop( |
| AF_INET6, ipv6(0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff), buf, 22)); |
| ASSERT_ERRNO_EQ(ENOSPC); |
| } |