netdb_test.cpp revision 58d33a51f336d6823ef1ec915949a5884699ff5f
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
26TEST(netdb, getaddrinfo_NULL_host) {
27  // It's okay for the host argument to be NULL, as long as service isn't.
28  addrinfo* ai = NULL;
29  ASSERT_EQ(0, getaddrinfo(NULL, "smtp", NULL, &ai));
30  // (sockaddr_in::sin_port and sockaddr_in6::sin6_port overlap.)
31  ASSERT_EQ(25U, ntohs(reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_port));
32  freeaddrinfo(ai);
33}
34
35TEST(netdb, getaddrinfo_NULL_service) {
36  // It's okay for the service argument to be NULL, as long as host isn't.
37  addrinfo* ai = NULL;
38  ASSERT_EQ(0, getaddrinfo("localhost", NULL, NULL, &ai));
39  ASSERT_TRUE(ai != NULL);
40  freeaddrinfo(ai);
41}
42
43TEST(netdb, getaddrinfo_NULL_hints) {
44  addrinfo* ai = NULL;
45  ASSERT_EQ(0, getaddrinfo("localhost", "9999", NULL, &ai));
46
47  bool saw_tcp = false;
48  bool saw_udp = false;
49  for (addrinfo* p = ai; p != NULL; p = p->ai_next) {
50    ASSERT_TRUE(p->ai_family == AF_INET || p->ai_family == AF_INET6);
51    if (p->ai_socktype == SOCK_STREAM) {
52      ASSERT_EQ(IPPROTO_TCP, p->ai_protocol);
53      saw_tcp = true;
54    } else if (p->ai_socktype == SOCK_DGRAM) {
55      ASSERT_EQ(IPPROTO_UDP, p->ai_protocol);
56      saw_udp = true;
57    }
58  }
59  ASSERT_TRUE(saw_tcp);
60  ASSERT_TRUE(saw_udp);
61
62  freeaddrinfo(ai);
63}
64
65TEST(netdb, getaddrinfo_service_lookup) {
66  addrinfo* ai = NULL;
67  ASSERT_EQ(0, getaddrinfo("localhost", "smtp", NULL, &ai));
68  ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
69  ASSERT_EQ(IPPROTO_TCP, ai->ai_protocol);
70  ASSERT_EQ(25, ntohs(reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_port));
71  freeaddrinfo(ai);
72}
73
74TEST(netdb, getaddrinfo_hints) {
75  addrinfo hints;
76  memset(&hints, 0, sizeof(hints));
77  hints.ai_family = AF_UNSPEC;
78  hints.ai_socktype = SOCK_STREAM;
79  hints.ai_protocol = IPPROTO_TCP;
80
81  addrinfo* ai = NULL;
82  ASSERT_EQ(0, getaddrinfo( "localhost", "9999", &hints, &ai));
83  ASSERT_EQ(AF_INET, ai->ai_family);
84  ASSERT_EQ(SOCK_STREAM, ai->ai_socktype);
85  ASSERT_EQ(IPPROTO_TCP, ai->ai_protocol);
86  ASSERT_TRUE(ai->ai_next == NULL);
87  freeaddrinfo(ai);
88}
89
90TEST(netdb, getnameinfo_salen) {
91  sockaddr_storage ss;
92  memset(&ss, 0, sizeof(ss));
93  sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
94  char tmp[16];
95
96  ss.ss_family = AF_INET;
97  socklen_t too_much = sizeof(ss);
98  socklen_t just_right = sizeof(sockaddr_in);
99  socklen_t too_little = sizeof(sockaddr_in) - 1;
100
101  ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
102  ASSERT_STREQ("0.0.0.0", tmp);
103  ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
104  ASSERT_STREQ("0.0.0.0", tmp);
105  ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
106
107  ss.ss_family = AF_INET6;
108  just_right = sizeof(sockaddr_in6);
109  too_little = sizeof(sockaddr_in6) - 1;
110  too_much = just_right + 1;
111
112  ASSERT_EQ(0, getnameinfo(sa, too_much, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
113  ASSERT_STREQ("::", tmp);
114  ASSERT_EQ(0, getnameinfo(sa, just_right, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
115  ASSERT_STREQ("::", tmp);
116  ASSERT_EQ(EAI_FAMILY, getnameinfo(sa, too_little, tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST));
117}
118
119void VerifyLocalhost(hostent *hent) {
120  ASSERT_TRUE(hent != NULL);
121  ASSERT_EQ(hent->h_addrtype, AF_INET);
122  ASSERT_EQ(hent->h_addr[0], 127);
123  ASSERT_EQ(hent->h_addr[1], 0);
124  ASSERT_EQ(hent->h_addr[2], 0);
125  ASSERT_EQ(hent->h_addr[3], 1);
126}
127
128TEST(netdb, gethostbyname) {
129  hostent* hp = gethostbyname("localhost");
130  VerifyLocalhost(hp);
131}
132
133TEST(netdb, gethostbyname2) {
134  hostent* hp = gethostbyname2("localhost", AF_INET);
135  VerifyLocalhost(hp);
136}
137
138TEST(netdb, gethostbyname_r) {
139  hostent hent;
140  hostent *hp;
141  char buf[512];
142  int err;
143  int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err);
144  ASSERT_EQ(0, result);
145  VerifyLocalhost(hp);
146
147  // Change hp->h_addr to test reentrancy.
148  hp->h_addr[0] = 0;
149
150  hostent hent2;
151  hostent *hp2;
152  char buf2[512];
153  result = gethostbyname_r("localhost", &hent2, buf2, sizeof(buf2), &hp2, &err);
154  ASSERT_EQ(0, result);
155  VerifyLocalhost(hp2);
156
157  ASSERT_EQ(0, hp->h_addr[0]);
158}
159
160TEST(netdb, gethostbyname2_r) {
161  hostent hent;
162  hostent *hp;
163  char buf[512];
164  int err;
165  int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err);
166  ASSERT_EQ(0, result);
167  VerifyLocalhost(hp);
168
169  // Change hp->h_addr to test reentrancy.
170  hp->h_addr[0] = 0;
171
172  hostent hent2;
173  hostent *hp2;
174  char buf2[512];
175  result = gethostbyname2_r("localhost", AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err);
176  ASSERT_EQ(0, result);
177  VerifyLocalhost(hp2);
178
179  ASSERT_EQ(0, hp->h_addr[0]);
180}
181
182TEST(netdb, gethostbyaddr) {
183  char addr[4];
184  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr));
185  hostent *hp = gethostbyaddr(addr, sizeof(addr), AF_INET);
186  VerifyLocalhost(hp);
187}
188
189TEST(netdb, gethostbyaddr_r) {
190  char addr[4];
191  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr));
192
193  hostent hent;
194  hostent *hp;
195  char buf[512];
196  int err;
197  int result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
198  ASSERT_EQ(0, result);
199  VerifyLocalhost(hp);
200
201  // Change hp->h_addr to test reentrancy.
202  hp->h_addr[0] = 0;
203
204  hostent hent2;
205  hostent *hp2;
206  char buf2[512];
207  result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err);
208  ASSERT_EQ(0, result);
209  VerifyLocalhost(hp2);
210
211  ASSERT_EQ(0, hp->h_addr[0]);
212}
213
214TEST(netdb, gethostbyname_r_ERANGE) {
215  hostent hent;
216  hostent *hp;
217  char buf[4]; // Use too small buffer.
218  int err;
219  int result = gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &err);
220  ASSERT_EQ(ERANGE, result);
221  ASSERT_EQ(NULL, hp);
222}
223
224TEST(netdb, gethostbyname2_r_ERANGE) {
225  hostent hent;
226  hostent *hp;
227  char buf[4]; // Use too small buffer.
228  int err;
229  int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err);
230  ASSERT_EQ(ERANGE, result);
231  ASSERT_EQ(NULL, hp);
232}
233
234TEST(netdb, gethostbyaddr_r_ERANGE) {
235  char addr[4];
236  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", addr));
237
238  hostent hent;
239  hostent *hp;
240  char buf[4]; // Use too small buffer.
241  int err;
242  int result = gethostbyaddr_r(addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
243  ASSERT_EQ(ERANGE, result);
244  ASSERT_EQ(NULL, hp);
245}
246
247TEST(netdb, getservbyname) {
248  // smtp is TCP-only, so we know we'll get 25/tcp back.
249  servent* s = getservbyname("smtp", NULL);
250  ASSERT_TRUE(s != NULL);
251  ASSERT_EQ(25, ntohs(s->s_port));
252  ASSERT_STREQ("tcp", s->s_proto);
253
254  // We get the same result by explicitly asking for tcp.
255  s = getservbyname("smtp", "tcp");
256  ASSERT_TRUE(s != NULL);
257  ASSERT_EQ(25, ntohs(s->s_port));
258  ASSERT_STREQ("tcp", s->s_proto);
259
260  // And we get a failure if we explicitly ask for udp.
261  s = getservbyname("smtp", "udp");
262  ASSERT_TRUE(s == NULL);
263
264  // But there are actually udp services.
265  s = getservbyname("echo", "udp");
266  ASSERT_TRUE(s != NULL);
267  ASSERT_EQ(7, ntohs(s->s_port));
268  ASSERT_STREQ("udp", s->s_proto);
269}
270