netdb_test.cpp revision c62a4b5a7aede760b06298f4b641b5a9768f5744
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <netdb.h>
18
19#include <gtest/gtest.h>
20
21#include <arpa/inet.h>
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25
26// https://code.google.com/p/android/issues/detail?id=13228
27TEST(netdb, freeaddrinfo_NULL) {
28  freeaddrinfo(NULL);
29}
30
31TEST(netdb, getaddrinfo_NULL_host) {
32  // It's okay for the host argument to be NULL, as long as service isn't.
33  addrinfo* ai = NULL;
34  ASSERT_EQ(0, getaddrinfo(NULL, "smtp", NULL, &ai));
35  // (sockaddr_in::sin_port and sockaddr_in6::sin6_port overlap.)
36  ASSERT_EQ(25U, ntohs(reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_port));
37  freeaddrinfo(ai);
38}
39
40TEST(netdb, getaddrinfo_NULL_service) {
41  // It's okay for the service argument to be NULL, as long as host isn't.
42  addrinfo* ai = NULL;
43  ASSERT_EQ(0, getaddrinfo("localhost", NULL, NULL, &ai));
44  ASSERT_TRUE(ai != NULL);
45  freeaddrinfo(ai);
46}
47
48TEST(netdb, getaddrinfo_NULL_hints) {
49  addrinfo* ai = NULL;
50  ASSERT_EQ(0, getaddrinfo("localhost", "9999", NULL, &ai));
51
52  bool saw_tcp = false;
53  bool saw_udp = false;
54  for (addrinfo* p = ai; p != NULL; p = p->ai_next) {
55    ASSERT_TRUE(p->ai_family == AF_INET || p->ai_family == AF_INET6);
56    if (p->ai_socktype == SOCK_STREAM) {
57      ASSERT_EQ(IPPROTO_TCP, p->ai_protocol);
58      saw_tcp = true;
59    } else if (p->ai_socktype == SOCK_DGRAM) {
60      ASSERT_EQ(IPPROTO_UDP, p->ai_protocol);
61      saw_udp = true;
62    }
63  }
64  ASSERT_TRUE(saw_tcp);
65  ASSERT_TRUE(saw_udp);
66
67  freeaddrinfo(ai);
68}
69
70TEST(netdb, getaddrinfo_service_lookup) {
71  addrinfo* ai = NULL;
72  ASSERT_EQ(0, getaddrinfo("localhost", "smtp", NULL, &ai));
73  ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
74  ASSERT_EQ(IPPROTO_TCP, ai->ai_protocol);
75  ASSERT_EQ(25, ntohs(reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_port));
76  freeaddrinfo(ai);
77}
78
79TEST(netdb, getaddrinfo_hints) {
80  addrinfo hints;
81  memset(&hints, 0, sizeof(hints));
82  hints.ai_family = AF_UNSPEC;
83  hints.ai_socktype = SOCK_STREAM;
84  hints.ai_protocol = IPPROTO_TCP;
85
86  addrinfo* ai = NULL;
87  ASSERT_EQ(0, getaddrinfo( "localhost", "9999", &hints, &ai));
88  ASSERT_EQ(AF_INET, ai->ai_family);
89  ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
90  ASSERT_EQ(IPPROTO_TCP, ai->ai_protocol);
91  ASSERT_TRUE(ai->ai_next == NULL);
92  freeaddrinfo(ai);
93}
94
95TEST(netdb, getnameinfo_salen) {
96  sockaddr_storage ss;
97  memset(&ss, 0, sizeof(ss));
98  sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
99  char tmp[16];
100
101  ss.ss_family = AF_INET;
102  socklen_t too_much = sizeof(ss);
103  socklen_t just_right = sizeof(sockaddr_in);
104  socklen_t too_little = sizeof(sockaddr_in) - 1;
105
106  ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
107  ASSERT_STREQ("0.0.0.0", tmp);
108  ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
109  ASSERT_STREQ("0.0.0.0", tmp);
110  ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
111
112  ss.ss_family = AF_INET6;
113  just_right = sizeof(sockaddr_in6);
114  too_little = sizeof(sockaddr_in6) - 1;
115  too_much = just_right + 1;
116
117  ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
118  ASSERT_STREQ("::", tmp);
119  ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
120  ASSERT_STREQ("::", tmp);
121  ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
122}
123
124void VerifyLocalhost(hostent *hent) {
125  ASSERT_TRUE(hent != NULL);
126  ASSERT_EQ(hent->h_addrtype, AF_INET);
127  ASSERT_EQ(hent->h_addr[0], 127);
128  ASSERT_EQ(hent->h_addr[1], 0);
129  ASSERT_EQ(hent->h_addr[2], 0);
130  ASSERT_EQ(hent->h_addr[3], 1);
131}
132
133TEST(netdb, gethostbyname) {
134  hostent* hp = gethostbyname("localhost");
135  VerifyLocalhost(hp);
136}
137
138TEST(netdb, gethostbyname2) {
139  hostent* hp = gethostbyname2("localhost", AF_INET);
140  VerifyLocalhost(hp);
141}
142
143TEST(netdb, gethostbyname_r) {
144  hostent hent;
145  hostent *hp;
146  char buf[512];
147  int err;
148  int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err);
149  ASSERT_EQ(0, result);
150  VerifyLocalhost(hp);
151
152  // Change hp->h_addr to test reentrancy.
153  hp->h_addr[0] = 0;
154
155  hostent hent2;
156  hostent *hp2;
157  char buf2[512];
158  result = gethostbyname_r("localhost", &hent2, buf2, sizeof(buf2), &hp2, &err);
159  ASSERT_EQ(0, result);
160  VerifyLocalhost(hp2);
161
162  ASSERT_EQ(0, hp->h_addr[0]);
163}
164
165TEST(netdb, gethostbyname2_r) {
166  hostent hent;
167  hostent *hp;
168  char buf[512];
169  int err;
170  int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err);
171  ASSERT_EQ(0, result);
172  VerifyLocalhost(hp);
173
174  // Change hp->h_addr to test reentrancy.
175  hp->h_addr[0] = 0;
176
177  hostent hent2;
178  hostent *hp2;
179  char buf2[512];
180  result = gethostbyname2_r("localhost", AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err);
181  ASSERT_EQ(0, result);
182  VerifyLocalhost(hp2);
183
184  ASSERT_EQ(0, hp->h_addr[0]);
185}
186
187TEST(netdb, gethostbyaddr) {
188  char addr[4];
189  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr));
190  hostent *hp = gethostbyaddr(addr, sizeof(addr), AF_INET);
191  VerifyLocalhost(hp);
192}
193
194TEST(netdb, gethostbyaddr_r) {
195  char addr[4];
196  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr));
197
198  hostent hent;
199  hostent *hp;
200  char buf[512];
201  int err;
202  int result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
203  ASSERT_EQ(0, result);
204  VerifyLocalhost(hp);
205
206  // Change hp->h_addr to test reentrancy.
207  hp->h_addr[0] = 0;
208
209  hostent hent2;
210  hostent *hp2;
211  char buf2[512];
212  result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err);
213  ASSERT_EQ(0, result);
214  VerifyLocalhost(hp2);
215
216  ASSERT_EQ(0, hp->h_addr[0]);
217}
218
219TEST(netdb, gethostbyname_r_ERANGE) {
220  hostent hent;
221  hostent *hp;
222  char buf[4]; // Use too small buffer.
223  int err;
224  int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err);
225  ASSERT_EQ(ERANGE, result);
226  ASSERT_EQ(NULL, hp);
227}
228
229TEST(netdb, gethostbyname2_r_ERANGE) {
230  hostent hent;
231  hostent *hp;
232  char buf[4]; // Use too small buffer.
233  int err;
234  int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err);
235  ASSERT_EQ(ERANGE, result);
236  ASSERT_EQ(NULL, hp);
237}
238
239TEST(netdb, gethostbyaddr_r_ERANGE) {
240  char addr[4];
241  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr));
242
243  hostent hent;
244  hostent *hp;
245  char buf[4]; // Use too small buffer.
246  int err;
247  int result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
248  ASSERT_EQ(ERANGE, result);
249  ASSERT_EQ(NULL, hp);
250}
251
252TEST(netdb, getservbyname) {
253  // smtp is TCP-only, so we know we'll get 25/tcp back.
254  servent* s = getservbyname("smtp", NULL);
255  ASSERT_TRUE(s != NULL);
256  ASSERT_EQ(25, ntohs(s->s_port));
257  ASSERT_STREQ("tcp", s->s_proto);
258
259  // We get the same result by explicitly asking for tcp.
260  s = getservbyname("smtp", "tcp");
261  ASSERT_TRUE(s != NULL);
262  ASSERT_EQ(25, ntohs(s->s_port));
263  ASSERT_STREQ("tcp", s->s_proto);
264
265  // And we get a failure if we explicitly ask for udp.
266  s = getservbyname("smtp", "udp");
267  ASSERT_TRUE(s == NULL);
268
269  // But there are actually udp services.
270  s = getservbyname("echo", "udp");
271  ASSERT_TRUE(s != NULL);
272  ASSERT_EQ(7, ntohs(s->s_port));
273  ASSERT_STREQ("udp", s->s_proto);
274}
275