]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - tools/regression/sockets/unix_sendtorace/unix_sendtorace.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / tools / regression / sockets / unix_sendtorace / unix_sendtorace.c
1 /*-
2  * Copyright (c) 2006 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 /*
30  * Attempts to exercise UNIX domain socket races relating to the non-atomic
31  * connect-and-send properties of sendto().  As the result of such a race is
32  * a kernel panic, this test simply completes or doesn't.
33  *
34  * XXX: Despite implementing support for sendto() on stream sockets with
35  * implied connect, the appropriate flag isn't set in the FreeBSD kernel so
36  * it does not work.  For now, don't call the stream test.
37  */
38
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/un.h>
42
43 #include <err.h>
44 #include <signal.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #define ITERATIONS      1000000
49
50 static char socket_path[] = "tmp.XXXXXX";
51
52 static void
53 stream_server(int listenfd)
54 {
55         int acceptfd;
56
57         while (1) {
58                 acceptfd = accept(listenfd, NULL, NULL);
59                 if (acceptfd < 0) {
60                         warn("stream_server: accept");
61                         continue;
62                 }
63                 sleep(1);
64                 close(acceptfd);
65         }
66 }
67
68 static void
69 stream_client(void)
70 {
71         struct sockaddr_un sun;
72         ssize_t len;
73         char c = 0;
74         int fd, i;
75
76         bzero(&sun, sizeof(sun));
77         sun.sun_len = sizeof(sun);
78         sun.sun_family = AF_UNIX;
79         strcpy(sun.sun_path, socket_path);
80         for (i = 0; i < ITERATIONS; i++) {
81                 fd = socket(PF_UNIX, SOCK_STREAM, 0);
82                 if (fd < 0) {
83                         warn("stream_client: socket");
84                         return;
85                 }
86                 len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
87                     sizeof(sun));
88                 if (len < 0)
89                         warn("stream_client: sendto");
90                 close(fd);
91         }
92 }
93
94 static void
95 stream_test(void)
96 {
97         struct sockaddr_un sun;
98         pid_t childpid;
99         int listenfd;
100
101         listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
102         if (listenfd < 0)
103                 err(-1, "stream_test: socket");
104
105         bzero(&sun, sizeof(sun));
106         sun.sun_len = sizeof(sun);
107         sun.sun_family = AF_UNIX;
108         strcpy(sun.sun_path, socket_path);
109
110         if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
111                 err(-1, "stream_test: bind");
112
113         if (listen(listenfd, -1) < 0)
114                 err(-1, "stream_test: listen");
115
116         childpid = fork();
117         if (childpid < 0)
118                 err(-1, "stream_test: fork");
119
120         if (childpid != 0) {
121                 sleep(1);
122                 stream_client();
123                 kill(childpid, SIGTERM);
124                 sleep(1);
125         } else
126                 stream_server(listenfd);
127
128         (void)unlink(socket_path);
129 }
130
131 static void
132 datagram_server(int serverfd)
133 {
134         ssize_t len;
135         char c;
136
137         while (1) {
138                 len = recv(serverfd, &c, sizeof(c), 0);
139                 if (len < 0)
140                         warn("datagram_server: recv");
141         }
142 }
143
144 static void
145 datagram_client(void)
146 {
147         struct sockaddr_un sun;
148         ssize_t len;
149         char c = 0;
150         int fd, i;
151
152         bzero(&sun, sizeof(sun));
153         sun.sun_len = sizeof(sun);
154         sun.sun_family = AF_UNIX;
155         strcpy(sun.sun_path, socket_path);
156         for (i = 0; i < ITERATIONS; i++) {
157                 fd = socket(PF_UNIX, SOCK_DGRAM, 0);
158                 if (fd < 0) {
159                         warn("datagram_client: socket");
160                         return;
161                 }
162                 len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
163                     sizeof(sun));
164                 if (len < 0)
165                         warn("datagram_client: sendto");
166                 close(fd);
167         }
168 }
169
170 static void
171 datagram_test(void)
172 {
173         struct sockaddr_un sun;
174         pid_t childpid;
175         int serverfd;
176
177         serverfd = socket(PF_UNIX, SOCK_DGRAM, 0);
178         if (serverfd < 0)
179                 err(-1, "datagram_test: socket");
180
181         bzero(&sun, sizeof(sun));
182         sun.sun_len = sizeof(sun);
183         sun.sun_family = AF_UNIX;
184         strcpy(sun.sun_path, socket_path);
185
186         if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
187                 err(-1, "datagram_test: bind");
188
189         childpid = fork();
190         if (childpid < 0)
191                 err(-1, "datagram_test: fork");
192
193         if (childpid != 0) {
194                 sleep(1);
195                 datagram_client();
196                 kill(childpid, SIGTERM);
197                 sleep(1);
198         } else
199                 datagram_server(serverfd);
200
201         (void)unlink(socket_path);
202 }
203
204 int
205 main(void)
206 {
207         
208         if (mkstemp(socket_path) == -1)
209                 err(1, "mkstemp failed");
210         (void)unlink(socket_path);
211         datagram_test();
212         if (0)
213                 stream_test();
214         return (0);
215 }