1 /* $NetBSD: t_tcp.c,v 1.3 2013/10/17 12:53:28 christos Exp $ */
4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the NetBSD
18 * Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/cdefs.h>
38 __RCSID("$Id: t_tcp.c,v 1.3 2013/10/17 12:53:28 christos Exp $");
41 /* Example code. Should block; does with accept not paccept. */
42 /* Original by: Justin Cormack <justin@specialbusrvrervice.com> */
44 #include <sys/param.h>
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
58 #define FAIL(msg, ...) err(EXIT_FAILURE, msg, ## __VA_ARGS__)
61 #define FAIL(msg, ...) ATF_CHECK_MSG(0, msg, ## __VA_ARGS__); goto fail
70 paccept_block(bool pacceptblock
, bool fcntlblock
)
72 int srvr
= -1, clnt
= -1, as
= -1;
75 struct sockaddr_in sin
, ba
;
78 srvr
= socket(AF_INET
, SOCK_STREAM
| SOCK_NONBLOCK
, 0);
82 memset(&sin
, 0, sizeof(sin
));
83 sin
.sin_family
= AF_INET
;
85 sin
.sin_len
= sizeof(sin
);
87 sin
.sin_port
= htons(0);
88 sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
89 ok
= bind(srvr
, (const struct sockaddr
*)&sin
, (socklen_t
)sizeof(sin
));
93 socklen_t addrlen
= sizeof(struct sockaddr_in
);
94 ok
= getsockname(srvr
, (struct sockaddr
*)&ba
, &addrlen
);
98 ok
= listen(srvr
, SOMAXCONN
);
102 clnt
= socket(AF_INET
, SOCK_STREAM
| SOCK_NONBLOCK
, 0);
106 /* may not connect first time */
107 ok
= connect(clnt
, (struct sockaddr
*) &ba
, addrlen
);
108 as
= paccept(srvr
, NULL
, NULL
, NULL
, pacceptblock
? 0 : SOCK_NONBLOCK
);
109 ok
= connect(clnt
, (struct sockaddr
*) &ba
, addrlen
);
110 if (ok
== -1 && errno
!= EISCONN
)
111 FAIL("both connects failed");
114 fl
= fcntl(srvr
, F_GETFL
, 0);
118 ok
= fcntl(srvr
, F_SETFL
, fl
& ~O_NONBLOCK
);
123 if (as
== -1) { /* not true under NetBSD */
124 as
= paccept(srvr
, NULL
, NULL
, NULL
, pacceptblock
? 0 : SOCK_NONBLOCK
);
129 fl
= fcntl(as
, F_GETFL
, 0);
132 if (fl
!= (O_RDWR
|O_NONBLOCK
))
133 FAIL("fl 0x%x != 0x%x\n", fl
, O_RDWR
|O_NONBLOCK
);
134 ok
= fcntl(as
, F_SETFL
, fl
& ~O_NONBLOCK
);
138 fl
= fcntl(as
, F_GETFL
, 0);
140 FAIL("fl non blocking after reset");
142 sa
.sa_handler
= ding
;
144 sigemptyset(&sa
.sa_mask
);
145 sigaction(SIGALRM
, &sa
, NULL
);
147 n
= read(as
, buf
, 10);
149 if (pacceptblock
|| fcntlblock
) {
150 if (n
== -1 && errno
!= EINTR
)
153 if (n
!= -1 || errno
!= EWOULDBLOCK
)
165 ATF_TC(paccept_reset_nonblock
);
166 ATF_TC_HEAD(paccept_reset_nonblock
, tc
)
169 atf_tc_set_md_var(tc
, "descr", "Check that paccept(2) resets "
170 "the non-blocking flag on non-blocking sockets");
173 ATF_TC_BODY(paccept_reset_nonblock
, tc
)
175 paccept_block(true, false);
178 ATF_TC(fcntl_reset_nonblock
);
179 ATF_TC_HEAD(fcntl_reset_nonblock
, tc
)
182 atf_tc_set_md_var(tc
, "descr", "Check that fcntl(2) resets "
183 "the non-blocking flag on non-blocking sockets");
186 ATF_TC_BODY(fcntl_reset_nonblock
, tc
)
188 paccept_block(false, true);
191 ATF_TC(paccept_nonblock
);
192 ATF_TC_HEAD(paccept_nonblock
, tc
)
195 atf_tc_set_md_var(tc
, "descr", "Check that fcntl(2) resets "
196 "the non-blocking flag on non-blocking sockets");
199 ATF_TC_BODY(paccept_nonblock
, tc
)
201 paccept_block(false, false);
207 ATF_TP_ADD_TC(tp
, paccept_reset_nonblock
);
208 ATF_TP_ADD_TC(tp
, fcntl_reset_nonblock
);
209 ATF_TP_ADD_TC(tp
, paccept_nonblock
);
210 return atf_no_error();
214 main(int argc
, char *argv
[])
216 paccept_block(false);