- use accept4 instead of paccept for everyone.

- add test for accept preserving non-block
- comment on FreeBSD and Linux behavior.
This commit is contained in:
christos 2019-10-26 23:08:27 +00:00
parent c61fe20bc9
commit a33f2da334

View File

@ -1,4 +1,4 @@
/* $NetBSD: t_tcp.c,v 1.10 2018/02/16 22:20:18 christos Exp $ */
/* $NetBSD: t_tcp.c,v 1.11 2019/10/26 23:08:27 christos Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -33,22 +33,27 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE
#include <sys/cdefs.h>
#ifdef __RCSID
__RCSID("$Id: t_tcp.c,v 1.10 2018/02/16 22:20:18 christos Exp $");
__RCSID("$Id: t_tcp.c,v 1.11 2019/10/26 23:08:27 christos Exp $");
#endif
/* Example code. Should block; does with accept not paccept. */
/* Example code. Should block; does with accept not accept4_. */
/* Original by: Justin Cormack <justin@specialbusrvrervice.com> */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sched.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <err.h>
@ -58,18 +63,14 @@ __RCSID("$Id: t_tcp.c,v 1.10 2018/02/16 22:20:18 christos Exp $");
#include "test.h"
#ifdef __linux__
#define paccept(a, b, c, d, e) accept4((a), (b), (c), (e))
#endif
static void
ding(int al)
{
}
static void
paccept_block(sa_family_t sfamily, sa_family_t cfamily,
bool pacceptblock, bool fcntlblock)
accept_test(sa_family_t sfamily, sa_family_t cfamily,
bool useaccept, bool accept4_block, bool fcntlblock)
{
int srvr = -1, clnt = -1, acpt = -1;
int ok, fl;
@ -152,9 +153,19 @@ paccept_block(sa_family_t sfamily, sa_family_t cfamily,
/* may not connect first time */
ok = connect(clnt, (struct sockaddr *) &bs, addrlen);
#ifndef __FreeBSD__
/* FreeBSD: What's going on here, connect succeeds with no-one
* accepting?
*/
if (ok != -1 || errno != EINPROGRESS)
FAIL("expected connect to fail");
acpt = paccept(srvr, NULL, NULL, NULL, pacceptblock ? 0 : SOCK_NONBLOCK);
#endif
if (useaccept) {
acpt = accept(srvr, NULL, NULL);
} else {
acpt = accept4(srvr, NULL, NULL,
accept4_block ? 0 : SOCK_NONBLOCK);
}
again:
ok = connect(clnt, (struct sockaddr *) &bs, addrlen);
if (ok == -1 && errno != EISCONN) {
@ -183,28 +194,44 @@ again:
#endif
if (acpt == -1) { /* not true under NetBSD */
acpt = paccept(srvr, NULL, NULL, NULL,
pacceptblock ? 0 : SOCK_NONBLOCK);
if (useaccept) {
acpt = accept(srvr, NULL, NULL);
} else {
acpt = accept4(srvr, NULL, NULL,
accept4_block ? 0 : SOCK_NONBLOCK);
}
if (acpt == -1)
FAIL("paccept");
FAIL("accept4_");
}
/* This is supposed to only work on Unix sockets but returns garbage */
#ifdef BSD4_4
#ifndef __FreeBSD__
/* NetBSD: This is supposed to only work on Unix sockets but returns
* garbage
* FreeBSD: fails with EISCONN
*/
if (getpeereid(clnt, &euid, &egid) != -1)
FAIL("getpeereid(clnt)");
/* This is supposed to only work on Unix sockets but returns garbage */
/* NetBSD: This is supposed to only work on Unix sockets but returns
* garbage
* FreeBSD: fails with EISCONN
*/
if (getpeereid(acpt, &euid, &egid) != -1)
FAIL("getpeereid(srvr)");
if (fcntlblock) {
#endif
#endif
if (fcntlblock || useaccept) {
fl = fcntl(acpt, F_GETFL, 0);
if (fl == -1)
FAIL("fnctl");
#ifndef __linux__
/* Linux accept returns a blocking socket */
if (fl != (O_RDWR|O_NONBLOCK))
FAIL("fl 0x%x != 0x%x\n", fl, O_RDWR|O_NONBLOCK);
ok = fcntl(acpt, F_SETFL, fl & ~O_NONBLOCK);
if (ok == -1)
FAIL("fnctl setfl");
#endif
fl = fcntl(acpt, F_GETFL, 0);
if (fl & O_NONBLOCK)
FAIL("fl non blocking after reset");
@ -216,7 +243,7 @@ again:
alarm(1);
n = read(acpt, buf, 10);
if (pacceptblock || fcntlblock) {
if (useaccept || accept4_block || fcntlblock) {
if (n == -1 && errno != EINTR)
FAIL("read");
} else {
@ -232,17 +259,30 @@ fail:
#ifndef TEST
ATF_TC(paccept44_reset_nonblock);
ATF_TC_HEAD(paccept44_reset_nonblock, tc)
ATF_TC(accept_44_preserve_nonblock);
ATF_TC_HEAD(accept_44_preserve_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets "
atf_tc_set_md_var(tc, "descr", "Check that accept(2) preserves "
"the non-blocking flag on non-blocking sockets (ipv4->ipv4)");
}
ATF_TC_BODY(paccept44_reset_nonblock, tc)
ATF_TC_BODY(accept_44_preserve_nonblock, tc)
{
paccept_block(AF_INET, AF_INET, true, false);
accept_test(AF_INET, AF_INET, true, false, false);
}
ATF_TC(accept4_44_reset_nonblock);
ATF_TC_HEAD(accept4_44_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that accept4(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4->ipv4)");
}
ATF_TC_BODY(accept4_44_reset_nonblock, tc)
{
accept_test(AF_INET, AF_INET, false, true, false);
}
ATF_TC(fcntl44_reset_nonblock);
@ -255,33 +295,33 @@ ATF_TC_HEAD(fcntl44_reset_nonblock, tc)
ATF_TC_BODY(fcntl44_reset_nonblock, tc)
{
paccept_block(AF_INET, AF_INET, false, true);
accept_test(AF_INET, AF_INET, false, false, true);
}
ATF_TC(paccept44_nonblock);
ATF_TC_HEAD(paccept44_nonblock, tc)
ATF_TC(accept4_44_nonblock);
ATF_TC_HEAD(accept4_44_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4->ipv4)");
}
ATF_TC_BODY(paccept44_nonblock, tc)
ATF_TC_BODY(accept4_44_nonblock, tc)
{
paccept_block(AF_INET, AF_INET, false, false);
accept_test(AF_INET, AF_INET, false, false, false);
}
ATF_TC(paccept66_reset_nonblock);
ATF_TC_HEAD(paccept66_reset_nonblock, tc)
ATF_TC(accept4_66_reset_nonblock);
ATF_TC_HEAD(accept4_66_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets "
atf_tc_set_md_var(tc, "descr", "Check that accept4(2) resets "
"the non-blocking flag on non-blocking sockets (ipv6->ipv6)");
}
ATF_TC_BODY(paccept66_reset_nonblock, tc)
ATF_TC_BODY(accept4_66_reset_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET6, true, false);
accept_test(AF_INET6, AF_INET6, false, true, false);
}
ATF_TC(fcntl66_reset_nonblock);
@ -294,33 +334,33 @@ ATF_TC_HEAD(fcntl66_reset_nonblock, tc)
ATF_TC_BODY(fcntl66_reset_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET6, false, true);
accept_test(AF_INET6, AF_INET6, false, false, true);
}
ATF_TC(paccept66_nonblock);
ATF_TC_HEAD(paccept66_nonblock, tc)
ATF_TC(accept4_66_nonblock);
ATF_TC_HEAD(accept4_66_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets "
"the non-blocking flag on non-blocking sockets (ipv6->ipv6)");
}
ATF_TC_BODY(paccept66_nonblock, tc)
ATF_TC_BODY(accept4_66_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET6, false, false);
accept_test(AF_INET6, AF_INET6, false, false, false);
}
ATF_TC(paccept46_reset_nonblock);
ATF_TC_HEAD(paccept46_reset_nonblock, tc)
ATF_TC(accept4_46_reset_nonblock);
ATF_TC_HEAD(accept4_46_reset_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets "
atf_tc_set_md_var(tc, "descr", "Check that accept4(2) resets "
"the non-blocking flag on non-blocking sockets (ipv4->ipv6)");
}
ATF_TC_BODY(paccept46_reset_nonblock, tc)
ATF_TC_BODY(accept4_46_reset_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET, true, false);
accept_test(AF_INET6, AF_INET, false, true, false);
}
ATF_TC(fcntl46_reset_nonblock);
@ -333,42 +373,42 @@ ATF_TC_HEAD(fcntl46_reset_nonblock, tc)
ATF_TC_BODY(fcntl46_reset_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET, false, true);
accept_test(AF_INET6, AF_INET, false, false, true);
}
ATF_TC(paccept46_nonblock);
ATF_TC_HEAD(paccept46_nonblock, tc)
ATF_TC(accept4_46_nonblock);
ATF_TC_HEAD(accept4_46_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)
ATF_TC_BODY(accept4_46_nonblock, tc)
{
paccept_block(AF_INET6, AF_INET, false, false);
accept_test(AF_INET6, AF_INET, false, false, false);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, paccept44_reset_nonblock);
ATF_TP_ADD_TC(tp, accept_44_preserve_nonblock);
ATF_TP_ADD_TC(tp, accept4_44_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, accept4_44_nonblock);
ATF_TP_ADD_TC(tp, accept4_66_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, accept4_66_nonblock);
ATF_TP_ADD_TC(tp, accept4_46_reset_nonblock);
ATF_TP_ADD_TC(tp, fcntl46_reset_nonblock);
ATF_TP_ADD_TC(tp, paccept46_nonblock);
ATF_TP_ADD_TC(tp, accept4_46_nonblock);
return atf_no_error();
}
#else
int
main(int argc, char *argv[])
{
paccept_block(AF_INET, AF_INET, false, false);
paccept_block(AF_INET, AF_INET, true, false);
accept_test(AF_INET, AF_INET, true, true, false);
return 0;
}
#endif