Home | History | Annotate | Download | only in lib6
      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 
     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 
     60 static void setup(void)
     61 {
     62 	TEST_PAUSE;
     63 }
     64 
     65 /* getaddrinfo tests (v4) */
     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) */
    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