xref: /freebsd/contrib/netbsd-tests/net/net/t_tcp.c (revision 57718be8)
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