diff options
author | sbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-28 02:32:54 +0000 |
---|---|---|
committer | sbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-28 02:32:54 +0000 |
commit | 0b4d50f2d28c98246e81ee5c816699a884034092 (patch) | |
tree | 2241cc285142f13a93e9fd9887159c5e66700e43 /native_client_sdk | |
parent | 8853f012ca0047aa009afb94eb9a02875dc3c15d (diff) | |
download | chromium_src-0b4d50f2d28c98246e81ee5c816699a884034092.zip chromium_src-0b4d50f2d28c98246e81ee5c816699a884034092.tar.gz chromium_src-0b4d50f2d28c98246e81ee5c816699a884034092.tar.bz2 |
[NaCl SDK] nacl_io: Fix inet_ntop to be consistent with glibc.
Update inet_ntop to output ipv4 address for ::A.B.C.D as
well as ::ffff:A:B:C:D so that its consistent the glibc's
implementation.
Also, add two missing socket syscalls: inet_addr and
inet_aton.
Also, add test for this case and cleanup test code these
socket utility function.
Alos, rename some, .cc files to .c in nacl_io syscalls.
R=binji@chromium.org
Review URL: https://codereview.chromium.org/139283003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247394 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc | 18 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/library.dsc | 6 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.c | 31 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc | 54 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/syscalls/inet_addr.c | 20 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c | 54 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.c (renamed from native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc) | 12 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc | 58 | ||||
-rw-r--r-- | native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c | 4 | ||||
-rw-r--r-- | native_client_sdk/src/tests/nacl_io_test/socket_test.cc | 239 |
10 files changed, 336 insertions, 160 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc index be052c0..edf1eb8 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc +++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc @@ -377,77 +377,95 @@ sighandler_t ki_sigset(int signum, sighandler_t handler) { #ifdef PROVIDES_SOCKET_API // Socket Functions int ki_accept(int fd, struct sockaddr* addr, socklen_t* len) { + ON_NOSYS_RETURN(-1); return s_kp->accept(fd, addr, len); } int ki_bind(int fd, const struct sockaddr* addr, socklen_t len) { + ON_NOSYS_RETURN(-1); return s_kp->bind(fd, addr, len); } int ki_connect(int fd, const struct sockaddr* addr, socklen_t len) { + ON_NOSYS_RETURN(-1); return s_kp->connect(fd, addr, len); } struct hostent* ki_gethostbyname(const char* name) { + ON_NOSYS_RETURN(NULL); return s_kp->gethostbyname(name); } int ki_getpeername(int fd, struct sockaddr* addr, socklen_t* len) { + ON_NOSYS_RETURN(-1); return s_kp->getpeername(fd, addr, len); } int ki_getsockname(int fd, struct sockaddr* addr, socklen_t* len) { + ON_NOSYS_RETURN(-1); return s_kp->getsockname(fd, addr, len); } int ki_getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) { + ON_NOSYS_RETURN(-1); return s_kp->getsockopt(fd, lvl, optname, optval, len); } int ki_listen(int fd, int backlog) { + ON_NOSYS_RETURN(-1); return s_kp->listen(fd, backlog); } ssize_t ki_recv(int fd, void* buf, size_t len, int flags) { + ON_NOSYS_RETURN(-1); return s_kp->recv(fd, buf, len, flags); } ssize_t ki_recvfrom(int fd, void* buf, size_t len, int flags, struct sockaddr* addr, socklen_t* addrlen) { + ON_NOSYS_RETURN(-1); return s_kp->recvfrom(fd, buf, len, flags, addr, addrlen); } ssize_t ki_recvmsg(int fd, struct msghdr* msg, int flags) { + ON_NOSYS_RETURN(-1); return s_kp->recvmsg(fd, msg, flags); } ssize_t ki_send(int fd, const void* buf, size_t len, int flags) { + ON_NOSYS_RETURN(-1); return s_kp->send(fd, buf, len, flags); } ssize_t ki_sendto(int fd, const void* buf, size_t len, int flags, const struct sockaddr* addr, socklen_t addrlen) { + ON_NOSYS_RETURN(-1); return s_kp->sendto(fd, buf, len, flags, addr, addrlen); } ssize_t ki_sendmsg(int fd, const struct msghdr* msg, int flags) { + ON_NOSYS_RETURN(-1); return s_kp->sendmsg(fd, msg, flags); } int ki_setsockopt(int fd, int lvl, int optname, const void* optval, socklen_t len) { + ON_NOSYS_RETURN(-1); return s_kp->setsockopt(fd, lvl, optname, optval, len); } int ki_shutdown(int fd, int how) { + ON_NOSYS_RETURN(-1); return s_kp->shutdown(fd, how); } int ki_socket(int domain, int type, int protocol) { + ON_NOSYS_RETURN(-1); return s_kp->socket(domain, type, protocol); } int ki_socketpair(int domain, int type, int protocol, int* sv) { + ON_NOSYS_RETURN(-1); return s_kp->socketpair(domain, type, protocol, sv); } #endif // PROVIDES_SOCKET_API diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc index e76ecd8..0b74074 100644 --- a/native_client_sdk/src/libraries/nacl_io/library.dsc +++ b/native_client_sdk/src/libraries/nacl_io/library.dsc @@ -86,10 +86,12 @@ "syscalls/getsockopt.c", "syscalls/getwd.c", "syscalls/herror.c", - "syscalls/hstrerror.cc", + "syscalls/hstrerror.c", "syscalls/htonl.c", "syscalls/htons.c", - "syscalls/inet_ntoa.cc", + "syscalls/inet_addr.c", + "syscalls/inet_aton.c", + "syscalls/inet_ntoa.c", "syscalls/inet_ntop.cc", "syscalls/inet_pton.c", "syscalls/ioctl.c", diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.c b/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.c new file mode 100644 index 0000000..d250f3f --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.c @@ -0,0 +1,31 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "nacl_io/ossocket.h" + +#ifdef PROVIDES_SOCKET_API + +#include <stdio.h> + +const char* hstrerror(int err) { + switch (err) { + case HOST_NOT_FOUND: + return "The specified host is unknown."; + case NO_ADDRESS: + return "The requested name is valid but does not have an IP address."; + case NO_RECOVERY: + return "A nonrecoverable name server error occurred."; + case TRY_AGAIN: + return "A temporary error occurred on an authoritative name server. " + "Try again later."; + case NETDB_INTERNAL: + return "Internal error in gethostbyname."; + } + + static char rtn[128]; + snprintf(rtn, sizeof(rtn), "Unknown error in gethostbyname: %d.", err); + return rtn; +} + +#endif // PROVIDES_SOCKET_API diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc deleted file mode 100644 index f1354d9..0000000 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "nacl_io/ossocket.h" - -#ifdef PROVIDES_SOCKET_API - -#include <sstream> -#include <string> -#include "sdk_util/macros.h" - -EXTERN_C_BEGIN - -const char* hstrerror(int err) { - // These error message texts are taken straight from the man page - const char* host_not_found_msg = - "The specified host is unknown."; - const char* no_address_msg = - "The requested name is valid but does not have an IP address."; - const char* no_recovery_msg = - "A nonrecoverable name server error occurred."; - const char* try_again_msg = - "A temporary error occurred on an authoritative name server. " - "Try again later."; - const char* internal_msg = - "Internal error in gethostbyname."; - const char* unknown_msg_base = - "Unknown error in gethostbyname: "; - - switch (err) { - case HOST_NOT_FOUND: - return host_not_found_msg; - case NO_ADDRESS: - return no_address_msg; - case NO_RECOVERY: - return no_recovery_msg; - case TRY_AGAIN: - return try_again_msg; - case NETDB_INTERNAL: - return internal_msg; - default: - std::stringstream msg; - msg << unknown_msg_base << err << "."; - - static std::string unknown_msg; - unknown_msg.assign(msg.str()); - return unknown_msg.c_str(); - } -} - -EXTERN_C_END - -#endif // PROVIDES_SOCKET_API diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_addr.c b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_addr.c new file mode 100644 index 0000000..98dbe8f --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_addr.c @@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "nacl_io/ossocket.h" + +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) + +#include <string.h> + +in_addr_t inet_addr(const char* addr) { + struct in_addr rtn = { 0 }; + int ret = inet_aton(addr, &rtn); + // inet_ntoa returns zero if addr is not valid + if (ret == 0) + return INADDR_NONE; + return rtn.s_addr; +} + +#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c new file mode 100644 index 0000000..964587a --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c @@ -0,0 +1,54 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "nacl_io/ossocket.h" + +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) + +#include <string.h> +#include <limits.h> + +int inet_aton(const char *cp, struct in_addr *inp) { + unsigned int p1 = 0, p2 = 0, p3 = 0, p4 = 0; + int consumed = 0; + int matched = sscanf(cp, "%u.%u.%u.%u%n", &p1, &p2, &p3, &p4, + &consumed); + + if (strlen(cp) == consumed && matched == 4) { + if ((p1 | p2 | p3 | p4) <= UCHAR_MAX) { + in_addr_t host_order_addr = (p1 << 24) | (p2 << 16) | (p3 << 8) | p4; + inp->s_addr = htonl(host_order_addr); + return 1; + } + } + + matched = sscanf(cp, "%u.%u.%u%n", &p1, &p2, &p3, &consumed); + if (strlen(cp) == consumed && matched == 3) { + if ((p1 | p2) <= UCHAR_MAX && p3 <= USHRT_MAX) { + in_addr_t host_order_addr = (p1 << 24) | (p2 << 16) | p3; + inp->s_addr = htonl(host_order_addr); + return 1; + } + } + + matched = sscanf(cp, "%u.%u%n", &p1, &p2, &consumed); + if (strlen(cp) == consumed && matched == 2) { + if (p1 <= UCHAR_MAX && p1 <= 1 << 24) { + in_addr_t host_order_addr = (p1 << 24) | p2; + inp->s_addr = htonl(host_order_addr); + return 1; + } + } + + matched = sscanf(cp, "%u%n", &p1, &consumed); + if (strlen(cp) == consumed && matched == 1) { + inp->s_addr = htonl(p1); + return 1; + } + + // Failure + return 0; +} + +#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.c index c6cf610..380cbc8 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.c @@ -3,18 +3,14 @@ // found in the LICENSE file. #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) -#include <string.h> -#include "sdk_util/macros.h" +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) static uint8_t GetByte(const void* addr, int byte) { - const char* buf = static_cast<const char*>(addr); - return static_cast<uint8_t>(buf[byte]); + const char* buf = (const char*)addr; + return (uint8_t)buf[byte]; } -EXTERN_C_BEGIN - char* inet_ntoa(struct in_addr in) { static char addr[INET_ADDRSTRLEN]; snprintf(addr, INET_ADDRSTRLEN, "%u.%u.%u.%u", @@ -23,6 +19,4 @@ char* inet_ntoa(struct in_addr in) { return addr; } -EXTERN_C_END - #endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc index ceabae5..e9bde2b 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc @@ -14,7 +14,6 @@ #include "sdk_util/macros.h" - EXTERN_C_BEGIN const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { @@ -35,16 +34,58 @@ const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { errno = ENOSPC; return NULL; } - const uint8_t* tuples = static_cast<const uint8_t*>(src); - std::stringstream output; + + // Convert to an array of 8 host order shorts + const uint16_t* tuples = static_cast<const uint16_t*>(src); + uint16_t host_tuples[8]; + int zero_run_start = -1; + int zero_run_end = -1; for (int i = 0; i < 8; i++) { - uint16_t tuple = (tuples[2*i] << 8) + tuples[2*i+1]; - output << std::hex << tuple; - if (i < 7) { - output << ":"; + host_tuples[i] = ntohs(tuples[i]); + if (host_tuples[i] == 0) { + if (zero_run_start == -1) + zero_run_start = i; + } else if (zero_run_start != -1 && zero_run_end == -1) { + zero_run_end = i; + } + } + + if (zero_run_start != -1) { + if (zero_run_end == -1) + zero_run_end = 8; + if (zero_run_end - zero_run_start < 2) { + zero_run_start = -1; + zero_run_end = -1; } } - memcpy(dst, output.str().c_str(), output.str().size() + 1); + + // Mimick glibc's behaviour here and allow ipv4 address to be specified + // as either ::A.B.C.D or ::ffff:A.B.C.D. + if (zero_run_start == 0 && + (zero_run_end == 6 || + (zero_run_end == 5 && host_tuples[zero_run_end] == 0xffff))) { + + if (zero_run_end == 5) { + strcpy(dst, "::ffff:"); + } else { + strcpy(dst, "::"); + } + inet_ntop(AF_INET, host_tuples+6, dst+strlen(dst), INET_ADDRSTRLEN); + } else { + std::stringstream output; + for (int i = 0; i < 8; i++) { + if (i == zero_run_start) { + output << "::"; + continue; + } + if (i > zero_run_start && i < zero_run_end) + continue; + output << std::hex << host_tuples[i]; + if (i < 7 && i + 1 != zero_run_start) + output << ":"; + } + memcpy(dst, output.str().c_str(), output.str().size() + 1); + } return dst; } @@ -55,4 +96,3 @@ const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { EXTERN_C_END #endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) - diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c index b1a2d7a..91d3c6c 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c @@ -13,8 +13,8 @@ #include "sdk_util/macros.h" enum { -kIpv4AddressSize = 4, -kIpv6AddressSize = 16, + kIpv4AddressSize = sizeof(in_addr_t), + kIpv6AddressSize = sizeof(struct in6_addr), }; /* Helper function for inet_pton() for IPv4 addresses. */ diff --git a/native_client_sdk/src/tests/nacl_io_test/socket_test.cc b/native_client_sdk/src/tests/nacl_io_test/socket_test.cc index fb13de9..70a02e0 100644 --- a/native_client_sdk/src/tests/nacl_io_test/socket_test.cc +++ b/native_client_sdk/src/tests/nacl_io_test/socket_test.cc @@ -269,6 +269,8 @@ TEST(SocketUtilityFunctions, Hstrerror) { "Unknown error in gethostbyname: 2718."); } +#endif // !defined(__GLIBC__) + TEST(SocketUtilityFunctions, Htonl) { uint32_t host_long = 0x44332211; uint32_t network_long = htonl(host_long); @@ -289,151 +291,220 @@ TEST(SocketUtilityFunctions, Htons) { EXPECT_EQ(network_bytes[1], 0x11); } -static struct in_addr generate_ipv4_addr(int tuple1, int tuple2, - int tuple3, int tuple4) { +static struct in_addr generate_ipv4_addr(uint8_t* tuple) { unsigned char addr[4]; - addr[0] = static_cast<unsigned char>(tuple1); - addr[1] = static_cast<unsigned char>(tuple2); - addr[2] = static_cast<unsigned char>(tuple3); - addr[3] = static_cast<unsigned char>(tuple4); + addr[0] = static_cast<unsigned char>(tuple[0]); + addr[1] = static_cast<unsigned char>(tuple[1]); + addr[2] = static_cast<unsigned char>(tuple[2]); + addr[3] = static_cast<unsigned char>(tuple[3]); struct in_addr real_addr; memcpy(&real_addr, addr, 4); return real_addr; } -static struct in6_addr generate_ipv6_addr(int* tuples) { +static struct in6_addr generate_ipv6_addr(uint16_t* tuple) { unsigned char addr[16]; for (int i = 0; i < 8; i++) { - addr[2*i] = (tuples[i] >> 8) & 0xFF; - addr[2*i+1] = tuples[i] & 0xFF; + addr[2*i] = (tuple[i] >> 8) & 0xFF; + addr[2*i+1] = tuple[i] & 0xFF; } struct in6_addr real_addr; memcpy(&real_addr, addr, 16); return real_addr; } -TEST(SocketUtilityFunctions, Inet_ntoa) { - char* stringified_addr = inet_ntoa(generate_ipv4_addr(0,0,0,0)); - ASSERT_TRUE(NULL != stringified_addr); - EXPECT_STREQ("0.0.0.0", stringified_addr); +TEST(SocketUtilityFunctions, Inet_addr) { + // Fails for if string contains non-integers. + ASSERT_EQ(INADDR_NONE, inet_addr("foobar")); + + // Fails if there are too many quads + ASSERT_EQ(INADDR_NONE, inet_addr("0.0.0.0.0")); + + // Fails if a single element is > 255 + ASSERT_EQ(INADDR_NONE, inet_addr("999.0.0.0")); + + // Fails if a single element is negative. + ASSERT_EQ(INADDR_NONE, inet_addr("-55.0.0.0")); + + // In tripple, notation third integer cannot be larger + // and 16bit unsigned int. + ASSERT_EQ(INADDR_NONE, inet_addr("1.2.66000")); + + // Success cases. + // Normal dotted-quad address. + uint32_t expected_addr = ntohl(0x07060504); + ASSERT_EQ(expected_addr, inet_addr("7.6.5.4")); + expected_addr = ntohl(0xffffffff); + ASSERT_EQ(expected_addr, inet_addr("255.255.255.255")); + + // Tripple case + expected_addr = ntohl(1 << 24 | 2 << 16 | 3); + ASSERT_EQ(expected_addr, inet_addr("1.2.3")); + expected_addr = ntohl(1 << 24 | 2 << 16 | 300); + ASSERT_EQ(expected_addr, inet_addr("1.2.300")); + + // Double case + expected_addr = ntohl(1 << 24 | 20000); + ASSERT_EQ(expected_addr, inet_addr("1.20000")); + expected_addr = ntohl(1 << 24 | 2); + ASSERT_EQ(expected_addr, inet_addr("1.2")); + + // Single case + expected_addr = ntohl(255); + ASSERT_EQ(expected_addr, inet_addr("255")); + expected_addr = ntohl(4000000000U); + ASSERT_EQ(expected_addr, inet_addr("4000000000")); +} - stringified_addr = inet_ntoa(generate_ipv4_addr(127,0,0,1)); - ASSERT_TRUE(NULL != stringified_addr); - EXPECT_STREQ("127.0.0.1", stringified_addr); +TEST(SocketUtilityFunctions, Inet_aton) { + struct in_addr addr; - stringified_addr = inet_ntoa(generate_ipv4_addr(255,255,255,255)); - ASSERT_TRUE(NULL != stringified_addr); - EXPECT_STREQ("255.255.255.255", stringified_addr); -} + // Failure cases + ASSERT_EQ(0, inet_aton("foobar", &addr)); + ASSERT_EQ(0, inet_aton("0.0.0.0.0", &addr)); + ASSERT_EQ(0, inet_aton("999.0.0.0", &addr)); -TEST(SocketUtilityFunctions, Inet_ntop_ipv4) { - char stringified_addr[INET_ADDRSTRLEN]; + // Success cases + uint32_t expected_addr = htonl(0xff020304); + ASSERT_NE(0, inet_aton("255.2.3.4", &addr)); + ASSERT_EQ(expected_addr, addr.s_addr); - struct in_addr real_addr = generate_ipv4_addr(0,0,0,0); - EXPECT_TRUE(NULL != inet_ntop(AF_INET, &real_addr, - stringified_addr, INET_ADDRSTRLEN)); - EXPECT_STREQ("0.0.0.0", stringified_addr); + expected_addr = htonl(0x01000002); + ASSERT_NE(0, inet_aton("1.2", &addr)); + ASSERT_EQ(expected_addr, addr.s_addr); - real_addr = generate_ipv4_addr(127,0,0,1); - EXPECT_TRUE(NULL != inet_ntop(AF_INET, &real_addr, - stringified_addr, INET_ADDRSTRLEN)); - EXPECT_STREQ("127.0.0.1", stringified_addr); + expected_addr = htonl(0x01020003); + ASSERT_NE(0, inet_aton("1.2.3", &addr)); + ASSERT_EQ(expected_addr, addr.s_addr); - real_addr = generate_ipv4_addr(255,255,255,255); - EXPECT_TRUE(NULL != inet_ntop(AF_INET, &real_addr, - stringified_addr, INET_ADDRSTRLEN)); - EXPECT_STREQ("255.255.255.255", stringified_addr); + expected_addr = htonl(0x0000100); + ASSERT_NE(0, inet_aton("256", &addr)); + ASSERT_EQ(expected_addr, addr.s_addr); } -TEST(SocketUtilityFunctions, Inet_ntop_ipv6) { - char stringified_addr[INET6_ADDRSTRLEN]; +TEST(SocketUtilityFunctions, Inet_ntoa) { + struct { + unsigned char addr_tuple[4]; + const char* output; + } tests[] = { + { { 0, 0, 0, 0 }, "0.0.0.0" }, + { { 127, 0, 0, 1 }, "127.0.0.1" }, + { { 255, 255, 255, 255 }, "255.255.255.255" }, + }; - { - int addr_tuples[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - struct in6_addr real_addr = generate_ipv6_addr(addr_tuples); - EXPECT_TRUE(NULL != inet_ntop(AF_INET6, &real_addr, - stringified_addr, INET6_ADDRSTRLEN)); - EXPECT_STREQ("0:0:0:0:0:0:0:0", stringified_addr); + for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { + char* stringified_addr = inet_ntoa(generate_ipv4_addr(tests[i].addr_tuple)); + ASSERT_TRUE(NULL != stringified_addr); + EXPECT_STREQ(tests[i].output, stringified_addr); } +} - { - int addr_tuples[8] = { 0x1234, 0xa, 0x12, 0x0000, - 0x5678, 0x9abc, 0xdef, 0xffff }; - struct in6_addr real_addr = generate_ipv6_addr(addr_tuples); - EXPECT_TRUE(NULL != inet_ntop(AF_INET6, &real_addr, - stringified_addr, INET6_ADDRSTRLEN)); - EXPECT_STREQ("1234:a:12:0:5678:9abc:def:ffff", stringified_addr); +TEST(SocketUtilityFunctions, Inet_ntop_ipv4) { + struct { + unsigned char addr_tuple[4]; + const char* output; + } tests[] = { + { { 0, 0, 0, 0 }, "0.0.0.0" }, + { { 127, 0, 0, 1 }, "127.0.0.1" }, + { { 255, 255, 255, 255 }, "255.255.255.255" }, + }; + + for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { + char stringified_addr[INET_ADDRSTRLEN]; + struct in_addr real_addr = generate_ipv4_addr(tests[i].addr_tuple); + EXPECT_TRUE(NULL != inet_ntop(AF_INET, &real_addr, + stringified_addr, INET_ADDRSTRLEN)); + EXPECT_STREQ(tests[i].output, stringified_addr); } +} + +TEST(SocketUtilityFunctions, Inet_ntop_ipv6) { + struct { + unsigned short addr_tuple[8]; + const char* output; + } tests[] = { + { { 0, 0, 0, 0, 0, 0, 0, 0 }, "::" }, + { { 1, 2, 3, 0, 0, 0, 0, 0 }, "1:2:3::" }, + { { 0, 0, 0, 0, 0, 1, 2, 3 }, "::1:2:3" }, + { { 0x1234, 0xa, 0x12, 0x0000, 0x5678, 0x9abc, 0xdef, 0xffff }, + "1234:a:12:0:5678:9abc:def:ffff" }, + { { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }, + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" }, + { { 0, 0, 0, 0, 0, 0xffff, 0x101, 0x101 }, "::ffff:1.1.1.1" }, + { { 0, 0, 0, 0, 0, 0, 0x101, 0x101 }, "::1.1.1.1" }, + }; - { - int addr_tuples[8] = { 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff }; - struct in6_addr real_addr = generate_ipv6_addr(addr_tuples); + for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { + char stringified_addr[INET6_ADDRSTRLEN]; + struct in6_addr real_addr = generate_ipv6_addr(tests[i].addr_tuple); EXPECT_TRUE(NULL != inet_ntop(AF_INET6, &real_addr, stringified_addr, INET6_ADDRSTRLEN)); - EXPECT_STREQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", stringified_addr); + EXPECT_STREQ(tests[i].output, stringified_addr); } } TEST(SocketUtilityFunctions, Inet_ntop_failure) { char addr_name[INET6_ADDRSTRLEN]; - int addr_tuples[8] = { 0xffff, 0xffff, 0xffff, 0xffff, + uint16_t addr6_tuple[8] = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }; - struct in6_addr ipv6_addr = generate_ipv6_addr(addr_tuples); - struct in_addr ipv4_addr = generate_ipv4_addr(255,255,255,255); + uint8_t addr_tuple[4] = { 255, 255, 255, 255 }; + struct in6_addr ipv6_addr = generate_ipv6_addr(addr6_tuple); + struct in_addr ipv4_addr = generate_ipv4_addr(addr_tuple); - EXPECT_TRUE(NULL == inet_ntop(AF_UNIX, &ipv6_addr, - addr_name, INET6_ADDRSTRLEN)); - EXPECT_EQ(errno, EAFNOSUPPORT); + EXPECT_EQ(NULL, inet_ntop(AF_UNIX, &ipv6_addr, + addr_name, INET6_ADDRSTRLEN)); + EXPECT_EQ(EAFNOSUPPORT, errno); - EXPECT_TRUE(NULL == inet_ntop(AF_INET, &ipv4_addr, - addr_name, INET_ADDRSTRLEN - 1)); - EXPECT_EQ(errno, ENOSPC); + EXPECT_EQ(NULL, inet_ntop(AF_INET, &ipv4_addr, + addr_name, INET_ADDRSTRLEN - 1)); + EXPECT_EQ(ENOSPC, errno); - EXPECT_TRUE(NULL == inet_ntop(AF_INET6, &ipv6_addr, - addr_name, INET6_ADDRSTRLEN - 1)); - EXPECT_EQ(errno, ENOSPC); + EXPECT_EQ(NULL, inet_ntop(AF_INET6, &ipv6_addr, + addr_name, INET6_ADDRSTRLEN / 2)); + EXPECT_EQ(ENOSPC, errno); } TEST(SocketUtilityFunctions, Inet_pton) { struct { int family; const char* input; - const char* output; + const char* output; // NULL means output should match input } tests[] = { { AF_INET, "127.127.12.0", NULL }, { AF_INET, "0.0.0.0", NULL }, - { AF_INET6, "0:0:0:0:0:0:0:0", NULL }, + { AF_INET6, "0:0:0:0:0:0:0:0", "::" }, { AF_INET6, "1234:5678:9abc:def0:1234:5678:9abc:def0", NULL }, { AF_INET6, "1:2:3:4:5:6:7:8", NULL }, { AF_INET6, "a:b:c:d:e:f:1:2", NULL }, { AF_INET6, "A:B:C:D:E:F:1:2", "a:b:c:d:e:f:1:2" }, - { AF_INET6, "::", "0:0:0:0:0:0:0:0" }, - { AF_INET6, "::12", "0:0:0:0:0:0:0:12" }, - { AF_INET6, "::1:2:3", "0:0:0:0:0:1:2:3" }, - { AF_INET6, "12::", "12:0:0:0:0:0:0:0" }, - { AF_INET6, "1:2::", "1:2:0:0:0:0:0:0" }, - { AF_INET6, "::12:0:0:0:0:0:0:0", "12:0:0:0:0:0:0:0" }, - { AF_INET6, "1:2:3::4:5", "1:2:3:0:0:0:4:5" }, - { AF_INET6, "::1.1.1.1", "0:0:0:0:0:0:101:101" }, - { AF_INET6, "::ffff:1.1.1.1", "0:0:0:0:0:ffff:101:101" }, - { AF_INET6, "ffff::1.1.1.1", "ffff:0:0:0:0:0:101:101" }, - { AF_INET6, "::1.1.1.1", "0:0:0:0:0:0:101:101" }, + { AF_INET6, "::", "::" }, + { AF_INET6, "::12", "::12" }, + { AF_INET6, "::1:2:3", "::1:2:3" }, + { AF_INET6, "12::", "12::" }, + { AF_INET6, "1:2::", "1:2::" }, + { AF_INET6, "12:0:0:0:0:0:0:0", "12::" }, + { AF_INET6, "1:2:3::4:5", "1:2:3::4:5" }, + { AF_INET6, "::ffff:1.1.1.1", "::ffff:1.1.1.1" }, + { AF_INET6, "ffff::1.1.1.1", "ffff::101:101" }, + { AF_INET6, "::1.1.1.1", "::1.1.1.1" }, }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { uint8_t addr[16]; - EXPECT_TRUE(inet_pton(tests[i].family, tests[i].input, addr)); + ASSERT_TRUE(inet_pton(tests[i].family, tests[i].input, addr)) + << "inet_pton failed for " << tests[i].input; const char* expected = tests[i].output ? tests[i].output : tests[i].input; char out_buffer[256]; - EXPECT_TRUE( - inet_ntop(tests[i].family, addr, out_buffer, sizeof(out_buffer))); - EXPECT_EQ(std::string(expected), std::string(out_buffer)); + ASSERT_EQ(out_buffer, + inet_ntop(tests[i].family, addr, out_buffer, sizeof(out_buffer))); + ASSERT_STREQ(expected, out_buffer); } } TEST(SocketUtilityFunctions, Inet_pton_failure) { + // All these are examples of strings that do not map + // to IP address. inet_pton returns 0 on failure. uint8_t addr[16]; EXPECT_EQ(0, inet_pton(AF_INET, "127.127.12.24312", &addr)); EXPECT_EQ(0, inet_pton(AF_INET, "127.127.12.24 ", &addr)); @@ -455,6 +526,7 @@ TEST(SocketUtilityFunctions, Inet_pton_failure) { EXPECT_EQ(0, inet_pton(AF_INET6, "0:0:0:0:0:0:1:0.0.0.0", &addr)); EXPECT_EQ(0, inet_pton(AF_INET6, "::0.0.0.0:1", &addr)); EXPECT_EQ(0, inet_pton(AF_INET6, "::0.0.0.0.0", &addr)); + EXPECT_EQ(0, inet_pton(AF_INET6, "::1.2.3.4.5.6.7.8", &addr)); } TEST(SocketUtilityFunctions, Ntohs) { @@ -473,5 +545,4 @@ TEST(SocketUtilityFunctions, Ntohl) { EXPECT_EQ(host_long, 0x44332211); } -#endif // !defined(__GLIBC__) #endif // PROVIDES_SOCKETPAIR_API |