1*57718be8SEnji Cooper /* $NetBSD: t_tcp.c,v 1.3 2013/10/17 12:53:28 christos Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2013 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 8*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 9*57718be8SEnji Cooper * are met: 10*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 11*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 12*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 13*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 14*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 15*57718be8SEnji Cooper * 3. All advertising materials mentioning features or use of this software 16*57718be8SEnji Cooper * must display the following acknowledgement: 17*57718be8SEnji Cooper * This product includes software developed by the NetBSD 18*57718be8SEnji Cooper * Foundation, Inc. and its contributors. 19*57718be8SEnji Cooper * 4. Neither the name of The NetBSD Foundation nor the names of its 20*57718be8SEnji Cooper * contributors may be used to endorse or promote products derived 21*57718be8SEnji Cooper * from this software without specific prior written permission. 22*57718be8SEnji Cooper * 23*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 34*57718be8SEnji Cooper */ 35*57718be8SEnji Cooper 36*57718be8SEnji Cooper #include <sys/cdefs.h> 37*57718be8SEnji Cooper #ifdef __RCSID 38*57718be8SEnji Cooper __RCSID("$Id: t_tcp.c,v 1.3 2013/10/17 12:53:28 christos Exp $"); 39*57718be8SEnji Cooper #endif 40*57718be8SEnji Cooper 41*57718be8SEnji Cooper /* Example code. Should block; does with accept not paccept. */ 42*57718be8SEnji Cooper /* Original by: Justin Cormack <justin@specialbusrvrervice.com> */ 43*57718be8SEnji Cooper 44*57718be8SEnji Cooper #include <sys/param.h> 45*57718be8SEnji Cooper #include <sys/types.h> 46*57718be8SEnji Cooper #include <sys/socket.h> 47*57718be8SEnji Cooper #include <netinet/in.h> 48*57718be8SEnji Cooper #include <stdio.h> 49*57718be8SEnji Cooper #include <stdbool.h> 50*57718be8SEnji Cooper #include <unistd.h> 51*57718be8SEnji Cooper #include <fcntl.h> 52*57718be8SEnji Cooper #include <errno.h> 53*57718be8SEnji Cooper #include <err.h> 54*57718be8SEnji Cooper #include <stdlib.h> 55*57718be8SEnji Cooper #include <signal.h> 56*57718be8SEnji Cooper 57*57718be8SEnji Cooper #ifdef TEST 58*57718be8SEnji Cooper #define FAIL(msg, ...) err(EXIT_FAILURE, msg, ## __VA_ARGS__) 59*57718be8SEnji Cooper #else 60*57718be8SEnji Cooper #include <atf-c.h> 61*57718be8SEnji Cooper #define FAIL(msg, ...) ATF_CHECK_MSG(0, msg, ## __VA_ARGS__); goto fail 62*57718be8SEnji Cooper #endif 63*57718be8SEnji Cooper 64*57718be8SEnji Cooper static void 65*57718be8SEnji Cooper ding(int al) 66*57718be8SEnji Cooper { 67*57718be8SEnji Cooper } 68*57718be8SEnji Cooper 69*57718be8SEnji Cooper static void 70*57718be8SEnji Cooper paccept_block(bool pacceptblock, bool fcntlblock) 71*57718be8SEnji Cooper { 72*57718be8SEnji Cooper int srvr = -1, clnt = -1, as = -1; 73*57718be8SEnji Cooper int ok, fl, n; 74*57718be8SEnji Cooper char buf[10]; 75*57718be8SEnji Cooper struct sockaddr_in sin, ba; 76*57718be8SEnji Cooper struct sigaction sa; 77*57718be8SEnji Cooper 78*57718be8SEnji Cooper srvr = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 79*57718be8SEnji Cooper if (srvr == -1) 80*57718be8SEnji Cooper FAIL("socket"); 81*57718be8SEnji Cooper 82*57718be8SEnji Cooper memset(&sin, 0, sizeof(sin)); 83*57718be8SEnji Cooper sin.sin_family = AF_INET; 84*57718be8SEnji Cooper #ifdef BSD4_4 85*57718be8SEnji Cooper sin.sin_len = sizeof(sin); 86*57718be8SEnji Cooper #endif 87*57718be8SEnji Cooper sin.sin_port = htons(0); 88*57718be8SEnji Cooper sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 89*57718be8SEnji Cooper ok = bind(srvr, (const struct sockaddr *)&sin, (socklen_t)sizeof(sin)); 90*57718be8SEnji Cooper if (ok == -1) 91*57718be8SEnji Cooper FAIL("bind"); 92*57718be8SEnji Cooper 93*57718be8SEnji Cooper socklen_t addrlen = sizeof(struct sockaddr_in); 94*57718be8SEnji Cooper ok = getsockname(srvr, (struct sockaddr *)&ba, &addrlen); 95*57718be8SEnji Cooper if (ok == -1) 96*57718be8SEnji Cooper FAIL("getsockname"); 97*57718be8SEnji Cooper 98*57718be8SEnji Cooper ok = listen(srvr, SOMAXCONN); 99*57718be8SEnji Cooper if (ok == -1) 100*57718be8SEnji Cooper FAIL("listen"); 101*57718be8SEnji Cooper 102*57718be8SEnji Cooper clnt = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 103*57718be8SEnji Cooper if (clnt == -1) 104*57718be8SEnji Cooper FAIL("socket"); 105*57718be8SEnji Cooper 106*57718be8SEnji Cooper /* may not connect first time */ 107*57718be8SEnji Cooper ok = connect(clnt, (struct sockaddr *) &ba, addrlen); 108*57718be8SEnji Cooper as = paccept(srvr, NULL, NULL, NULL, pacceptblock ? 0 : SOCK_NONBLOCK); 109*57718be8SEnji Cooper ok = connect(clnt, (struct sockaddr *) &ba, addrlen); 110*57718be8SEnji Cooper if (ok == -1 && errno != EISCONN) 111*57718be8SEnji Cooper FAIL("both connects failed"); 112*57718be8SEnji Cooper 113*57718be8SEnji Cooper #if 0 114*57718be8SEnji Cooper fl = fcntl(srvr, F_GETFL, 0); 115*57718be8SEnji Cooper if (fl == -1) 116*57718be8SEnji Cooper FAIL("fnctl getfl"); 117*57718be8SEnji Cooper 118*57718be8SEnji Cooper ok = fcntl(srvr, F_SETFL, fl & ~O_NONBLOCK); 119*57718be8SEnji Cooper if (ok == -1) 120*57718be8SEnji Cooper FAIL("fnctl setfl"); 121*57718be8SEnji Cooper #endif 122*57718be8SEnji Cooper 123*57718be8SEnji Cooper if (as == -1) { /* not true under NetBSD */ 124*57718be8SEnji Cooper as = paccept(srvr, NULL, NULL, NULL, pacceptblock ? 0 : SOCK_NONBLOCK); 125*57718be8SEnji Cooper if (as == -1) 126*57718be8SEnji Cooper FAIL("paccept"); 127*57718be8SEnji Cooper } 128*57718be8SEnji Cooper if (fcntlblock) { 129*57718be8SEnji Cooper fl = fcntl(as, F_GETFL, 0); 130*57718be8SEnji Cooper if (fl == -1) 131*57718be8SEnji Cooper FAIL("fnctl"); 132*57718be8SEnji Cooper if (fl != (O_RDWR|O_NONBLOCK)) 133*57718be8SEnji Cooper FAIL("fl 0x%x != 0x%x\n", fl, O_RDWR|O_NONBLOCK); 134*57718be8SEnji Cooper ok = fcntl(as, F_SETFL, fl & ~O_NONBLOCK); 135*57718be8SEnji Cooper if (ok == -1) 136*57718be8SEnji Cooper FAIL("fnctl setfl"); 137*57718be8SEnji Cooper 138*57718be8SEnji Cooper fl = fcntl(as, F_GETFL, 0); 139*57718be8SEnji Cooper if (fl & O_NONBLOCK) 140*57718be8SEnji Cooper FAIL("fl non blocking after reset"); 141*57718be8SEnji Cooper } 142*57718be8SEnji Cooper sa.sa_handler = ding; 143*57718be8SEnji Cooper sa.sa_flags = 0; 144*57718be8SEnji Cooper sigemptyset(&sa.sa_mask); 145*57718be8SEnji Cooper sigaction(SIGALRM, &sa, NULL); 146*57718be8SEnji Cooper alarm(1); 147*57718be8SEnji Cooper n = read(as, buf, 10); 148*57718be8SEnji Cooper 149*57718be8SEnji Cooper if (pacceptblock || fcntlblock) { 150*57718be8SEnji Cooper if (n == -1 && errno != EINTR) 151*57718be8SEnji Cooper FAIL("read"); 152*57718be8SEnji Cooper } else { 153*57718be8SEnji Cooper if (n != -1 || errno != EWOULDBLOCK) 154*57718be8SEnji Cooper FAIL("read"); 155*57718be8SEnji Cooper } 156*57718be8SEnji Cooper return; 157*57718be8SEnji Cooper fail: 158*57718be8SEnji Cooper close(srvr); 159*57718be8SEnji Cooper close(clnt); 160*57718be8SEnji Cooper close(as); 161*57718be8SEnji Cooper } 162*57718be8SEnji Cooper 163*57718be8SEnji Cooper #ifndef TEST 164*57718be8SEnji Cooper 165*57718be8SEnji Cooper ATF_TC(paccept_reset_nonblock); 166*57718be8SEnji Cooper ATF_TC_HEAD(paccept_reset_nonblock, tc) 167*57718be8SEnji Cooper { 168*57718be8SEnji Cooper 169*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Check that paccept(2) resets " 170*57718be8SEnji Cooper "the non-blocking flag on non-blocking sockets"); 171*57718be8SEnji Cooper } 172*57718be8SEnji Cooper 173*57718be8SEnji Cooper ATF_TC_BODY(paccept_reset_nonblock, tc) 174*57718be8SEnji Cooper { 175*57718be8SEnji Cooper paccept_block(true, false); 176*57718be8SEnji Cooper } 177*57718be8SEnji Cooper 178*57718be8SEnji Cooper ATF_TC(fcntl_reset_nonblock); 179*57718be8SEnji Cooper ATF_TC_HEAD(fcntl_reset_nonblock, tc) 180*57718be8SEnji Cooper { 181*57718be8SEnji Cooper 182*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets " 183*57718be8SEnji Cooper "the non-blocking flag on non-blocking sockets"); 184*57718be8SEnji Cooper } 185*57718be8SEnji Cooper 186*57718be8SEnji Cooper ATF_TC_BODY(fcntl_reset_nonblock, tc) 187*57718be8SEnji Cooper { 188*57718be8SEnji Cooper paccept_block(false, true); 189*57718be8SEnji Cooper } 190*57718be8SEnji Cooper 191*57718be8SEnji Cooper ATF_TC(paccept_nonblock); 192*57718be8SEnji Cooper ATF_TC_HEAD(paccept_nonblock, tc) 193*57718be8SEnji Cooper { 194*57718be8SEnji Cooper 195*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Check that fcntl(2) resets " 196*57718be8SEnji Cooper "the non-blocking flag on non-blocking sockets"); 197*57718be8SEnji Cooper } 198*57718be8SEnji Cooper 199*57718be8SEnji Cooper ATF_TC_BODY(paccept_nonblock, tc) 200*57718be8SEnji Cooper { 201*57718be8SEnji Cooper paccept_block(false, false); 202*57718be8SEnji Cooper } 203*57718be8SEnji Cooper 204*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 205*57718be8SEnji Cooper { 206*57718be8SEnji Cooper 207*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, paccept_reset_nonblock); 208*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, fcntl_reset_nonblock); 209*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, paccept_nonblock); 210*57718be8SEnji Cooper return atf_no_error(); 211*57718be8SEnji Cooper } 212*57718be8SEnji Cooper #else 213*57718be8SEnji Cooper int 214*57718be8SEnji Cooper main(int argc, char *argv[]) 215*57718be8SEnji Cooper { 216*57718be8SEnji Cooper paccept_block(false); 217*57718be8SEnji Cooper paccept_block(true); 218*57718be8SEnji Cooper return 0; 219*57718be8SEnji Cooper } 220*57718be8SEnji Cooper #endif 221