• Home
  • 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 #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