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$ 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 PATH "/tmp/123" 49164298Srwatson#define ITERATIONS 1000000 50164298Srwatson 51164298Srwatsonstatic void 52164298Srwatsonstream_server(int listenfd) 53164298Srwatson{ 54164298Srwatson int acceptfd; 55164298Srwatson 56164298Srwatson while (1) { 57164298Srwatson acceptfd = accept(listenfd, NULL, NULL); 58164298Srwatson if (acceptfd < 0) { 59164298Srwatson warn("stream_server: accept"); 60164298Srwatson continue; 61164298Srwatson } 62164298Srwatson sleep(1); 63164298Srwatson close(acceptfd); 64164298Srwatson } 65164298Srwatson} 66164298Srwatson 67164298Srwatsonstatic void 68164298Srwatsonstream_client(void) 69164298Srwatson{ 70164298Srwatson struct sockaddr_un sun; 71164298Srwatson ssize_t len; 72164298Srwatson char c = 0; 73164298Srwatson int fd, i; 74164298Srwatson 75164298Srwatson bzero(&sun, sizeof(sun)); 76164298Srwatson sun.sun_len = sizeof(sun); 77164298Srwatson sun.sun_family = AF_UNIX; 78164298Srwatson strcpy(sun.sun_path, PATH); 79164298Srwatson for (i = 0; i < ITERATIONS; i++) { 80164298Srwatson fd = socket(PF_UNIX, SOCK_STREAM, 0); 81164298Srwatson if (fd < 0) { 82164298Srwatson warn("stream_client: socket"); 83164298Srwatson return; 84164298Srwatson } 85164298Srwatson len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, 86164298Srwatson sizeof(sun)); 87164298Srwatson if (len < 0) 88164298Srwatson warn("stream_client: sendto"); 89164298Srwatson close(fd); 90164298Srwatson } 91164298Srwatson} 92164298Srwatson 93164298Srwatsonstatic void 94164298Srwatsonstream_test(void) 95164298Srwatson{ 96164298Srwatson struct sockaddr_un sun; 97164298Srwatson pid_t childpid; 98164298Srwatson int listenfd; 99164298Srwatson 100164298Srwatson listenfd = socket(PF_UNIX, SOCK_STREAM, 0); 101164298Srwatson if (listenfd < 0) 102164298Srwatson err(-1, "stream_test: socket"); 103164298Srwatson 104164298Srwatson bzero(&sun, sizeof(sun)); 105164298Srwatson sun.sun_len = sizeof(sun); 106164298Srwatson sun.sun_family = AF_UNIX; 107164298Srwatson strcpy(sun.sun_path, PATH); 108164298Srwatson 109164298Srwatson if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) 110164298Srwatson err(-1, "stream_test: bind"); 111164298Srwatson 112164298Srwatson if (listen(listenfd, -1) < 0) 113164298Srwatson err(-1, "stream_test: listen"); 114164298Srwatson 115164298Srwatson childpid = fork(); 116164298Srwatson if (childpid < 0) 117164298Srwatson err(-1, "stream_test: fork"); 118164298Srwatson 119164298Srwatson if (childpid != 0) { 120164298Srwatson sleep(1); 121164298Srwatson stream_client(); 122164298Srwatson kill(childpid, SIGTERM); 123164298Srwatson sleep(1); 124164298Srwatson } else 125164298Srwatson stream_server(listenfd); 126164298Srwatson 127164298Srwatson (void)unlink(PATH); 128164298Srwatson} 129164298Srwatson 130164298Srwatsonstatic void 131164298Srwatsondatagram_server(int serverfd) 132164298Srwatson{ 133164298Srwatson ssize_t len; 134164298Srwatson char c; 135164298Srwatson 136164298Srwatson while (1) { 137164298Srwatson len = recv(serverfd, &c, sizeof(c), 0); 138164298Srwatson if (len < 0) 139164298Srwatson warn("datagram_server: recv"); 140164298Srwatson } 141164298Srwatson} 142164298Srwatson 143164298Srwatsonstatic void 144164298Srwatsondatagram_client(void) 145164298Srwatson{ 146164298Srwatson struct sockaddr_un sun; 147164298Srwatson ssize_t len; 148164298Srwatson char c = 0; 149164298Srwatson int fd, i; 150164298Srwatson 151164298Srwatson bzero(&sun, sizeof(sun)); 152164298Srwatson sun.sun_len = sizeof(sun); 153164298Srwatson sun.sun_family = AF_UNIX; 154164298Srwatson strcpy(sun.sun_path, PATH); 155164298Srwatson for (i = 0; i < ITERATIONS; i++) { 156164298Srwatson fd = socket(PF_UNIX, SOCK_DGRAM, 0); 157164298Srwatson if (fd < 0) { 158164298Srwatson warn("datagram_client: socket"); 159164298Srwatson return; 160164298Srwatson } 161164298Srwatson len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, 162164298Srwatson sizeof(sun)); 163164298Srwatson if (len < 0) 164164298Srwatson warn("datagram_client: sendto"); 165164298Srwatson close(fd); 166164298Srwatson } 167164298Srwatson} 168164298Srwatson 169164298Srwatsonstatic void 170164298Srwatsondatagram_test(void) 171164298Srwatson{ 172164298Srwatson struct sockaddr_un sun; 173164298Srwatson pid_t childpid; 174164298Srwatson int serverfd; 175164298Srwatson 176164298Srwatson serverfd = socket(PF_UNIX, SOCK_DGRAM, 0); 177164298Srwatson if (serverfd < 0) 178164298Srwatson err(-1, "datagram_test: socket"); 179164298Srwatson 180164298Srwatson bzero(&sun, sizeof(sun)); 181164298Srwatson sun.sun_len = sizeof(sun); 182164298Srwatson sun.sun_family = AF_UNIX; 183164298Srwatson strcpy(sun.sun_path, PATH); 184164298Srwatson 185164298Srwatson if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) 186164298Srwatson err(-1, "datagram_test: bind"); 187164298Srwatson 188164298Srwatson childpid = fork(); 189164298Srwatson if (childpid < 0) 190164298Srwatson err(-1, "datagram_test: fork"); 191164298Srwatson 192164298Srwatson if (childpid != 0) { 193164298Srwatson sleep(1); 194164298Srwatson datagram_client(); 195164298Srwatson kill(childpid, SIGTERM); 196164298Srwatson sleep(1); 197164298Srwatson } else 198164298Srwatson datagram_server(serverfd); 199164298Srwatson 200164298Srwatson (void)unlink(PATH); 201164298Srwatson} 202164298Srwatson 203164298Srwatsonint 204164298Srwatsonmain(int argc, char *argv[]) 205164298Srwatson{ 206164298Srwatson 207164298Srwatson (void)unlink(PATH); 208164298Srwatson datagram_test(); 209164298Srwatson if (0) 210164298Srwatson stream_test(); 211164298Srwatson return (0); 212164298Srwatson} 213