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 
     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 
     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 
     59 static void setup(void)
     60 {
     61 	TEST_PAUSE;
     62 }
     63 
     64 /* getaddrinfo tests (v4) */
     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) */
    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