| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2001 |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| * the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* |
| * Test Name: getaddrinfo_01 |
| * |
| * Test Description: |
| * Tests for getaddrinfo library function |
| * |
| * Usage: <for command-line> |
| * getaddrinfo_01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] |
| * where, -c n : Run n copies concurrently. |
| * -e : Turn on errno logging. |
| * -i n : Execute test n times. |
| * -I x : Execute test for x seconds. |
| * -P x : Pause for x seconds between iterations. |
| * -t : Turn on syscall timing. |
| * |
| * HISTORY |
| * 07/2004 written by David L Stevens |
| * |
| * RESTRICTIONS: |
| * None. |
| * |
| */ |
| |
| #include <unistd.h> |
| #include <errno.h> |
| |
| #include <sys/socket.h> |
| #include <netdb.h> |
| #include <arpa/inet.h> |
| |
| #include "test.h" |
| |
| #ifndef AI_V4MAPPED |
| #define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ |
| #endif |
| |
| char *TCID = "getaddrinfo_01"; /* Test program identifier. */ |
| int testno; |
| |
| void setup(void), cleanup(void); |
| |
| int TST_TOTAL = 1; |
| |
| /* a host that isn't where LTP is running */ |
| #define REMOTEHOSTNAME "www.ibm.com" |
| |
| void gaiv4(void), gaiv6(void); |
| void dumpres(struct addrinfo *); |
| |
| int main(int argc, char *argv[]) |
| { |
| int lc; |
| const char *msg; |
| |
| /* Parse standard options given to run the test. */ |
| msg = parse_opts(argc, argv, NULL, NULL); |
| if (msg != NULL) { |
| tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| } |
| |
| setup(); |
| |
| for (lc = 0; TEST_LOOPING(lc); ++lc) { |
| gaiv4(); |
| gaiv6(); |
| } |
| cleanup(); |
| |
| return (0); |
| } |
| |
| /* getaddrinfo tests (v4) */ |
| |
| void gaiv4(void) |
| { |
| struct addrinfo *aires, hints, *pai; |
| char hostname[MAXHOSTNAMELEN + 1]; |
| char shortname[MAXHOSTNAMELEN + 1]; |
| char service[NI_MAXSERV + 1]; |
| int servnum; |
| char *p; |
| |
| if (gethostname(hostname, sizeof(hostname)) < 0) |
| tst_brkm(TBROK, NULL, "gethostname failed - %s", |
| strerror(errno)); |
| strncpy(shortname, hostname, MAXHOSTNAMELEN); |
| shortname[MAXHOSTNAMELEN] = '\0'; |
| p = strchr(shortname, '.'); |
| if (p) |
| *p = '\0'; |
| |
| /* test 1, IPv4 basic lookup */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| TEST(getaddrinfo(hostname, 0, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in *psin = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in); |
| err |= pai->ai_addr == 0; |
| psin = (struct sockaddr_in *)pai->ai_addr; |
| if (pai->ai_addr) { |
| err |= psin->sin_family != AF_INET; |
| err |= psin->sin_port != 0; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 basic lookup: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin, |
| psin ? psin->sin_family : 0, |
| psin ? psin->sin_port : 0, |
| psin ? htons(psin->sin_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 basic lookup"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv4 basic " |
| "lookup (\"%s\") returns %ld (\"%s\")", hostname, |
| TEST_RETURN, gai_strerror(TEST_RETURN)); |
| |
| /* test 2, IPv4 canonical name */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| hints.ai_flags = AI_CANONNAME; |
| TEST(getaddrinfo(shortname, 0, &hints, &aires)); |
| if (!TEST_RETURN) { |
| for (pai = aires; pai; pai = pai->ai_next) |
| if (pai->ai_canonname) |
| break; |
| if (!pai) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 canonical name: no " |
| "entries with canonical name set"); |
| } else if (strcasecmp(hostname, pai->ai_canonname)) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 canonical name " |
| "(\"%s\") doesn't match hostname (\"%s\")", |
| pai->ai_canonname, hostname); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 canonical name"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv4 " |
| "canonical name (\"%s\") returns %ld (\"%s\")", |
| shortname, TEST_RETURN, gai_strerror(TEST_RETURN)); |
| |
| /* test 3, IPv4 host+service name */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| /* |
| * These are hard-coded for echo/7 to avoid using getservbyname(), |
| * since it isn't thread-safe and these tests may be re-used |
| * multithreaded. Sigh. |
| */ |
| strcpy(service, "echo"); |
| servnum = 7; |
| hints.ai_family = AF_INET; |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in *psin = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in); |
| err |= pai->ai_addr == 0; |
| psin = (struct sockaddr_in *)pai->ai_addr; |
| if (pai->ai_addr) { |
| err |= psin->sin_family != AF_INET; |
| err |= psin->sin_port != htons(servnum); |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 host+service: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin, |
| psin ? psin->sin_family : 0, |
| psin ? psin->sin_port : 0, |
| psin ? htons(psin->sin_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 host+service"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv4 host+" |
| "service returns %ld (\"%s\")", TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 4, IPv4 hostname+service, AI_PASSIVE */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| hints.ai_flags = AI_PASSIVE; |
| hints.ai_socktype = SOCK_STREAM; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in *psin = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in); |
| err |= pai->ai_addr == 0; |
| psin = (struct sockaddr_in *)pai->ai_addr; |
| if (pai->ai_addr) { |
| /* AI_PASSIVE is ignored if hostname is |
| * non-null; address must be set |
| */ |
| err |= psin->sin_addr.s_addr == 0; |
| err |= psin->sin_family != AF_INET; |
| err |= psin->sin_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 host+service, PASSIVE" |
| ": fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin, |
| psin ? psin->sin_family : 0, |
| psin ? psin->sin_port : 0, |
| psin ? htons(psin->sin_port) : 0); |
| } else |
| tst_resm(TPASS, |
| "getaddrinfo IPv4 host+service PASSIVE"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv4 host+" |
| "service, PASSIVE (\"%s\", \"%s\") returns %ld (\"%s\")", |
| hostname, service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 5, IPv4 host+service w/ AI_NUMERICHOST */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| strcpy(service, "echo"); |
| servnum = 7; |
| hints.ai_family = AF_INET; |
| hints.ai_flags = AI_NUMERICHOST; |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (TEST_RETURN != EAI_NONAME) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 AI_NUMERICHOST w/ hostname: " |
| "returns %ld expected %d (EAI_NONAME)", |
| TEST_RETURN, EAI_NONAME); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 AI_NUMERICHOST w/ hostname"); |
| if (!TEST_RETURN) |
| freeaddrinfo(aires); |
| |
| /* test 6, IPv4 0+service, AI_PASSIVE */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| hints.ai_flags = AI_PASSIVE; |
| hints.ai_socktype = SOCK_STREAM; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in *psin = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in); |
| err |= pai->ai_addr == 0; |
| psin = (struct sockaddr_in *)pai->ai_addr; |
| if (pai->ai_addr) { |
| |
| /* AI_PASSIVE means addr must be INADDR_ANY */ |
| err |= psin->sin_addr.s_addr != 0; |
| err |= psin->sin_family != AF_INET; |
| err |= psin->sin_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 0+service, PASSIVE:" |
| " fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin, |
| psin ? psin->sin_family : 0, |
| psin ? psin->sin_port : 0, |
| psin ? htons(psin->sin_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 0+service, PASSIVE"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN == EAI_BADFLAGS ? TPASS : TFAIL, |
| "getaddrinfo IPv4 0+service, PASSIVE (\"\", \"%s\") " |
| "returns %ld (\"%s\")", service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 7, IPv4 0+service */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| hints.ai_socktype = SOCK_STREAM; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in *psin = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in); |
| err |= pai->ai_addr == 0; |
| psin = (struct sockaddr_in *)pai->ai_addr; |
| if (pai->ai_addr) { |
| /* hostname not set; addr should be loopback */ |
| err |= psin->sin_addr.s_addr != |
| htonl(INADDR_LOOPBACK); |
| err |= psin->sin_family != AF_INET; |
| err |= psin->sin_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 0+service: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin, |
| psin ? psin->sin_family : 0, |
| psin ? psin->sin_port : 0, |
| psin ? htons(psin->sin_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 0+service"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN == EAI_BADFLAGS ? TPASS : TFAIL, |
| "getaddrinfo IPv4 0+service (\"\", \"%s\") returns %ld " |
| "(\"%s\")", service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 8, IPv4 host+service, AI_NUMERICSERV */ |
| |
| #ifndef AI_NUMERICSERV |
| tst_resm(TFAIL, "getaddrinfo IPv4 host+service, AI_NUMERICSERV: flag " |
| "not implemented"); |
| #else |
| memset(&hints, 0, sizeof(hints)); |
| strcpy(service, "echo"); |
| servnum = 7; |
| hints.ai_family = AF_INET; |
| hints.ai_flags = AI_NUMERICSERV; |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (TEST_RETURN != EAI_NONAME) { |
| tst_resm(TFAIL, |
| "getaddrinfo IPv4 host+service, AI_NUMERICSERV: " |
| "returns %ld (\"%s\") expected %d (EAI_NONAME)", |
| TEST_RETURN, gai_strerror(TEST_RETURN), EAI_NONAME); |
| } else |
| tst_resm(TPASS, |
| "getaddrinfo IPv4 host+service, AI_NUMERICSERV"); |
| if (!TEST_RETURN) |
| freeaddrinfo(aires); |
| #endif /* AI_NUMERICSERV */ |
| |
| /* test 9, IPv4 SOCK_STREAM/IPPROTO_UDP hints */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| hints.ai_socktype = SOCK_STREAM; |
| hints.ai_protocol = IPPROTO_UDP; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 SOCK_STREAM/IPPROTO_UDP " |
| "hints"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 SOCK_STREAM/IPPROTO_UDP " |
| "hints"); |
| |
| /* test 10, IPv4 socktype 0, 513 */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| hints.ai_socktype = 0; |
| strcpy(service, "513"); |
| servnum = htons(513); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in *psin = 0; |
| int got_tcp, got_udp; |
| int err = 0; |
| |
| got_tcp = got_udp = 0; |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in); |
| err |= pai->ai_addr == 0; |
| got_tcp |= pai->ai_socktype == SOCK_STREAM; |
| got_udp |= pai->ai_socktype == SOCK_DGRAM; |
| psin = (struct sockaddr_in *)pai->ai_addr; |
| if (pai->ai_addr) { |
| /* hostname not set; addr should be loopback */ |
| err |= psin->sin_addr.s_addr != |
| htonl(INADDR_LOOPBACK); |
| err |= psin->sin_family != AF_INET; |
| err |= psin->sin_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 socktype 0,513: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin, |
| psin ? psin->sin_family : 0, |
| psin ? psin->sin_port : 0, |
| psin ? htons(psin->sin_port) : 0); |
| } else if (got_tcp && got_udp) |
| tst_resm(TPASS, "getaddrinfo IPv4 socktype 0,513"); |
| else |
| tst_resm(TFAIL, "getaddrinfo IPv4 socktype 0,513 TCP %d" |
| " UDP %d", got_tcp, got_udp); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN == EAI_BADFLAGS ? TPASS : TFAIL, |
| "getaddrinfo IPv4 socktype 0,513 (\"\", \"%s\") returns" |
| " %ld (\"%s\")", service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 11, IPv4 AI_V4MAPPED */ |
| |
| /* AI_V4MAPPED should be ignored because family != AF_INET6 */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET; |
| hints.ai_flags = AI_V4MAPPED; |
| TEST(getaddrinfo(hostname, 0, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in *psin = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in); |
| err |= pai->ai_addr == 0; |
| psin = (struct sockaddr_in *)pai->ai_addr; |
| if (pai->ai_addr) { |
| err |= psin->sin_family != AF_INET; |
| err |= psin->sin_port != 0; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv4 AI_V4MAPPED: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin, |
| psin ? psin->sin_family : 0, |
| psin ? psin->sin_port : 0, |
| psin ? htons(psin->sin_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv4 AI_V4MAPPED"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv4 " |
| "AI_V4MAPPED (\"%s\") returns %ld (\"%s\")", hostname, |
| TEST_RETURN, gai_strerror(TEST_RETURN)); |
| } |
| |
| /* getaddrinfo tests (v6) */ |
| |
| void gaiv6(void) |
| { |
| struct addrinfo *aires, hints, *pai; |
| char hostname[MAXHOSTNAMELEN + 1]; |
| char shortname[MAXHOSTNAMELEN + 1]; |
| char service[NI_MAXSERV + 1]; |
| int servnum; |
| char *p; |
| |
| if (gethostname(hostname, sizeof(hostname)) < 0) |
| tst_brkm(TBROK, NULL, "gethostname failed - %s", |
| strerror(errno)); |
| strncpy(shortname, hostname, MAXHOSTNAMELEN); |
| shortname[MAXHOSTNAMELEN] = '\0'; |
| p = strchr(shortname, '.'); |
| if (p) |
| *p = '\0'; |
| |
| /* test 12, IPv6 basic lookup */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| TEST(getaddrinfo(hostname, 0, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in6 *psin6 = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET6; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in6); |
| err |= pai->ai_addr == 0; |
| psin6 = (struct sockaddr_in6 *)pai->ai_addr; |
| if (pai->ai_addr) { |
| err |= psin6->sin6_family != AF_INET6; |
| err |= psin6->sin6_port != 0; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 basic lookup: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin6, |
| psin6 ? psin6->sin6_family : 0, |
| psin6 ? psin6->sin6_port : 0, |
| psin6 ? htons(psin6->sin6_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 basic lookup"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv6 basic " |
| "lookup (\"%s\") returns %ld (\"%s\")", hostname, |
| TEST_RETURN, gai_strerror(TEST_RETURN)); |
| |
| /* test 13, IPv6 canonical name */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| hints.ai_flags = AI_CANONNAME; |
| TEST(getaddrinfo(shortname, 0, &hints, &aires)); |
| if (!TEST_RETURN) { |
| for (pai = aires; pai; pai = pai->ai_next) |
| if (pai->ai_canonname) |
| break; |
| if (!pai) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 canonical name: no " |
| "entries with canonical name set"); |
| } else if (strcasecmp(hostname, pai->ai_canonname)) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 canonical name " |
| "(\"%s\") doesn't match hostname (\"%s\")", |
| pai->ai_canonname, hostname); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 canonical name"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv6 " |
| "canonical name (\"%s\") returns %ld (\"%s\")", |
| shortname, TEST_RETURN, gai_strerror(TEST_RETURN)); |
| |
| /* test 14, IPv6 host+service name */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| /* |
| * These are hard-coded for echo/7 to avoid using getservbyname(), |
| * since it isn't thread-safe and these tests may be re-used |
| * multithreaded. Sigh. |
| */ |
| strcpy(service, "echo"); |
| servnum = 7; |
| hints.ai_family = AF_INET6; |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in6 *psin6 = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET6; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in6); |
| err |= pai->ai_addr == 0; |
| psin6 = (struct sockaddr_in6 *)pai->ai_addr; |
| if (pai->ai_addr) { |
| err |= psin6->sin6_family != AF_INET6; |
| err |= psin6->sin6_port != htons(servnum); |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 host+service: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin6, |
| psin6 ? psin6->sin6_family : 0, |
| psin6 ? psin6->sin6_port : 0, |
| psin6 ? htons(psin6->sin6_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 host+service"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv6 host+" |
| "service returns %ld (\"%s\")", TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 15, IPv6 hostname+service, AI_PASSIVE */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| hints.ai_flags = AI_PASSIVE; |
| hints.ai_socktype = SOCK_STREAM; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in6 *psin6 = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET6; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in6); |
| err |= pai->ai_addr == 0; |
| psin6 = (struct sockaddr_in6 *)pai->ai_addr; |
| if (pai->ai_addr) { |
| /* AI_PASSIVE is ignored if hostname is |
| * non-null; address must be set |
| */ |
| err |= memcmp(&psin6->sin6_addr, &in6addr_any, |
| sizeof(struct in6_addr)) == 0; |
| err |= psin6->sin6_family != AF_INET6; |
| err |= psin6->sin6_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 host+service, PASSIVE" |
| ": fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin6, |
| psin6 ? psin6->sin6_family : 0, |
| psin6 ? psin6->sin6_port : 0, |
| psin6 ? htons(psin6->sin6_port) : 0); |
| } else |
| tst_resm(TPASS, |
| "getaddrinfo IPv6 host+service PASSIVE"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv6 host+" |
| "service, PASSIVE (\"%s\", \"%s\") returns %ld (\"%s\")", |
| hostname, service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 16, IPv6 host+service w/ AI_NUMERICHOST */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| strcpy(service, "echo"); |
| servnum = 7; |
| hints.ai_family = AF_INET6; |
| hints.ai_flags = AI_NUMERICHOST; |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (TEST_RETURN != EAI_NONAME) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 AI_NUMERICHOST w/ hostname: " |
| "returns %ld expected %d (EAI_NONAME)", |
| TEST_RETURN, EAI_NONAME); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 AI_NUMERICHOST w/ hostname"); |
| if (!TEST_RETURN) |
| freeaddrinfo(aires); |
| |
| /* test 17, IPv6 0+service, AI_PASSIVE */ |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| hints.ai_flags = AI_PASSIVE; |
| hints.ai_socktype = SOCK_STREAM; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in6 *psin6 = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET6; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in6); |
| err |= pai->ai_addr == 0; |
| psin6 = (struct sockaddr_in6 *)pai->ai_addr; |
| if (pai->ai_addr) { |
| |
| /* AI_PASSIVE means addr must be INADDR_ANY */ |
| err |= memcmp(&psin6->sin6_addr, &in6addr_any, |
| sizeof(struct in6_addr)) != 0; |
| err |= psin6->sin6_family != AF_INET6; |
| err |= psin6->sin6_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 0+service, PASSIVE:" |
| " fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin6, |
| psin6 ? psin6->sin6_family : 0, |
| psin6 ? psin6->sin6_port : 0, |
| psin6 ? htons(psin6->sin6_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 0+service, PASSIVE"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN == EAI_BADFLAGS ? TPASS : TFAIL, |
| "getaddrinfo IPv6 0+service, PASSIVE (\"\", \"%s\") " |
| "returns %ld (\"%s\")", service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 18, IPv6 0+service */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| hints.ai_socktype = SOCK_STREAM; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in6 *psin6 = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET6; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in6); |
| err |= pai->ai_addr == 0; |
| psin6 = (struct sockaddr_in6 *)pai->ai_addr; |
| if (pai->ai_addr) { |
| /* hostname not set; addr should be loopback */ |
| err |= memcmp(&psin6->sin6_addr, |
| &in6addr_loopback, |
| sizeof(struct in6_addr)) != 0; |
| err |= psin6->sin6_family != AF_INET6; |
| err |= psin6->sin6_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 0+service: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin6, |
| psin6 ? psin6->sin6_family : 0, |
| psin6 ? psin6->sin6_port : 0, |
| psin6 ? htons(psin6->sin6_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 0+service"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN == EAI_BADFLAGS ? TPASS : TFAIL, |
| "getaddrinfo IPv6 0+service (\"\", \"%s\") returns %ld " |
| "(\"%s\")", service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 19, IPv6 host+service, AI_NUMERICSERV */ |
| |
| #ifndef AI_NUMERICSERV |
| tst_resm(TFAIL, "getaddrinfo IPv6 host+service, AI_NUMERICSERV: flag " |
| "not implemented"); |
| #else |
| memset(&hints, 0, sizeof(hints)); |
| strcpy(service, "echo"); |
| servnum = 7; |
| hints.ai_family = AF_INET6; |
| hints.ai_flags = AI_NUMERICSERV; |
| TEST(getaddrinfo(hostname, service, &hints, &aires)); |
| if (TEST_RETURN != EAI_NONAME) { |
| tst_resm(TFAIL, |
| "getaddrinfo IPv6 host+service, AI_NUMERICSERV: " |
| "returns %ld (\"%s\") expected %d (EAI_NONAME)", |
| TEST_RETURN, gai_strerror(TEST_RETURN), EAI_NONAME); |
| } else |
| tst_resm(TPASS, |
| "getaddrinfo IPv6 host+service, AI_NUMERICSERV"); |
| if (!TEST_RETURN) |
| freeaddrinfo(aires); |
| #endif /* AI_NUMERICSERV */ |
| |
| /* test 20, IPv6 SOCK_STREAM/IPPROTO_UDP hints */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| hints.ai_socktype = SOCK_STREAM; |
| hints.ai_protocol = IPPROTO_UDP; |
| strcpy(service, "9462"); |
| servnum = htons(9462); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 SOCK_STREAM/IPPROTO_UDP " |
| "hints"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 SOCK_STREAM/IPPROTO_UDP " |
| "hints"); |
| |
| /* test 21, IPv6 socktype 0, 513 */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| hints.ai_socktype = 0; |
| strcpy(service, "513"); |
| servnum = htons(513); |
| TEST(getaddrinfo(0, service, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in6 *psin6 = 0; |
| int got_tcp, got_udp; |
| int err = 0; |
| |
| got_tcp = got_udp = 0; |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET6; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in6); |
| err |= pai->ai_addr == 0; |
| got_tcp |= pai->ai_socktype == SOCK_STREAM; |
| got_udp |= pai->ai_socktype == SOCK_DGRAM; |
| psin6 = (struct sockaddr_in6 *)pai->ai_addr; |
| if (pai->ai_addr) { |
| /* hostname not set; addr should be loopback */ |
| err |= memcmp(&psin6->sin6_addr, |
| &in6addr_loopback, |
| sizeof(struct in6_addr)) != 0; |
| err |= psin6->sin6_family != AF_INET6; |
| err |= psin6->sin6_port != servnum; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 socktype 0,513: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin6, |
| psin6 ? psin6->sin6_family : 0, |
| psin6 ? psin6->sin6_port : 0, |
| psin6 ? htons(psin6->sin6_port) : 0); |
| } else if (got_tcp && got_udp) |
| tst_resm(TPASS, "getaddrinfo IPv6 socktype 0,513"); |
| else |
| tst_resm(TFAIL, "getaddrinfo IPv6 socktype 0,513 TCP %d" |
| " UDP %d", got_tcp, got_udp); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN == EAI_BADFLAGS ? TPASS : TFAIL, |
| "getaddrinfo IPv6 socktype 0,513 (\"\", \"%s\") returns" |
| " %ld (\"%s\")", service, TEST_RETURN, |
| gai_strerror(TEST_RETURN)); |
| |
| /* test 22, IPv6 AI_V4MAPPED */ |
| |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = AF_INET6; |
| hints.ai_flags = AI_V4MAPPED; |
| TEST(getaddrinfo(hostname, 0, &hints, &aires)); |
| if (!TEST_RETURN) { |
| struct sockaddr_in6 *psin6 = 0; |
| int err = 0; |
| |
| for (pai = aires; pai; pai = pai->ai_next) { |
| err |= pai->ai_family != AF_INET6; |
| err |= pai->ai_addrlen != sizeof(struct sockaddr_in6); |
| err |= pai->ai_addr == 0; |
| psin6 = (struct sockaddr_in6 *)pai->ai_addr; |
| if (pai->ai_addr) { |
| err |= psin6->sin6_family != AF_INET6; |
| err |= psin6->sin6_port != 0; |
| } |
| if (err) |
| break; |
| } |
| if (err) { |
| tst_resm(TFAIL, "getaddrinfo IPv6 AI_V4MAPPED: " |
| "fam %d alen %d addr 0x%p addr/fam %d " |
| "addr/port %d H[%d]", |
| pai->ai_family, pai->ai_addrlen, psin6, |
| psin6 ? psin6->sin6_family : 0, |
| psin6 ? psin6->sin6_port : 0, |
| psin6 ? htons(psin6->sin6_port) : 0); |
| } else |
| tst_resm(TPASS, "getaddrinfo IPv6 AI_V4MAPPED"); |
| freeaddrinfo(aires); |
| } else |
| tst_resm(TEST_RETURN ? TFAIL : TPASS, "getaddrinfo IPv6 " |
| "AI_V4MAPPED (\"%s\") returns %ld (\"%s\")", hostname, |
| TEST_RETURN, gai_strerror(TEST_RETURN)); |
| } |
| |
| /* this prints an addrinfo list; useful for debugging */ |
| void dumpres(struct addrinfo *pai) |
| { |
| int count = 1; |
| for (; pai; pai = pai->ai_next, count++) { |
| printf("result %d [0x%p]\n", count, pai); |
| printf("\tai_flags %x\n", pai->ai_flags); |
| printf("\tai_family %d\n", pai->ai_family); |
| printf("\tai_socktype %d\n", pai->ai_socktype); |
| printf("\tai_protocol %d\n", pai->ai_protocol); |
| printf("\tai_addrlen %d\n", pai->ai_addrlen); |
| printf("\tai_canonname \"%s\"\n", pai->ai_canonname); |
| printf("\tai_addr.sa_family %x\n", pai->ai_addr->sa_family); |
| if (pai->ai_addr->sa_family == AF_INET) { |
| char buf[1024]; |
| struct sockaddr_in *psin = |
| (struct sockaddr_in *)pai->ai_addr; |
| |
| if (!inet_ntop(AF_INET, &psin->sin_addr, buf, |
| sizeof(buf))) |
| buf[0] = '\0'; |
| printf("\tai_addr.sin_addr \"%s\"\n", buf); |
| } else if (pai->ai_addr->sa_family == AF_INET6) { |
| char buf[1024]; |
| |
| struct sockaddr_in6 *psin6 = |
| (struct sockaddr_in6 *)pai->ai_addr; |
| if (!inet_ntop(AF_INET6, &psin6->sin6_addr, buf, |
| sizeof(buf))) |
| buf[0] = '\0'; |
| printf("\tai_addr.sin6_addr \"%s\"\n", buf); |
| |
| } |
| printf("\tai_next %p\n", pai->ai_next); |
| } |
| } |
| |
| void setup(void) |
| { |
| TEST_PAUSE; /* if -P option specified */ |
| } |
| |
| void cleanup(void) |
| { |
| } |