summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authorcernekee <cernekee@chromium.org>2016-02-09 14:16:53 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-09 22:18:45 +0000
commitc03b3edd866d172c13f96fde1c3773ca631462b9 (patch)
tree745b739c79ff38eee71b641d44e4357c2e0a3a67 /native_client_sdk
parent94fb5d4a5bf05e7d230c29be6df8ea1a21628032 (diff)
downloadchromium_src-c03b3edd866d172c13f96fde1c3773ca631462b9.zip
chromium_src-c03b3edd866d172c13f96fde1c3773ca631462b9.tar.gz
chromium_src-c03b3edd866d172c13f96fde1c3773ca631462b9.tar.bz2
nacl_io: Add bare-bones getnameinfo() implementation
This can't perform reverse DNS queries, but at least it can translate sockaddr_in and sockaddr_in6 into numeric IP strings. BUG=386832 CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_nacl_sdk;tryserver.chromium.mac:mac_nacl_sdk;tryserver.chromium.win:win_nacl_sdk Review URL: https://codereview.chromium.org/1683553002 Cr-Commit-Position: refs/heads/master@{#374498}
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/libraries/nacl_io/host_resolver.cc48
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc103
2 files changed, 147 insertions, 4 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/host_resolver.cc b/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
index 4dd50ac..150e0cf 100644
--- a/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
+++ b/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
@@ -8,8 +8,11 @@
#include "nacl_io/host_resolver.h"
+#include <arpa/inet.h>
#include <assert.h>
+#include <netinet/in.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -221,14 +224,51 @@ void HostResolver::freeaddrinfo(struct addrinfo* res) {
}
}
-int HostResolver::getnameinfo(const struct sockaddr *sa,
+int HostResolver::getnameinfo(const struct sockaddr* sa,
socklen_t salen,
- char *host,
+ char* host,
size_t hostlen,
- char *serv,
+ char* serv,
size_t servlen,
int flags) {
- return ENOSYS;
+ in_port_t port;
+ const void* addr;
+
+ if (host == NULL && serv == NULL) {
+ LOG_TRACE("host and serv are NULL.");
+ return EAI_NONAME;
+ }
+
+ // Currently we only handle numeric hosts and services.
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+
+ if (sa->sa_family == AF_INET) {
+ if (salen < sizeof(struct sockaddr_in))
+ return EAI_FAMILY;
+
+ const struct sockaddr_in* sock =
+ reinterpret_cast<const struct sockaddr_in*>(sa);
+ port = sock->sin_port;
+ addr = &sock->sin_addr.s_addr;
+ } else if (sa->sa_family == AF_INET6) {
+ if (salen < sizeof(struct sockaddr_in6))
+ return EAI_FAMILY;
+
+ const struct sockaddr_in6* sock =
+ reinterpret_cast<const struct sockaddr_in6*>(sa);
+ port = sock->sin6_port;
+ addr = sock->sin6_addr.s6_addr;
+ } else {
+ return EAI_FAMILY;
+ }
+
+ if (host && inet_ntop(sa->sa_family, addr, host, hostlen) == NULL)
+ return EAI_OVERFLOW;
+ if (serv && (size_t)snprintf(serv, servlen, "%u", htons(port)) >= servlen)
+ return EAI_OVERFLOW;
+
+ return 0;
}
int HostResolver::getaddrinfo(const char* node,
diff --git a/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc b/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc
index 3aaec27..a153240 100644
--- a/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc
@@ -135,6 +135,109 @@ TEST_F(HostResolverTest, Getaddrinfo_NumericService) {
ki_freeaddrinfo(ai);
}
+TEST_F(HostResolverTest, Getnameinfo_Numeric) {
+ char host[64];
+ char serv[64];
+
+ // IPv4 host + service to strings.
+ struct sockaddr_in in;
+
+ memset(&in, 0, sizeof(in));
+ memset(host, 0, sizeof(host));
+ memset(serv, 0, sizeof(serv));
+ in.sin_family = AF_INET;
+ in.sin_port = ntohs(443);
+ in.sin_addr.s_addr = ntohl(0x01020304);
+
+ ASSERT_EQ(0, ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in),
+ sizeof(in), host, sizeof(host), serv,
+ sizeof(serv), NI_NUMERICSERV));
+ ASSERT_STREQ(host, "1.2.3.4");
+ ASSERT_STREQ(serv, "443");
+
+ // IPv4 host only.
+ memset(host, 0, sizeof(host));
+ ASSERT_EQ(0,
+ ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in), sizeof(in),
+ host, sizeof(host), NULL, 0, NI_NUMERICSERV));
+ ASSERT_STREQ(host, "1.2.3.4");
+
+ // IPv6 host + service.
+ struct sockaddr_in6 in6;
+
+ memset(&in6, 0, sizeof(in6));
+ memset(host, 0, sizeof(host));
+ memset(serv, 0, sizeof(serv));
+ in6.sin6_family = AF_INET6;
+ in6.sin6_port = ntohs(80);
+ in6.sin6_addr.s6_addr[0] = 0xfe;
+ in6.sin6_addr.s6_addr[1] = 0x80;
+ in6.sin6_addr.s6_addr[12] = 0x05;
+ in6.sin6_addr.s6_addr[13] = 0x06;
+ in6.sin6_addr.s6_addr[14] = 0x07;
+ in6.sin6_addr.s6_addr[15] = 0x08;
+
+ ASSERT_EQ(0, ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in6),
+ sizeof(in6), host, sizeof(host), serv,
+ sizeof(serv), NI_NUMERICSERV));
+ ASSERT_STREQ(host, "fe80::506:708");
+ ASSERT_STREQ(serv, "80");
+
+ // IPv6 service only.
+ memset(serv, 0, sizeof(serv));
+ ASSERT_EQ(
+ 0, ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in6), sizeof(in6),
+ NULL, 0, serv, sizeof(serv), NI_NUMERICSERV));
+ ASSERT_STREQ(serv, "80");
+}
+
+TEST_F(HostResolverTest, Getnameinfo_ErrorHandling) {
+ struct sockaddr_in in;
+ char host[64];
+ char serv[64];
+
+ memset(&in, 0, sizeof(in));
+ memset(host, 0, sizeof(host));
+ memset(serv, 0, sizeof(serv));
+ in.sin_family = AF_INET;
+ in.sin_port = ntohs(443);
+ in.sin_addr.s_addr = ntohl(0x01020304);
+
+ // Bogus salen, hostlen, or servlen.
+ ASSERT_EQ(EAI_FAMILY, ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in),
+ sizeof(in) - 4, host, sizeof(host), serv,
+ sizeof(serv), NI_NUMERICSERV));
+ ASSERT_EQ(EAI_OVERFLOW,
+ ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in), sizeof(in),
+ host, 7, serv, sizeof(serv), NI_NUMERICSERV));
+ ASSERT_EQ(EAI_OVERFLOW,
+ ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in), sizeof(in),
+ host, sizeof(host), serv, 3, NI_NUMERICSERV));
+
+ // User insists on names, but we can only provide numbers.
+ ASSERT_EQ(EAI_NONAME,
+ ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in), sizeof(in),
+ host, sizeof(host), serv, 3, NI_NAMEREQD));
+
+ // User forgot to pass a host or serv buffer.
+ ASSERT_EQ(EAI_NONAME,
+ ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&in), sizeof(in),
+ NULL, 0, NULL, 0, NI_NUMERICSERV));
+
+ // Wrong socket type.
+ struct sockaddr unix_sock;
+ memset(&unix_sock, 0, sizeof(unix_sock));
+ memset(host, 0, sizeof(host));
+ memset(serv, 0, sizeof(serv));
+ unix_sock.sa_family = AF_UNIX;
+ ASSERT_EQ(EAI_FAMILY,
+ ki_getnameinfo(reinterpret_cast<struct sockaddr*>(&unix_sock),
+ sizeof(unix_sock), host, sizeof(host), serv,
+ sizeof(serv), NI_NUMERICSERV));
+ ASSERT_STREQ(host, "");
+ ASSERT_STREQ(serv, "");
+}
+
TEST_F(HostResolverTest, Getaddrinfo_MissingPPAPI) {
// Verify that full lookups fail due to lack of PPAPI interfaces
struct addrinfo* ai = NULL;