1164298Srwatson/*-
2164298Srwatson * Copyright (c) 2006 Robert N. M. Watson
3164298Srwatson * All rights reserved.
4164298Srwatson *
5164298Srwatson * Redistribution and use in source and binary forms, with or without
6164298Srwatson * modification, are permitted provided that the following conditions
7164298Srwatson * are met:
8164298Srwatson * 1. Redistributions of source code must retain the above copyright
9164298Srwatson *    notice, this list of conditions and the following disclaimer.
10164298Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11164298Srwatson *    notice, this list of conditions and the following disclaimer in the
12164298Srwatson *    documentation and/or other materials provided with the distribution.
13164298Srwatson *
14164298Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15164298Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16164298Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17164298Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18164298Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19164298Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20164298Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21164298Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22164298Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23164298Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24164298Srwatson * SUCH DAMAGE.
25164298Srwatson *
26164298Srwatson * $FreeBSD: releng/10.2/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c 281974 2015-04-25 05:31:52Z ngie $
27164298Srwatson */
28164298Srwatson
29164298Srwatson/*
30164298Srwatson * Attempts to exercise UNIX domain socket races relating to the non-atomic
31164298Srwatson * connect-and-send properties of sendto().  As the result of such a race is
32164298Srwatson * a kernel panic, this test simply completes or doesn't.
33164298Srwatson *
34164298Srwatson * XXX: Despite implementing support for sendto() on stream sockets with
35164298Srwatson * implied connect, the appropriate flag isn't set in the FreeBSD kernel so
36164298Srwatson * it does not work.  For now, don't call the stream test.
37164298Srwatson */
38164298Srwatson
39164298Srwatson#include <sys/types.h>
40164298Srwatson#include <sys/socket.h>
41164298Srwatson#include <sys/un.h>
42164298Srwatson
43164298Srwatson#include <err.h>
44164298Srwatson#include <signal.h>
45164298Srwatson#include <string.h>
46164298Srwatson#include <unistd.h>
47164298Srwatson
48164298Srwatson#define	ITERATIONS	1000000
49164298Srwatson
50281974Sngiestatic char socket_path[] = "tmp.XXXXXX";
51281974Sngie
52164298Srwatsonstatic void
53164298Srwatsonstream_server(int listenfd)
54164298Srwatson{
55164298Srwatson	int acceptfd;
56164298Srwatson
57164298Srwatson	while (1) {
58164298Srwatson		acceptfd = accept(listenfd, NULL, NULL);
59164298Srwatson		if (acceptfd < 0) {
60164298Srwatson			warn("stream_server: accept");
61164298Srwatson			continue;
62164298Srwatson		}
63164298Srwatson		sleep(1);
64164298Srwatson		close(acceptfd);
65164298Srwatson	}
66164298Srwatson}
67164298Srwatson
68164298Srwatsonstatic void
69164298Srwatsonstream_client(void)
70164298Srwatson{
71164298Srwatson	struct sockaddr_un sun;
72164298Srwatson	ssize_t len;
73164298Srwatson	char c = 0;
74164298Srwatson	int fd, i;
75164298Srwatson
76164298Srwatson	bzero(&sun, sizeof(sun));
77164298Srwatson	sun.sun_len = sizeof(sun);
78164298Srwatson	sun.sun_family = AF_UNIX;
79281974Sngie	strcpy(sun.sun_path, socket_path);
80164298Srwatson	for (i = 0; i < ITERATIONS; i++) {
81164298Srwatson		fd = socket(PF_UNIX, SOCK_STREAM, 0);
82164298Srwatson		if (fd < 0) {
83164298Srwatson			warn("stream_client: socket");
84164298Srwatson			return;
85164298Srwatson		}
86164298Srwatson		len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
87164298Srwatson		    sizeof(sun));
88164298Srwatson		if (len < 0)
89164298Srwatson			warn("stream_client: sendto");
90164298Srwatson		close(fd);
91164298Srwatson	}
92164298Srwatson}
93164298Srwatson
94164298Srwatsonstatic void
95164298Srwatsonstream_test(void)
96164298Srwatson{
97164298Srwatson	struct sockaddr_un sun;
98164298Srwatson	pid_t childpid;
99164298Srwatson	int listenfd;
100164298Srwatson
101164298Srwatson	listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
102164298Srwatson	if (listenfd < 0)
103164298Srwatson		err(-1, "stream_test: socket");
104164298Srwatson
105164298Srwatson	bzero(&sun, sizeof(sun));
106164298Srwatson	sun.sun_len = sizeof(sun);
107164298Srwatson	sun.sun_family = AF_UNIX;
108281974Sngie	strcpy(sun.sun_path, socket_path);
109164298Srwatson
110164298Srwatson	if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
111164298Srwatson		err(-1, "stream_test: bind");
112164298Srwatson
113164298Srwatson	if (listen(listenfd, -1) < 0)
114164298Srwatson		err(-1, "stream_test: listen");
115164298Srwatson
116164298Srwatson	childpid = fork();
117164298Srwatson	if (childpid < 0)
118164298Srwatson		err(-1, "stream_test: fork");
119164298Srwatson
120164298Srwatson	if (childpid != 0) {
121164298Srwatson		sleep(1);
122164298Srwatson		stream_client();
123164298Srwatson		kill(childpid, SIGTERM);
124164298Srwatson		sleep(1);
125164298Srwatson	} else
126164298Srwatson		stream_server(listenfd);
127164298Srwatson
128281974Sngie	(void)unlink(socket_path);
129164298Srwatson}
130164298Srwatson
131164298Srwatsonstatic void
132164298Srwatsondatagram_server(int serverfd)
133164298Srwatson{
134164298Srwatson	ssize_t len;
135164298Srwatson	char c;
136164298Srwatson
137164298Srwatson	while (1) {
138164298Srwatson		len = recv(serverfd, &c, sizeof(c), 0);
139164298Srwatson		if (len < 0)
140164298Srwatson			warn("datagram_server: recv");
141164298Srwatson	}
142164298Srwatson}
143164298Srwatson
144164298Srwatsonstatic void
145164298Srwatsondatagram_client(void)
146164298Srwatson{
147164298Srwatson	struct sockaddr_un sun;
148164298Srwatson	ssize_t len;
149164298Srwatson	char c = 0;
150164298Srwatson	int fd, i;
151164298Srwatson
152164298Srwatson	bzero(&sun, sizeof(sun));
153164298Srwatson	sun.sun_len = sizeof(sun);
154164298Srwatson	sun.sun_family = AF_UNIX;
155281974Sngie	strcpy(sun.sun_path, socket_path);
156164298Srwatson	for (i = 0; i < ITERATIONS; i++) {
157164298Srwatson		fd = socket(PF_UNIX, SOCK_DGRAM, 0);
158164298Srwatson		if (fd < 0) {
159164298Srwatson			warn("datagram_client: socket");
160164298Srwatson			return;
161164298Srwatson		}
162164298Srwatson		len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
163164298Srwatson		    sizeof(sun));
164164298Srwatson		if (len < 0)
165164298Srwatson			warn("datagram_client: sendto");
166164298Srwatson		close(fd);
167164298Srwatson	}
168164298Srwatson}
169164298Srwatson
170164298Srwatsonstatic void
171164298Srwatsondatagram_test(void)
172164298Srwatson{
173164298Srwatson	struct sockaddr_un sun;
174164298Srwatson	pid_t childpid;
175164298Srwatson	int serverfd;
176164298Srwatson
177164298Srwatson	serverfd = socket(PF_UNIX, SOCK_DGRAM, 0);
178164298Srwatson	if (serverfd < 0)
179164298Srwatson		err(-1, "datagram_test: socket");
180164298Srwatson
181164298Srwatson	bzero(&sun, sizeof(sun));
182164298Srwatson	sun.sun_len = sizeof(sun);
183164298Srwatson	sun.sun_family = AF_UNIX;
184281974Sngie	strcpy(sun.sun_path, socket_path);
185164298Srwatson
186164298Srwatson	if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
187164298Srwatson		err(-1, "datagram_test: bind");
188164298Srwatson
189164298Srwatson	childpid = fork();
190164298Srwatson	if (childpid < 0)
191164298Srwatson		err(-1, "datagram_test: fork");
192164298Srwatson
193164298Srwatson	if (childpid != 0) {
194164298Srwatson		sleep(1);
195164298Srwatson		datagram_client();
196164298Srwatson		kill(childpid, SIGTERM);
197164298Srwatson		sleep(1);
198164298Srwatson	} else
199164298Srwatson		datagram_server(serverfd);
200164298Srwatson
201281974Sngie	(void)unlink(socket_path);
202164298Srwatson}
203164298Srwatson
204164298Srwatsonint
205281974Sngiemain(void)
206164298Srwatson{
207281974Sngie
208281974Sngie	if (mkstemp(socket_path) == -1)
209281974Sngie		err(1, "mkstemp failed");
210281974Sngie	(void)unlink(socket_path);
211164298Srwatson	datagram_test();
212164298Srwatson	if (0)
213164298Srwatson		stream_test();
214164298Srwatson	return (0);
215164298Srwatson}
216