xref: /freebsd-src/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
157c4583fSRobert Watson /*-
257c4583fSRobert Watson  * Copyright (c) 2006 Robert N. M. Watson
357c4583fSRobert Watson  * All rights reserved.
457c4583fSRobert Watson  *
557c4583fSRobert Watson  * Redistribution and use in source and binary forms, with or without
657c4583fSRobert Watson  * modification, are permitted provided that the following conditions
757c4583fSRobert Watson  * are met:
857c4583fSRobert Watson  * 1. Redistributions of source code must retain the above copyright
957c4583fSRobert Watson  *    notice, this list of conditions and the following disclaimer.
1057c4583fSRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
1157c4583fSRobert Watson  *    notice, this list of conditions and the following disclaimer in the
1257c4583fSRobert Watson  *    documentation and/or other materials provided with the distribution.
1357c4583fSRobert Watson  *
1457c4583fSRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1557c4583fSRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1657c4583fSRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1757c4583fSRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1857c4583fSRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1957c4583fSRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2057c4583fSRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2157c4583fSRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2257c4583fSRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2357c4583fSRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2457c4583fSRobert Watson  * SUCH DAMAGE.
2557c4583fSRobert Watson  */
2657c4583fSRobert Watson 
2757c4583fSRobert Watson /*
2857c4583fSRobert Watson  * Attempts to exercise UNIX domain socket races relating to the non-atomic
2957c4583fSRobert Watson  * connect-and-send properties of sendto().  As the result of such a race is
3057c4583fSRobert Watson  * a kernel panic, this test simply completes or doesn't.
3157c4583fSRobert Watson  *
3257c4583fSRobert Watson  * XXX: Despite implementing support for sendto() on stream sockets with
3357c4583fSRobert Watson  * implied connect, the appropriate flag isn't set in the FreeBSD kernel so
3457c4583fSRobert Watson  * it does not work.  For now, don't call the stream test.
3557c4583fSRobert Watson  */
3657c4583fSRobert Watson 
3757c4583fSRobert Watson #include <sys/types.h>
3857c4583fSRobert Watson #include <sys/socket.h>
3957c4583fSRobert Watson #include <sys/un.h>
4057c4583fSRobert Watson 
4157c4583fSRobert Watson #include <err.h>
4257c4583fSRobert Watson #include <signal.h>
4357c4583fSRobert Watson #include <string.h>
4457c4583fSRobert Watson #include <unistd.h>
4557c4583fSRobert Watson 
4657c4583fSRobert Watson #define	ITERATIONS	1000000
4757c4583fSRobert Watson 
48*5a3935b6SEnji Cooper static char socket_path[] = "tmp.XXXXXX";
49*5a3935b6SEnji Cooper 
5057c4583fSRobert Watson static void
stream_server(int listenfd)5157c4583fSRobert Watson stream_server(int listenfd)
5257c4583fSRobert Watson {
5357c4583fSRobert Watson 	int acceptfd;
5457c4583fSRobert Watson 
5557c4583fSRobert Watson 	while (1) {
5657c4583fSRobert Watson 		acceptfd = accept(listenfd, NULL, NULL);
5757c4583fSRobert Watson 		if (acceptfd < 0) {
5857c4583fSRobert Watson 			warn("stream_server: accept");
5957c4583fSRobert Watson 			continue;
6057c4583fSRobert Watson 		}
6157c4583fSRobert Watson 		sleep(1);
6257c4583fSRobert Watson 		close(acceptfd);
6357c4583fSRobert Watson 	}
6457c4583fSRobert Watson }
6557c4583fSRobert Watson 
6657c4583fSRobert Watson static void
stream_client(void)6757c4583fSRobert Watson stream_client(void)
6857c4583fSRobert Watson {
6957c4583fSRobert Watson 	struct sockaddr_un sun;
7057c4583fSRobert Watson 	ssize_t len;
7157c4583fSRobert Watson 	char c = 0;
7257c4583fSRobert Watson 	int fd, i;
7357c4583fSRobert Watson 
7457c4583fSRobert Watson 	bzero(&sun, sizeof(sun));
7557c4583fSRobert Watson 	sun.sun_len = sizeof(sun);
7657c4583fSRobert Watson 	sun.sun_family = AF_UNIX;
77*5a3935b6SEnji Cooper 	strcpy(sun.sun_path, socket_path);
7857c4583fSRobert Watson 	for (i = 0; i < ITERATIONS; i++) {
7957c4583fSRobert Watson 		fd = socket(PF_UNIX, SOCK_STREAM, 0);
8057c4583fSRobert Watson 		if (fd < 0) {
8157c4583fSRobert Watson 			warn("stream_client: socket");
8257c4583fSRobert Watson 			return;
8357c4583fSRobert Watson 		}
8457c4583fSRobert Watson 		len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
8557c4583fSRobert Watson 		    sizeof(sun));
8657c4583fSRobert Watson 		if (len < 0)
8757c4583fSRobert Watson 			warn("stream_client: sendto");
8857c4583fSRobert Watson 		close(fd);
8957c4583fSRobert Watson 	}
9057c4583fSRobert Watson }
9157c4583fSRobert Watson 
9257c4583fSRobert Watson static void
stream_test(void)9357c4583fSRobert Watson stream_test(void)
9457c4583fSRobert Watson {
9557c4583fSRobert Watson 	struct sockaddr_un sun;
9657c4583fSRobert Watson 	pid_t childpid;
9757c4583fSRobert Watson 	int listenfd;
9857c4583fSRobert Watson 
9957c4583fSRobert Watson 	listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
10057c4583fSRobert Watson 	if (listenfd < 0)
10157c4583fSRobert Watson 		err(-1, "stream_test: socket");
10257c4583fSRobert Watson 
10357c4583fSRobert Watson 	bzero(&sun, sizeof(sun));
10457c4583fSRobert Watson 	sun.sun_len = sizeof(sun);
10557c4583fSRobert Watson 	sun.sun_family = AF_UNIX;
106*5a3935b6SEnji Cooper 	strcpy(sun.sun_path, socket_path);
10757c4583fSRobert Watson 
10857c4583fSRobert Watson 	if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
10957c4583fSRobert Watson 		err(-1, "stream_test: bind");
11057c4583fSRobert Watson 
11157c4583fSRobert Watson 	if (listen(listenfd, -1) < 0)
11257c4583fSRobert Watson 		err(-1, "stream_test: listen");
11357c4583fSRobert Watson 
11457c4583fSRobert Watson 	childpid = fork();
11557c4583fSRobert Watson 	if (childpid < 0)
11657c4583fSRobert Watson 		err(-1, "stream_test: fork");
11757c4583fSRobert Watson 
11857c4583fSRobert Watson 	if (childpid != 0) {
11957c4583fSRobert Watson 		sleep(1);
12057c4583fSRobert Watson 		stream_client();
12157c4583fSRobert Watson 		kill(childpid, SIGTERM);
12257c4583fSRobert Watson 		sleep(1);
12357c4583fSRobert Watson 	} else
12457c4583fSRobert Watson 		stream_server(listenfd);
12557c4583fSRobert Watson 
126*5a3935b6SEnji Cooper 	(void)unlink(socket_path);
12757c4583fSRobert Watson }
12857c4583fSRobert Watson 
12957c4583fSRobert Watson static void
datagram_server(int serverfd)13057c4583fSRobert Watson datagram_server(int serverfd)
13157c4583fSRobert Watson {
13257c4583fSRobert Watson 	ssize_t len;
13357c4583fSRobert Watson 	char c;
13457c4583fSRobert Watson 
13557c4583fSRobert Watson 	while (1) {
13657c4583fSRobert Watson 		len = recv(serverfd, &c, sizeof(c), 0);
13757c4583fSRobert Watson 		if (len < 0)
13857c4583fSRobert Watson 			warn("datagram_server: recv");
13957c4583fSRobert Watson 	}
14057c4583fSRobert Watson }
14157c4583fSRobert Watson 
14257c4583fSRobert Watson static void
datagram_client(void)14357c4583fSRobert Watson datagram_client(void)
14457c4583fSRobert Watson {
14557c4583fSRobert Watson 	struct sockaddr_un sun;
14657c4583fSRobert Watson 	ssize_t len;
14757c4583fSRobert Watson 	char c = 0;
14857c4583fSRobert Watson 	int fd, i;
14957c4583fSRobert Watson 
15057c4583fSRobert Watson 	bzero(&sun, sizeof(sun));
15157c4583fSRobert Watson 	sun.sun_len = sizeof(sun);
15257c4583fSRobert Watson 	sun.sun_family = AF_UNIX;
153*5a3935b6SEnji Cooper 	strcpy(sun.sun_path, socket_path);
15457c4583fSRobert Watson 	for (i = 0; i < ITERATIONS; i++) {
15557c4583fSRobert Watson 		fd = socket(PF_UNIX, SOCK_DGRAM, 0);
15657c4583fSRobert Watson 		if (fd < 0) {
15757c4583fSRobert Watson 			warn("datagram_client: socket");
15857c4583fSRobert Watson 			return;
15957c4583fSRobert Watson 		}
16057c4583fSRobert Watson 		len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
16157c4583fSRobert Watson 		    sizeof(sun));
16257c4583fSRobert Watson 		if (len < 0)
16357c4583fSRobert Watson 			warn("datagram_client: sendto");
16457c4583fSRobert Watson 		close(fd);
16557c4583fSRobert Watson 	}
16657c4583fSRobert Watson }
16757c4583fSRobert Watson 
16857c4583fSRobert Watson static void
datagram_test(void)16957c4583fSRobert Watson datagram_test(void)
17057c4583fSRobert Watson {
17157c4583fSRobert Watson 	struct sockaddr_un sun;
17257c4583fSRobert Watson 	pid_t childpid;
17357c4583fSRobert Watson 	int serverfd;
17457c4583fSRobert Watson 
17557c4583fSRobert Watson 	serverfd = socket(PF_UNIX, SOCK_DGRAM, 0);
17657c4583fSRobert Watson 	if (serverfd < 0)
17757c4583fSRobert Watson 		err(-1, "datagram_test: socket");
17857c4583fSRobert Watson 
17957c4583fSRobert Watson 	bzero(&sun, sizeof(sun));
18057c4583fSRobert Watson 	sun.sun_len = sizeof(sun);
18157c4583fSRobert Watson 	sun.sun_family = AF_UNIX;
182*5a3935b6SEnji Cooper 	strcpy(sun.sun_path, socket_path);
18357c4583fSRobert Watson 
18457c4583fSRobert Watson 	if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
18557c4583fSRobert Watson 		err(-1, "datagram_test: bind");
18657c4583fSRobert Watson 
18757c4583fSRobert Watson 	childpid = fork();
18857c4583fSRobert Watson 	if (childpid < 0)
18957c4583fSRobert Watson 		err(-1, "datagram_test: fork");
19057c4583fSRobert Watson 
19157c4583fSRobert Watson 	if (childpid != 0) {
19257c4583fSRobert Watson 		sleep(1);
19357c4583fSRobert Watson 		datagram_client();
19457c4583fSRobert Watson 		kill(childpid, SIGTERM);
19557c4583fSRobert Watson 		sleep(1);
19657c4583fSRobert Watson 	} else
19757c4583fSRobert Watson 		datagram_server(serverfd);
19857c4583fSRobert Watson 
199*5a3935b6SEnji Cooper 	(void)unlink(socket_path);
20057c4583fSRobert Watson }
20157c4583fSRobert Watson 
20257c4583fSRobert Watson int
main(void)203*5a3935b6SEnji Cooper main(void)
20457c4583fSRobert Watson {
20557c4583fSRobert Watson 
206*5a3935b6SEnji Cooper 	if (mkstemp(socket_path) == -1)
207*5a3935b6SEnji Cooper 		err(1, "mkstemp failed");
208*5a3935b6SEnji Cooper 	(void)unlink(socket_path);
20957c4583fSRobert Watson 	datagram_test();
21057c4583fSRobert Watson 	if (0)
21157c4583fSRobert Watson 		stream_test();
21257c4583fSRobert Watson 	return (0);
21357c4583fSRobert Watson }
214