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