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