add tests for 4->6 connections.

This commit is contained in:
christos 2017-08-28 10:19:57 +00:00
parent dc977faaf4
commit 64e9b5d330
1 changed files with 138 additions and 49 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: t_tcp.c,v 1.5 2017/08/28 09:30:29 christos Exp $ */
/* $NetBSD: t_tcp.c,v 1.6 2017/08/28 10:19:57 christos Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
#include <sys/cdefs.h>
#ifdef __RCSID
__RCSID("$Id: t_tcp.c,v 1.5 2017/08/28 09:30:29 christos Exp $");
__RCSID("$Id: t_tcp.c,v 1.6 2017/08/28 10:19:57 christos Exp $");
#endif
/* Example code. Should block; does with accept not paccept. */
@ -46,6 +46,7 @@ __RCSID("$Id: t_tcp.c,v 1.5 2017/08/28 09:30:29 christos Exp $");
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sched.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
@ -55,10 +56,18 @@ __RCSID("$Id: t_tcp.c,v 1.5 2017/08/28 09:30:29 christos Exp $");
#include <signal.h>
#ifdef TEST
#define FAIL(msg, ...) err(EXIT_FAILURE, msg, ## __VA_ARGS__)
#define FAIL(msg) err(EXIT_FAILURE, msg)
#define FAILX(msg, ...) err(EXIT_FAILURE, msg, ## __VA_ARGS__)
#else
#include <atf-c.h>
#define FAIL(msg, ...) ATF_CHECK_MSG(0, msg, ## __VA_ARGS__); goto fail
#define FAIL(msg) do { \
ATF_CHECK_MSG(0, msg " (%s)", strerror(errno)); \
goto fail; \
} while (/*CONSTCOND*/0)
#define FAILX(msg, ...) do { \
ATF_CHECK_MSG(0, msg, ## __VA_ARGS__); \
goto fail; \
} while (/*CONSTCOND*/0)
#endif
#ifdef __linux__
@ -71,10 +80,12 @@ ding(int al)
}
static void
paccept_block(sa_family_t family, bool pacceptblock, bool fcntlblock)
paccept_block(sa_family_t sfamily, sa_family_t cfamily,
bool pacceptblock, bool fcntlblock)
{
int srvr = -1, clnt = -1, as = -1;
int ok, fl;
int count = 5;
ssize_t n;
char buf[10];
struct sockaddr_storage ss, bs;
@ -83,12 +94,12 @@ paccept_block(sa_family_t family, bool pacceptblock, bool fcntlblock)
struct sigaction sa;
socklen_t slen;
srvr = socket(family, SOCK_STREAM | SOCK_NONBLOCK, 0);
srvr = socket(sfamily, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (srvr == -1)
FAIL("socket");
memset(&ss, 0, sizeof(ss));
switch (ss.ss_family = family) {
switch (ss.ss_family = sfamily) {
case AF_INET:
sin = (void *)&ss;
slen = sizeof(*sin);
@ -99,7 +110,11 @@ paccept_block(sa_family_t family, bool pacceptblock, bool fcntlblock)
sin6 = (void *)&ss;
slen = sizeof(*sin6);
sin6->sin6_port = htons(0);
sin6->sin6_addr = in6addr_loopback;
if (sfamily == AF_INET6 && cfamily == AF_INET) {
sin6->sin6_addr = in6addr_any;
} else {
sin6->sin6_addr = in6addr_loopback;
}
break;
default:
errno = EINVAL;
@ -108,6 +123,12 @@ paccept_block(sa_family_t family, bool pacceptblock, bool fcntlblock)
#ifdef BSD4_4
ss.ss_len = slen;
#endif
if (sfamily == AF_INET6 && cfamily == AF_INET) {
int off = 0;
if (setsockopt(srvr, IPPROTO_IPV6, IPV6_V6ONLY,
(void *)&off, sizeof(off)) == -1)
FAIL("setsockopt IPV6_V6ONLY");
}
ok = bind(srvr, (const struct sockaddr *)&ss, slen);
if (ok == -1)
@ -122,18 +143,44 @@ paccept_block(sa_family_t family, bool pacceptblock, bool fcntlblock)
if (ok == -1)
FAIL("listen");
clnt = socket(family, SOCK_STREAM | SOCK_NONBLOCK, 0);
clnt = socket(cfamily, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (clnt == -1)
FAIL("socket");
if (sfamily == AF_INET6 && cfamily == AF_INET) {
ss = bs;
sin6 = (void *)&ss;
sin = (void *)&bs;
addrlen = sizeof(*sin);
#ifdef BSD4_4
sin->sin_len = sizeof(*sin);
#endif
sin->sin_family = AF_INET;
sin->sin_port = sin6->sin6_port;
sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
/* may not connect first time */
ok = connect(clnt, (struct sockaddr *) &bs, addrlen);
if (ok != -1 || errno != EINPROGRESS)
FAIL("expected connect to fail");
as = paccept(srvr, NULL, NULL, NULL, pacceptblock ? 0 : SOCK_NONBLOCK);
again:
ok = connect(clnt, (struct sockaddr *) &bs, addrlen);
if (ok == -1 && errno != EISCONN)
if (ok == -1 && errno != EISCONN) {
if (count-- && errno == EALREADY) {
fprintf(stderr, "retry\n");
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 1000000;
nanosleep(&ts, NULL);
#if 0
sched_yield();
#endif
goto again;
}
FAIL("connect failed");
}
#if 0
fl = fcntl(srvr, F_GETFL, 0);
@ -155,7 +202,7 @@ paccept_block(sa_family_t family, bool pacceptblock, bool fcntlblock)
if (fl == -1)
FAIL("fnctl");
if (fl != (O_RDWR|O_NONBLOCK))
FAIL("fl 0x%x != 0x%x\n", fl, O_RDWR|O_NONBLOCK);
FAILX("fl 0x%x != 0x%x\n", fl, O_RDWR|O_NONBLOCK);
ok = fcntl(as, F_SETFL, fl & ~O_NONBLOCK);
if (ok == -1)
FAIL("fnctl setfl");
@ -187,101 +234,143 @@ fail:
#ifndef TEST
ATF_TC(paccept4_reset_nonblock);
ATF_TC_HEAD(paccept4_reset_nonblock, tc)
ATF_TC(paccept44_reset_nonblock);
ATF_TC_HEAD(paccept44_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4)");
"the non-blocking flag on non-blocking sockets (ipv4->ipv4)");
}
ATF_TC_BODY(paccept4_reset_nonblock, tc)
ATF_TC_BODY(paccept44_reset_nonblock, tc)
{
paccept_block(AF_INET, true, false);
paccept_block(AF_INET, AF_INET, true, false);
}
ATF_TC(fcntl4_reset_nonblock);
ATF_TC_HEAD(fcntl4_reset_nonblock, tc)
ATF_TC(fcntl44_reset_nonblock);
ATF_TC_HEAD(fcntl44_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4)");
"the non-blocking flag on non-blocking sockets (ipv4->ipv4)");
}
ATF_TC_BODY(fcntl4_reset_nonblock, tc)
ATF_TC_BODY(fcntl44_reset_nonblock, tc)
{
paccept_block(AF_INET, false, true);
paccept_block(AF_INET, AF_INET, false, true);
}
ATF_TC(paccept4_nonblock);
ATF_TC_HEAD(paccept4_nonblock, tc)
ATF_TC(paccept44_nonblock);
ATF_TC_HEAD(paccept44_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4)");
"the non-blocking flag on non-blocking sockets (ipv4->ipv4)");
}
ATF_TC_BODY(paccept4_nonblock, tc)
ATF_TC_BODY(paccept44_nonblock, tc)
{
paccept_block(AF_INET, false, false);
paccept_block(AF_INET, AF_INET, false, false);
}
ATF_TC(paccept6_reset_nonblock);
ATF_TC_HEAD(paccept6_reset_nonblock, tc)
ATF_TC(paccept66_reset_nonblock);
ATF_TC_HEAD(paccept66_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets "
"the non-blocking flag on non-blocking sockets (ipv6)");
"the non-blocking flag on non-blocking sockets (ipv6->ipv6)");
}
ATF_TC_BODY(paccept6_reset_nonblock, tc)
ATF_TC_BODY(paccept66_reset_nonblock, tc)
{
paccept_block(AF_INET6, true, false);
paccept_block(AF_INET6, AF_INET6, true, false);
}
ATF_TC(fcntl6_reset_nonblock);
ATF_TC_HEAD(fcntl6_reset_nonblock, tc)
ATF_TC(fcntl66_reset_nonblock);
ATF_TC_HEAD(fcntl66_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv6)");
"the non-blocking flag on non-blocking sockets (ipv6->ipv6)");
}
ATF_TC_BODY(fcntl6_reset_nonblock, tc)
ATF_TC_BODY(fcntl66_reset_nonblock, tc)
{
paccept_block(AF_INET6, false, true);
paccept_block(AF_INET6, AF_INET6, false, true);
}
ATF_TC(paccept6_nonblock);
ATF_TC_HEAD(paccept6_nonblock, tc)
ATF_TC(paccept66_nonblock);
ATF_TC_HEAD(paccept66_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv6)");
"the non-blocking flag on non-blocking sockets (ipv6->ipv6)");
}
ATF_TC_BODY(paccept6_nonblock, tc)
ATF_TC_BODY(paccept66_nonblock, tc)
{
paccept_block(AF_INET6, false, false);
paccept_block(AF_INET6, AF_INET6, false, false);
}
ATF_TC(paccept46_reset_nonblock);
ATF_TC_HEAD(paccept46_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4->ipv6)");
}
ATF_TC_BODY(paccept46_reset_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET, true, false);
}
ATF_TC(fcntl46_reset_nonblock);
ATF_TC_HEAD(fcntl46_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4->ipv6)");
}
ATF_TC_BODY(fcntl46_reset_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET, false, true);
}
ATF_TC(paccept46_nonblock);
ATF_TC_HEAD(paccept46_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4->ipv6)");
}
ATF_TC_BODY(paccept46_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET, false, false);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, paccept4_reset_nonblock);
ATF_TP_ADD_TC(tp, fcntl4_reset_nonblock);
ATF_TP_ADD_TC(tp, paccept4_nonblock);
ATF_TP_ADD_TC(tp, paccept6_reset_nonblock);
ATF_TP_ADD_TC(tp, fcntl6_reset_nonblock);
ATF_TP_ADD_TC(tp, paccept6_nonblock);
ATF_TP_ADD_TC(tp, paccept44_reset_nonblock);
ATF_TP_ADD_TC(tp, fcntl44_reset_nonblock);
ATF_TP_ADD_TC(tp, paccept44_nonblock);
ATF_TP_ADD_TC(tp, paccept66_reset_nonblock);
ATF_TP_ADD_TC(tp, fcntl66_reset_nonblock);
ATF_TP_ADD_TC(tp, paccept66_nonblock);
ATF_TP_ADD_TC(tp, paccept46_reset_nonblock);
ATF_TP_ADD_TC(tp, fcntl46_reset_nonblock);
ATF_TP_ADD_TC(tp, paccept46_nonblock);
return atf_no_error();
}
#else
int
main(int argc, char *argv[])
{
paccept_block(AF_INET, false, false);
paccept_block(AF_INET, true, false);
paccept_block(AF_INET, AF_INET, false, false);
paccept_block(AF_INET, AF_INET, true, false);
return 0;
}
#endif