1313498Sngie/* $NetBSD: t_tcp.c,v 1.4 2016/03/04 18:52:01 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2013 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 3. All advertising materials mentioning features or use of this software 16272343Sngie * must display the following acknowledgement: 17272343Sngie * This product includes software developed by the NetBSD 18272343Sngie * Foundation, Inc. and its contributors. 19272343Sngie * 4. Neither the name of The NetBSD Foundation nor the names of its 20272343Sngie * contributors may be used to endorse or promote products derived 21272343Sngie * from this software without specific prior written permission. 22272343Sngie * 23272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33272343Sngie * POSSIBILITY OF SUCH DAMAGE. 34272343Sngie */ 35272343Sngie 36272343Sngie#include <sys/cdefs.h> 37272343Sngie#ifdef __RCSID 38313498Sngie__RCSID("$Id: t_tcp.c,v 1.4 2016/03/04 18:52:01 christos Exp $"); 39272343Sngie#endif 40272343Sngie 41272343Sngie/* Example code. Should block; does with accept not paccept. */ 42272343Sngie/* Original by: Justin Cormack <justin@specialbusrvrervice.com> */ 43272343Sngie 44272343Sngie#include <sys/param.h> 45272343Sngie#include <sys/types.h> 46272343Sngie#include <sys/socket.h> 47272343Sngie#include <netinet/in.h> 48272343Sngie#include <stdio.h> 49272343Sngie#include <stdbool.h> 50272343Sngie#include <unistd.h> 51272343Sngie#include <fcntl.h> 52272343Sngie#include <errno.h> 53272343Sngie#include <err.h> 54272343Sngie#include <stdlib.h> 55272343Sngie#include <signal.h> 56272343Sngie 57272343Sngie#ifdef TEST 58272343Sngie#define FAIL(msg, ...) err(EXIT_FAILURE, msg, ## __VA_ARGS__) 59272343Sngie#else 60272343Sngie#include <atf-c.h> 61272343Sngie#define FAIL(msg, ...) ATF_CHECK_MSG(0, msg, ## __VA_ARGS__); goto fail 62272343Sngie#endif 63272343Sngie 64313498Sngie#ifdef __linux__ 65313498Sngie#define paccept(a, b, c, d, e) accept4((a), (b), (c), (e)) 66313498Sngie#endif 67313498Sngie 68272343Sngiestatic void 69272343Sngieding(int al) 70272343Sngie{ 71272343Sngie} 72272343Sngie 73272343Sngiestatic void 74272343Sngiepaccept_block(bool pacceptblock, bool fcntlblock) 75272343Sngie{ 76272343Sngie int srvr = -1, clnt = -1, as = -1; 77313498Sngie int ok, fl; 78313498Sngie ssize_t n; 79272343Sngie char buf[10]; 80272343Sngie struct sockaddr_in sin, ba; 81272343Sngie struct sigaction sa; 82272343Sngie 83272343Sngie srvr = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 84272343Sngie if (srvr == -1) 85272343Sngie FAIL("socket"); 86272343Sngie 87272343Sngie memset(&sin, 0, sizeof(sin)); 88272343Sngie sin.sin_family = AF_INET; 89272343Sngie#ifdef BSD4_4 90272343Sngie sin.sin_len = sizeof(sin); 91272343Sngie#endif 92272343Sngie sin.sin_port = htons(0); 93272343Sngie sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 94272343Sngie ok = bind(srvr, (const struct sockaddr *)&sin, (socklen_t)sizeof(sin)); 95272343Sngie if (ok == -1) 96272343Sngie FAIL("bind"); 97272343Sngie 98272343Sngie socklen_t addrlen = sizeof(struct sockaddr_in); 99272343Sngie ok = getsockname(srvr, (struct sockaddr *)&ba, &addrlen); 100272343Sngie if (ok == -1) 101272343Sngie FAIL("getsockname"); 102272343Sngie 103272343Sngie ok = listen(srvr, SOMAXCONN); 104272343Sngie if (ok == -1) 105272343Sngie FAIL("listen"); 106272343Sngie 107272343Sngie clnt = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 108272343Sngie if (clnt == -1) 109272343Sngie FAIL("socket"); 110272343Sngie 111272343Sngie /* may not connect first time */ 112272343Sngie ok = connect(clnt, (struct sockaddr *) &ba, addrlen); 113313498Sngie if (ok != -1 || errno != EINPROGRESS) 114313498Sngie FAIL("expected connect to fail"); 115272343Sngie as = paccept(srvr, NULL, NULL, NULL, pacceptblock ? 0 : SOCK_NONBLOCK); 116272343Sngie ok = connect(clnt, (struct sockaddr *) &ba, addrlen); 117272343Sngie if (ok == -1 && errno != EISCONN) 118313498Sngie FAIL("connect failed"); 119272343Sngie 120272343Sngie#if 0 121272343Sngie fl = fcntl(srvr, F_GETFL, 0); 122272343Sngie if (fl == -1) 123272343Sngie FAIL("fnctl getfl"); 124272343Sngie 125272343Sngie ok = fcntl(srvr, F_SETFL, fl & ~O_NONBLOCK); 126272343Sngie if (ok == -1) 127272343Sngie FAIL("fnctl setfl"); 128272343Sngie#endif 129272343Sngie 130272343Sngie if (as == -1) { /* not true under NetBSD */ 131272343Sngie as = paccept(srvr, NULL, NULL, NULL, pacceptblock ? 0 : SOCK_NONBLOCK); 132272343Sngie if (as == -1) 133272343Sngie FAIL("paccept"); 134272343Sngie } 135272343Sngie if (fcntlblock) { 136272343Sngie fl = fcntl(as, F_GETFL, 0); 137272343Sngie if (fl == -1) 138272343Sngie FAIL("fnctl"); 139272343Sngie if (fl != (O_RDWR|O_NONBLOCK)) 140272343Sngie FAIL("fl 0x%x != 0x%x\n", fl, O_RDWR|O_NONBLOCK); 141272343Sngie ok = fcntl(as, F_SETFL, fl & ~O_NONBLOCK); 142272343Sngie if (ok == -1) 143272343Sngie FAIL("fnctl setfl"); 144272343Sngie 145272343Sngie fl = fcntl(as, F_GETFL, 0); 146272343Sngie if (fl & O_NONBLOCK) 147272343Sngie FAIL("fl non blocking after reset"); 148272343Sngie } 149272343Sngie sa.sa_handler = ding; 150272343Sngie sa.sa_flags = 0; 151272343Sngie sigemptyset(&sa.sa_mask); 152272343Sngie sigaction(SIGALRM, &sa, NULL); 153272343Sngie alarm(1); 154272343Sngie n = read(as, buf, 10); 155272343Sngie 156272343Sngie if (pacceptblock || fcntlblock) { 157272343Sngie if (n == -1 && errno != EINTR) 158272343Sngie FAIL("read"); 159272343Sngie } else { 160272343Sngie if (n != -1 || errno != EWOULDBLOCK) 161272343Sngie FAIL("read"); 162272343Sngie } 163272343Sngie return; 164272343Sngiefail: 165272343Sngie close(srvr); 166272343Sngie close(clnt); 167272343Sngie close(as); 168272343Sngie} 169272343Sngie 170272343Sngie#ifndef TEST 171272343Sngie 172272343SngieATF_TC(paccept_reset_nonblock); 173272343SngieATF_TC_HEAD(paccept_reset_nonblock, tc) 174272343Sngie{ 175272343Sngie 176272343Sngie atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets " 177272343Sngie "the non-blocking flag on non-blocking sockets"); 178272343Sngie} 179272343Sngie 180272343SngieATF_TC_BODY(paccept_reset_nonblock, tc) 181272343Sngie{ 182272343Sngie paccept_block(true, false); 183272343Sngie} 184272343Sngie 185272343SngieATF_TC(fcntl_reset_nonblock); 186272343SngieATF_TC_HEAD(fcntl_reset_nonblock, tc) 187272343Sngie{ 188272343Sngie 189272343Sngie atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets " 190272343Sngie "the non-blocking flag on non-blocking sockets"); 191272343Sngie} 192272343Sngie 193272343SngieATF_TC_BODY(fcntl_reset_nonblock, tc) 194272343Sngie{ 195272343Sngie paccept_block(false, true); 196272343Sngie} 197272343Sngie 198272343SngieATF_TC(paccept_nonblock); 199272343SngieATF_TC_HEAD(paccept_nonblock, tc) 200272343Sngie{ 201272343Sngie 202272343Sngie atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets " 203272343Sngie "the non-blocking flag on non-blocking sockets"); 204272343Sngie} 205272343Sngie 206272343SngieATF_TC_BODY(paccept_nonblock, tc) 207272343Sngie{ 208272343Sngie paccept_block(false, false); 209272343Sngie} 210272343Sngie 211272343SngieATF_TP_ADD_TCS(tp) 212272343Sngie{ 213272343Sngie 214272343Sngie ATF_TP_ADD_TC(tp, paccept_reset_nonblock); 215272343Sngie ATF_TP_ADD_TC(tp, fcntl_reset_nonblock); 216272343Sngie ATF_TP_ADD_TC(tp, paccept_nonblock); 217272343Sngie return atf_no_error(); 218272343Sngie} 219272343Sngie#else 220272343Sngieint 221272343Sngiemain(int argc, char *argv[]) 222272343Sngie{ 223272343Sngie paccept_block(false); 224272343Sngie paccept_block(true); 225272343Sngie return 0; 226272343Sngie} 227272343Sngie#endif 228