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 <netinet/in.h>
23 #include <string.h>
24 #include <sys/cdefs.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 
28 // https://code.google.com/p/android/issues/detail?id=13228
TEST(netdb,freeaddrinfo_NULL)29 TEST(netdb, freeaddrinfo_NULL) {
30   freeaddrinfo(nullptr);
31 }
32 
TEST(netdb,getaddrinfo_NULL_host)33 TEST(netdb, getaddrinfo_NULL_host) {
34   // It's okay for the host argument to be NULL, as long as service isn't.
35   addrinfo* ai = nullptr;
36   ASSERT_EQ(0, getaddrinfo(nullptr, "smtp", nullptr, &ai));
37   // (sockaddr_in::sin_port and sockaddr_in6::sin6_port overlap.)
38   ASSERT_EQ(25U, ntohs(reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_port));
39   freeaddrinfo(ai);
40 }
41 
TEST(netdb,getaddrinfo_NULL_service)42 TEST(netdb, getaddrinfo_NULL_service) {
43   // It's okay for the service argument to be NULL, as long as host isn't.
44   addrinfo* ai = nullptr;
45   ASSERT_EQ(0, getaddrinfo("localhost", nullptr, nullptr, &ai));
46   ASSERT_TRUE(ai != nullptr);
47   freeaddrinfo(ai);
48 }
49 
TEST(netdb,getaddrinfo_NULL_hints)50 TEST(netdb, getaddrinfo_NULL_hints) {
51   addrinfo* ai = nullptr;
52   ASSERT_EQ(0, getaddrinfo("localhost", "9999", nullptr, &ai));
53 
54   bool saw_tcp = false;
55   bool saw_udp = false;
56   for (addrinfo* p = ai; p != nullptr; p = p->ai_next) {
57     ASSERT_TRUE(p->ai_family == AF_INET || p->ai_family == AF_INET6);
58     if (p->ai_socktype == SOCK_STREAM) {
59       ASSERT_EQ(IPPROTO_TCP, p->ai_protocol);
60       saw_tcp = true;
61     } else if (p->ai_socktype == SOCK_DGRAM) {
62       ASSERT_EQ(IPPROTO_UDP, p->ai_protocol);
63       saw_udp = true;
64     }
65   }
66   ASSERT_TRUE(saw_tcp);
67   ASSERT_TRUE(saw_udp);
68 
69   freeaddrinfo(ai);
70 }
71 
TEST(netdb,getaddrinfo_service_lookup)72 TEST(netdb, getaddrinfo_service_lookup) {
73   addrinfo* ai = nullptr;
74   ASSERT_EQ(0, getaddrinfo("localhost", "smtp", nullptr, &ai));
75   ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
76   ASSERT_EQ(IPPROTO_TCP, ai->ai_protocol);
77   ASSERT_EQ(25, ntohs(reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_port));
78   freeaddrinfo(ai);
79 }
80 
TEST(netdb,getaddrinfo_hints)81 TEST(netdb, getaddrinfo_hints) {
82   addrinfo hints;
83   memset(&hints, 0, sizeof(hints));
84   hints.ai_family = AF_INET;
85   hints.ai_socktype = SOCK_STREAM;
86   hints.ai_protocol = IPPROTO_TCP;
87 
88   addrinfo* ai = nullptr;
89   ASSERT_EQ(0, getaddrinfo( "localhost", "9999", &hints, &ai));
90   ASSERT_TRUE(ai != nullptr);
91   // In glibc, getaddrinfo() converts ::1 to 127.0.0.1 for localhost,
92   // so one or two addrinfo may be returned.
93   addrinfo* tai = ai;
94   while (tai != nullptr) {
95     ASSERT_EQ(AF_INET, tai->ai_family);
96     ASSERT_EQ(SOCK_STREAM, tai->ai_socktype);
97     ASSERT_EQ(IPPROTO_TCP, tai->ai_protocol);
98     tai = tai->ai_next;
99   }
100   freeaddrinfo(ai);
101 }
102 
TEST(netdb,getaddrinfo_ip6_localhost)103 TEST(netdb, getaddrinfo_ip6_localhost) {
104   addrinfo* ai = nullptr;
105   ASSERT_EQ(0, getaddrinfo("ip6-localhost", nullptr, nullptr, &ai));
106   ASSERT_TRUE(ai != nullptr);
107   ASSERT_GE(ai->ai_addrlen, static_cast<socklen_t>(sizeof(sockaddr_in6)));
108   ASSERT_TRUE(ai->ai_addr != nullptr);
109   sockaddr_in6 *addr = reinterpret_cast<sockaddr_in6*>(ai->ai_addr);
110   ASSERT_EQ(addr->sin6_family, AF_INET6);
111   ASSERT_EQ(0, memcmp(&addr->sin6_addr, &in6addr_loopback, sizeof(in6_addr)));
112   freeaddrinfo(ai);
113 }
114 
TEST(netdb,getnameinfo_salen)115 TEST(netdb, getnameinfo_salen) {
116   sockaddr_storage ss;
117   memset(&ss, 0, sizeof(ss));
118   sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
119   char tmp[16];
120 
121   ss.ss_family = AF_INET;
122   socklen_t too_much = sizeof(ss);
123   socklen_t just_right = sizeof(sockaddr_in);
124   socklen_t too_little = sizeof(sockaddr_in) - 1;
125 
126   ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), nullptr, 0, NI_NUMERICHOST));
127   ASSERT_STREQ("0.0.0.0", tmp);
128   ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), nullptr, 0, NI_NUMERICHOST));
129   ASSERT_STREQ("0.0.0.0", tmp);
130   ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), nullptr, 0, NI_NUMERICHOST));
131 
132   ss.ss_family = AF_INET6;
133   just_right = sizeof(sockaddr_in6);
134   too_little = sizeof(sockaddr_in6) - 1;
135   too_much = just_right + 1;
136 
137   ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), nullptr, 0, NI_NUMERICHOST));
138   ASSERT_STREQ("::", tmp);
139   ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), nullptr, 0, NI_NUMERICHOST));
140   ASSERT_STREQ("::", tmp);
141   ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), nullptr, 0, NI_NUMERICHOST));
142 }
143 
TEST(netdb,getnameinfo_localhost)144 TEST(netdb, getnameinfo_localhost) {
145   sockaddr_in addr;
146   char host[NI_MAXHOST];
147   memset(&addr, 0, sizeof(sockaddr_in));
148   addr.sin_family = AF_INET;
149   addr.sin_addr.s_addr = htonl(0x7f000001);
150   ASSERT_EQ(0, getnameinfo(reinterpret_cast<sockaddr*>(&addr), sizeof(addr),
151                            host, sizeof(host), nullptr, 0, 0));
152   ASSERT_STREQ(host, "localhost");
153 }
154 
VerifyLocalhostName(const char * name)155 static void VerifyLocalhostName(const char* name) {
156   // Test possible localhost name and aliases, which depend on /etc/hosts or /system/etc/hosts.
157   ASSERT_TRUE(strcmp(name, "localhost") == 0 ||
158               strcmp(name, "ip6-localhost") == 0 ||
159               strcmp(name, "ip6-loopback") == 0) << name;
160 }
161 
TEST(netdb,getnameinfo_ip6_localhost)162 TEST(netdb, getnameinfo_ip6_localhost) {
163   sockaddr_in6 addr;
164   char host[NI_MAXHOST];
165   memset(&addr, 0, sizeof(sockaddr_in6));
166   addr.sin6_family = AF_INET6;
167   addr.sin6_addr = in6addr_loopback;
168   ASSERT_EQ(0, getnameinfo(reinterpret_cast<sockaddr*>(&addr), sizeof(addr),
169                            host, sizeof(host), nullptr, 0, 0));
170   VerifyLocalhostName(host);
171 }
172 
VerifyLocalhost(hostent * hent)173 static void VerifyLocalhost(hostent *hent) {
174   ASSERT_TRUE(hent != nullptr);
175   VerifyLocalhostName(hent->h_name);
176   for (size_t i = 0; hent->h_aliases[i] != nullptr; ++i) {
177     VerifyLocalhostName(hent->h_aliases[i]);
178   }
179   ASSERT_EQ(hent->h_addrtype, AF_INET);
180   ASSERT_EQ(hent->h_addr[0], 127);
181   ASSERT_EQ(hent->h_addr[1], 0);
182   ASSERT_EQ(hent->h_addr[2], 0);
183   ASSERT_EQ(hent->h_addr[3], 1);
184 }
185 
TEST(netdb,gethostbyname)186 TEST(netdb, gethostbyname) {
187   hostent* hp = gethostbyname("localhost");
188   VerifyLocalhost(hp);
189 }
190 
TEST(netdb,gethostbyname2)191 TEST(netdb, gethostbyname2) {
192   hostent* hp = gethostbyname2("localhost", AF_INET);
193   VerifyLocalhost(hp);
194 }
195 
TEST(netdb,gethostbyname_r)196 TEST(netdb, gethostbyname_r) {
197   hostent hent;
198   hostent *hp;
199   char buf[512];
200   int err;
201   int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err);
202   ASSERT_EQ(0, result);
203   VerifyLocalhost(hp);
204 
205   // Change hp->h_addr to test reentrancy.
206   hp->h_addr[0] = 0;
207 
208   hostent hent2;
209   hostent *hp2;
210   char buf2[512];
211   result = gethostbyname_r("localhost", &hent2, buf2, sizeof(buf2), &hp2, &err);
212   ASSERT_EQ(0, result);
213   VerifyLocalhost(hp2);
214 
215   ASSERT_EQ(0, hp->h_addr[0]);
216 }
217 
TEST(netdb,gethostbyname2_r)218 TEST(netdb, gethostbyname2_r) {
219   hostent hent;
220   hostent *hp;
221   char buf[512];
222   int err;
223   int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err);
224   ASSERT_EQ(0, result);
225   VerifyLocalhost(hp);
226 
227   // Change hp->h_addr to test reentrancy.
228   hp->h_addr[0] = 0;
229 
230   hostent hent2;
231   hostent *hp2;
232   char buf2[512];
233   result = gethostbyname2_r("localhost", AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err);
234   ASSERT_EQ(0, result);
235   VerifyLocalhost(hp2);
236 
237   ASSERT_EQ(0, hp->h_addr[0]);
238 }
239 
TEST(netdb,gethostbyaddr)240 TEST(netdb, gethostbyaddr) {
241   in_addr addr = { htonl(0x7f000001) };
242   hostent *hp = gethostbyaddr(&addr, sizeof(addr), AF_INET);
243   VerifyLocalhost(hp);
244 }
245 
TEST(netdb,gethostbyaddr_r)246 TEST(netdb, gethostbyaddr_r) {
247   in_addr addr = { htonl(0x7f000001) };
248   hostent hent;
249   hostent *hp;
250   char buf[512];
251   int err;
252   int result = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
253   ASSERT_EQ(0, result);
254   VerifyLocalhost(hp);
255 
256   // Change hp->h_addr to test reentrancy.
257   hp->h_addr[0] = 0;
258 
259   hostent hent2;
260   hostent *hp2;
261   char buf2[512];
262   result = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err);
263   ASSERT_EQ(0, result);
264   VerifyLocalhost(hp2);
265 
266   ASSERT_EQ(0, hp->h_addr[0]);
267 }
268 
269 #if defined(ANDROID_HOST_MUSL)
270 // musl doesn't define NETDB_INTERNAL.  It also never sets *err to -1, but
271 // since gethostbyname_r is a glibc extension, the difference in behavior
272 // between musl and  glibc should probably be considered a bug in musl.
273 #define NETDB_INTERNAL -1
274 #endif
275 
TEST(netdb,gethostbyname_r_ERANGE)276 TEST(netdb, gethostbyname_r_ERANGE) {
277   hostent hent;
278   hostent *hp;
279   char buf[4]; // Use too small buffer.
280   int err = 0;
281   int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err);
282   EXPECT_EQ(NETDB_INTERNAL, err);
283   EXPECT_EQ(ERANGE, result);
284   EXPECT_EQ(nullptr, hp);
285 }
286 
TEST(netdb,gethostbyname2_r_ERANGE)287 TEST(netdb, gethostbyname2_r_ERANGE) {
288   hostent hent;
289   hostent *hp;
290   char buf[4]; // Use too small buffer.
291   int err = 0;
292   int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err);
293   EXPECT_EQ(NETDB_INTERNAL, err);
294   EXPECT_EQ(ERANGE, result);
295   EXPECT_EQ(nullptr, hp);
296 }
297 
TEST(netdb,gethostbyaddr_r_ERANGE)298 TEST(netdb, gethostbyaddr_r_ERANGE) {
299   in_addr addr = { htonl(0x7f000001) };
300   hostent hent;
301   hostent *hp;
302   char buf[4]; // Use too small buffer.
303   int err = 0;
304   int result = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
305   EXPECT_EQ(NETDB_INTERNAL, err);
306   EXPECT_EQ(ERANGE, result);
307   EXPECT_EQ(nullptr, hp);
308 }
309 
TEST(netdb,gethostbyname_r_HOST_NOT_FOUND)310 TEST(netdb, gethostbyname_r_HOST_NOT_FOUND) {
311   hostent hent;
312   hostent *hp;
313   char buf[BUFSIZ];
314   int err;
315   int result = gethostbyname_r("does.not.exist.google.com", &hent, buf, sizeof(buf), &hp, &err);
316   EXPECT_EQ(HOST_NOT_FOUND, err);
317   EXPECT_EQ(0, result);
318   EXPECT_EQ(nullptr, hp);
319 }
320 
TEST(netdb,gethostbyname2_r_HOST_NOT_FOUND)321 TEST(netdb, gethostbyname2_r_HOST_NOT_FOUND) {
322   hostent hent;
323   hostent *hp;
324   char buf[BUFSIZ];
325   int err;
326   int result = gethostbyname2_r("does.not.exist.google.com", AF_INET, &hent, buf, sizeof(buf), &hp, &err);
327   EXPECT_EQ(HOST_NOT_FOUND, err);
328   EXPECT_EQ(0, result);
329   EXPECT_EQ(nullptr, hp);
330 }
331 
TEST(netdb,gethostbyaddr_r_HOST_NOT_FOUND)332 TEST(netdb, gethostbyaddr_r_HOST_NOT_FOUND) {
333   in_addr addr = { htonl(0xffffffff) };
334   hostent hent;
335   hostent *hp;
336   char buf[BUFSIZ];
337   int err;
338   int result = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
339   EXPECT_EQ(HOST_NOT_FOUND, err);
340   EXPECT_EQ(0, result);
341   EXPECT_EQ(nullptr, hp);
342 }
343 
TEST(netdb,getservbyname)344 TEST(netdb, getservbyname) {
345   // smtp is TCP-only, so we know we'll get 25/tcp back.
346   servent* s = getservbyname("smtp", nullptr);
347   ASSERT_TRUE(s != nullptr);
348   ASSERT_STREQ("smtp", s->s_name);
349   ASSERT_EQ(25, ntohs(s->s_port));
350   ASSERT_STREQ("tcp", s->s_proto);
351 
352   // We get the same result by explicitly asking for tcp.
353   s = getservbyname("smtp", "tcp");
354   ASSERT_TRUE(s != nullptr);
355   ASSERT_STREQ("smtp", s->s_name);
356   ASSERT_EQ(25, ntohs(s->s_port));
357   ASSERT_STREQ("tcp", s->s_proto);
358 
359   // And we get a failure if we explicitly ask for udp.
360   s = getservbyname("smtp", "udp");
361   ASSERT_TRUE(s == nullptr);
362 
363   // But there are actually udp services.
364   s = getservbyname("echo", "udp");
365   ASSERT_TRUE(s != nullptr);
366   ASSERT_STREQ("echo", s->s_name);
367   ASSERT_EQ(7, ntohs(s->s_port));
368   ASSERT_STREQ("udp", s->s_proto);
369 }
370 
TEST(netdb,getservbyport)371 TEST(netdb, getservbyport) {
372   // smtp is TCP-only, so we know we'll get 25/tcp back.
373   servent* s = getservbyport(htons(25), nullptr);
374   ASSERT_TRUE(s != nullptr);
375   ASSERT_STREQ("smtp", s->s_name);
376   ASSERT_EQ(25, ntohs(s->s_port));
377   ASSERT_STREQ("tcp", s->s_proto);
378 
379   // We get the same result by explicitly asking for tcp.
380   s = getservbyport(htons(25), "tcp");
381   ASSERT_TRUE(s != nullptr);
382   ASSERT_STREQ("smtp", s->s_name);
383   ASSERT_EQ(25, ntohs(s->s_port));
384   ASSERT_STREQ("tcp", s->s_proto);
385 
386   // And we get a failure if we explicitly ask for udp.
387   s = getservbyport(htons(25), "udp");
388   ASSERT_TRUE(s == nullptr);
389 
390   // But there are actually udp services.
391   s = getservbyport(htons(7), "udp");
392   ASSERT_TRUE(s != nullptr);
393   ASSERT_STREQ("echo", s->s_name);
394   ASSERT_EQ(7, ntohs(s->s_port));
395   ASSERT_STREQ("udp", s->s_proto);
396 }
397 
TEST(netdb,endnetent_getnetent_setnetent)398 TEST(netdb, endnetent_getnetent_setnetent) {
399   setnetent(0);
400   setnetent(1);
401   endnetent();
402   while (getnetent() != nullptr) {
403   }
404 }
405 
TEST(netdb,getnetbyaddr)406 TEST(netdb, getnetbyaddr) {
407   getnetbyaddr(0, 0);
408 }
409 
TEST(netdb,getnetbyname)410 TEST(netdb, getnetbyname) {
411   getnetbyname("x");
412 }
413 
TEST(netdb,endprotoent_getprotoent_setprotoent)414 TEST(netdb, endprotoent_getprotoent_setprotoent) {
415   setprotoent(0);
416   setprotoent(1);
417   endprotoent();
418   while (getprotoent() != nullptr) {
419   }
420 }
421 
TEST(netdb,getprotobyname)422 TEST(netdb, getprotobyname) {
423   getprotobyname("tcp");
424 }
425 
TEST(netdb,getprotobynumber)426 TEST(netdb, getprotobynumber) {
427   getprotobynumber(6);
428 }
429 
TEST(netdb,endservent_getservent_setservent)430 TEST(netdb, endservent_getservent_setservent) {
431   setservent(0);
432   setservent(1);
433   endservent();
434   size_t service_count = 0;
435   while (getservent() != nullptr) {
436     ++service_count;
437   }
438   ASSERT_GT(service_count, 0U);
439 }
440 
TEST(netdb,getservbyname_getservent_conflicts)441 TEST(netdb, getservbyname_getservent_conflicts) {
442   // Calling getservbyname shouldn't affect getservent's iteration order.
443   endservent();
444   while (getservent() != nullptr) {
445     ASSERT_TRUE(getservbyname("smtp", "tcp") != nullptr);
446   }
447 }
448 
TEST(netdb,getservbyport_getservent_conflicts)449 TEST(netdb, getservbyport_getservent_conflicts) {
450   // Calling getservbyport shouldn't affect getservent's iteration order.
451   endservent();
452   while (getservent() != nullptr) {
453     ASSERT_TRUE(getservbyport(htons(25), "tcp") != nullptr);
454   }
455 }
456 
TEST(netdb,endservent_resets)457 TEST(netdb, endservent_resets) {
458   endservent();
459   std::string first_service(getservent()->s_name);
460   endservent();
461   ASSERT_EQ(first_service, std::string(getservent()->s_name));
462 }
463 
TEST(netdb,setservent_resets)464 TEST(netdb, setservent_resets) {
465   endservent();
466   std::string first_service(getservent()->s_name);
467   setservent(0);
468   ASSERT_EQ(first_service, std::string(getservent()->s_name));
469 }
470 
TEST(netdb,endhostent_gethostent_sethostent)471 TEST(netdb, endhostent_gethostent_sethostent) {
472   sethostent(0);
473   sethostent(1);
474   endhostent();
475   size_t host_count = 0;
476   while (gethostent() != nullptr) {
477     ++host_count;
478   }
479   ASSERT_GT(host_count, 0U);
480 }
481 
TEST(netdb,endhostent_resets)482 TEST(netdb, endhostent_resets) {
483   endhostent();
484   std::string first_host(gethostent()->h_name);
485   endhostent();
486   ASSERT_EQ(first_host, std::string(gethostent()->h_name));
487 }
488 
TEST(netdb,sethostent_resets)489 TEST(netdb, sethostent_resets) {
490   endhostent();
491   std::string first_host(gethostent()->h_name);
492   sethostent(0);
493   ASSERT_EQ(first_host, std::string(gethostent()->h_name));
494 }
495