1 /*
2 * Copyright (c) 2015 Fujitsu Ltd.
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: David L Stevens
19 */
20
21 #include <unistd.h>
22 #include <errno.h>
23
24 #include <sys/socket.h>
25 #include <netdb.h>
26 #include <arpa/inet.h>
27
28 #include "test.h"
29
30 #ifndef AI_V4MAPPED
31 #define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
32 #endif
33
34 static void setup(void);
35 static void gaiv4(void);
36 static void gaiv6(void);
37
38 char *TCID = "getaddrinfo_01";
39 int TST_TOTAL = 22;
40
main(int argc,char * argv[])41 int main(int argc, char *argv[])
42 {
43 int lc;
44
45 tst_parse_opts(argc, argv, NULL, NULL);
46
47 setup();
48
49 for (lc = 0; TEST_LOOPING(lc); ++lc) {
50 tst_count = 0;
51
52 gaiv4();
53 gaiv6();
54 }
55
56 tst_exit();
57 }
58
setup(void)59 static void setup(void)
60 {
61 TEST_PAUSE;
62 }
63
64 /* getaddrinfo tests (v4) */
gaiv4(void)65 static void gaiv4(void)
66 {
67 struct addrinfo *aires, hints, *pai;
68 char hostname[MAXHOSTNAMELEN + 1];
69 char shortname[MAXHOSTNAMELEN + 1];
70 char service[NI_MAXSERV + 1];
71 int servnum;
72 char *p;
73
74 if (gethostname(hostname, sizeof(hostname)) < 0)
75 tst_brkm(TBROK | TERRNO, NULL, "gethostname failed");
76 strncpy(shortname, hostname, MAXHOSTNAMELEN);
77 shortname[MAXHOSTNAMELEN] = '\0';
78 p = strchr(shortname, '.');
79 if (p)
80 *p = '\0';
81
82 /* test 1, IPv4 basic lookup */
83 memset(&hints, 0, sizeof(hints));
84 hints.ai_family = AF_INET;
85 TEST(getaddrinfo(hostname, 0, &hints, &aires));
86 if (!TEST_RETURN) {
87 struct sockaddr_in *psin = 0;
88 int err = 0;
89
90 for (pai = aires; pai; pai = pai->ai_next) {
91 err |= pai->ai_family != AF_INET;
92 err |= pai->ai_addrlen != sizeof(struct sockaddr_in);
93 err |= pai->ai_addr == 0;
94 psin = (struct sockaddr_in *)pai->ai_addr;
95 if (pai->ai_addr) {
96 err |= psin->sin_family != AF_INET;
97 err |= psin->sin_port != 0;
98 }
99 if (err)
100 break;
101 }
102 if (err) {
103 tst_resm(TFAIL, "getaddrinfo IPv4 basic lookup: "
104 "fam %d alen %d addr 0x%p addr/fam %d "
105 "addr/port %d H[%d]",
106 pai->ai_family, pai->ai_addrlen, psin,
107 psin ? psin->sin_family : 0,
108 psin ? psin->sin_port : 0,
109 psin ? htons(psin->sin_port) : 0);
110 freeaddrinfo(aires);
111 return;
112 }
113 tst_resm(TPASS, "getaddrinfo IPv4 basic lookup");
114 freeaddrinfo(aires);
115 } else {
116 tst_resm(TFAIL, "getaddrinfo IPv4 basic "
117 "lookup (\"%s\") returns %ld (\"%s\")", hostname,
118 TEST_RETURN, gai_strerror(TEST_RETURN));
119 return;
120 }
121
122 /* test 2, IPv4 canonical name */
123 memset(&hints, 0, sizeof(hints));
124 hints.ai_family = AF_INET;
125 hints.ai_flags = AI_CANONNAME;
126 TEST(getaddrinfo(shortname, 0, &hints, &aires));
127 if (!TEST_RETURN) {
128 for (pai = aires; pai; pai = pai->ai_next)
129 if (pai->ai_canonname)
130 break;
131 if (!pai) {
132 tst_resm(TFAIL, "getaddrinfo IPv4 canonical name: no "
133 "entries with canonical name set");
134 freeaddrinfo(aires);
135 return;
136 } else if (strcasecmp(hostname, pai->ai_canonname)) {
137 tst_resm(TFAIL, "getaddrinfo IPv4 canonical name "
138 "(\"%s\") doesn't match hostname (\"%s\")",
139 pai->ai_canonname, hostname);
140 freeaddrinfo(aires);
141 return;
142 }
143 tst_resm(TPASS, "getaddrinfo IPv4 canonical name");
144 freeaddrinfo(aires);
145 } else {
146 tst_resm(TFAIL, "getaddrinfo IPv4 "
147 "canonical name (\"%s\") returns %ld (\"%s\")",
148 shortname, TEST_RETURN, gai_strerror(TEST_RETURN));
149 return;
150 }
151
152 /* test 3, IPv4 host+service name */
153 memset(&hints, 0, sizeof(hints));
154 /*
155 * These are hard-coded for echo/7 to avoid using getservbyname(),
156 * since it isn't thread-safe and these tests may be re-used
157 * multithreaded. Sigh.
158 */
159 strcpy(service, "echo");
160 servnum = 7;
161 hints.ai_family = AF_INET;
162 TEST(getaddrinfo(hostname, service, &hints, &aires));
163 if (!TEST_RETURN) {
164 struct sockaddr_in *psin = 0;
165 int err = 0;
166
167 for (pai = aires; pai; pai = pai->ai_next) {
168 err |= pai->ai_family != AF_INET;
169 err |= pai->ai_addrlen != sizeof(struct sockaddr_in);
170 err |= pai->ai_addr == 0;
171 psin = (struct sockaddr_in *)pai->ai_addr;
172 if (pai->ai_addr) {
173 err |= psin->sin_family != AF_INET;
174 err |= psin->sin_port != htons(servnum);
175 }
176 if (err)
177 break;
178 }
179 if (err) {
180 tst_resm(TFAIL, "getaddrinfo IPv4 host+service: "
181 "fam %d alen %d addr 0x%p addr/fam %d "
182 "addr/port %d H[%d]",
183 pai->ai_family, pai->ai_addrlen, psin,
184 psin ? psin->sin_family : 0,
185 psin ? psin->sin_port : 0,
186 psin ? htons(psin->sin_port) : 0);
187 freeaddrinfo(aires);
188 return;
189 }
190 tst_resm(TPASS, "getaddrinfo IPv4 host+service");
191 freeaddrinfo(aires);
192 } else {
193 tst_resm(TFAIL, "getaddrinfo IPv4 host+"
194 "service returns %ld (\"%s\")", TEST_RETURN,
195 gai_strerror(TEST_RETURN));
196 return;
197 }
198
199 /* test 4, IPv4 hostname+service, AI_PASSIVE */
200 memset(&hints, 0, sizeof(hints));
201 hints.ai_family = AF_INET;
202 hints.ai_flags = AI_PASSIVE;
203 hints.ai_socktype = SOCK_STREAM;
204 strcpy(service, "9462");
205 servnum = htons(9462);
206 TEST(getaddrinfo(hostname, service, &hints, &aires));
207 if (!TEST_RETURN) {
208 struct sockaddr_in *psin = 0;
209 int err = 0;
210
211 for (pai = aires; pai; pai = pai->ai_next) {
212 err |= pai->ai_family != AF_INET;
213 err |= pai->ai_addrlen != sizeof(struct sockaddr_in);
214 err |= pai->ai_addr == 0;
215 psin = (struct sockaddr_in *)pai->ai_addr;
216 if (pai->ai_addr) {
217 /* AI_PASSIVE is ignored if hostname is
218 * non-null; address must be set
219 */
220 err |= psin->sin_addr.s_addr == 0;
221 err |= psin->sin_family != AF_INET;
222 err |= psin->sin_port != servnum;
223 }
224 if (err)
225 break;
226 }
227 if (err) {
228 tst_resm(TFAIL, "getaddrinfo IPv4 host+service, PASSIVE"
229 ": fam %d alen %d addr 0x%p addr/fam %d "
230 "addr/port %d H[%d]",
231 pai->ai_family, pai->ai_addrlen, psin,
232 psin ? psin->sin_family : 0,
233 psin ? psin->sin_port : 0,
234 psin ? htons(psin->sin_port) : 0);
235 freeaddrinfo(aires);
236 return;
237 }
238 tst_resm(TPASS, "getaddrinfo IPv4 host+service PASSIVE");
239 freeaddrinfo(aires);
240 } else {
241 tst_resm(TFAIL, "getaddrinfo IPv4 host+"
242 "service, PASSIVE (\"%s\", \"%s\") returns %ld (\"%s\")",
243 hostname, service, TEST_RETURN,
244 gai_strerror(TEST_RETURN));
245 return;
246 }
247
248 /* test 5, IPv4 host+service w/ AI_NUMERICHOST */
249 memset(&hints, 0, sizeof(hints));
250 strcpy(service, "echo");
251 servnum = 7;
252 hints.ai_family = AF_INET;
253 hints.ai_flags = AI_NUMERICHOST;
254 TEST(getaddrinfo(hostname, service, &hints, &aires));
255 if (TEST_RETURN != EAI_NONAME) {
256 tst_resm(TFAIL, "getaddrinfo IPv4 AI_NUMERICHOST w/ hostname: "
257 "returns %ld expected %d (EAI_NONAME)",
258 TEST_RETURN, EAI_NONAME);
259 if (!TEST_RETURN)
260 freeaddrinfo(aires);
261 return;
262 }
263 tst_resm(TPASS, "getaddrinfo IPv4 AI_NUMERICHOST w/ hostname");
264 if (!TEST_RETURN)
265 freeaddrinfo(aires);
266
267 /* test 6, IPv4 0+service, AI_PASSIVE */
268 memset(&hints, 0, sizeof(hints));
269 hints.ai_family = AF_INET;
270 hints.ai_flags = AI_PASSIVE;
271 hints.ai_socktype = SOCK_STREAM;
272 strcpy(service, "9462");
273 servnum = htons(9462);
274 TEST(getaddrinfo(0, service, &hints, &aires));
275 if (!TEST_RETURN) {
276 struct sockaddr_in *psin = 0;
277 int err = 0;
278
279 for (pai = aires; pai; pai = pai->ai_next) {
280 err |= pai->ai_family != AF_INET;
281 err |= pai->ai_addrlen != sizeof(struct sockaddr_in);
282 err |= pai->ai_addr == 0;
283 psin = (struct sockaddr_in *)pai->ai_addr;
284 if (pai->ai_addr) {
285
286 /* AI_PASSIVE means addr must be INADDR_ANY */
287 err |= psin->sin_addr.s_addr != 0;
288 err |= psin->sin_family != AF_INET;
289 err |= psin->sin_port != servnum;
290 }
291 if (err)
292 break;
293 }
294 if (err) {
295 tst_resm(TFAIL, "getaddrinfo IPv4 0+service, PASSIVE:"
296 " fam %d alen %d addr 0x%p addr/fam %d "
297 "addr/port %d H[%d]",
298 pai->ai_family, pai->ai_addrlen, psin,
299 psin ? psin->sin_family : 0,
300 psin ? psin->sin_port : 0,
301 psin ? htons(psin->sin_port) : 0);
302 freeaddrinfo(aires);
303 return;
304 }
305 tst_resm(TPASS, "getaddrinfo IPv4 0+service, PASSIVE");
306 freeaddrinfo(aires);
307 } else {
308 if (TEST_RETURN == EAI_BADFLAGS) {
309 tst_resm(TPASS, "getaddrinfo IPv4 0+service,"
310 " PASSIVE (\"\", \"%s\") returns %ld (\"%s\")",
311 service, TEST_RETURN,
312 gai_strerror(TEST_RETURN));
313 } else {
314 tst_resm(TFAIL, "getaddrinfo IPv4 0+service,"
315 " PASSIVE (\"\", \"%s\") returns %ld (\"%s\")",
316 service, TEST_RETURN,
317 gai_strerror(TEST_RETURN));
318 return;
319 }
320 }
321
322 /* test 7, IPv4 0+service */
323 memset(&hints, 0, sizeof(hints));
324 hints.ai_family = AF_INET;
325 hints.ai_socktype = SOCK_STREAM;
326 strcpy(service, "9462");
327 servnum = htons(9462);
328 TEST(getaddrinfo(0, service, &hints, &aires));
329 if (!TEST_RETURN) {
330 struct sockaddr_in *psin = 0;
331 int err = 0;
332
333 for (pai = aires; pai; pai = pai->ai_next) {
334 err |= pai->ai_family != AF_INET;
335 err |= pai->ai_addrlen != sizeof(struct sockaddr_in);
336 err |= pai->ai_addr == 0;
337 psin = (struct sockaddr_in *)pai->ai_addr;
338 if (pai->ai_addr) {
339 /* hostname not set; addr should be loopback */
340 err |= psin->sin_addr.s_addr !=
341 htonl(INADDR_LOOPBACK);
342 err |= psin->sin_family != AF_INET;
343 err |= psin->sin_port != servnum;
344 }
345 if (err)
346 break;
347 }
348 if (err) {
349 tst_resm(TFAIL, "getaddrinfo IPv4 0+service: "
350 "fam %d alen %d addr 0x%p addr/fam %d "
351 "addr/port %d H[%d]",
352 pai->ai_family, pai->ai_addrlen, psin,
353 psin ? psin->sin_family : 0,
354 psin ? psin->sin_port : 0,
355 psin ? htons(psin->sin_port) : 0);
356 freeaddrinfo(aires);
357 return;
358 }
359 tst_resm(TPASS, "getaddrinfo IPv4 0+service");
360 freeaddrinfo(aires);
361 } else {
362 if (TEST_RETURN == EAI_BADFLAGS) {
363 tst_resm(TPASS, "getaddrinfo IPv4 "
364 "0+service (\"\", \"%s\") returns %ld (\"%s\")",
365 service, TEST_RETURN,
366 gai_strerror(TEST_RETURN));
367 } else {
368 tst_resm(TFAIL, "getaddrinfo IPv4 "
369 "0+service (\"\", \"%s\") returns %ld (\"%s\")",
370 service, TEST_RETURN,
371 gai_strerror(TEST_RETURN));
372 return;
373 }
374 }
375
376 /* test 8, IPv4 host+service, AI_NUMERICSERV */
377 #ifndef AI_NUMERICSERV
378 tst_resm(TCONF, "getaddrinfo IPv4 host+service, AI_NUMERICSERV: flag "
379 "not implemented");
380 #else
381 memset(&hints, 0, sizeof(hints));
382 strcpy(service, "echo");
383 servnum = 7;
384 hints.ai_family = AF_INET;
385 hints.ai_flags = AI_NUMERICSERV;
386 TEST(getaddrinfo(hostname, service, &hints, &aires));
387 if (TEST_RETURN != EAI_NONAME) {
388 tst_resm(TFAIL,
389 "getaddrinfo IPv4 host+service, AI_NUMERICSERV: "
390 "returns %ld (\"%s\") expected %d (EAI_NONAME)",
391 TEST_RETURN, gai_strerror(TEST_RETURN), EAI_NONAME);
392 if (!TEST_RETURN)
393 freeaddrinfo(aires);
394 return;
395 }
396 tst_resm(TPASS, "getaddrinfo IPv4 host+service, AI_NUMERICSERV");
397 if (!TEST_RETURN)
398 freeaddrinfo(aires);
399 #endif /* AI_NUMERICSERV */
400
401 /* test 9, IPv4 SOCK_STREAM/IPPROTO_UDP hints */
402 memset(&hints, 0, sizeof(hints));
403 hints.ai_family = AF_INET;
404 hints.ai_socktype = SOCK_STREAM;
405 hints.ai_protocol = IPPROTO_UDP;
406 strcpy(service, "9462");
407 servnum = htons(9462);
408 TEST(getaddrinfo(0, service, &hints, &aires));
409 if (!TEST_RETURN) {
410 tst_resm(TFAIL, "getaddrinfo IPv4 SOCK_STREAM/IPPROTO_UDP "
411 "hints");
412 freeaddrinfo(aires);
413 return;
414 }
415 tst_resm(TPASS, "getaddrinfo IPv4 SOCK_STREAM/IPPROTO_UDP hints");
416
417 /* test 10, IPv4 socktype 0, 513 */
418 memset(&hints, 0, sizeof(hints));
419 hints.ai_family = AF_INET;
420 hints.ai_socktype = 0;
421 strcpy(service, "513");
422 servnum = htons(513);
423 TEST(getaddrinfo(0, service, &hints, &aires));
424 if (!TEST_RETURN) {
425 struct sockaddr_in *psin = 0;
426 int got_tcp, got_udp;
427 int err = 0;
428
429 got_tcp = got_udp = 0;
430 for (pai = aires; pai; pai = pai->ai_next) {
431 err |= pai->ai_family != AF_INET;
432 err |= pai->ai_addrlen != sizeof(struct sockaddr_in);
433 err |= pai->ai_addr == 0;
434 got_tcp |= pai->ai_socktype == SOCK_STREAM;
435 got_udp |= pai->ai_socktype == SOCK_DGRAM;
436 psin = (struct sockaddr_in *)pai->ai_addr;
437 if (pai->ai_addr) {
438 /* hostname not set; addr should be loopback */
439 err |= psin->sin_addr.s_addr !=
440 htonl(INADDR_LOOPBACK);
441 err |= psin->sin_family != AF_INET;
442 err |= psin->sin_port != servnum;
443 }
444 if (err)
445 break;
446 }
447 if (err) {
448 tst_resm(TFAIL, "getaddrinfo IPv4 socktype 0,513: "
449 "fam %d alen %d addr 0x%p addr/fam %d "
450 "addr/port %d H[%d]",
451 pai->ai_family, pai->ai_addrlen, psin,
452 psin ? psin->sin_family : 0,
453 psin ? psin->sin_port : 0,
454 psin ? htons(psin->sin_port) : 0);
455 freeaddrinfo(aires);
456 return;
457 } else if (got_tcp && got_udp) {
458 tst_resm(TPASS, "getaddrinfo IPv4 socktype 0,513");
459 freeaddrinfo(aires);
460 } else {
461 tst_resm(TFAIL, "getaddrinfo IPv4 socktype 0,513 TCP %d"
462 " UDP %d", got_tcp, got_udp);
463 freeaddrinfo(aires);
464 return;
465 }
466 } else {
467 if (TEST_RETURN == EAI_BADFLAGS) {
468 tst_resm(TPASS, "getaddrinfo IPv4 socktype 0,513"
469 " (\"\", \"%s\") returns %ld (\"%s\")", service,
470 TEST_RETURN, gai_strerror(TEST_RETURN));
471 } else {
472 tst_resm(TFAIL, "getaddrinfo IPv4 socktype 0,513"
473 " (\"\", \"%s\") returns %ld (\"%s\")", service,
474 TEST_RETURN, gai_strerror(TEST_RETURN));
475 return;
476 }
477 }
478
479 /* test 11, IPv4 AI_V4MAPPED */
480 /* AI_V4MAPPED should be ignored because family != AF_INET6 */
481 memset(&hints, 0, sizeof(hints));
482 hints.ai_family = AF_INET;
483 hints.ai_flags = AI_V4MAPPED;
484 TEST(getaddrinfo(hostname, 0, &hints, &aires));
485 if (!TEST_RETURN) {
486 struct sockaddr_in *psin = 0;
487 int err = 0;
488
489 for (pai = aires; pai; pai = pai->ai_next) {
490 err |= pai->ai_family != AF_INET;
491 err |= pai->ai_addrlen != sizeof(struct sockaddr_in);
492 err |= pai->ai_addr == 0;
493 psin = (struct sockaddr_in *)pai->ai_addr;
494 if (pai->ai_addr) {
495 err |= psin->sin_family != AF_INET;
496 err |= psin->sin_port != 0;
497 }
498 if (err)
499 break;
500 }
501 if (err) {
502 tst_resm(TFAIL, "getaddrinfo IPv4 AI_V4MAPPED: "
503 "fam %d alen %d addr 0x%p addr/fam %d "
504 "addr/port %d H[%d]",
505 pai->ai_family, pai->ai_addrlen, psin,
506 psin ? psin->sin_family : 0,
507 psin ? psin->sin_port : 0,
508 psin ? htons(psin->sin_port) : 0);
509 freeaddrinfo(aires);
510 return;
511 }
512 tst_resm(TPASS, "getaddrinfo IPv4 AI_V4MAPPED");
513 freeaddrinfo(aires);
514 } else {
515 tst_resm(TFAIL, "getaddrinfo IPv4 "
516 "AI_V4MAPPED (\"%s\") returns %ld (\"%s\")", hostname,
517 TEST_RETURN, gai_strerror(TEST_RETURN));
518 return;
519 }
520 }
521
522 /* getaddrinfo tests (v6) */
gaiv6(void)523 static void gaiv6(void)
524 {
525 struct addrinfo *aires, hints, *pai;
526 char hostname[MAXHOSTNAMELEN + 1];
527 char shortname[MAXHOSTNAMELEN + 1];
528 char service[NI_MAXSERV + 1];
529 int servnum;
530 char *p;
531
532 if (gethostname(hostname, sizeof(hostname)) < 0)
533 tst_brkm(TBROK, NULL, "gethostname failed - %s",
534 strerror(errno));
535 strncpy(shortname, hostname, MAXHOSTNAMELEN);
536 shortname[MAXHOSTNAMELEN] = '\0';
537 p = strchr(shortname, '.');
538 if (p)
539 *p = '\0';
540
541 /* test 12, IPv6 basic lookup */
542 memset(&hints, 0, sizeof(hints));
543 hints.ai_family = AF_INET6;
544 TEST(getaddrinfo(hostname, 0, &hints, &aires));
545 if (!TEST_RETURN) {
546 struct sockaddr_in6 *psin6 = 0;
547 int err = 0;
548
549 for (pai = aires; pai; pai = pai->ai_next) {
550 err |= pai->ai_family != AF_INET6;
551 err |= pai->ai_addrlen != sizeof(struct sockaddr_in6);
552 err |= pai->ai_addr == 0;
553 psin6 = (struct sockaddr_in6 *)pai->ai_addr;
554 if (pai->ai_addr) {
555 err |= psin6->sin6_family != AF_INET6;
556 err |= psin6->sin6_port != 0;
557 }
558 if (err)
559 break;
560 }
561 if (err) {
562 tst_resm(TFAIL, "getaddrinfo IPv6 basic lookup: "
563 "fam %d alen %d addr 0x%p addr/fam %d "
564 "addr/port %d H[%d]",
565 pai->ai_family, pai->ai_addrlen, psin6,
566 psin6 ? psin6->sin6_family : 0,
567 psin6 ? psin6->sin6_port : 0,
568 psin6 ? htons(psin6->sin6_port) : 0);
569 freeaddrinfo(aires);
570 return;
571 }
572 tst_resm(TPASS, "getaddrinfo IPv6 basic lookup");
573 freeaddrinfo(aires);
574 } else {
575 tst_resm(TFAIL, "getaddrinfo IPv6 basic "
576 "lookup (\"%s\") returns %ld (\"%s\")", hostname,
577 TEST_RETURN, gai_strerror(TEST_RETURN));
578 return;
579 }
580
581 /* test 13, IPv6 canonical name */
582 memset(&hints, 0, sizeof(hints));
583 hints.ai_family = AF_INET6;
584 hints.ai_flags = AI_CANONNAME;
585 TEST(getaddrinfo(shortname, 0, &hints, &aires));
586 if (!TEST_RETURN) {
587 for (pai = aires; pai; pai = pai->ai_next)
588 if (pai->ai_canonname)
589 break;
590 if (!pai) {
591 tst_resm(TFAIL, "getaddrinfo IPv6 canonical name: no "
592 "entries with canonical name set");
593 freeaddrinfo(aires);
594 return;
595 } else if (strcasecmp(hostname, pai->ai_canonname)) {
596 tst_resm(TFAIL, "getaddrinfo IPv6 canonical name "
597 "(\"%s\") doesn't match hostname (\"%s\")",
598 pai->ai_canonname, hostname);
599 freeaddrinfo(aires);
600 return;
601 }
602 tst_resm(TPASS, "getaddrinfo IPv6 canonical name");
603 freeaddrinfo(aires);
604 } else {
605 tst_resm(TFAIL, "getaddrinfo IPv6 "
606 "canonical name (\"%s\") returns %ld (\"%s\")",
607 shortname, TEST_RETURN, gai_strerror(TEST_RETURN));
608 return;
609 }
610
611 /* test 14, IPv6 host+service name */
612 memset(&hints, 0, sizeof(hints));
613 /*
614 * These are hard-coded for echo/7 to avoid using getservbyname(),
615 * since it isn't thread-safe and these tests may be re-used
616 * multithreaded. Sigh.
617 */
618 strcpy(service, "echo");
619 servnum = 7;
620 hints.ai_family = AF_INET6;
621 TEST(getaddrinfo(hostname, service, &hints, &aires));
622 if (!TEST_RETURN) {
623 struct sockaddr_in6 *psin6 = 0;
624 int err = 0;
625
626 for (pai = aires; pai; pai = pai->ai_next) {
627 err |= pai->ai_family != AF_INET6;
628 err |= pai->ai_addrlen != sizeof(struct sockaddr_in6);
629 err |= pai->ai_addr == 0;
630 psin6 = (struct sockaddr_in6 *)pai->ai_addr;
631 if (pai->ai_addr) {
632 err |= psin6->sin6_family != AF_INET6;
633 err |= psin6->sin6_port != htons(servnum);
634 }
635 if (err)
636 break;
637 }
638 if (err) {
639 tst_resm(TFAIL, "getaddrinfo IPv6 host+service: "
640 "fam %d alen %d addr 0x%p addr/fam %d "
641 "addr/port %d H[%d]",
642 pai->ai_family, pai->ai_addrlen, psin6,
643 psin6 ? psin6->sin6_family : 0,
644 psin6 ? psin6->sin6_port : 0,
645 psin6 ? htons(psin6->sin6_port) : 0);
646 freeaddrinfo(aires);
647 return;
648 }
649 tst_resm(TPASS, "getaddrinfo IPv6 host+service");
650 freeaddrinfo(aires);
651 } else {
652 tst_resm(TFAIL, "getaddrinfo IPv6 host+"
653 "service returns %ld (\"%s\")", TEST_RETURN,
654 gai_strerror(TEST_RETURN));
655 return;
656 }
657
658 /* test 15, IPv6 hostname+service, AI_PASSIVE */
659 memset(&hints, 0, sizeof(hints));
660 hints.ai_family = AF_INET6;
661 hints.ai_flags = AI_PASSIVE;
662 hints.ai_socktype = SOCK_STREAM;
663 strcpy(service, "9462");
664 servnum = htons(9462);
665 TEST(getaddrinfo(hostname, service, &hints, &aires));
666 if (!TEST_RETURN) {
667 struct sockaddr_in6 *psin6 = 0;
668 int err = 0;
669
670 for (pai = aires; pai; pai = pai->ai_next) {
671 err |= pai->ai_family != AF_INET6;
672 err |= pai->ai_addrlen != sizeof(struct sockaddr_in6);
673 err |= pai->ai_addr == 0;
674 psin6 = (struct sockaddr_in6 *)pai->ai_addr;
675 if (pai->ai_addr) {
676 /* AI_PASSIVE is ignored if hostname is
677 * non-null; address must be set
678 */
679 err |= memcmp(&psin6->sin6_addr, &in6addr_any,
680 sizeof(struct in6_addr)) == 0;
681 err |= psin6->sin6_family != AF_INET6;
682 err |= psin6->sin6_port != servnum;
683 }
684 if (err)
685 break;
686 }
687 if (err) {
688 tst_resm(TFAIL, "getaddrinfo IPv6 host+service, PASSIVE"
689 ": fam %d alen %d addr 0x%p addr/fam %d "
690 "addr/port %d H[%d]",
691 pai->ai_family, pai->ai_addrlen, psin6,
692 psin6 ? psin6->sin6_family : 0,
693 psin6 ? psin6->sin6_port : 0,
694 psin6 ? htons(psin6->sin6_port) : 0);
695 freeaddrinfo(aires);
696 return;
697 }
698 tst_resm(TPASS, "getaddrinfo IPv6 host+service PASSIVE");
699 freeaddrinfo(aires);
700 } else {
701 tst_resm(TFAIL, "getaddrinfo IPv6 host+"
702 "service, PASSIVE (\"%s\", \"%s\") returns %ld (\"%s\")",
703 hostname, service, TEST_RETURN,
704 gai_strerror(TEST_RETURN));
705 return;
706 }
707
708 /* test 16, IPv6 host+service w/ AI_NUMERICHOST */
709 memset(&hints, 0, sizeof(hints));
710 strcpy(service, "echo");
711 servnum = 7;
712 hints.ai_family = AF_INET6;
713 hints.ai_flags = AI_NUMERICHOST;
714 TEST(getaddrinfo(hostname, service, &hints, &aires));
715 if (TEST_RETURN != EAI_NONAME) {
716 tst_resm(TFAIL, "getaddrinfo IPv6 AI_NUMERICHOST w/ hostname: "
717 "returns %ld expected %d (EAI_NONAME)",
718 TEST_RETURN, EAI_NONAME);
719 if (!TEST_RETURN)
720 freeaddrinfo(aires);
721 return;
722 }
723 tst_resm(TPASS, "getaddrinfo IPv6 AI_NUMERICHOST w/ hostname");
724 if (!TEST_RETURN)
725 freeaddrinfo(aires);
726
727 /* test 17, IPv6 0+service, AI_PASSIVE */
728 memset(&hints, 0, sizeof(hints));
729 hints.ai_family = AF_INET6;
730 hints.ai_flags = AI_PASSIVE;
731 hints.ai_socktype = SOCK_STREAM;
732 strcpy(service, "9462");
733 servnum = htons(9462);
734 TEST(getaddrinfo(0, service, &hints, &aires));
735 if (!TEST_RETURN) {
736 struct sockaddr_in6 *psin6 = 0;
737 int err = 0;
738
739 for (pai = aires; pai; pai = pai->ai_next) {
740 err |= pai->ai_family != AF_INET6;
741 err |= pai->ai_addrlen != sizeof(struct sockaddr_in6);
742 err |= pai->ai_addr == 0;
743 psin6 = (struct sockaddr_in6 *)pai->ai_addr;
744 if (pai->ai_addr) {
745
746 /* AI_PASSIVE means addr must be INADDR_ANY */
747 err |= memcmp(&psin6->sin6_addr, &in6addr_any,
748 sizeof(struct in6_addr)) != 0;
749 err |= psin6->sin6_family != AF_INET6;
750 err |= psin6->sin6_port != servnum;
751 }
752 if (err)
753 break;
754 }
755 if (err) {
756 tst_resm(TFAIL, "getaddrinfo IPv6 0+service, PASSIVE:"
757 " fam %d alen %d addr 0x%p addr/fam %d "
758 "addr/port %d H[%d]",
759 pai->ai_family, pai->ai_addrlen, psin6,
760 psin6 ? psin6->sin6_family : 0,
761 psin6 ? psin6->sin6_port : 0,
762 psin6 ? htons(psin6->sin6_port) : 0);
763 freeaddrinfo(aires);
764 return;
765 }
766 tst_resm(TPASS, "getaddrinfo IPv6 0+service, PASSIVE");
767 freeaddrinfo(aires);
768 } else {
769 if (TEST_RETURN == EAI_BADFLAGS) {
770 tst_resm(TPASS, "getaddrinfo IPv6 0+service, PASSIVE"
771 " (\"\", \"%s\") returns %ld (\"%s\")", service,
772 TEST_RETURN, gai_strerror(TEST_RETURN));
773 } else {
774 tst_resm(TFAIL, "getaddrinfo IPv6 0+service, PASSIVE"
775 " (\"\", \"%s\") returns %ld (\"%s\")", service,
776 TEST_RETURN, gai_strerror(TEST_RETURN));
777 return;
778 }
779 }
780
781 /* test 18, IPv6 0+service */
782 memset(&hints, 0, sizeof(hints));
783 hints.ai_family = AF_INET6;
784 hints.ai_socktype = SOCK_STREAM;
785 strcpy(service, "9462");
786 servnum = htons(9462);
787 TEST(getaddrinfo(0, service, &hints, &aires));
788 if (!TEST_RETURN) {
789 struct sockaddr_in6 *psin6 = 0;
790 int err = 0;
791
792 for (pai = aires; pai; pai = pai->ai_next) {
793 err |= pai->ai_family != AF_INET6;
794 err |= pai->ai_addrlen != sizeof(struct sockaddr_in6);
795 err |= pai->ai_addr == 0;
796 psin6 = (struct sockaddr_in6 *)pai->ai_addr;
797 if (pai->ai_addr) {
798 /* hostname not set; addr should be loopback */
799 err |= memcmp(&psin6->sin6_addr,
800 &in6addr_loopback,
801 sizeof(struct in6_addr)) != 0;
802 err |= psin6->sin6_family != AF_INET6;
803 err |= psin6->sin6_port != servnum;
804 }
805 if (err)
806 break;
807 }
808 if (err) {
809 tst_resm(TFAIL, "getaddrinfo IPv6 0+service: "
810 "fam %d alen %d addr 0x%p addr/fam %d "
811 "addr/port %d H[%d]",
812 pai->ai_family, pai->ai_addrlen, psin6,
813 psin6 ? psin6->sin6_family : 0,
814 psin6 ? psin6->sin6_port : 0,
815 psin6 ? htons(psin6->sin6_port) : 0);
816 freeaddrinfo(aires);
817 return;
818 }
819 tst_resm(TPASS, "getaddrinfo IPv6 0+service");
820 freeaddrinfo(aires);
821 } else {
822 if (TEST_RETURN == EAI_BADFLAGS) {
823 tst_resm(TPASS, "getaddrinfo IPv6 0+service"
824 " (\"\", \"%s\") returns %ld (\"%s\")", service,
825 TEST_RETURN, gai_strerror(TEST_RETURN));
826 } else {
827 tst_resm(TFAIL, "getaddrinfo IPv6 0+service"
828 " (\"\", \"%s\") returns %ld (\"%s\")", service,
829 TEST_RETURN, gai_strerror(TEST_RETURN));
830 return;
831 }
832 }
833
834 /* test 19, IPv6 host+service, AI_NUMERICSERV */
835 #ifndef AI_NUMERICSERV
836 tst_resm(TCONF, "getaddrinfo IPv6 host+service, AI_NUMERICSERV: flag "
837 "not implemented");
838 #else
839 memset(&hints, 0, sizeof(hints));
840 strcpy(service, "echo");
841 servnum = 7;
842 hints.ai_family = AF_INET6;
843 hints.ai_flags = AI_NUMERICSERV;
844 TEST(getaddrinfo(hostname, service, &hints, &aires));
845 if (TEST_RETURN != EAI_NONAME) {
846 tst_resm(TFAIL,
847 "getaddrinfo IPv6 host+service, AI_NUMERICSERV: "
848 "returns %ld (\"%s\") expected %d (EAI_NONAME)",
849 TEST_RETURN, gai_strerror(TEST_RETURN), EAI_NONAME);
850 if (!TEST_RETURN)
851 freeaddrinfo(aires);
852 return;
853 }
854 tst_resm(TPASS, "getaddrinfo IPv6 host+service, AI_NUMERICSERV");
855 if (!TEST_RETURN)
856 freeaddrinfo(aires);
857 #endif /* AI_NUMERICSERV */
858
859 /* test 20, IPv6 SOCK_STREAM/IPPROTO_UDP hints */
860 memset(&hints, 0, sizeof(hints));
861 hints.ai_family = AF_INET6;
862 hints.ai_socktype = SOCK_STREAM;
863 hints.ai_protocol = IPPROTO_UDP;
864 strcpy(service, "9462");
865 servnum = htons(9462);
866 TEST(getaddrinfo(0, service, &hints, &aires));
867 if (!TEST_RETURN) {
868 tst_resm(TFAIL, "getaddrinfo IPv6 SOCK_STREAM/IPPROTO_UDP "
869 "hints");
870 freeaddrinfo(aires);
871 return;
872 }
873 tst_resm(TPASS, "getaddrinfo IPv6 SOCK_STREAM/IPPROTO_UDP hints");
874
875 /* test 21, IPv6 socktype 0, 513 */
876 memset(&hints, 0, sizeof(hints));
877 hints.ai_family = AF_INET6;
878 hints.ai_socktype = 0;
879 strcpy(service, "513");
880 servnum = htons(513);
881 TEST(getaddrinfo(0, service, &hints, &aires));
882 if (!TEST_RETURN) {
883 struct sockaddr_in6 *psin6 = 0;
884 int got_tcp, got_udp;
885 int err = 0;
886
887 got_tcp = got_udp = 0;
888 for (pai = aires; pai; pai = pai->ai_next) {
889 err |= pai->ai_family != AF_INET6;
890 err |= pai->ai_addrlen != sizeof(struct sockaddr_in6);
891 err |= pai->ai_addr == 0;
892 got_tcp |= pai->ai_socktype == SOCK_STREAM;
893 got_udp |= pai->ai_socktype == SOCK_DGRAM;
894 psin6 = (struct sockaddr_in6 *)pai->ai_addr;
895 if (pai->ai_addr) {
896 /* hostname not set; addr should be loopback */
897 err |= memcmp(&psin6->sin6_addr,
898 &in6addr_loopback,
899 sizeof(struct in6_addr)) != 0;
900 err |= psin6->sin6_family != AF_INET6;
901 err |= psin6->sin6_port != servnum;
902 }
903 if (err)
904 break;
905 }
906 if (err) {
907 tst_resm(TFAIL, "getaddrinfo IPv6 socktype 0,513: "
908 "fam %d alen %d addr 0x%p addr/fam %d "
909 "addr/port %d H[%d]",
910 pai->ai_family, pai->ai_addrlen, psin6,
911 psin6 ? psin6->sin6_family : 0,
912 psin6 ? psin6->sin6_port : 0,
913 psin6 ? htons(psin6->sin6_port) : 0);
914 freeaddrinfo(aires);
915 return;
916 } else if (got_tcp && got_udp) {
917 tst_resm(TPASS, "getaddrinfo IPv6 socktype 0,513");
918 freeaddrinfo(aires);
919 } else {
920 tst_resm(TFAIL, "getaddrinfo IPv6 socktype 0,513 TCP %d"
921 " UDP %d", got_tcp, got_udp);
922 freeaddrinfo(aires);
923 return;
924 }
925 } else {
926 if (TEST_RETURN == EAI_BADFLAGS) {
927 tst_resm(TPASS, "getaddrinfo IPv6 socktype 0,513"
928 " (\"\", \"%s\") returns %ld (\"%s\")", service,
929 TEST_RETURN, gai_strerror(TEST_RETURN));
930 } else {
931 tst_resm(TFAIL, "getaddrinfo IPv6 socktype 0,513"
932 " (\"\", \"%s\") returns %ld (\"%s\")", service,
933 TEST_RETURN, gai_strerror(TEST_RETURN));
934 return;
935 }
936 }
937
938 /* test 22, IPv6 AI_V4MAPPED */
939 memset(&hints, 0, sizeof(hints));
940 hints.ai_family = AF_INET6;
941 hints.ai_flags = AI_V4MAPPED;
942 TEST(getaddrinfo(hostname, 0, &hints, &aires));
943 if (!TEST_RETURN) {
944 struct sockaddr_in6 *psin6 = 0;
945 int err = 0;
946
947 for (pai = aires; pai; pai = pai->ai_next) {
948 err |= pai->ai_family != AF_INET6;
949 err |= pai->ai_addrlen != sizeof(struct sockaddr_in6);
950 err |= pai->ai_addr == 0;
951 psin6 = (struct sockaddr_in6 *)pai->ai_addr;
952 if (pai->ai_addr) {
953 err |= psin6->sin6_family != AF_INET6;
954 err |= psin6->sin6_port != 0;
955 }
956 if (err)
957 break;
958 }
959 if (err) {
960 tst_resm(TFAIL, "getaddrinfo IPv6 AI_V4MAPPED: "
961 "fam %d alen %d addr 0x%p addr/fam %d "
962 "addr/port %d H[%d]",
963 pai->ai_family, pai->ai_addrlen, psin6,
964 psin6 ? psin6->sin6_family : 0,
965 psin6 ? psin6->sin6_port : 0,
966 psin6 ? htons(psin6->sin6_port) : 0);
967 freeaddrinfo(aires);
968 return;
969 }
970 tst_resm(TPASS, "getaddrinfo IPv6 AI_V4MAPPED");
971 freeaddrinfo(aires);
972 } else {
973 tst_resm(TFAIL, "getaddrinfo IPv6 "
974 "AI_V4MAPPED (\"%s\") returns %ld (\"%s\")", hostname,
975 TEST_RETURN, gai_strerror(TEST_RETURN));
976 return;
977 }
978 }
979