unix_sendtorace.c revision 281974
168349Sobrien/*-
268349Sobrien * Copyright (c) 2006 Robert N. M. Watson
368349Sobrien * All rights reserved.
468349Sobrien *
568349Sobrien * Redistribution and use in source and binary forms, with or without
668349Sobrien * modification, are permitted provided that the following conditions
768349Sobrien * are met:
868349Sobrien * 1. Redistributions of source code must retain the above copyright
968349Sobrien *    notice, this list of conditions and the following disclaimer.
1068349Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1168349Sobrien *    notice, this list of conditions and the following disclaimer in the
1268349Sobrien *    documentation and/or other materials provided with the distribution.
1368349Sobrien *
1468349Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1568349Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1668349Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1768349Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1868349Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1968349Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20133359Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21133359Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2268349Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2368349Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24133359Sobrien * SUCH DAMAGE.
25133359Sobrien *
2668349Sobrien * $FreeBSD: stable/10/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c 281974 2015-04-25 05:31:52Z ngie $
2768349Sobrien */
28133359Sobrien
29133359Sobrien/*
3068349Sobrien * Attempts to exercise UNIX domain socket races relating to the non-atomic
3168349Sobrien * connect-and-send properties of sendto().  As the result of such a race is
3268349Sobrien * a kernel panic, this test simply completes or doesn't.
3369216Sobrien *
3469216Sobrien * XXX: Despite implementing support for sendto() on stream sockets with
3569216Sobrien * implied connect, the appropriate flag isn't set in the FreeBSD kernel so
3669216Sobrien * it does not work.  For now, don't call the stream test.
3769216Sobrien */
3869216Sobrien
3969216Sobrien#include <sys/types.h>
4068349Sobrien#include <sys/socket.h>
4169216Sobrien#include <sys/un.h>
4269216Sobrien
4369216Sobrien#include <err.h>
4469216Sobrien#include <signal.h>
4569216Sobrien#include <string.h>
4669216Sobrien#include <unistd.h>
4769216Sobrien
4869216Sobrien#define	ITERATIONS	1000000
4969216Sobrien
5069216Sobrienstatic char socket_path[] = "tmp.XXXXXX";
5169216Sobrien
5268349Sobrienstatic void
5368349Sobrienstream_server(int listenfd)
5468349Sobrien{
5568349Sobrien	int acceptfd;
5668349Sobrien
5768349Sobrien	while (1) {
5868349Sobrien		acceptfd = accept(listenfd, NULL, NULL);
5968349Sobrien		if (acceptfd < 0) {
6068349Sobrien			warn("stream_server: accept");
6168349Sobrien			continue;
6268349Sobrien		}
6368349Sobrien		sleep(1);
6468349Sobrien		close(acceptfd);
6568349Sobrien	}
6668349Sobrien}
6768349Sobrien
6868349Sobrienstatic void
6968349Sobrienstream_client(void)
7068349Sobrien{
7168349Sobrien	struct sockaddr_un sun;
7268349Sobrien	ssize_t len;
7368349Sobrien	char c = 0;
7468349Sobrien	int fd, i;
7568349Sobrien
7668349Sobrien	bzero(&sun, sizeof(sun));
7768349Sobrien	sun.sun_len = sizeof(sun);
7868349Sobrien	sun.sun_family = AF_UNIX;
7968349Sobrien	strcpy(sun.sun_path, socket_path);
8068349Sobrien	for (i = 0; i < ITERATIONS; i++) {
8168349Sobrien		fd = socket(PF_UNIX, SOCK_STREAM, 0);
8268349Sobrien		if (fd < 0) {
8368349Sobrien			warn("stream_client: socket");
8468349Sobrien			return;
8568349Sobrien		}
8668349Sobrien		len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
8768349Sobrien		    sizeof(sun));
88103373Sobrien		if (len < 0)
8968349Sobrien			warn("stream_client: sendto");
9068349Sobrien		close(fd);
9168349Sobrien	}
9268349Sobrien}
9368349Sobrien
9468349Sobrienstatic void
9568349Sobrienstream_test(void)
9668349Sobrien{
9768349Sobrien	struct sockaddr_un sun;
9868349Sobrien	pid_t childpid;
9968349Sobrien	int listenfd;
10068349Sobrien
10168349Sobrien	listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
10268349Sobrien	if (listenfd < 0)
10368349Sobrien		err(-1, "stream_test: socket");
10468349Sobrien
10568349Sobrien	bzero(&sun, sizeof(sun));
10668349Sobrien	sun.sun_len = sizeof(sun);
10768349Sobrien	sun.sun_family = AF_UNIX;
10868349Sobrien	strcpy(sun.sun_path, socket_path);
10968349Sobrien
11068349Sobrien	if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
11168349Sobrien		err(-1, "stream_test: bind");
11268349Sobrien
11368349Sobrien	if (listen(listenfd, -1) < 0)
11468349Sobrien		err(-1, "stream_test: listen");
11568349Sobrien
11668349Sobrien	childpid = fork();
11768349Sobrien	if (childpid < 0)
11868349Sobrien		err(-1, "stream_test: fork");
11968349Sobrien
12068349Sobrien	if (childpid != 0) {
12168349Sobrien		sleep(1);
12268349Sobrien		stream_client();
12368349Sobrien		kill(childpid, SIGTERM);
12468349Sobrien		sleep(1);
12568349Sobrien	} else
12668349Sobrien		stream_server(listenfd);
12768349Sobrien
12868349Sobrien	(void)unlink(socket_path);
12968349Sobrien}
13068349Sobrien
13168349Sobrienstatic void
13268349Sobriendatagram_server(int serverfd)
13368349Sobrien{
13468349Sobrien	ssize_t len;
13568349Sobrien	char c;
13668349Sobrien
13768349Sobrien	while (1) {
13868349Sobrien		len = recv(serverfd, &c, sizeof(c), 0);
13968349Sobrien		if (len < 0)
14068349Sobrien			warn("datagram_server: recv");
14168349Sobrien	}
14268349Sobrien}
14368349Sobrien
14468349Sobrienstatic void
14568349Sobriendatagram_client(void)
14668349Sobrien{
14768349Sobrien	struct sockaddr_un sun;
14868349Sobrien	ssize_t len;
14968349Sobrien	char c = 0;
15068349Sobrien	int fd, i;
151110949Sobrien
152110949Sobrien	bzero(&sun, sizeof(sun));
15368349Sobrien	sun.sun_len = sizeof(sun);
154110949Sobrien	sun.sun_family = AF_UNIX;
15568349Sobrien	strcpy(sun.sun_path, socket_path);
15668349Sobrien	for (i = 0; i < ITERATIONS; i++) {
15768349Sobrien		fd = socket(PF_UNIX, SOCK_DGRAM, 0);
15868349Sobrien		if (fd < 0) {
15968349Sobrien			warn("datagram_client: socket");
16068349Sobrien			return;
16168349Sobrien		}
16268349Sobrien		len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun,
16368349Sobrien		    sizeof(sun));
16468349Sobrien		if (len < 0)
16568349Sobrien			warn("datagram_client: sendto");
16668349Sobrien		close(fd);
167133359Sobrien	}
168133359Sobrien}
169133359Sobrien
170133359Sobrienstatic void
171133359Sobriendatagram_test(void)
17268349Sobrien{
17368349Sobrien	struct sockaddr_un sun;
17468349Sobrien	pid_t childpid;
17568349Sobrien	int serverfd;
17668349Sobrien
17768349Sobrien	serverfd = socket(PF_UNIX, SOCK_DGRAM, 0);
17868349Sobrien	if (serverfd < 0)
17968349Sobrien		err(-1, "datagram_test: socket");
18068349Sobrien
18168349Sobrien	bzero(&sun, sizeof(sun));
18268349Sobrien	sun.sun_len = sizeof(sun);
18368349Sobrien	sun.sun_family = AF_UNIX;
18468349Sobrien	strcpy(sun.sun_path, socket_path);
18568349Sobrien
18668349Sobrien	if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0)
18768349Sobrien		err(-1, "datagram_test: bind");
18868349Sobrien
18968349Sobrien	childpid = fork();
19068349Sobrien	if (childpid < 0)
19168349Sobrien		err(-1, "datagram_test: fork");
19268349Sobrien
19368349Sobrien	if (childpid != 0) {
19468349Sobrien		sleep(1);
19568349Sobrien		datagram_client();
19668349Sobrien		kill(childpid, SIGTERM);
19768349Sobrien		sleep(1);
19868349Sobrien	} else
19968349Sobrien		datagram_server(serverfd);
20068349Sobrien
20168349Sobrien	(void)unlink(socket_path);
20268349Sobrien}
20368349Sobrien
20468349Sobrienint
20568349Sobrienmain(void)
20668349Sobrien{
20768349Sobrien
20868349Sobrien	if (mkstemp(socket_path) == -1)
20968349Sobrien		err(1, "mkstemp failed");
21068349Sobrien	(void)unlink(socket_path);
21168349Sobrien	datagram_test();
21268349Sobrien	if (0)
21368349Sobrien		stream_test();
21468349Sobrien	return (0);
21568349Sobrien}
21668349Sobrien