/*
* Copyright (c) 2015 Fujitsu Ltd.
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Author: David L Stevens
*/
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/param.h>
#include "test.h"
#ifndef AI_V4MAPPED
#define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
#endif
static void setup(void);
static void gaiv4(void);
static void gaiv6(void);
char *TCID = "getaddrinfo_01";
int TST_TOTAL = 22;
int main(int argc, char *argv[])
{
int lc;
tst_parse_opts(argc, argv, NULL, NULL);
setup();
for (lc = 0; TEST_LOOPING(lc); ++lc) {
tst_count = 0;
gaiv4();
gaiv6();
}
tst_exit();
}
static void setup(void)
{
TEST_PAUSE;
}
/* getaddrinfo tests (v4) */
static 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 | TERRNO, NULL, "gethostname failed");
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv4 basic lookup");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 basic "
"lookup (\"%s\") returns %ld (\"%s\")", hostname,
TEST_RETURN, gai_strerror(TEST_RETURN));
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");
freeaddrinfo(aires);
return;
} else if (strcasecmp(hostname, pai->ai_canonname)) {
tst_resm(TFAIL, "getaddrinfo IPv4 canonical name "
"(\"%s\") doesn't match hostname (\"%s\")",
pai->ai_canonname, hostname);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv4 canonical name");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 "
"canonical name (\"%s\") returns %ld (\"%s\")",
shortname, TEST_RETURN, gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv4 host+service");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 host+"
"service returns %ld (\"%s\")", TEST_RETURN,
gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv4 host+service PASSIVE");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 host+"
"service, PASSIVE (\"%s\", \"%s\") returns %ld (\"%s\")",
hostname, service, TEST_RETURN,
gai_strerror(TEST_RETURN));
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);
if (!TEST_RETURN)
freeaddrinfo(aires);
return;
}
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv4 0+service, PASSIVE");
freeaddrinfo(aires);
} else {
if (TEST_RETURN == EAI_BADFLAGS) {
tst_resm(TPASS, "getaddrinfo IPv4 0+service,"
" PASSIVE (\"\", \"%s\") returns %ld (\"%s\")",
service, TEST_RETURN,
gai_strerror(TEST_RETURN));
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 0+service,"
" PASSIVE (\"\", \"%s\") returns %ld (\"%s\")",
service, TEST_RETURN,
gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv4 0+service");
freeaddrinfo(aires);
} else {
if (TEST_RETURN == EAI_BADFLAGS) {
tst_resm(TPASS, "getaddrinfo IPv4 "
"0+service (\"\", \"%s\") returns %ld (\"%s\")",
service, TEST_RETURN,
gai_strerror(TEST_RETURN));
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 "
"0+service (\"\", \"%s\") returns %ld (\"%s\")",
service, TEST_RETURN,
gai_strerror(TEST_RETURN));
return;
}
}
/* test 8, IPv4 host+service, AI_NUMERICSERV */
#ifndef AI_NUMERICSERV
tst_resm(TCONF, "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);
if (!TEST_RETURN)
freeaddrinfo(aires);
return;
}
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);
return;
}
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);
freeaddrinfo(aires);
return;
} else if (got_tcp && got_udp) {
tst_resm(TPASS, "getaddrinfo IPv4 socktype 0,513");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 socktype 0,513 TCP %d"
" UDP %d", got_tcp, got_udp);
freeaddrinfo(aires);
return;
}
} else {
if (TEST_RETURN == EAI_BADFLAGS) {
tst_resm(TPASS, "getaddrinfo IPv4 socktype 0,513"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 socktype 0,513"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv4 AI_V4MAPPED");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv4 "
"AI_V4MAPPED (\"%s\") returns %ld (\"%s\")", hostname,
TEST_RETURN, gai_strerror(TEST_RETURN));
return;
}
}
/* getaddrinfo tests (v6) */
static 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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv6 basic lookup");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 basic "
"lookup (\"%s\") returns %ld (\"%s\")", hostname,
TEST_RETURN, gai_strerror(TEST_RETURN));
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");
freeaddrinfo(aires);
return;
} else if (strcasecmp(hostname, pai->ai_canonname)) {
tst_resm(TFAIL, "getaddrinfo IPv6 canonical name "
"(\"%s\") doesn't match hostname (\"%s\")",
pai->ai_canonname, hostname);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv6 canonical name");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 "
"canonical name (\"%s\") returns %ld (\"%s\")",
shortname, TEST_RETURN, gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv6 host+service");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 host+"
"service returns %ld (\"%s\")", TEST_RETURN,
gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv6 host+service PASSIVE");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 host+"
"service, PASSIVE (\"%s\", \"%s\") returns %ld (\"%s\")",
hostname, service, TEST_RETURN,
gai_strerror(TEST_RETURN));
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);
if (!TEST_RETURN)
freeaddrinfo(aires);
return;
}
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv6 0+service, PASSIVE");
freeaddrinfo(aires);
} else {
if (TEST_RETURN == EAI_BADFLAGS) {
tst_resm(TPASS, "getaddrinfo IPv6 0+service, PASSIVE"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 0+service, PASSIVE"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv6 0+service");
freeaddrinfo(aires);
} else {
if (TEST_RETURN == EAI_BADFLAGS) {
tst_resm(TPASS, "getaddrinfo IPv6 0+service"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 0+service"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
return;
}
}
/* test 19, IPv6 host+service, AI_NUMERICSERV */
#ifndef AI_NUMERICSERV
tst_resm(TCONF, "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);
if (!TEST_RETURN)
freeaddrinfo(aires);
return;
}
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);
return;
}
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);
freeaddrinfo(aires);
return;
} else if (got_tcp && got_udp) {
tst_resm(TPASS, "getaddrinfo IPv6 socktype 0,513");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 socktype 0,513 TCP %d"
" UDP %d", got_tcp, got_udp);
freeaddrinfo(aires);
return;
}
} else {
if (TEST_RETURN == EAI_BADFLAGS) {
tst_resm(TPASS, "getaddrinfo IPv6 socktype 0,513"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 socktype 0,513"
" (\"\", \"%s\") returns %ld (\"%s\")", service,
TEST_RETURN, gai_strerror(TEST_RETURN));
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);
freeaddrinfo(aires);
return;
}
tst_resm(TPASS, "getaddrinfo IPv6 AI_V4MAPPED");
freeaddrinfo(aires);
} else {
tst_resm(TFAIL, "getaddrinfo IPv6 "
"AI_V4MAPPED (\"%s\") returns %ld (\"%s\")", hostname,
TEST_RETURN, gai_strerror(TEST_RETURN));
return;
}
}