• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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