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