]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/regression/sockets/unix_sendtorace/unix_sendtorace.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 PATH            "/tmp/123"
49 #define ITERATIONS      1000000
50
51 static void
52 stream_server(int listenfd)
53 {
54         int acceptfd;
55
56         while (1) {
57                 acceptfd = accept(listenfd, NULL, NULL);
58                 if (acceptfd < 0) {
59                         warn("stream_server: accept");
60                         continue;
61                 }
62                 sleep(1);
63                 close(acceptfd);
64         }
65 }
66
67 static void
68 stream_client(void)
69 {
70         struct sockaddr_un sun;
71         ssize_t len;
72         char c = 0;
73         int fd, i;
74
75         bzero(&sun, sizeof(sun));
76         sun.sun_len = sizeof(sun);
77         sun.sun_family = AF_UNIX;
78         strcpy(sun.sun_path, PATH);
79         for (i = 0; i < ITERATIONS; i++) {
80                 fd = socket(PF_UNIX, SOCK_STREAM, 0);
81                 if (fd < 0) {
82                         warn("stream_client: socket");
83                         return;
84                 }
85                 len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
86                     sizeof(sun));
87                 if (len < 0)
88                         warn("stream_client: sendto");
89                 close(fd);
90         }
91 }
92
93 static void
94 stream_test(void)
95 {
96         struct sockaddr_un sun;
97         pid_t childpid;
98         int listenfd;
99
100         listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
101         if (listenfd < 0)
102                 err(-1, "stream_test: socket");
103
104         bzero(&sun, sizeof(sun));
105         sun.sun_len = sizeof(sun);
106         sun.sun_family = AF_UNIX;
107         strcpy(sun.sun_path, PATH);
108
109         if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
110                 err(-1, "stream_test: bind");
111
112         if (listen(listenfd, -1) < 0)
113                 err(-1, "stream_test: listen");
114
115         childpid = fork();
116         if (childpid < 0)
117                 err(-1, "stream_test: fork");
118
119         if (childpid != 0) {
120                 sleep(1);
121                 stream_client();
122                 kill(childpid, SIGTERM);
123                 sleep(1);
124         } else
125                 stream_server(listenfd);
126
127         (void)unlink(PATH);
128 }
129
130 static void
131 datagram_server(int serverfd)
132 {
133         ssize_t len;
134         char c;
135
136         while (1) {
137                 len = recv(serverfd, &c, sizeof(c), 0);
138                 if (len < 0)
139                         warn("datagram_server: recv");
140         }
141 }
142
143 static void
144 datagram_client(void)
145 {
146         struct sockaddr_un sun;
147         ssize_t len;
148         char c = 0;
149         int fd, i;
150
151         bzero(&sun, sizeof(sun));
152         sun.sun_len = sizeof(sun);
153         sun.sun_family = AF_UNIX;
154         strcpy(sun.sun_path, PATH);
155         for (i = 0; i < ITERATIONS; i++) {
156                 fd = socket(PF_UNIX, SOCK_DGRAM, 0);
157                 if (fd < 0) {
158                         warn("datagram_client: socket");
159                         return;
160                 }
161                 len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
162                     sizeof(sun));
163                 if (len < 0)
164                         warn("datagram_client: sendto");
165                 close(fd);
166         }
167 }
168
169 static void
170 datagram_test(void)
171 {
172         struct sockaddr_un sun;
173         pid_t childpid;
174         int serverfd;
175
176         serverfd = socket(PF_UNIX, SOCK_DGRAM, 0);
177         if (serverfd < 0)
178                 err(-1, "datagram_test: socket");
179
180         bzero(&sun, sizeof(sun));
181         sun.sun_len = sizeof(sun);
182         sun.sun_family = AF_UNIX;
183         strcpy(sun.sun_path, PATH);
184
185         if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
186                 err(-1, "datagram_test: bind");
187
188         childpid = fork();
189         if (childpid < 0)
190                 err(-1, "datagram_test: fork");
191
192         if (childpid != 0) {
193                 sleep(1);
194                 datagram_client();
195                 kill(childpid, SIGTERM);
196                 sleep(1);
197         } else
198                 datagram_server(serverfd);
199
200         (void)unlink(PATH);
201 }
202
203 int
204 main(int argc, char *argv[])
205 {
206
207         (void)unlink(PATH);
208         datagram_test();
209         if (0)
210                 stream_test();
211         return (0);
212 }