xref: /netbsd-src/tests/net/tcp/tcp_shutdown.c (revision 3df6c9b812215d4068516867ebe41f42f4fb2777)
1*3df6c9b8Sozaki-r /*	$NetBSD: tcp_shutdown.c,v 1.1 2022/11/04 08:01:42 ozaki-r Exp $	*/
2*3df6c9b8Sozaki-r 
3*3df6c9b8Sozaki-r /*-
4*3df6c9b8Sozaki-r  * Copyright (c) 2022 Internet Initiative Japan Inc.
5*3df6c9b8Sozaki-r  * All rights reserved.
6*3df6c9b8Sozaki-r  *
7*3df6c9b8Sozaki-r  * This code is derived from software contributed to The NetBSD Foundation
8*3df6c9b8Sozaki-r  * by Christos Zoulas.
9*3df6c9b8Sozaki-r  *
10*3df6c9b8Sozaki-r  * Redistribution and use in source and binary forms, with or without
11*3df6c9b8Sozaki-r  * modification, are permitted provided that the following conditions
12*3df6c9b8Sozaki-r  * are met:
13*3df6c9b8Sozaki-r  * 1. Redistributions of source code must retain the above copyright
14*3df6c9b8Sozaki-r  *    notice, this list of conditions and the following disclaimer.
15*3df6c9b8Sozaki-r  * 2. Redistributions in binary form must reproduce the above copyright
16*3df6c9b8Sozaki-r  *    notice, this list of conditions and the following disclaimer in the
17*3df6c9b8Sozaki-r  *    documentation and/or other materials provided with the distribution.
18*3df6c9b8Sozaki-r  *
19*3df6c9b8Sozaki-r  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*3df6c9b8Sozaki-r  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*3df6c9b8Sozaki-r  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*3df6c9b8Sozaki-r  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*3df6c9b8Sozaki-r  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*3df6c9b8Sozaki-r  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*3df6c9b8Sozaki-r  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*3df6c9b8Sozaki-r  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*3df6c9b8Sozaki-r  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*3df6c9b8Sozaki-r  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*3df6c9b8Sozaki-r  * POSSIBILITY OF SUCH DAMAGE.
30*3df6c9b8Sozaki-r  */
31*3df6c9b8Sozaki-r #include <sys/cdefs.h>
32*3df6c9b8Sozaki-r #ifdef __RCSID
33*3df6c9b8Sozaki-r __RCSID("$NetBSD: tcp_shutdown.c,v 1.1 2022/11/04 08:01:42 ozaki-r Exp $");
34*3df6c9b8Sozaki-r #else
35*3df6c9b8Sozaki-r extern const char *__progname;
36*3df6c9b8Sozaki-r #define getprogname() __progname
37*3df6c9b8Sozaki-r #endif
38*3df6c9b8Sozaki-r 
39*3df6c9b8Sozaki-r #include <sys/types.h>
40*3df6c9b8Sozaki-r #include <sys/socket.h>
41*3df6c9b8Sozaki-r #include <netinet/in.h>
42*3df6c9b8Sozaki-r #include <arpa/inet.h>
43*3df6c9b8Sozaki-r 
44*3df6c9b8Sozaki-r #include <stdio.h>
45*3df6c9b8Sozaki-r #include <string.h>
46*3df6c9b8Sozaki-r #include <stdlib.h>
47*3df6c9b8Sozaki-r #include <unistd.h>
48*3df6c9b8Sozaki-r #include <err.h>
49*3df6c9b8Sozaki-r #include <errno.h>
50*3df6c9b8Sozaki-r #include <stdbool.h>
51*3df6c9b8Sozaki-r 
52*3df6c9b8Sozaki-r static inline bool
match(const char * a,const char * b)53*3df6c9b8Sozaki-r match(const char *a, const char *b)
54*3df6c9b8Sozaki-r {
55*3df6c9b8Sozaki-r 
56*3df6c9b8Sozaki-r 	return strncmp(a, b, strlen(b)) == 0;
57*3df6c9b8Sozaki-r }
58*3df6c9b8Sozaki-r 
59*3df6c9b8Sozaki-r int
main(int argc,char * argv[])60*3df6c9b8Sozaki-r main(int argc, char *argv[])
61*3df6c9b8Sozaki-r {
62*3df6c9b8Sozaki-r 	int s, e;
63*3df6c9b8Sozaki-r 	char *target;
64*3df6c9b8Sozaki-r 
65*3df6c9b8Sozaki-r 	if (argc != 2)
66*3df6c9b8Sozaki-r 		errx(EXIT_FAILURE, "invalid argument");
67*3df6c9b8Sozaki-r 	target = argv[1];
68*3df6c9b8Sozaki-r 
69*3df6c9b8Sozaki-r 	s = socket(AF_INET, SOCK_STREAM, 0);
70*3df6c9b8Sozaki-r 	if (s == -1)
71*3df6c9b8Sozaki-r 		err(EXIT_FAILURE, "socket");
72*3df6c9b8Sozaki-r 	e = shutdown(s, SHUT_RDWR);
73*3df6c9b8Sozaki-r 	if (e == -1)
74*3df6c9b8Sozaki-r 		err(EXIT_FAILURE, "shutdown");
75*3df6c9b8Sozaki-r 
76*3df6c9b8Sozaki-r 	if (match(target, "connect")) {
77*3df6c9b8Sozaki-r 		struct sockaddr_in sin;
78*3df6c9b8Sozaki-r 
79*3df6c9b8Sozaki-r 		memset(&sin, 0, sizeof(sin));
80*3df6c9b8Sozaki-r 		sin.sin_port = htons(31522);
81*3df6c9b8Sozaki-r 		sin.sin_addr.s_addr = inet_addr("127.0.0.1");
82*3df6c9b8Sozaki-r 		sin.sin_family = AF_INET;
83*3df6c9b8Sozaki-r 
84*3df6c9b8Sozaki-r 		e = connect(s, (struct sockaddr *)&sin, sizeof(sin));
85*3df6c9b8Sozaki-r 		if (e == 0)
86*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "connect didn't fail on a shudown socket");
87*3df6c9b8Sozaki-r 		if (e == -1 && errno != EINVAL)
88*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "connect failed with unexpected error");
89*3df6c9b8Sozaki-r 	} else if (match(target, "setsockopt")) {
90*3df6c9b8Sozaki-r 		int opt = 1;
91*3df6c9b8Sozaki-r 		e = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
92*3df6c9b8Sozaki-r 		if (e == 0)
93*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "setsockopt didn't fail on a shutdown socket");
94*3df6c9b8Sozaki-r 		if (e == -1 && errno != ECONNRESET)
95*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "setsockopt failed with unexpected error");
96*3df6c9b8Sozaki-r 	} else if (match(target, "getsockname")) {
97*3df6c9b8Sozaki-r 		struct sockaddr_storage ss;
98*3df6c9b8Sozaki-r 		socklen_t len;
99*3df6c9b8Sozaki-r 		e = getsockname(s, (struct sockaddr *)&ss, &len);
100*3df6c9b8Sozaki-r 		if (e == 0)
101*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "getsockname didn't fail on a shutdown socket");
102*3df6c9b8Sozaki-r 		if (e == -1 && errno != EINVAL)
103*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "getsockname failed with unexpected error");
104*3df6c9b8Sozaki-r 	} else if (match(target, "listen")) {
105*3df6c9b8Sozaki-r 		e = listen(s, 5);
106*3df6c9b8Sozaki-r 		if (e == 0)
107*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "listen didn't fail on a shutdown socket");
108*3df6c9b8Sozaki-r 		if (e == -1 && errno != EINVAL)
109*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "listen failed with unexpected error");
110*3df6c9b8Sozaki-r 	} else if (match(target, "bind")) {
111*3df6c9b8Sozaki-r 		struct sockaddr_in sin;
112*3df6c9b8Sozaki-r 
113*3df6c9b8Sozaki-r 		memset(&sin, 0, sizeof(sin));
114*3df6c9b8Sozaki-r 		sin.sin_port = htons(31522);
115*3df6c9b8Sozaki-r 		sin.sin_addr.s_addr = inet_addr("127.0.0.1");
116*3df6c9b8Sozaki-r 		sin.sin_family = AF_INET;
117*3df6c9b8Sozaki-r 
118*3df6c9b8Sozaki-r 		e = bind(s, (struct sockaddr *)&sin, sizeof(sin));
119*3df6c9b8Sozaki-r 		if (e == 0)
120*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "bind didn't fail on a shutdown socket");
121*3df6c9b8Sozaki-r 		if (e == -1 && errno != EINVAL)
122*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "bind failed with unexpected error");
123*3df6c9b8Sozaki-r 	} else if (match(target, "shutdown")) {
124*3df6c9b8Sozaki-r 		e = shutdown(s, SHUT_RDWR);
125*3df6c9b8Sozaki-r 		if (e == 0)
126*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "shutdown didn't fail on a shutdown socket");
127*3df6c9b8Sozaki-r 		if (e == -1 && errno != EINVAL)
128*3df6c9b8Sozaki-r 			err(EXIT_FAILURE, "shutdown failed with unexpected error");
129*3df6c9b8Sozaki-r 	} else {
130*3df6c9b8Sozaki-r 		errx(EXIT_FAILURE, "unknown target: %s", target);
131*3df6c9b8Sozaki-r 	}
132*3df6c9b8Sozaki-r 
133*3df6c9b8Sozaki-r 	e = close(s);
134*3df6c9b8Sozaki-r 	if (e == -1)
135*3df6c9b8Sozaki-r 		err(EXIT_FAILURE, "close");
136*3df6c9b8Sozaki-r 	return 0;
137*3df6c9b8Sozaki-r }
138