Index: stable/10/tools/regression/sockets/accept_fd_leak/Makefile =================================================================== --- stable/10/tools/regression/sockets/accept_fd_leak/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/accept_fd_leak/Makefile (revision 281974) @@ -1,11 +1,9 @@ # # $FreeBSD$ # PROG= accept_fd_leak MAN= - -regress: - ./accept_fd_leak +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c =================================================================== --- stable/10/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c (revision 281973) +++ stable/10/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c (revision 281974) @@ -1,197 +1,215 @@ /*- * Copyright (c) 2004 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ -#include +#include #include #include #include #include #include #include #include #include #include #include #include +#define BIND_ATTEMPTS 10 #define LOOPS 500 +#define NUM_ATTEMPTS 1000 -volatile int quit; +static volatile int quit; static void -child_died(int sig) +child_died(int sig __unused) { + quit = 1; } /* * This test is intended to detect a leak of a file descriptor in the process * following a failed non-blocking accept. It measures an available fd * baseline, then performs 1000 failing accepts, then checks to see what the * next fd is. It relies on sequential fd allocation, and will test for it * briefly before beginning (not 100% reliable, but a good start). */ int -main(int argc, char *argv[]) +main(void) { struct sockaddr_in sin; socklen_t size; pid_t child; - int fd1, fd2, fd3, i, s; - int status; + int fd1, fd2, fd3, i, listen_port, s, status; printf("1..2\n"); /* * Check for sequential fd allocation, and give up early if not. */ fd1 = dup(STDIN_FILENO); fd2 = dup(STDIN_FILENO); if (fd2 != fd1 + 1) errx(-1, "Non-sequential fd allocation\n"); s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) errx(-1, "socket: %s", strerror(errno)); bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(8080); - if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) != 0) - errx(-1, "bind: %s", strerror(errno)); + srandomdev(); + for (i = 0; i < BIND_ATTEMPTS; i++) { + /* Pick a random unprivileged port 1025-65535 */ + listen_port = MAX((int)random() % 65535, 1025); + sin.sin_port = htons(listen_port); + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0) + break; + warn("bind with %d failed", listen_port); + usleep(1000); + } + if (i >= BIND_ATTEMPTS) { + printf("Bail out!\n"); + exit(1); + } + if (listen(s, -1) != 0) errx(-1, "listen: %s", strerror(errno)); i = fcntl(s, F_GETFL); if (i == -1) errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); i |= O_NONBLOCK; if (fcntl(s, F_SETFL, i) != 0) errx(-1, "ioctl(F_SETFL): %s", strerror(errno)); i = fcntl(s, F_GETFL); if (i == -1) errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); if ((i & O_NONBLOCK) != O_NONBLOCK) errx(-1, "Failed to set O_NONBLOCK (i=0x%x)\n", i); for (i = 0; i < LOOPS; i++) { size = sizeof(sin); if (accept(s, (struct sockaddr *)&sin, &size) != -1) errx(-1, "accept succeeded\n"); if (errno != EAGAIN) errx(-1, "accept: %s", strerror(errno)); } /* * Allocate a file descriptor and make sure it's fd2+2. 2 because * we allocate an fd for the socket. */ fd3 = dup(STDIN_FILENO); if (fd3 != fd2 + 2) printf("not ok 1 - (%d, %d, %d)\n", fd1, fd2, fd3); else printf("ok 1\n"); /* * Try failing accept's w/o non-blocking where the destination * address pointer is invalid. */ close(fd3); signal(SIGCHLD, child_died); child = fork(); if (child < 0) errx(-1, "fork: %s", strerror(errno)); /* - * Child process does 1000 connect's. + * Child process does `NUM_ATTEMPTS` connects. */ if (child == 0) { + close(fd1); + close(fd2); + close(s); + bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(8080); + sin.sin_port = htons(listen_port); - for (i = 0; i < 1000; i++) { + for (i = 0; i < NUM_ATTEMPTS; i++) { s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) errx(-1, "socket: %s", strerror(errno)); if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) errx(-1, "connect: %s", strerror(errno)); close(s); } - exit(0); + _exit(0); } /* Reset back to a blocking socket. */ i = fcntl(s, F_GETFL); if (i == -1) errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); i &= ~O_NONBLOCK; if (fcntl(s, F_SETFL, i) != 0) errx(-1, "ioctl(F_SETFL): %s", strerror(errno)); i = fcntl(s, F_GETFL); if (i == -1) errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); if (i & O_NONBLOCK) errx(-1, "Failed to clear O_NONBLOCK (i=0x%x)\n", i); - - /* Do 1000 accept's with an invalid pointer. */ - for (i = 0; !quit && i < 1000; i++) { + + /* Do `NUM_ATTEMPTS` accepts with an invalid pointer. */ + for (i = 0; !quit && i < NUM_ATTEMPTS; i++) { size = sizeof(sin); if (accept(s, (struct sockaddr *)(uintptr_t)(0x100), &size) != -1) errx(-1, "accept succeeded\n"); if (errno != EFAULT) errx(-1, "accept: %s", strerror(errno)); } if (waitpid(child, &status, 0) < 0) errx(-1, "waitpid: %s", strerror(errno)); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) warnx("child process died"); - + /* * Allocate a file descriptor and make sure it's fd2+2. 2 because * we allocate an fd for the socket. */ fd3 = dup(STDIN_FILENO); if (fd3 != fd2 + 2) printf("not ok 2 - (%d, %d, %d)\n", fd1, fd2, fd3); else printf("ok 2\n"); return (0); } Index: stable/10/tools/regression/sockets/accf_data_attach/Makefile =================================================================== --- stable/10/tools/regression/sockets/accf_data_attach/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/accf_data_attach/Makefile (revision 281974) @@ -1,11 +1,9 @@ # # $FreeBSD$ # PROG= accf_data_attach MAN= - -accf_data_attach: accf_data_attach.c - gcc -Wall -o accf_data_attach accf_data_attach.c +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/accf_data_attach/accf_data_attach.c =================================================================== --- stable/10/tools/regression/sockets/accf_data_attach/accf_data_attach.c (revision 281973) +++ stable/10/tools/regression/sockets/accf_data_attach/accf_data_attach.c (revision 281974) @@ -1,216 +1,216 @@ /*- * Copyright (c) 2004 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #define ACCF_NAME "dataready" /* * A number of small tests to confirm that attaching ACCF_DATA accept filters * to inet4 ports works as expected. We test: * * - That no accept filter is attached on a newly created socket. * - That bind() has no affect on the accept filter state. * - That we can't attach an accept filter to a socket that isn't in the * listen state. * - That after we fail to attach the filter, querying the kernel shows no * filter attached. * - That we can attach an accept filter to a socket that is in the listen * state. * - That once an accept filter is attached, we can query to make sure it is * attached. * - That once an accept filter is attached, we can remove it and query to * make sure it is removed. */ int -main(int argc, char *argv[]) +main(void) { struct accept_filter_arg afa; struct sockaddr_in sin; socklen_t len; int lso, ret; printf("1..11\n"); /* * Step 0. Open socket(). */ lso = socket(PF_INET, SOCK_STREAM, 0); if (lso == -1) errx(-1, "not ok 1 - socket: %s", strerror(errno)); printf("ok 1 - socket\n"); /* * Step 1. After socket(). Should return EINVAL, since no accept * filter should be attached. */ bzero(&afa, sizeof(afa)); len = sizeof(afa); ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); if (ret != -1) errx(-1, "not ok 2 - getsockopt() after socket() succeeded"); if (errno != EINVAL) errx(-1, "not ok 2 - getsockopt() after socket() failed with " "%d (%s)", errno, strerror(errno)); printf("ok 2 - getsockopt\n"); /* * Step 2. Bind(). Ideally this will succeed. */ bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_port = htons(8080); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(lso, (struct sockaddr *)&sin, sizeof(sin)) < 0) errx(-1, "not ok 3 - bind %s", strerror(errno)); printf("ok 3 - bind\n"); /* * Step 3: After bind(). getsockopt() should return EINVAL, since no * accept filter should be attached. */ len = sizeof(afa); ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); if (ret != -1) errx(-1, "not ok 4 - getsockopt() after bind() succeeded"); if (errno != EINVAL) errx(-1, "not ok 4 - getsockopt() after bind() failed with %d (%s)", errno, strerror(errno)); printf("ok 4 - getsockopt\n"); /* * Step 4: Setsockopt() before listen(). Should fail, since it's not * yet a listen() socket. */ bzero(&afa, sizeof(afa)); strcpy(afa.af_name, ACCF_NAME); ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); if (ret == 0) errx(-1, "not ok 5 - setsockopt() before listen() succeeded"); printf("ok 5 - setsockopt\n"); /* * Step 5: Getsockopt() after pre-listen() setsockopt(). Should * fail with EINVAL, since setsockopt() should have failed. */ len = sizeof(afa); ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); if (ret == 0) errx(-1, "not ok 6 - getsockopt() after pre-listen() setsockopt() " "succeeded"); if (errno != EINVAL) errx(-1, "not ok 6 - pre-listen() getsockopt() failed with %d (%s)", errno, strerror(errno)); printf("ok 6 - getsockopt\n"); /* * Step 6: listen(). */ if (listen(lso, -1) < 0) errx(-1, "not ok 7 - listen: %s", strerror(errno)); printf("ok 7 - listen\n"); /* * Step 7: Getsockopt() after listen(). Should fail with EINVAL, * since we have not installed accept filter yet. */ len = sizeof(afa); ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); if (ret == 0) errx(-1, "not ok 8 - getsockopt() after listen() but before " "setsockopt() succeeded"); if (errno != EINVAL) errx(-1, "not ok 8 - getsockopt() after listen() but before " "setsockopt() failed with %d (%s)", errno, strerror(errno)); printf("ok 8 - getsockopt\n"); /* * Step 8: After listen(). This call to setsockopt() should succeed. */ bzero(&afa, sizeof(afa)); strcpy(afa.af_name, ACCF_NAME); ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); if (ret != 0) errx(-1, "not ok 9 - setsockopt() after listen() failed with %d " "(%s)", errno, strerror(errno)); printf("ok 9 - setsockopt\n"); /* * Step 9: After setsockopt(). Should succeed and identify * ACCF_NAME. */ bzero(&afa, sizeof(afa)); len = sizeof(afa); ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); if (ret != 0) errx(-1, "not ok 10 - getsockopt() after listen() setsockopt() " "failed with %d (%s)", errno, strerror(errno)); if (len != sizeof(afa)) errx(-1, "not ok 10 - getsockopt() after setsockopet() after " "listen() returned wrong size (got %d expected %zd)", len, sizeof(afa)); if (strcmp(afa.af_name, ACCF_NAME) != 0) errx(-1, "not ok 10 - getsockopt() after setsockopt() after " "listen() mismatch (got %s expected %s)", afa.af_name, ACCF_NAME); printf("ok 10 - getsockopt\n"); /* * Step 10: Remove accept filter. After removing the accept filter * getsockopt() should fail with EINVAL. */ ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0); if (ret != 0) errx(-1, "not ok 11 - setsockopt() after listen() " "failed with %d (%s)", errno, strerror(errno)); bzero(&afa, sizeof(afa)); len = sizeof(afa); ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); if (ret == 0) errx(-1, "not ok 11 - getsockopt() after removing " "the accept filter returns valid accept filter %s", afa.af_name); if (errno != EINVAL) errx(-1, "not ok 11 - getsockopt() after removing the accept" "filter failed with %d (%s)", errno, strerror(errno)); printf("ok 11 - setsockopt\n"); close(lso); return (0); } Index: stable/10/tools/regression/sockets/fstat/Makefile =================================================================== --- stable/10/tools/regression/sockets/fstat/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/fstat/Makefile (revision 281974) @@ -1,9 +1,9 @@ # # $FreeBSD$ # PROG= fstat MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/fstat/fstat.c =================================================================== --- stable/10/tools/regression/sockets/fstat/fstat.c (revision 281973) +++ stable/10/tools/regression/sockets/fstat/fstat.c (revision 281974) @@ -1,71 +1,71 @@ /*- * Copyright (c) 2008 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include /* * Basic test to make sure that fstat(2) returns success on various socket * types. In the future we should also validate the fields, confirming * expected results such as the effect of shutdown(2) on permissions, etc. */ static void dotest(int domain, int type, int protocol) { struct stat sb; int sock; sock = socket(domain, type, protocol); if (sock < 0) err(-1, "socket(%d, %d, %d)", domain, type, protocol); if (fstat(sock, &sb) < 0) err(-1, "fstat on socket(%d, %d, %d)", domain, type, protocol); close(sock); } int -main(int argc, char *argv[]) +main(void) { dotest(PF_INET, SOCK_DGRAM, 0); dotest(PF_INET, SOCK_STREAM, 0); dotest(PF_INET6, SOCK_DGRAM, 0); dotest(PF_INET6, SOCK_STREAM, 0); dotest(PF_LOCAL, SOCK_DGRAM, 0); dotest(PF_LOCAL, SOCK_STREAM, 0); return (0); } Index: stable/10/tools/regression/sockets/kqueue/Makefile =================================================================== --- stable/10/tools/regression/sockets/kqueue/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/kqueue/Makefile (revision 281974) @@ -1,8 +1,9 @@ # # $FreeBSD$ # PROG= kqueue MAN= +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/kqueue/kqueue.c =================================================================== --- stable/10/tools/regression/sockets/kqueue/kqueue.c (revision 281973) +++ stable/10/tools/regression/sockets/kqueue/kqueue.c (revision 281974) @@ -1,368 +1,368 @@ /*- * Copyright (c) 2004 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include static int curtest = 1; /*- * This test uses UNIX domain socket pairs to perform some basic exercising * of kqueue functionality on sockets. In particular, testing that for read * and write filters, we see the correct detection of whether reads and * writes should actually be able to occur. * * TODO: * - Test read/write filters for listen/accept sockets. * - Handle the XXXRW below regarding datagram sockets. * - Test that watermark/buffer size "data" fields returned by kqueue are * correct. * - Check that kqueue does something sensible when the remote endpoing is * closed. */ #define OK(testname) printf("ok %d - %s\n", curtest, testname); \ curtest++; static void fail(int error, const char *func, const char *socktype, const char *rest) { printf("not ok %d\n", curtest); if (socktype == NULL) printf("# %s(): %s\n", func, strerror(error)); else if (rest == NULL) printf("# %s(%s): %s\n", func, socktype, strerror(error)); else printf("# %s(%s, %s): %s\n", func, socktype, rest, strerror(error)); exit(-1); } static void fail_assertion(const char *func, const char *socktype, const char *rest, const char *assertion) { printf("not ok %d - %s\n", curtest, assertion); if (socktype == NULL) printf("# %s(): assertion %s failed\n", func, assertion); else if (rest == NULL) printf("# %s(%s): assertion %s failed\n", func, socktype, assertion); else printf("# %s(%s, %s): assertion %s failed\n", func, socktype, rest, assertion); exit(-1); } /* * Test read kevent on a socket pair: check to make sure endpoint 0 isn't * readable when we start, then write to endpoint 1 and confirm that endpoint * 0 is now readable. Drain the write, then check that it's not readable * again. Use non-blocking kqueue operations and socket operations. */ static void test_evfilt_read(int kq, int fd[2], const char *socktype) { struct timespec ts; struct kevent ke; ssize_t len; char ch; int i; EV_SET(&ke, fd[0], EVFILT_READ, EV_ADD, 0, 0, NULL); if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) fail(errno, "kevent", socktype, "EVFILT_READ, EV_ADD"); OK("EVFILT_READ, EV_ADD"); /* * Confirm not readable to begin with, no I/O yet. */ ts.tv_sec = 0; ts.tv_nsec = 0; i = kevent(kq, NULL, 0, &ke, 1, &ts); if (i == -1) fail(errno, "kevent", socktype, "EVFILT_READ"); OK("EVFILT_READ"); if (i != 0) fail_assertion("kevent", socktype, "EVFILT_READ", "empty socket unreadable"); OK("empty socket unreadable"); /* * Write a byte to one end. */ ch = 'a'; len = write(fd[1], &ch, sizeof(ch)); if (len == -1) fail(errno, "write", socktype, NULL); OK("write one byte"); if (len != sizeof(ch)) fail_assertion("write", socktype, NULL, "write length"); OK("write one byte length"); /* * Other end should now be readable. */ ts.tv_sec = 0; ts.tv_nsec = 0; i = kevent(kq, NULL, 0, &ke, 1, &ts); if (i == -1) fail(errno, "kevent", socktype, "EVFILT_READ"); OK("EVFILT_READ"); if (i != 1) fail_assertion("kevent", socktype, "EVFILT_READ", "non-empty socket unreadable"); OK("non-empty socket unreadable"); /* * Read a byte to clear the readable state. */ len = read(fd[0], &ch, sizeof(ch)); if (len == -1) fail(errno, "read", socktype, NULL); OK("read one byte"); if (len != sizeof(ch)) fail_assertion("read", socktype, NULL, "read length"); OK("read one byte length"); /* * Now re-check for readability. */ ts.tv_sec = 0; ts.tv_nsec = 0; i = kevent(kq, NULL, 0, &ke, 1, &ts); if (i == -1) fail(errno, "kevent", socktype, "EVFILT_READ"); OK("EVFILT_READ"); if (i != 0) fail_assertion("kevent", socktype, "EVFILT_READ", "empty socket unreadable"); OK("empty socket unreadable"); EV_SET(&ke, fd[0], EVFILT_READ, EV_DELETE, 0, 0, NULL); if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) fail(errno, "kevent", socktype, "EVFILT_READ, EV_DELETE"); OK("EVFILT_READ, EV_DELETE"); } static void test_evfilt_write(int kq, int fd[2], const char *socktype) { struct timespec ts; struct kevent ke; ssize_t len; char ch; int i; EV_SET(&ke, fd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_ADD"); OK("EVFILE_WRITE, EV_ADD"); /* * Confirm writable to begin with, no I/O yet. */ ts.tv_sec = 0; ts.tv_nsec = 0; i = kevent(kq, NULL, 0, &ke, 1, &ts); if (i == -1) fail(errno, "kevent", socktype, "EVFILT_WRITE"); OK("EVFILE_WRITE"); if (i != 1) fail_assertion("kevent", socktype, "EVFILT_WRITE", "empty socket unwritable"); OK("empty socket unwritable"); /* * Write bytes into the socket until we can't write anymore. */ ch = 'a'; while ((len = write(fd[0], &ch, sizeof(ch))) == sizeof(ch)) {}; if (len == -1 && errno != EAGAIN && errno != ENOBUFS) fail(errno, "write", socktype, NULL); OK("write"); if (len != -1 && len != sizeof(ch)) fail_assertion("write", socktype, NULL, "write length"); OK("write length"); /* * Check to make sure the socket is no longer writable. */ ts.tv_sec = 0; ts.tv_nsec = 0; i = kevent(kq, NULL, 0, &ke, 1, &ts); if (i == -1) fail(errno, "kevent", socktype, "EVFILT_WRITE"); OK("EVFILT_WRITE"); if (i != 0) fail_assertion("kevent", socktype, "EVFILT_WRITE", "full socket writable"); OK("full socket writable"); EV_SET(&ke, fd[0], EVFILT_WRITE, EV_DELETE, 0, 0, NULL); if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_DELETE"); OK("EVFILT_WRITE, EV_DELETE"); } /* * Basic registration exercise for kqueue(2). Create several types/brands of * sockets, and confirm that we can register for various events on them. */ int -main(int argc, char *argv[]) +main(void) { - int i, kq, sv[2]; + int kq, sv[2]; printf("1..49\n"); kq = kqueue(); if (kq == -1) fail(errno, "kqueue", NULL, NULL); OK("kqueue()"); /* * Create a UNIX domain datagram socket, and attach/test/detach a * read filter on it. */ if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1) fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL); OK("socketpair() 1"); if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); OK("fcntl() 1"); if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); OK("fnctl() 2"); test_evfilt_read(kq, sv, "PF_UNIX, SOCK_DGRAM"); if (close(sv[0]) == -1) fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]"); OK("close() 1"); if (close(sv[1]) == -1) fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]"); OK("close() 2"); #if 0 /* * XXXRW: We disable the write test in the case of datagram sockets, * as kqueue can't tell when the remote socket receive buffer is * full, whereas the UNIX domain socket implementation can tell and * returns ENOBUFS. */ /* * Create a UNIX domain datagram socket, and attach/test/detach a * write filter on it. */ if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1) fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL); if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); test_evfilt_write(kq, sv, "PF_UNIX, SOCK_DGRAM"); if (close(sv[0]) == -1) fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]"); if (close(sv[1]) == -1) fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]"); #endif /* * Create a UNIX domain stream socket, and attach/test/detach a * read filter on it. */ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL); OK("socketpair() 2"); if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); OK("fcntl() 3"); if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); OK("fcntl() 4"); test_evfilt_read(kq, sv, "PF_UNIX, SOCK_STREAM"); if (close(sv[0]) == -1) fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]"); OK("close() 3"); if (close(sv[1]) == -1) fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]"); OK("close() 4"); /* * Create a UNIX domain stream socket, and attach/test/detach a * write filter on it. */ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL); OK("socketpair() 3"); if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); OK("fcntl() 5"); if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); OK("fcntl() 6"); test_evfilt_write(kq, sv, "PF_UNIX, SOCK_STREAM"); if (close(sv[0]) == -1) fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]"); OK("close() 5"); if (close(sv[1]) == -1) fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]"); OK("close() 6"); if (close(kq) == -1) fail(errno, "close", "kq", NULL); OK("close() 7"); return (0); } Index: stable/10/tools/regression/sockets/listen_backlog/Makefile =================================================================== --- stable/10/tools/regression/sockets/listen_backlog/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/listen_backlog/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= listen_backlog -WARNS?= 3 MAN= +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/listen_backlog/listen_backlog.c =================================================================== --- stable/10/tools/regression/sockets/listen_backlog/listen_backlog.c (revision 281973) +++ stable/10/tools/regression/sockets/listen_backlog/listen_backlog.c (revision 281974) @@ -1,382 +1,383 @@ /*- * Copyright (c) 2005 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include /* * This regression test is intended to validate that the backlog parameter * set by listen() is properly set, can be retrieved using SO_LISTENQLIMIT, * and that it can be updated by later calls to listen(). We also check that * SO_LISTENQLIMIT cannot be set. * * Future things to test: * * - That if we change the value of kern.ipc.somaxconn, the limits really * do change. * * - That limits are, approximately, enforced and implemented. * * - All this on multiple socket types -- i.e., PF_LOCAL. * * - That we also test SO_LISTENQLEN and SO_LISTENINCQLEN. */ /* * We retrieve kern.ipc.somaxconn before running the tests in order to use a * run-time set value of SOMAXCONN, rather than compile-time set. We assume * that no other process will be simultaneously frobbing it, and these tests * may fail if that assumption is not held. */ static int somaxconn; /* * Retrieve the current socket listen queue limit using SO_LISTENQLIMIT. */ static int socket_get_backlog(int sock, int *backlogp, const char *testclass, const char *test, const char *testfunc) { socklen_t len; int i; len = sizeof(i); if (getsockopt(sock, SOL_SOCKET, SO_LISTENQLIMIT, &i, &len) < 0) { warn("%s: %s: %s: socket_get_backlog: getsockopt(" "SOL_SOCKET, SO_LISTENQLIMIT)", testclass, test, testfunc); return (-1); } if (len != sizeof(i)) { warnx("%s: %s: %s: socket_get_backlog: getsockopt(" "SOL_SOCKET, SO_LISTENQLIMIT): returned size %d", testclass, test, testfunc, len); return (-1); } *backlogp = i; return (0); } /* * Create a socket, check the queue limit on creation, perform a listen(), * and make sure that the limit was set as expected by listen(). */ static int socket_listen(int domain, int type, int protocol, int backlog, int create_backlog_assertion, int listen_backlog_assertion, int *sockp, const char *domainstring, const char *typestring, const char *testclass, const char *test) { int backlog_retrieved, sock; sock = socket(domain, type, protocol); if (sock < 0) { warn("%s: %s: socket_listen: socket(%s, %s)", testclass, test, domainstring, typestring); close(sock); return (-1); } if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, "socket_listen") < 0) { close(sock); return (-1); } if (backlog_retrieved != create_backlog_assertion) { warnx("%s: %s: socket_listen: create backlog is %d not %d", testclass, test, backlog_retrieved, create_backlog_assertion); close(sock); return (-1); } if (listen(sock, backlog) < 0) { warn("%s: %s: socket_listen: listen(, %d)", testclass, test, backlog); close(sock); return (-1); } if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, "socket_listen") < 0) { close(sock); return (-1); } if (backlog_retrieved != listen_backlog_assertion) { warnx("%s: %s: socket_listen: listen backlog is %d not %d", testclass, test, backlog_retrieved, listen_backlog_assertion); close(sock); return (-1); } *sockp = sock; return (0); } /* * This test creates sockets and tests default states before and after * listen(). Specifically, we expect a queue limit of 0 before listen, and * then various settings for after listen(). If the passed backlog was * either < 0 or > somaxconn, it should be set to somaxconn; otherwise, the * passed queue depth. */ static void test_defaults(void) { int sock; /* * First pass. Confirm the default is 0. Listen with a backlog of * 0 and confirm it gets set that way. */ if (socket_listen(PF_INET, SOCK_STREAM, 0, 0, 0, 0, &sock, "PF_INET", "SOCK_STREAM", "test_defaults", "default_0_listen_0") < 0) exit(-1); close(sock); /* * Second pass. Listen with a backlog of -1 and make sure it is set * to somaxconn. */ if (socket_listen(PF_INET, SOCK_STREAM, 0, -1, 0, somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_defaults", "default_0_listen_-1") < 0) exit(-1); close(sock); /* * Third pass. Listen with a backlog of 1 and make sure it is set to * 1. */ if (socket_listen(PF_INET, SOCK_STREAM, 0, 1, 0, 1, &sock, "PF_INET", "SOCK_STREAM", "test_defaults", "default_0_listen_1") < 0) exit(-1); close(sock); /* * Fourth pass. Listen with a backlog of somaxconn and make sure it * is set to somaxconn. */ if (socket_listen(PF_INET, SOCK_STREAM, 0, somaxconn, 0, somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_defaults", "default_0_listen_somaxconn") < 0) exit(-1); close(sock); /* * Fifth pass. Listen with a backlog of somaxconn+1 and make sure it * is set to somaxconn. */ if (socket_listen(PF_INET, SOCK_STREAM, 0, somaxconn+1, 0, somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_defaults", "default_0_listen_somaxconn+1") < 0) exit(-1); close(sock); } /* * Create a socket, set the initial listen() state, then update the queue * depth using listen(). Check that the backlog is as expected after both * the first and second listen(). */ static int -socket_listen_update(int domain, int type, int protocol, int backlog, +socket_listen_update(int domain __unused, int type __unused, + int protocol __unused, int backlog, int update_backlog, int listen_backlog_assertion, int update_backlog_assertion, int *sockp, const char *domainstring, const char *typestring, const char *testclass, const char *test) { int backlog_retrieved, sock; sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) { warn("%s: %s: socket_listen_update: socket(%s, %s)", testclass, test, domainstring, typestring); return (-1); } if (listen(sock, backlog) < 0) { warn("%s: %s: socket_listen_update: initial listen(, %d)", testclass, test, backlog); close(sock); return (-1); } if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, "socket_listen_update") < 0) { close(sock); return (-1); } if (backlog_retrieved != listen_backlog_assertion) { warnx("%s: %s: socket_listen_update: initial backlog is %d " "not %d", testclass, test, backlog_retrieved, listen_backlog_assertion); close(sock); return (-1); } if (listen(sock, update_backlog) < 0) { warn("%s: %s: socket_listen_update: update listen(, %d)", testclass, test, update_backlog); close(sock); return (-1); } if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, "socket_listen_update") < 0) { close(sock); return (-1); } if (backlog_retrieved != update_backlog_assertion) { warnx("%s: %s: socket_listen_update: updated backlog is %d " "not %d", testclass, test, backlog_retrieved, update_backlog_assertion); close(sock); return (-1); } *sockp = sock; return (0); } /* * This test tests using listen() to update the queue depth after a socket * has already been marked as listening. We test several cases: setting the * socket < 0, 0, 1, somaxconn, and somaxconn + 1. */ static void test_listen_update(void) { int sock; /* * Set to 5, update to -1, which should give somaxconn. */ if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, -1, 5, somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", "update_5,-1") < 0) exit(-1); close(sock); /* * Set to 5, update to 0, which should give 0. */ if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, 0, 5, 0, &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", "update_5,0") < 0) exit(-1); close(sock); /* * Set to 5, update to 1, which should give 1. */ if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, 1, 5, 1, &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", "update_5,1") < 0) exit(-1); close(sock); /* * Set to 5, update to somaxconn, which should give somaxconn. */ if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, somaxconn, 5, somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", "update_5,somaxconn") < 0) exit(-1); close(sock); /* * Set to 5, update to somaxconn+1, which should give somaxconn. */ if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, somaxconn+1, 5, somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", "update_5,somaxconn+1") < 0) exit(-1); close(sock); } /* * SO_LISTENQLIMIT is a read-only socket option, so make sure we get an error * if we try to write it. */ static void test_set_qlimit(void) { int i, ret, sock; sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) err(-1, "test_set_qlimit: socket(PF_INET, SOCK_STREAM)"); i = 0; ret = setsockopt(sock, SOL_SOCKET, SO_LISTENQLIMIT, &i, sizeof(i)); if (ret < 0 && errno != ENOPROTOOPT) { warn("test_set_qlimit: setsockopt(SOL_SOCKET, " "SO_LISTENQLIMIT, 0): unexpected error"); close(sock); } if (ret == 0) { warnx("test_set_qlimit: setsockopt(SOL_SOCKET, " "SO_LISTENQLIMIT, 0) succeeded"); close(sock); exit(-1); } close(sock); } int -main(int argc, char *argv[]) +main(void) { size_t len; len = sizeof(somaxconn); if (sysctlbyname("kern.ipc.somaxconn", &somaxconn, &len, NULL, 0) < 0) err(-1, "sysctlbyname(kern.ipc.somaxconn)"); test_defaults(); test_listen_update(); test_set_qlimit(); return (0); } Index: stable/10/tools/regression/sockets/listenclose/Makefile =================================================================== --- stable/10/tools/regression/sockets/listenclose/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/listenclose/Makefile (revision 281974) @@ -1,9 +1,9 @@ # # $FreeBSD$ # PROG= listenclose MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/listenclose/listenclose.c =================================================================== --- stable/10/tools/regression/sockets/listenclose/listenclose.c (revision 281973) +++ stable/10/tools/regression/sockets/listenclose/listenclose.c (revision 281974) @@ -1,111 +1,111 @@ /*- * Copyright (c) 2004-2005 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include /* * The listenclose regression test is designed to catch kernel bugs that may * trigger as a result of performing a close on a listen() socket with as-yet * unaccepted connections in its queues. This results in the connections * being aborted, which is a not-often-followed code path. To do this, we * create a local TCP socket, build a non-blocking connection to it, and then * close the accept socket. The connection must be non-blocking or the * program will block and as such connect() will not return as accept() is * never called. */ int -main(int argc, char *argv[]) +main(void) { int listen_sock, connect_sock; struct sockaddr_in sin; socklen_t len; u_short port; int arg; listen_sock = socket(PF_INET, SOCK_STREAM, 0); if (listen_sock == -1) errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for listen socket: %s", strerror(errno)); bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = 0; if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) errx(-1, "bind(%s, %d) for listen socket: %s", inet_ntoa(sin.sin_addr), 0, strerror(errno)); len = sizeof(sin); if (getsockname(listen_sock, (struct sockaddr *)&sin, &len) < 0) errx(-1, "getsockname() for listen socket: %s", strerror(errno)); port = sin.sin_port; if (listen(listen_sock, -1) < 0) errx(-1, "listen() for listen socket: %s", strerror(errno)); connect_sock = socket(PF_INET, SOCK_STREAM, 0); if (connect_sock == -1) errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect " "socket: %s", strerror(errno)); arg = O_NONBLOCK; if (fcntl(connect_sock, F_SETFL, &arg) < 0) errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect socket" ": %s", strerror(errno)); bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = port; if (connect(connect_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) errx(-1, "connect() for connect socket: %s", strerror(errno)); close(connect_sock); close(listen_sock); return (0); } Index: stable/10/tools/regression/sockets/pr_atomic/Makefile =================================================================== --- stable/10/tools/regression/sockets/pr_atomic/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/pr_atomic/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= pr_atomic MAN= -WARNS?= 3 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/pr_atomic/pr_atomic.c =================================================================== --- stable/10/tools/regression/sockets/pr_atomic/pr_atomic.c (revision 281973) +++ stable/10/tools/regression/sockets/pr_atomic/pr_atomic.c (revision 281974) @@ -1,109 +1,109 @@ /*- * Copyright (c) 2006 Bruce M. Simpson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Regression test for uiomove in kernel; specifically for PR kern/38495. */ #include #include #include #include #include #include #include #include #include #include -#define TEST_SOCKET "/tmp/test_socket" +static char socket_path[] = "tmp.XXXXXX"; static jmp_buf myjmpbuf; -void handle_sigalrm(int signo); - -void handle_sigalrm(int signo) +static void handle_sigalrm(int signo __unused) { longjmp(myjmpbuf, 1); } int -main(int argc, char *argv[]) +main(void) { struct sockaddr_un un; pid_t pid; int s; + if (mkstemp(socket_path) == -1) + err(1, "mkstemp"); s = socket(PF_LOCAL, SOCK_DGRAM, 0); if (s == -1) errx(-1, "socket"); memset(&un, 0, sizeof(un)); un.sun_family = AF_LOCAL; - unlink(TEST_SOCKET); - strcpy(un.sun_path, TEST_SOCKET); + unlink(socket_path); + strcpy(un.sun_path, socket_path); if (bind(s, (struct sockaddr *)&un, sizeof(un)) == -1) errx(-1, "bind"); pid = fork(); if (pid == -1) errx(-1, "fork"); if (pid == 0) { int conn; char buf[] = "AAAAAAAAA"; close(s); conn = socket(AF_LOCAL, SOCK_DGRAM, 0); if (conn == -1) errx(-1,"socket"); if (sendto(conn, buf, sizeof(buf), 0, (struct sockaddr *)&un, sizeof(un)) != sizeof(buf)) errx(-1,"sendto"); close(conn); _exit(0); } sleep(5); /* Make sure the data is there when we try to receive it. */ if (recvfrom(s, (void *)-1, 1, 0, NULL, NULL) != -1) errx(-1,"recvfrom succeeded when failure expected"); (void)signal(SIGALRM, handle_sigalrm); if (setjmp(myjmpbuf) == 0) { /* * This recvfrom will panic an unpatched system, and block * a patched one. */ alarm(5); (void)recvfrom(s, (void *)-1, 1, 0, NULL, NULL); } /* We should reach here via longjmp() and all should be well. */ return (0); } Index: stable/10/tools/regression/sockets/reconnect/Makefile =================================================================== --- stable/10/tools/regression/sockets/reconnect/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/reconnect/Makefile (revision 281974) @@ -1,9 +1,9 @@ # # $FreeBSD$ # PROG= reconnect MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/reconnect/reconnect.c =================================================================== --- stable/10/tools/regression/sockets/reconnect/reconnect.c (revision 281973) +++ stable/10/tools/regression/sockets/reconnect/reconnect.c (revision 281974) @@ -1,140 +1,132 @@ /*- * Copyright (c) 2005 Maxim Sobolev * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * The reconnect regression test is designed to catch kernel bug that may * prevent changing association of already associated datagram unix domain * socket when server side of connection has been closed. */ #include #include #include #include #include #include #include #include #include #include #include #include -static char *uds_name1 = NULL; -static char *uds_name2 = NULL; +static char uds_name1[] = "reconnect.XXXXXXXX"; +static char uds_name2[] = "reconnect.XXXXXXXX"; #define sstosa(ss) ((struct sockaddr *)(ss)) -void +static void prepare_ifsun(struct sockaddr_un *ifsun, const char *path) { memset(ifsun, '\0', sizeof(*ifsun)); #if !defined(__linux__) && !defined(__solaris__) ifsun->sun_len = strlen(path); #endif ifsun->sun_family = AF_LOCAL; strcpy(ifsun->sun_path, path); } -int +static int create_uds_server(const char *path) { struct sockaddr_un ifsun; int sock; prepare_ifsun(&ifsun, path); unlink(ifsun.sun_path); sock = socket(PF_LOCAL, SOCK_DGRAM, 0); if (sock == -1) err(1, "can't create socket"); setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sock, sizeof(sock)); if (bind(sock, sstosa(&ifsun), sizeof(ifsun)) < 0) err(1, "can't bind to a socket"); return sock; } -void +static void connect_uds_server(int sock, const char *path) { struct sockaddr_un ifsun; int e; prepare_ifsun(&ifsun, path); e = connect(sock, sstosa(&ifsun), sizeof(ifsun)); if (e < 0) err(1, "can't connect to a socket"); } -void +static void cleanup(void) { - if (uds_name1 != NULL) - unlink(uds_name1); - if (uds_name2 != NULL) - unlink(uds_name2); + unlink(uds_name1); + unlink(uds_name2); } int main() { int s_sock1, s_sock2, c_sock; atexit(cleanup); - uds_name1 = strdup("/tmp/reconnect.XXXXXX"); - if (uds_name1 == NULL) - err(1, "can't allocate memory"); - uds_name1 = mktemp(uds_name1); - if (uds_name1 == NULL) - err(1, "mktemp(3) failed"); + if (mkstemp(uds_name1) == -1) + err(1, "mkstemp"); + unlink(uds_name1); s_sock1 = create_uds_server(uds_name1); - uds_name2 = strdup("/tmp/reconnect.XXXXXX"); - if (uds_name2 == NULL) - err(1, "can't allocate memory"); - uds_name2 = mktemp(uds_name2); - if (uds_name2 == NULL) - err(1, "mktemp(3) failed"); + if (mkstemp(uds_name2) == -1) + err(1, "mkstemp"); + unlink(uds_name2); s_sock2 = create_uds_server(uds_name2); c_sock = socket(PF_LOCAL, SOCK_DGRAM, 0); if (c_sock < 0) err(1, "can't create socket"); connect_uds_server(c_sock, uds_name1); close(s_sock1); connect_uds_server(c_sock, uds_name2); exit (0); } Index: stable/10/tools/regression/sockets/rtsocket/Makefile =================================================================== --- stable/10/tools/regression/sockets/rtsocket/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/rtsocket/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= rtsocket MAN= -WARNS?= 3 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/rtsocket/rtsocket.c =================================================================== --- stable/10/tools/regression/sockets/rtsocket/rtsocket.c (revision 281973) +++ stable/10/tools/regression/sockets/rtsocket/rtsocket.c (revision 281974) @@ -1,101 +1,101 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Simple routing socket regression test: create and destroy a raw routing * socket, and make sure that dgram and stream don't work, socketpair, etc. */ #include #include #include #include #include #include int -main(int argc, char *argv[]) +main(void) { int sock, socks[2]; sock = socket(PF_ROUTE, SOCK_STREAM, 0); if (sock >= 0) { close(sock); errx(-1, "socket(PF_ROUTE, SOCK_STREAM, 0) returned %d", sock); } if (errno != EPROTONOSUPPORT) err(-1, "socket(PF_ROUTE, SOCK_STREAM, 0)"); sock = socket(PF_ROUTE, SOCK_DGRAM, 0); if (sock >= 0) { close(sock); errx(-1, "socket(PF_ROUTE, SOCK_DGRAM, 0) returned %d", sock); } if (errno != EPROTONOSUPPORT) err(-1, "socket(PF_ROUTE, SOCK_DGRAM, 0)"); sock = socket(PF_ROUTE, SOCK_RAW, 0); if (sock < 0) err(-1, "socket(PF_ROUTE, SOCK_RAW, 0)"); close(sock); if (socketpair(PF_ROUTE, SOCK_STREAM, 0, socks) == 0) { close(socks[0]); close(socks[1]); errx(-1, "socketpair(PF_ROUTE, SOCK_STREAM, 0, socks) success"); } if (errno != EPROTONOSUPPORT) err(-1, "socketpair(PF_ROUTE, SOCK_STREAM, 0, socks)"); if (socketpair(PF_ROUTE, SOCK_DGRAM, 0, socks) == 0) { close(socks[0]); close(socks[1]); errx(-1, "socketpair(PF_ROUTE, SOCK_DGRAM, 0, socks) success"); } if (errno != EPROTONOSUPPORT) err(-1, "socketpair(PF_ROUTE, SOCK_DGRAM, 0, socks)"); if (socketpair(PF_ROUTE, SOCK_RAW, 0, socks) == 0) { close(socks[0]); close(socks[1]); errx(-1, "socketpair(PF_ROUTE, SOCK_STREAM, 0, socks) success"); } return (0); } Index: stable/10/tools/regression/sockets/sblock/Makefile =================================================================== --- stable/10/tools/regression/sockets/sblock/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/sblock/Makefile (revision 281974) @@ -1,9 +1,9 @@ # # $FreeBSD$ # PROG= sblock MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/sblock/sblock.c =================================================================== --- stable/10/tools/regression/sockets/sblock/sblock.c (revision 281973) +++ stable/10/tools/regression/sockets/sblock/sblock.c (revision 281974) @@ -1,207 +1,207 @@ /*- * Copyright (c) 2007 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Sockets serialize I/O in each direction in order to avoid interlacing of * I/O by multiple processes or threcvs recving or sending the socket. This * is done using some form of kernel lock (varies by kernel version), called * "sblock" in FreeBSD. However, to avoid unkillable processes waiting on * I/O that may be entirely controlled by a remote network endpoint, that * lock acquisition must be interruptible. * * To test this, set up a local domain stream socket pair and a set of three * processes. Two processes block in recv(), the first on sbwait (wait for * I/O), and the second on the sblock waiting for the first to finish. A * third process is responsible for signalling the second process, then * writing to the socket. Depending on the error returned in the second * process, we can tell whether the sblock wait was interrupted, or if * instead the process only woke up when the write was performed. */ #include #include #include #include #include #include #include static int interrupted; static void -signal_handler(int signum) +signal_handler(int signum __unused) { interrupted++; } /* * Process that will perform a blocking recv on a UNIX domain socket. This * should return one byte of data. */ static void blocking_recver(int fd) { ssize_t len; char ch; len = recv(fd, &ch, sizeof(ch), 0); if (len < 0) err(-1, "FAIL: blocking_recver: recv"); if (len == 0) errx(-1, "FAIL: blocking_recver: recv: eof"); if (len != 1) errx(-1, "FAIL: blocking_recver: recv: %zd bytes", len); if (interrupted) errx(-1, "FAIL: blocking_recver: interrupted wrong pid"); } /* * Process that will perform a locking recv on a UNIX domain socket. * * This is where we figure out if the test worked or not. If it has failed, * then recv() will return EOF, as the close() arrives before the signal, * meaning that the wait for the sblock was not interrupted; if it has * succeeded, we get EINTR as the signal interrupts the lock request. */ static void locking_recver(int fd) { ssize_t len; char ch; - if (sleep(1) < 0) + if (sleep(1) != 0) err(-1, "FAIL: locking_recver: sleep"); len = recv(fd, &ch, sizeof(ch), 0); if (len < 0 && errno != EINTR) err(-1, "FAIL: locking_recver: recv"); if (len < 0 && errno == EINTR) { fprintf(stderr, "PASS\n"); exit(0); } if (len == 0) errx(-1, "FAIL: locking_recver: recv: eof"); if (!interrupted) errx(-1, "FAIL: locking_recver: not interrupted"); } static void signaller(pid_t locking_recver_pid, int fd) { ssize_t len; char ch; - if (sleep(2) < 0) { + if (sleep(2) != 0) { warn("signaller sleep(2)"); return; } if (kill(locking_recver_pid, SIGHUP) < 0) { warn("signaller kill(%d)", locking_recver_pid); return; } - if (sleep(1) < 0) { + if (sleep(1) != 0) { warn("signaller sleep(1)"); return; } len = send(fd, &ch, sizeof(ch), 0); if (len < 0) { warn("signaller send"); return; } if (len != sizeof(ch)) { warnx("signaller send ret %zd", len); return; } if (close(fd) < 0) { warn("signaller close"); return; } - if (sleep(1) < 0) { + if (sleep(1) != 0) { warn("signaller sleep(1)"); return; } } int -main(int argc, char *argv[]) +main(void) { int error, fds[2], recver_fd, sender_fd; pid_t blocking_recver_pid; pid_t locking_recver_pid; struct sigaction sa; if (sigaction(SIGHUP, NULL, &sa) < 0) err(-1, "FAIL: sigaction(SIGHUP, NULL, &sa)"); sa.sa_handler = signal_handler; if (sa.sa_flags & SA_RESTART) printf("SIGHUP restartable by default (cleared)\n"); sa.sa_flags &= ~SA_RESTART; if (sigaction(SIGHUP, &sa, NULL) < 0) err(-1, "FAIL: sigaction(SIGHUP, &sa, NULL)"); #if 0 if (signal(SIGHUP, signal_handler) == SIG_ERR) err(-1, "FAIL: signal(SIGHUP)"); #endif if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) err(-1, "FAIL: socketpair(PF_LOCAL, SOGK_STREAM, 0)"); sender_fd = fds[0]; recver_fd = fds[1]; blocking_recver_pid = fork(); if (blocking_recver_pid < 0) err(-1, "FAIL: fork"); if (blocking_recver_pid == 0) { close(sender_fd); blocking_recver(recver_fd); exit(0); } locking_recver_pid = fork(); if (locking_recver_pid < 0) { error = errno; kill(blocking_recver_pid, SIGKILL); errno = error; err(-1, "FAIL: fork"); } if (locking_recver_pid == 0) { close(sender_fd); locking_recver(recver_fd); exit(0); } signaller(locking_recver_pid, sender_fd); kill(blocking_recver_pid, SIGKILL); kill(locking_recver_pid, SIGKILL); exit(0); } Index: stable/10/tools/regression/sockets/sendfile/sendfile.c =================================================================== --- stable/10/tools/regression/sockets/sendfile/sendfile.c (revision 281973) +++ stable/10/tools/regression/sockets/sendfile/sendfile.c (revision 281974) @@ -1,486 +1,486 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Simple regression test for sendfile. Creates a file sized at four pages * and then proceeds to send it over a series of sockets, exercising a number * of cases and performing limited validation. */ #define FAIL(msg) {printf("# %s\n", msg); \ return (-1);} #define FAIL_ERR(msg) {printf("# %s: %s\n", msg, strerror(errno)); \ return (-1);} #define TEST_PORT 5678 #define TEST_MAGIC 0x4440f7bb #define TEST_PAGES 4 #define TEST_SECONDS 30 struct test_header { uint32_t th_magic; uint32_t th_header_length; uint32_t th_offset; uint32_t th_length; char th_md5[33]; }; struct sendfile_test { uint32_t hdr_length; uint32_t offset; uint32_t length; uint32_t file_size; }; static int file_fd; static char path[PATH_MAX]; static int listen_socket; static int accept_socket; static int test_th(struct test_header *th, uint32_t *header_length, uint32_t *offset, uint32_t *length); static void signal_alarm(int signum); static void setup_alarm(int seconds); static void cancel_alarm(void); static int receive_test(void); static void run_child(void); static int new_test_socket(int *connect_socket); static void init_th(struct test_header *th, uint32_t header_length, uint32_t offset, uint32_t length); static int send_test(int connect_socket, struct sendfile_test); static int write_test_file(size_t file_size); static void run_parent(void); static void cleanup(void); static int test_th(struct test_header *th, uint32_t *header_length, uint32_t *offset, uint32_t *length) { if (th->th_magic != htonl(TEST_MAGIC)) FAIL("magic number not found in header") *header_length = ntohl(th->th_header_length); *offset = ntohl(th->th_offset); *length = ntohl(th->th_length); return (0); } static void signal_alarm(int signum) { (void)signum; printf("# test timeout\n"); if (accept_socket > 0) close(accept_socket); if (listen_socket > 0) close(listen_socket); _exit(-1); } static void setup_alarm(int seconds) { struct itimerval itv; bzero(&itv, sizeof(itv)); (void)seconds; itv.it_value.tv_sec = seconds; signal(SIGALRM, signal_alarm); setitimer(ITIMER_REAL, &itv, NULL); } static void cancel_alarm(void) { struct itimerval itv; bzero(&itv, sizeof(itv)); setitimer(ITIMER_REAL, &itv, NULL); } static int receive_test(void) { uint32_t header_length, offset, length, counter; struct test_header th; ssize_t len; char buf[10240]; MD5_CTX md5ctx; char *rxmd5; len = read(accept_socket, &th, sizeof(th)); if (len < 0 || (size_t)len < sizeof(th)) FAIL_ERR("read") if (test_th(&th, &header_length, &offset, &length) != 0) return (-1); MD5Init(&md5ctx); counter = 0; while (1) { len = read(accept_socket, buf, sizeof(buf)); if (len < 0 || len == 0) break; counter += len; MD5Update(&md5ctx, buf, len); } rxmd5 = MD5End(&md5ctx, NULL); if ((counter != header_length+length) || memcmp(th.th_md5, rxmd5, 33) != 0) FAIL("receive length mismatch") free(rxmd5); return (0); } static void run_child(void) { struct sockaddr_in sin; int rc = 0; listen_socket = socket(PF_INET, SOCK_STREAM, 0); if (listen_socket < 0) { printf("# socket: %s\n", strerror(errno)); rc = -1; } if (!rc) { bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = htons(TEST_PORT); if (bind(listen_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0) { printf("# bind: %s\n", strerror(errno)); rc = -1; } } if (!rc && listen(listen_socket, -1) < 0) { printf("# listen: %s\n", strerror(errno)); rc = -1; } if (!rc) { accept_socket = accept(listen_socket, NULL, NULL); setup_alarm(TEST_SECONDS); if (receive_test() != 0) rc = -1; } cancel_alarm(); if (accept_socket > 0) close(accept_socket); if (listen_socket > 0) close(listen_socket); _exit(rc); } static int new_test_socket(int *connect_socket) { struct sockaddr_in sin; int rc = 0; *connect_socket = socket(PF_INET, SOCK_STREAM, 0); if (*connect_socket < 0) FAIL_ERR("socket") bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = htons(TEST_PORT); if (connect(*connect_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0) FAIL_ERR("connect") return (rc); } static void init_th(struct test_header *th, uint32_t header_length, uint32_t offset, uint32_t length) { bzero(th, sizeof(*th)); th->th_magic = htonl(TEST_MAGIC); th->th_header_length = htonl(header_length); th->th_offset = htonl(offset); th->th_length = htonl(length); MD5FileChunk(path, th->th_md5, offset, length); } static int send_test(int connect_socket, struct sendfile_test test) { struct test_header th; struct sf_hdtr hdtr, *hdtrp; struct iovec headers; char *header; ssize_t len; int length; off_t off; len = lseek(file_fd, 0, SEEK_SET); if (len != 0) FAIL_ERR("lseek") struct stat st; if (fstat(file_fd, &st) < 0) FAIL_ERR("fstat") length = st.st_size - test.offset; if (test.length > 0 && test.length < (uint32_t)length) length = test.length; init_th(&th, test.hdr_length, test.offset, length); len = write(connect_socket, &th, sizeof(th)); if (len != sizeof(th)) return (-1); if (test.hdr_length != 0) { header = malloc(test.hdr_length); if (header == NULL) FAIL_ERR("malloc") hdtrp = &hdtr; bzero(&headers, sizeof(headers)); headers.iov_base = header; headers.iov_len = test.hdr_length; bzero(&hdtr, sizeof(hdtr)); hdtr.headers = &headers; hdtr.hdr_cnt = 1; hdtr.trailers = NULL; hdtr.trl_cnt = 0; } else { hdtrp = NULL; header = NULL; } if (sendfile(file_fd, connect_socket, test.offset, test.length, hdtrp, &off, 0) < 0) { if (header != NULL) free(header); FAIL_ERR("sendfile") } if (length == 0) { struct stat sb; if (fstat(file_fd, &sb) == 0) length = sb.st_size - test.offset; } if (header != NULL) free(header); if (off != length) FAIL("offset != length") return (0); } static int write_test_file(size_t file_size) { char *page_buffer; ssize_t len; static size_t current_file_size = 0; if (file_size == current_file_size) return (0); else if (file_size < current_file_size) { if (ftruncate(file_fd, file_size) != 0) FAIL_ERR("ftruncate"); current_file_size = file_size; return (0); } page_buffer = malloc(file_size); if (page_buffer == NULL) FAIL_ERR("malloc") bzero(page_buffer, file_size); len = write(file_fd, page_buffer, file_size); if (len < 0) FAIL_ERR("write") len = lseek(file_fd, 0, SEEK_SET); if (len < 0) FAIL_ERR("lseek") if (len != 0) FAIL("len != 0") free(page_buffer); current_file_size = file_size; return (0); } static void run_parent(void) { int connect_socket; int status; int test_num; int test_count; int pid; size_t desired_file_size = 0; const int pagesize = getpagesize(); struct sendfile_test tests[] = { { .hdr_length = 0, .offset = 0, .length = 1 }, { .hdr_length = 0, .offset = 0, .length = pagesize }, { .hdr_length = 0, .offset = 1, .length = 1 }, { .hdr_length = 0, .offset = 1, .length = pagesize }, { .hdr_length = 0, .offset = pagesize, .length = pagesize }, { .hdr_length = 0, .offset = 0, .length = 2*pagesize }, { .hdr_length = 0, .offset = 0, .length = 0 }, { .hdr_length = 0, .offset = pagesize, .length = 0 }, { .hdr_length = 0, .offset = 2*pagesize, .length = 0 }, { .hdr_length = 0, .offset = TEST_PAGES*pagesize, .length = 0 }, { .hdr_length = 0, .offset = 0, .length = pagesize, .file_size = 1 } }; test_count = sizeof(tests) / sizeof(tests[0]); printf("1..%d\n", test_count); for (test_num = 1; test_num <= test_count; test_num++) { desired_file_size = tests[test_num - 1].file_size; if (desired_file_size == 0) desired_file_size = TEST_PAGES * pagesize; if (write_test_file(desired_file_size) != 0) { printf("not ok %d\n", test_num); continue; } pid = fork(); if (pid == -1) { printf("not ok %d\n", test_num); continue; } if (pid == 0) run_child(); usleep(250000); if (new_test_socket(&connect_socket) != 0) { printf("not ok %d\n", test_num); kill(pid, SIGALRM); close(connect_socket); continue; } if (send_test(connect_socket, tests[test_num-1]) != 0) { printf("not ok %d\n", test_num); kill(pid, SIGALRM); close(connect_socket); continue; } close(connect_socket); if (waitpid(pid, &status, 0) == pid) { if (WIFEXITED(status) && WEXITSTATUS(status) == 0) printf("%s %d\n", "ok", test_num); else printf("%s %d\n", "not ok", test_num); } else { printf("not ok %d\n", test_num); } } } static void cleanup(void) { - if (*path != '\0') - unlink(path); + + unlink(path); } int main(int argc, char *argv[]) { int pagesize; - *path = '\0'; + path[0] = '\0'; pagesize = getpagesize(); if (argc == 1) { - snprintf(path, PATH_MAX, "/tmp/sendfile.XXXXXXXXXXXX"); + snprintf(path, sizeof(path), "sendfile.XXXXXXXXXXXX"); file_fd = mkstemp(path); if (file_fd == -1) FAIL_ERR("mkstemp"); } else if (argc == 2) { (void)strlcpy(path, argv[1], sizeof(path)); file_fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0600); if (file_fd == -1) FAIL_ERR("open"); } else { FAIL("usage: sendfile [path]"); } atexit(cleanup); run_parent(); return (0); } Index: stable/10/tools/regression/sockets/shutdown/Makefile =================================================================== --- stable/10/tools/regression/sockets/shutdown/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/shutdown/Makefile (revision 281974) @@ -1,9 +1,9 @@ # # $FreeBSD$ # PROG= shutdown MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/shutdown/shutdown.c =================================================================== --- stable/10/tools/regression/sockets/shutdown/shutdown.c (revision 281973) +++ stable/10/tools/regression/sockets/shutdown/shutdown.c (revision 281974) @@ -1,108 +1,110 @@ /*- * Copyright (C) 2005 The FreeBSD Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include int main(void) { struct sockaddr_in sock; socklen_t len; int listen_sock, connect_sock; u_short port; + listen_sock = -1; + /* Shutdown(2) on an invalid file descriptor has to return EBADF. */ if ((shutdown(listen_sock, SHUT_RDWR) != -1) && (errno != EBADF)) errx(-1, "shutdown() for invalid file descriptor does not " "return EBADF"); listen_sock = socket(PF_INET, SOCK_STREAM, 0); if (listen_sock == -1) errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for listen socket: %s", strerror(errno)); bzero(&sock, sizeof(sock)); sock.sin_len = sizeof(sock); sock.sin_family = AF_INET; sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sock.sin_port = 0; if (bind(listen_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0) errx(-1, "bind(%s, %d) for listen socket: %s", inet_ntoa(sock.sin_addr), sock.sin_port, strerror(errno)); len = sizeof(sock); if (getsockname(listen_sock, (struct sockaddr *)&sock, &len) < 0) errx(-1, "getsockname() for listen socket: %s", strerror(errno)); port = sock.sin_port; if (listen(listen_sock, -1) < 0) errx(-1, "listen() for listen socket: %s", strerror(errno)); connect_sock = socket(PF_INET, SOCK_STREAM, 0); if (connect_sock == -1) errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect " "socket: %s", strerror(errno)); bzero(&sock, sizeof(sock)); sock.sin_len = sizeof(sock); sock.sin_family = AF_INET; sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sock.sin_port = port; if (connect(connect_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0) errx(-1, "connect() for connect socket: %s", strerror(errno)); /* Try to pass an invalid flags. */ if ((shutdown(connect_sock, SHUT_RD - 1) != -1) && (errno != EINVAL)) errx(-1, "shutdown(SHUT_RD - 1) does not return EINVAL"); if ((shutdown(connect_sock, SHUT_RDWR + 1) != -1) && (errno != EINVAL)) errx(-1, "shutdown(SHUT_RDWR + 1) does not return EINVAL"); if (shutdown(connect_sock, SHUT_RD) < 0) errx(-1, "shutdown(SHUT_RD) for connect socket: %s", strerror(errno)); if (shutdown(connect_sock, SHUT_WR) < 0) errx(-1, "shutdown(SHUT_WR) for connect socket: %s", strerror(errno)); close(connect_sock); close(listen_sock); return (0); } Index: stable/10/tools/regression/sockets/sigpipe/Makefile =================================================================== --- stable/10/tools/regression/sockets/sigpipe/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/sigpipe/Makefile (revision 281974) @@ -1,9 +1,9 @@ # # $FreeBSD$ # PROG= sigpipe MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/sigpipe/sigpipe.c =================================================================== --- stable/10/tools/regression/sockets/sigpipe/sigpipe.c (revision 281973) +++ stable/10/tools/regression/sockets/sigpipe/sigpipe.c (revision 281974) @@ -1,322 +1,322 @@ /*- * Copyright (c) 2005 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include /* * This regression test is intended to verify whether or not SIGPIPE is * properly generated in several simple test cases, as well as testing * whether SO_NOSIGPIPE disables SIGPIPE, if available on the system. * SIGPIPE is generated if a write or send is attempted on a socket that has * been shutdown for write. This test runs several test cases with UNIX * domain sockets and TCP sockets to confirm that either EPIPE or SIGPIPE is * properly returned. * * For the purposes of testing TCP, an unused port number must be specified. */ static void usage(void) { errx(-1, "usage: sigpipe tcpport"); } /* * Signal catcher. Set a global flag that can be tested by the caller. */ static int signaled; static int got_signal(void) { return (signaled); } static void -signal_handler(int signum) +signal_handler(int signum __unused) { signaled = 1; } static void signal_setup(const char *testname) { signaled = 0; if (signal(SIGPIPE, signal_handler) == SIG_ERR) err(-1, "%s: signal(SIGPIPE)", testname); } static void test_send(const char *testname, int sock) { ssize_t len; char ch; ch = 0; len = send(sock, &ch, sizeof(ch), 0); if (len < 0) { if (errno == EPIPE) return; err(-1, "%s: send", testname); } errx(-1, "%s: send: returned %zd", testname, len); } static void test_write(const char *testname, int sock) { ssize_t len; char ch; ch = 0; len = write(sock, &ch, sizeof(ch)); if (len < 0) { if (errno == EPIPE) return; err(-1, "%s: write", testname); } errx(-1, "%s: write: returned %zd", testname, len); } static void test_send_wantsignal(const char *testname, int sock1, int sock2) { if (shutdown(sock2, SHUT_WR) < 0) err(-1, "%s: shutdown", testname); signal_setup(testname); test_send(testname, sock2); if (!got_signal()) errx(-1, "%s: send: didn't receive SIGPIPE", testname); close(sock1); close(sock2); } #ifdef SO_NOSIGPIPE static void test_send_dontsignal(const char *testname, int sock1, int sock2) { int i; i = 1; if (setsockopt(sock2, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof(i)) < 0) err(-1, "%s: setsockopt(SOL_SOCKET, SO_NOSIGPIPE)", testname); if (shutdown(sock2, SHUT_WR) < 0) err(-1, "%s: shutdown", testname); signal_setup(testname); test_send(testname, sock2); if (got_signal()) errx(-1, "%s: send: got SIGPIPE", testname); close(sock1); close(sock2); } #endif static void test_write_wantsignal(const char *testname, int sock1, int sock2) { if (shutdown(sock2, SHUT_WR) < 0) err(-1, "%s: shutdown", testname); signal_setup(testname); test_write(testname, sock2); if (!got_signal()) errx(-1, "%s: write: didn't receive SIGPIPE", testname); close(sock1); close(sock2); } #ifdef SO_NOSIGPIPE static void test_write_dontsignal(const char *testname, int sock1, int sock2) { int i; i = 1; if (setsockopt(sock2, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof(i)) < 0) err(-1, "%s: setsockopt(SOL_SOCKET, SO_NOSIGPIPE)", testname); if (shutdown(sock2, SHUT_WR) < 0) err(-1, "%s: shutdown", testname); signal_setup(testname); test_write(testname, sock2); if (got_signal()) errx(-1, "%s: write: got SIGPIPE", testname); close(sock1); close(sock2); } #endif static int listen_sock; static void tcp_setup(u_short port) { struct sockaddr_in sin; listen_sock = socket(PF_INET, SOCK_STREAM, 0); if (listen_sock < 0) err(-1, "tcp_setup: listen"); bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = htons(port); if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "tcp_setup: bind"); if (listen(listen_sock, -1) < 0) err(-1, "tcp_setup: listen"); } static void tcp_teardown(void) { close(listen_sock); } static void tcp_pair(u_short port, int sock[2]) { int accept_sock, connect_sock; struct sockaddr_in sin; socklen_t len; connect_sock = socket(PF_INET, SOCK_STREAM, 0); if (connect_sock < 0) err(-1, "tcp_pair: socket"); bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = htons(port); if (connect(connect_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "tcp_pair: connect"); sleep(1); /* Time for TCP to settle. */ len = sizeof(sin); accept_sock = accept(listen_sock, (struct sockaddr *)&sin, &len); if (accept_sock < 0) err(-1, "tcp_pair: accept"); sleep(1); /* Time for TCP to settle. */ sock[0] = accept_sock; sock[1] = connect_sock; } int main(int argc, char *argv[]) { char *dummy; int sock[2]; long port; if (argc != 2) usage(); port = strtol(argv[1], &dummy, 10); if (port < 0 || port > 65535 || *dummy != '\0') usage(); #ifndef SO_NOSIGPIPE warnx("sigpipe: SO_NOSIGPIPE not defined, skipping some tests"); #endif /* * UNIX domain socketpair(). */ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_send_wantsignal("test_send_wantsignal(PF_LOCAL)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_send_dontsignal("test_send_dontsignal(PF_LOCAL)", sock[0], sock[1]); #endif if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_write_wantsignal("test_write_wantsignal(PF_LOCAL)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); test_write_dontsignal("test_write_dontsignal(PF_LOCAL)", sock[0], sock[1]); #endif /* * TCP. */ tcp_setup(port); tcp_pair(port, sock); test_send_wantsignal("test_send_wantsignal(PF_INET)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE tcp_pair(port, sock); test_send_dontsignal("test_send_dontsignal(PF_INET)", sock[0], sock[1]); #endif tcp_pair(port, sock); test_write_wantsignal("test_write_wantsignal(PF_INET)", sock[0], sock[1]); #ifdef SO_NOSIGPIPE tcp_pair(port, sock); test_write_dontsignal("test_write_dontsignal(PF_INET)", sock[0], sock[1]); #endif tcp_teardown(); fprintf(stderr, "PASS\n"); return (0); } Index: stable/10/tools/regression/sockets/so_setfib/so_setfib.t =================================================================== --- stable/10/tools/regression/sockets/so_setfib/so_setfib.t (revision 281973) +++ stable/10/tools/regression/sockets/so_setfib/so_setfib.t (nonexistent) @@ -1,59 +0,0 @@ -#!/bin/sh -#- -# Copyright (c) 2012 Cisco Systems, Inc. -# All rights reserved. -# -# This software was developed by Bjoern Zeeb under contract to -# Cisco Systems, Inc.. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $FreeBSD$ -# - -cd `dirname $0` - -EXECUTABLE=`basename $0 .t` - -FIBS=`sysctl -n net.fibs` -INET=`sysctl -n kern.features.inet` -INET6=`sysctl -n kern.features.inet6` - -case "${INET}" in -1) OPTS="${OPTS} -DINET" ;; -*) INET=0 ;; -esac -case "${INET6}" in -1) OPTS="${OPTS} -DINET6" ;; -*) INET6=0 ;; -esac - -make ${EXECUTABLE} ${OPTS} 2>&1 > /dev/null - -# two out of bounds on each side + 3 random -FIBS=$((2 + FIBS + 2 + 3)) -# ROUTE and LOCAL are 1 domain together given 2 or 1 types only -TESTS=$(((1 + ${INET} + ${INET6}) * 3 * ${FIBS})) - -echo "1..${TESTS}" - -exec ./${EXECUTABLE} Property changes on: stable/10/tools/regression/sockets/so_setfib/so_setfib.t ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/10/tools/regression/sockets/so_setfib/Makefile =================================================================== --- stable/10/tools/regression/sockets/so_setfib/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/so_setfib/Makefile (revision 281974) @@ -1,14 +1,16 @@ # $FreeBSD$ +.include + PROG= so_setfib MAN= WARNS?= 6 -.ifdef INET6 -CFLAGS+= -DINET6 -.endif -.ifdef INET +.if ${MK_INET} != "no" CFLAGS+= -DINET +.endif +.if ${MK_INET6} != "no" +CFLAGS+= -DINET6 .endif .include Index: stable/10/tools/regression/sockets/so_setfib/so_setfib.c =================================================================== --- stable/10/tools/regression/sockets/so_setfib/so_setfib.c (revision 281973) +++ stable/10/tools/regression/sockets/so_setfib/so_setfib.c (revision 281974) @@ -1,189 +1,200 @@ /*- * Copyright (c) 2012 Cisco Systems, Inc. * All rights reserved. * * This software was developed by Bjoern Zeeb under contract to * Cisco Systems, Inc.. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Regression test on SO_SETFIB setsockopt(2). * * Check that the expected domain(9) families all handle the socket option * correctly and do proper bounds checks. * * Test plan: * 1. Get system wide number of FIBs from sysctl and convert to index (-= 1). * 2. For each protocol family (INET, INET6, ROUTE and LOCAL) open socketes of * type (STREAM, DGRAM and RAW) as supported. * 3. Do a sequence of -2, -1, 0, .. n, n+1, n+2 SO_SETFIB sockopt calls, * expecting the first two and last two to fail (valid 0 ... n). * 4. Try 3 random numbers. Calculate result based on valid range. * 5. Repeat for next domain family and type from (2) on. */ +#include #include #include #include #include #include #include #include #include #include static struct t_dom { int domain; const char *name; } t_dom[] = { #ifdef INET6 { .domain = PF_INET6, .name = "PF_INET6" }, #endif #ifdef INET { .domain = PF_INET, .name = "PF_INET" }, #endif { .domain = PF_ROUTE, .name = "PF_ROUTE" }, { .domain = PF_LOCAL, .name = "PF_LOCAL" }, }; static struct t_type { int type; const char *name; } t_type[] = { { .type = SOCK_STREAM, .name = "SOCK_STREAM" }, { .type = SOCK_DGRAM, .name = "SOCK_DGRAM" }, { .type = SOCK_RAW, .name = "SOCK_RAW" }, }; /* * Number of FIBs as read from net.fibs sysctl - 1. Initialize to clear out of * bounds value to not accidentally run on a limited range. */ static int rt_numfibs = -42; /* Number of test case. */ static int testno = 1; /* * Try the setsockopt with given FIB number i on socket s. * Handle result given on error and valid range and errno. */ static void so_setfib(int s, int i, u_int dom, u_int type) { int error; error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &i, sizeof(i)); /* For out of bounds we expect an error. */ if (error == -1 && (i < 0 || i > rt_numfibs)) printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name, t_type[type].name, i); else if (error != -1 && (i < 0 || i > rt_numfibs)) printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, " "SO_SETFIB, %d, ..) unexpectedly succeeded\n", testno, t_dom[dom].name, t_type[type].name, i, s, i); else if (error == 0) printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name, t_type[type].name, i); else if (errno != EINVAL) printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, " "SO_SETFIB, %d, ..) unexpected error: %s\n", testno, t_dom[dom].name, t_type[type].name, i, s, i, strerror(errno)); else printf("not ok %d %s_%s_%d\n", testno, t_dom[dom].name, t_type[type].name, i); /* Test run done, next please. */ testno++; } /* * Main test. Open socket given domain family and type. For each FIB, out of * bounds FIB numbers and 3 random FIB numbers set the socket option. */ static void t(u_int dom, u_int type) { int i, s; /* PF_ROUTE only supports RAW socket types, while PF_LOCAL does not. */ if (t_dom[dom].domain == PF_ROUTE && t_type[type].type != SOCK_RAW) return; if (t_dom[dom].domain == PF_LOCAL && t_type[type].type == SOCK_RAW) return; /* Open socket for given combination. */ s = socket(t_dom[dom].domain, t_type[type].type, 0); if (s == -1) { printf("not ok %d %s_%s # socket(): %s\n", testno, t_dom[dom].name, t_type[type].name, strerror(errno)); + testno++; return; } /* Test FIBs -2, -1, 0, .. n, n + 1, n + 2. */ for (i = -2; i <= (rt_numfibs + 2); i++) so_setfib(s, i, dom, type); /* Test 3 random FIB numbers. */ for (i = 0; i < 3; i++) so_setfib(s, (int)random(), dom, type); /* Close socket. */ close(s); } /* * Returns 0 if no program error, 1 on sysctlbyname error. * Test results are communicated by printf("[not ]ok .."). */ int main(int argc __unused, char *argv[] __unused) { u_int i, j; size_t s; + if (geteuid() != 0) { + printf("1..0 # SKIP: must be root"); + return (0); + } + /* Initalize randomness. */ srandomdev(); /* Get number of FIBs supported by kernel. */ s = sizeof(rt_numfibs); if (sysctlbyname("net.fibs", &rt_numfibs, &s, NULL, 0) == -1) err(1, "sysctlbyname(net.fibs, ..)"); + + printf("1..%lu\n", + (nitems(t_dom) - 1) * nitems(t_type) * (2 + rt_numfibs + 2 + 3)); + /* Adjust from number to index. */ rt_numfibs -= 1; /* Run tests. */ for (i = 0; i < sizeof(t_dom) / sizeof(struct t_dom); i++) for (j = 0; j < sizeof(t_type) / sizeof(struct t_type); j++) t(i, j); return (0); } /* end */ Index: stable/10/tools/regression/sockets/socketpair/Makefile =================================================================== --- stable/10/tools/regression/sockets/socketpair/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/socketpair/Makefile (revision 281974) @@ -1,9 +1,9 @@ # # $FreeBSD$ # PROG= socketpair MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/socketpair/socketpair.c =================================================================== --- stable/10/tools/regression/sockets/socketpair/socketpair.c (revision 281973) +++ stable/10/tools/regression/sockets/socketpair/socketpair.c (revision 281974) @@ -1,161 +1,161 @@ /*- * Copyright (c) 2004 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include /* * Open, then close a set of UNIX domain socket pairs for datagram and * stream. * * Confirm that we can't open INET datagram or stream socket pairs. * * More tests should be added, including confirming that sending on either * endpoint results in data at the other, that the right kind of socket was * created (stream vs. datagram), and that message boundaries fall in the * right places. */ int -main(int argc, char *argv[]) +main(void) { int fd1, fd2, fd3; int sv[2]; /* * UNIX domain socket pair, datagram. */ if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) != 0) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM): %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); exit(-1); } if (close(sv[0]) != 0) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM) close 0: %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); exit(-1); } if (close(sv[1]) != 0) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM) close 1: %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); exit(-1); } /* * UNIX domain socket pair, stream. */ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) != 0) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_STREAM): %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); exit(-1); } if (close(sv[0]) != 0) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_STREAM) close 0: %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); exit(-1); } if (close(sv[1]) != 0) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_STREAM) close 1: " "%s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); exit(-1); } /* * Confirm that PF_INET datagram socket pair creation fails. */ if (socketpair(PF_INET, SOCK_DGRAM, 0, sv) == 0) { fprintf(stderr, "socketpair(PF_INET, SOCK_DGRAM): opened\n"); fprintf(stderr, "FAIL\n"); exit(-1); } if (errno != EOPNOTSUPP) { fprintf(stderr, "socketpair(PF_INET, SOCK_DGRAM): %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); } /* * Confirm that PF_INET stream socket pair creation fails. */ if (socketpair(PF_INET, SOCK_STREAM, 0, sv) == 0) { fprintf(stderr, "socketpair(PF_INET, SOCK_STREAM): opened\n"); fprintf(stderr, "FAIL\n"); exit(-1); } if (errno != EOPNOTSUPP) { fprintf(stderr, "socketpair(PF_INET, SOCK_STREAM): %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); } /* * Check for sequential fd allocation, and give up early if not. */ fd1 = dup(STDIN_FILENO); fd2 = dup(STDIN_FILENO); if (fd2 != fd1 + 1) { fprintf(stderr, "Non-sequential fd allocation\n"); fprintf(stderr, "FAIL\n"); exit(-1); } /* Allocate a socketpair using a bad destination address. */ if (socketpair(PF_UNIX, SOCK_DGRAM, 0, NULL) == 0) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM, NULL): opened\n"); fprintf(stderr, "FAIL\n"); exit(-1); } if (errno != EFAULT) { fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM, NULL): %s\n", strerror(errno)); fprintf(stderr, "FAIL\n"); exit(-1); } /* Allocate a file descriptor and make sure it's fd2+1. */ fd3 = dup(STDIN_FILENO); if (fd3 != fd2 + 1) { fprintf(stderr, "socketpair(..., NULL) allocated descriptors\n"); fprintf(stderr, "FAIL\n"); exit(-1); } fprintf(stderr, "PASS\n"); exit(0); } Index: stable/10/tools/regression/sockets/unix_bindconnect/Makefile =================================================================== --- stable/10/tools/regression/sockets/unix_bindconnect/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/unix_bindconnect/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= unix_bindconnect MAN= -WARNS?= 2 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/unix_bindconnect/unix_bindconnect.c =================================================================== --- stable/10/tools/regression/sockets/unix_bindconnect/unix_bindconnect.c (revision 281973) +++ stable/10/tools/regression/sockets/unix_bindconnect/unix_bindconnect.c (revision 281974) @@ -1,318 +1,318 @@ /*- * Copyright (c) 2005 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include /* * Simple regression test to exercise some error cases relating to the use of * bind() and connect() on UNIX domain sockets. In particular, make sure * that when two sockets rendezvous using the file system name space, they * get the expected success/failure cases. * * TODO: * - Check that the resulting file mode/owner are right. * - Do the same tests with UNIX domain sockets. * - Check the results of getsockaddr() and getpeeraddr(). */ #define SOCK_NAME_ONE "socket.1" #define SOCK_NAME_TWO "socket.2" #define UNWIND_MAX 1024 -int unwind_len; -struct unwind { +static int unwind_len; +static struct unwind { char u_path[PATH_MAX]; } unwind_list[UNWIND_MAX]; static void push_path(const char *path) { if (unwind_len >= UNWIND_MAX) err(-1, "push_path: one path too many (%s)", path); strlcpy(unwind_list[unwind_len].u_path, path, PATH_MAX); unwind_len++; } static void unwind(void) { int i; for (i = unwind_len - 1; i >= 0; i--) { unlink(unwind_list[i].u_path); rmdir(unwind_list[i].u_path); } } static int bind_test(const char *directory_path) { char socket_path[PATH_MAX]; struct sockaddr_un sun; int sock1, sock2; sock1 = socket(PF_UNIX, SOCK_STREAM, 0); if (sock1 < 0) { warn("bind_test: socket(PF_UNIX, SOCK_STREAM, 0)"); return (-1); } if (snprintf(socket_path, sizeof(socket_path), "%s/%s", directory_path, SOCK_NAME_ONE) >= PATH_MAX) { warn("bind_test: snprintf(socket_path)"); close(sock1); return (-1); } bzero(&sun, sizeof(sun)); sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; if (snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", socket_path) - >= sizeof(sun.sun_path)) { + >= (int)sizeof(sun.sun_path)) { warn("bind_test: snprintf(sun.sun_path)"); close(sock1); return (-1); } if (bind(sock1, (struct sockaddr *)&sun, sizeof(sun)) < 0) { warn("bind_test: bind(sun) #1"); close(sock1); return (-1); } push_path(socket_path); /* * Once a STREAM UNIX domain socket has been bound, it can't be * rebound. Expected error is EINVAL. */ if (bind(sock1, (struct sockaddr *)&sun, sizeof(sun)) == 0) { warnx("bind_test: bind(sun) #2 succeeded"); close(sock1); return (-1); } if (errno != EINVAL) { warn("bind_test: bind(sun) #2"); close(sock1); return (-1); } sock2 = socket(PF_UNIX, SOCK_STREAM, 0); if (sock2 < 0) { warn("bind_test: socket(PF_UNIX, SOCK_STREAM, 0)"); close(sock1); return (-1); } /* * Since a socket is already bound to the pathname, it can't be bound * to a second socket. Expected error is EADDRINUSE. */ if (bind(sock2, (struct sockaddr *)&sun, sizeof(sun)) == 0) { warnx("bind_test: bind(sun) #3 succeeded"); close(sock1); close(sock2); return (-1); } if (errno != EADDRINUSE) { warn("bind_test: bind(sun) #2"); close(sock1); close(sock2); return (-1); } close(sock1); /* * The socket bound to the pathname has been closed, but the pathname * can't be reused without first being unlinked. Expected error is * EADDRINUSE. */ if (bind(sock2, (struct sockaddr *)&sun, sizeof(sun)) == 0) { warnx("bind_test: bind(sun) #4 succeeded"); close(sock2); return (-1); } if (errno != EADDRINUSE) { warn("bind_test: bind(sun) #4"); close(sock2); return (-1); } unlink(socket_path); /* * The pathname is now free, so the socket should be able to bind to * it. */ if (bind(sock2, (struct sockaddr *)&sun, sizeof(sun)) < 0) { warn("bind_test: bind(sun) #5"); close(sock2); return (-1); } close(sock2); return (0); } static int connect_test(const char *directory_path) { char socket_path[PATH_MAX]; struct sockaddr_un sun; int sock1, sock2; sock1 = socket(PF_UNIX, SOCK_STREAM, 0); if (sock1 < 0) { warn("connect_test: socket(PF_UNIX, SOCK_STREAM, 0)"); return (-1); } if (snprintf(socket_path, sizeof(socket_path), "%s/%s", directory_path, SOCK_NAME_TWO) >= PATH_MAX) { warn("connect_test: snprintf(socket_path)"); close(sock1); return (-1); } bzero(&sun, sizeof(sun)); sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; if (snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", socket_path) - >= sizeof(sun.sun_path)) { + >= (int)sizeof(sun.sun_path)) { warn("connect_test: snprintf(sun.sun_path)"); close(sock1); return (-1); } /* * Try connecting to a path that doesn't yet exist. Should fail with * ENOENT. */ if (connect(sock1, (struct sockaddr *)&sun, sizeof(sun)) == 0) { warnx("connect_test: connect(sun) #1 succeeded"); close(sock1); return (-1); } if (errno != ENOENT) { warn("connect_test: connect(sun) #1"); close(sock1); return (-1); } if (bind(sock1, (struct sockaddr *)&sun, sizeof(sun)) < 0) { warn("connect_test: bind(sun) #1"); close(sock1); return (-1); } if (listen(sock1, 3) < 0) { warn("connect_test: listen(sock1)"); close(sock1); return (-1); } push_path(socket_path); sock2 = socket(PF_UNIX, SOCK_STREAM, 0); if (sock2 < 0) { warn("socket(PF_UNIX, SOCK_STREAM, 0)"); close(sock1); return (-1); } /* * Do a simple connect and make sure that works. */ if (connect(sock2, (struct sockaddr *)&sun, sizeof(sun)) < 0) { warn("connect(sun) #2"); close(sock1); return (-1); } close(sock2); close(sock1); sock2 = socket(PF_UNIX, SOCK_STREAM, 0); if (sock2 < 0) { warn("socket(PF_UNIX, SOCK_STREAM, 0)"); return (-1); } /* * Confirm that once the listen socket is closed, we get a * connection refused (ECONNREFUSED) when attempting to connect to * the pathname. */ if (connect(sock2, (struct sockaddr *)&sun, sizeof(sun)) == 0) { warnx("connect(sun) #3 succeeded"); close(sock2); return (-1); } if (errno != ECONNREFUSED) { warn("connect(sun) #3"); close(sock2); return (-1); } close(sock2); unlink(socket_path); return (0); } int -main(int argc, char *argv[]) +main(void) { char directory_path[PATH_MAX]; int error; strlcpy(directory_path, "/tmp/unix_bind.XXXXXXX", PATH_MAX); if (mkdtemp(directory_path) == NULL) err(-1, "mkdtemp"); push_path(directory_path); error = bind_test(directory_path); if (error == 0) error = connect_test(directory_path); unwind(); return (error); } Index: stable/10/tools/regression/sockets/unix_close_race/Makefile =================================================================== --- stable/10/tools/regression/sockets/unix_close_race/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/unix_close_race/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= unix_close_race MAN= -WARNS?= 3 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/unix_close_race/unix_close_race.c =================================================================== --- stable/10/tools/regression/sockets/unix_close_race/unix_close_race.c (revision 281973) +++ stable/10/tools/regression/sockets/unix_close_race/unix_close_race.c (revision 281974) @@ -1,138 +1,143 @@ /*- * Copyright (c) 2010 Mikolaj Golub * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * This regression test attempts to trigger a race that occurs when both * endpoints of a connected UNIX domain socket are closed at once. The two * close paths may run concurrently leading to a call to sodisconnect() on an * already-closed socket in kernel. Before it was fixed, this might lead to * ENOTCONN being returned improperly from close(). * * This race is fairly timing-dependent, so it effectively requires SMP, and * may not even trigger then. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#define UNIXSTR_PATH "/tmp/mytest.socket" +static char socket_path[] = "tmp.XXXXXXXX"; + #define USLEEP 100 #define LOOPS 100000 int -main(int argc, char **argv) +main(void) { struct sockaddr_un servaddr; int listenfd, connfd, pid; u_int counter, ncpus; size_t len; len = sizeof(ncpus); if (sysctlbyname("kern.smp.cpus", &ncpus, &len, NULL, 0) < 0) err(1, "kern.smp.cpus"); if (len != sizeof(ncpus)) errx(1, "kern.smp.cpus: invalid length"); if (ncpus < 2) warnx("SMP not present, test may be unable to trigger race"); + if (mkstemp(socket_path) == -1) + err(1, "mkstemp failed"); + unlink(socket_path); + /* * Create a UNIX domain socket that the child will repeatedly * accept() from, and that the parent will repeatedly connect() to. */ if ((listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) err(1, "parent: socket error"); - (void)unlink(UNIXSTR_PATH); + (void)unlink(socket_path); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; - strcpy(servaddr.sun_path, UNIXSTR_PATH); + strcpy(servaddr.sun_path, socket_path); if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) err(1, "parent: bind error"); if (listen(listenfd, 1024) < 0) err(1, "parent: listen error"); pid = fork(); if (pid == -1) err(1, "fork()"); if (pid != 0) { /* * In the parent, repeatedly connect and disconnect from the * socket, attempting to induce the race. */ close(listenfd); sleep(1); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; - strcpy(servaddr.sun_path, UNIXSTR_PATH); + strcpy(servaddr.sun_path, socket_path); for (counter = 0; counter < LOOPS; counter++) { if ((connfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { (void)kill(pid, SIGTERM); err(1, "parent: socket error"); } if (connect(connfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { (void)kill(pid, SIGTERM); err(1, "parent: connect error"); } if (close(connfd) < 0) { (void)kill(pid, SIGTERM); err(1, "parent: close error"); } usleep(USLEEP); } (void)kill(pid, SIGTERM); } else { /* * In the child, loop accepting and closing. We may pick up * the race here so report errors from close(). */ for ( ; ; ) { if ((connfd = accept(listenfd, (struct sockaddr *)NULL, NULL)) < 0) err(1, "child: accept error"); if (close(connfd) < 0) err(1, "child: close error"); } } printf("OK\n"); exit(0); } Index: stable/10/tools/regression/sockets/unix_passfd/Makefile =================================================================== --- stable/10/tools/regression/sockets/unix_passfd/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/unix_passfd/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= unix_passfd MAN= -WARNS?= 2 +WARNS?= 3 .include Index: stable/10/tools/regression/sockets/unix_passfd/unix_passfd.c =================================================================== --- stable/10/tools/regression/sockets/unix_passfd/unix_passfd.c (revision 281973) +++ stable/10/tools/regression/sockets/unix_passfd/unix_passfd.c (revision 281974) @@ -1,335 +1,389 @@ /*- * Copyright (c) 2005 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include +#include +#include #include #include #include #include +#include #include #include /* * UNIX domain sockets allow file descriptors to be passed via "ancillary * data", or control messages. This regression test is intended to exercise * this facility, both performing some basic tests that it operates, and also * causing some kernel edge cases to execute, such as garbage collection when * there are cyclic file descriptor references. Right now we test only with * stream sockets, but ideally we'd also test with datagram sockets. */ static void domainsocketpair(const char *test, int *fdp) { if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdp) < 0) err(-1, "%s: socketpair(PF_UNIX, SOCK_STREAM)", test); } static void closesocketpair(int *fdp) { close(fdp[0]); close(fdp[1]); } static void devnull(const char *test, int *fdp) { int fd; fd = open("/dev/null", O_RDONLY); if (fd < 0) err(-1, "%s: open(/dev/null)", test); *fdp = fd; } static void tempfile(const char *test, int *fdp) { char path[PATH_MAX]; int fd; snprintf(path, PATH_MAX, "/tmp/unix_passfd.XXXXXXXXXXXXXXX"); fd = mkstemp(path); if (fd < 0) err(-1, "%s: mkstemp(%s)", test, path); (void)unlink(path); *fdp = fd; } static void dofstat(const char *test, int fd, struct stat *sb) { if (fstat(fd, sb) < 0) err(-1, "%s: fstat", test); } static void samefile(const char *test, struct stat *sb1, struct stat *sb2) { if (sb1->st_dev != sb2->st_dev) errx(-1, "%s: samefile: different device", test); if (sb1->st_ino != sb2->st_ino) errx(-1, "%s: samefile: different inode", test); } static void -sendfd(const char *test, int sockfd, int sendfd) +sendfd_payload(const char *test, int sockfd, int sendfd, + void *payload, size_t paylen) { struct iovec iovec; - char ch; - char message[CMSG_SPACE(sizeof(int))]; struct cmsghdr *cmsghdr; struct msghdr msghdr; ssize_t len; bzero(&msghdr, sizeof(msghdr)); bzero(&message, sizeof(message)); - ch = 0; msghdr.msg_control = message; msghdr.msg_controllen = sizeof(message); - iovec.iov_base = &ch; - iovec.iov_len = sizeof(ch); + iovec.iov_base = payload; + iovec.iov_len = paylen; msghdr.msg_iov = &iovec; msghdr.msg_iovlen = 1; cmsghdr = (struct cmsghdr *)message; cmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); cmsghdr->cmsg_level = SOL_SOCKET; cmsghdr->cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(cmsghdr) = sendfd; len = sendmsg(sockfd, &msghdr, 0); if (len < 0) err(-1, "%s: sendmsg", test); - if (len != sizeof(ch)) + if ((size_t)len != paylen) errx(-1, "%s: sendmsg: %zd bytes sent", test, len); } static void -recvfd(const char *test, int sockfd, int *recvfd) +sendfd(const char *test, int sockfd, int sendfd) { + char ch; + + return (sendfd_payload(test, sockfd, sendfd, &ch, sizeof(ch))); +} + +static void +recvfd_payload(const char *test, int sockfd, int *recvfd, + void *buf, size_t buflen) +{ struct cmsghdr *cmsghdr; - char message[CMSG_SPACE(sizeof(int))]; + char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)]; struct msghdr msghdr; struct iovec iovec; ssize_t len; - char ch; bzero(&msghdr, sizeof(msghdr)); - ch = 0; msghdr.msg_control = message; msghdr.msg_controllen = sizeof(message); - iovec.iov_base = &ch; - iovec.iov_len = sizeof(ch); + iovec.iov_base = buf; + iovec.iov_len = buflen; msghdr.msg_iov = &iovec; msghdr.msg_iovlen = 1; - iovec.iov_len = sizeof(ch); - - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - len = recvmsg(sockfd, &msghdr, 0); if (len < 0) err(-1, "%s: recvmsg", test); - if (len != sizeof(ch)) + if ((size_t)len != buflen) errx(-1, "%s: recvmsg: %zd bytes received", test, len); + cmsghdr = CMSG_FIRSTHDR(&msghdr); if (cmsghdr == NULL) errx(-1, "%s: recvmsg: did not receive control message", test); - if (cmsghdr->cmsg_len != CMSG_LEN(sizeof(int)) || - cmsghdr->cmsg_level != SOL_SOCKET || - cmsghdr->cmsg_type != SCM_RIGHTS) + *recvfd = -1; + for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) { + if (cmsghdr->cmsg_level == SOL_SOCKET && + cmsghdr->cmsg_type == SCM_RIGHTS && + cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) { + *recvfd = *(int *)CMSG_DATA(cmsghdr); + if (*recvfd == -1) + errx(-1, "%s: recvmsg: received fd -1", test); + } + } + if (*recvfd == -1) errx(-1, "%s: recvmsg: did not receive single-fd message", test); - *recvfd = *(int *)CMSG_DATA(cmsghdr); - if (*recvfd == -1) - errx(-1, "%s: recvmsg: received fd -1", test); } +static void +recvfd(const char *test, int sockfd, int *recvfd) +{ + char ch; + + return (recvfd_payload(test, sockfd, recvfd, &ch, sizeof(ch))); +} + int -main(int argc, char *argv[]) +main(void) { struct stat putfd_1_stat, putfd_2_stat, getfd_1_stat, getfd_2_stat; int fd[2], putfd_1, putfd_2, getfd_1, getfd_2; const char *test; /* * First test: put a temporary file into a UNIX domain socket, then * take it out and make sure it's the same file. First time around, * don't close the reference after sending. */ test = "test1-simplesendfd"; printf("beginning %s\n", test); domainsocketpair(test, fd); tempfile(test, &putfd_1); dofstat(test, putfd_1, &putfd_1_stat); sendfd(test, fd[0], putfd_1); recvfd(test, fd[1], &getfd_1); dofstat(test, getfd_1, &getfd_1_stat); samefile(test, &putfd_1_stat, &getfd_1_stat); close(putfd_1); close(getfd_1); closesocketpair(fd); printf("%s passed\n", test); /* * Second test: same as first, only close the file reference after * sending, so that the only reference is the descriptor in the UNIX * domain socket buffer. */ test = "test2-sendandclose"; printf("beginning %s\n", test); domainsocketpair(test, fd); tempfile(test, &putfd_1); dofstat(test, putfd_1, &putfd_1_stat); sendfd(test, fd[0], putfd_1); close(putfd_1); recvfd(test, fd[1], &getfd_1); dofstat(test, getfd_1, &getfd_1_stat); samefile(test, &putfd_1_stat, &getfd_1_stat); close(getfd_1); closesocketpair(fd); printf("%s passed\n", test); /* * Third test: put a temporary file into a UNIX domain socket, then * close both endpoints causing garbage collection to kick off. */ test = "test3-sendandcancel"; printf("beginning %s\n", test); domainsocketpair(test, fd); tempfile(test, &putfd_1); sendfd(test, fd[0], putfd_1); close(putfd_1); closesocketpair(fd); printf("%s passed\n", test); /* * Send two files. Then receive them. Make sure they are returned * in the right order, and both get there. */ test = "test4-twofile"; printf("beginning %s\n", test); domainsocketpair(test, fd); tempfile(test, &putfd_1); tempfile(test, &putfd_2); dofstat(test, putfd_1, &putfd_1_stat); dofstat(test, putfd_2, &putfd_2_stat); sendfd(test, fd[0], putfd_1); sendfd(test, fd[0], putfd_2); close(putfd_1); close(putfd_2); recvfd(test, fd[1], &getfd_1); recvfd(test, fd[1], &getfd_2); dofstat(test, getfd_1, &getfd_1_stat); dofstat(test, getfd_2, &getfd_2_stat); samefile(test, &putfd_1_stat, &getfd_1_stat); samefile(test, &putfd_2_stat, &getfd_2_stat); close(getfd_1); close(getfd_2); closesocketpair(fd); printf("%s passed\n", test); /* * Big bundling test. Send an endpoint of the UNIX domain socket * over itself, closing the door behind it. */ test = "test5-bundle"; printf("beginning %s\n", test); domainsocketpair(test, fd); sendfd(test, fd[0], fd[0]); close(fd[0]); recvfd(test, fd[1], &getfd_1); close(getfd_1); close(fd[1]); printf("%s passed\n", test); /* * Big bundling test part two: Send an endpoint of the UNIX domain * socket over itself, close the door behind it, and never remove it * from the other end. */ test = "test6-bundlecancel"; printf("beginning %s\n", test); domainsocketpair(test, fd); sendfd(test, fd[0], fd[0]); sendfd(test, fd[1], fd[0]); closesocketpair(fd); printf("%s passed\n", test); /* * Test for PR 151758: Send an character device over the UNIX * domain socket and then close both sockets to orphan the * device. */ test = "test7-devfsorphan"; printf("beginning %s\n", test); domainsocketpair(test, fd); devnull(test, &putfd_1); sendfd(test, fd[0], putfd_1); close(putfd_1); closesocketpair(fd); + + printf("%s passed\n", test); + + /* + * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel + * prepends a control message to the data. Sender sends large + * payload. Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer + * limit, and receiver receives truncated data. + */ + test = "test8-rights+creds+payload"; + printf("beginning %s\n", test); + + { + const int on = 1; + u_long sendspace; + size_t len; + void *buf; + + len = sizeof(sendspace); + if (sysctlbyname("net.local.stream.sendspace", &sendspace, + &len, NULL, 0) < 0) + err(-1, "%s: sysctlbyname(net.local.stream.sendspace)", + test); + + if ((buf = malloc(sendspace)) == NULL) + err(-1, "%s: malloc", test); + + domainsocketpair(test, fd); + if (setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on)) < 0) + err(-1, "%s: setsockopt(LOCAL_CREDS)", test); + tempfile(test, &putfd_1); + sendfd_payload(test, fd[0], putfd_1, buf, sendspace); + recvfd_payload(test, fd[1], &getfd_1, buf, sendspace); + close(putfd_1); + close(getfd_1); + closesocketpair(fd); + } printf("%s passed\n", test); return (0); } Index: stable/10/tools/regression/sockets/unix_sendtorace/Makefile =================================================================== --- stable/10/tools/regression/sockets/unix_sendtorace/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/unix_sendtorace/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= unix_sendtorace MAN= -WARNS?= 3 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c =================================================================== --- stable/10/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c (revision 281973) +++ stable/10/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c (revision 281974) @@ -1,212 +1,215 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Attempts to exercise UNIX domain socket races relating to the non-atomic * connect-and-send properties of sendto(). As the result of such a race is * a kernel panic, this test simply completes or doesn't. * * XXX: Despite implementing support for sendto() on stream sockets with * implied connect, the appropriate flag isn't set in the FreeBSD kernel so * it does not work. For now, don't call the stream test. */ #include #include #include #include #include #include #include -#define PATH "/tmp/123" #define ITERATIONS 1000000 +static char socket_path[] = "tmp.XXXXXX"; + static void stream_server(int listenfd) { int acceptfd; while (1) { acceptfd = accept(listenfd, NULL, NULL); if (acceptfd < 0) { warn("stream_server: accept"); continue; } sleep(1); close(acceptfd); } } static void stream_client(void) { struct sockaddr_un sun; ssize_t len; char c = 0; int fd, i; bzero(&sun, sizeof(sun)); sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, PATH); + strcpy(sun.sun_path, socket_path); for (i = 0; i < ITERATIONS; i++) { fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { warn("stream_client: socket"); return; } len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, sizeof(sun)); if (len < 0) warn("stream_client: sendto"); close(fd); } } static void stream_test(void) { struct sockaddr_un sun; pid_t childpid; int listenfd; listenfd = socket(PF_UNIX, SOCK_STREAM, 0); if (listenfd < 0) err(-1, "stream_test: socket"); bzero(&sun, sizeof(sun)); sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, PATH); + strcpy(sun.sun_path, socket_path); if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) err(-1, "stream_test: bind"); if (listen(listenfd, -1) < 0) err(-1, "stream_test: listen"); childpid = fork(); if (childpid < 0) err(-1, "stream_test: fork"); if (childpid != 0) { sleep(1); stream_client(); kill(childpid, SIGTERM); sleep(1); } else stream_server(listenfd); - (void)unlink(PATH); + (void)unlink(socket_path); } static void datagram_server(int serverfd) { ssize_t len; char c; while (1) { len = recv(serverfd, &c, sizeof(c), 0); if (len < 0) warn("datagram_server: recv"); } } static void datagram_client(void) { struct sockaddr_un sun; ssize_t len; char c = 0; int fd, i; bzero(&sun, sizeof(sun)); sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, PATH); + strcpy(sun.sun_path, socket_path); for (i = 0; i < ITERATIONS; i++) { fd = socket(PF_UNIX, SOCK_DGRAM, 0); if (fd < 0) { warn("datagram_client: socket"); return; } len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, sizeof(sun)); if (len < 0) warn("datagram_client: sendto"); close(fd); } } static void datagram_test(void) { struct sockaddr_un sun; pid_t childpid; int serverfd; serverfd = socket(PF_UNIX, SOCK_DGRAM, 0); if (serverfd < 0) err(-1, "datagram_test: socket"); bzero(&sun, sizeof(sun)); sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, PATH); + strcpy(sun.sun_path, socket_path); if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) err(-1, "datagram_test: bind"); childpid = fork(); if (childpid < 0) err(-1, "datagram_test: fork"); if (childpid != 0) { sleep(1); datagram_client(); kill(childpid, SIGTERM); sleep(1); } else datagram_server(serverfd); - (void)unlink(PATH); + (void)unlink(socket_path); } int -main(int argc, char *argv[]) +main(void) { - - (void)unlink(PATH); + + if (mkstemp(socket_path) == -1) + err(1, "mkstemp failed"); + (void)unlink(socket_path); datagram_test(); if (0) stream_test(); return (0); } Index: stable/10/tools/regression/sockets/unix_socket/Makefile =================================================================== --- stable/10/tools/regression/sockets/unix_socket/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/unix_socket/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= unix_socket MAN= -WARNS?= 3 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/unix_socket/unix_socket.c =================================================================== --- stable/10/tools/regression/sockets/unix_socket/unix_socket.c (revision 281973) +++ stable/10/tools/regression/sockets/unix_socket/unix_socket.c (revision 281974) @@ -1,84 +1,84 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Simple UNIX domain socket regression test: create and tear down various * supported and unsupported socket types. */ #include #include #include #include #include #include int -main(int argc, char *argv[]) +main(void) { int sock, socks[2]; sock = socket(PF_LOCAL, SOCK_STREAM, 0); if (sock < 0) err(-1, "socket(PF_LOCAL, SOCK_STREAM, 0)"); close(sock); sock = socket(PF_LOCAL, SOCK_DGRAM, 0); if (sock < 0) err(-1, "socket(PF_LOCAL, SOCK_DGRAM, 0)"); close(sock); sock = socket(PF_LOCAL, SOCK_RAW, 0); if (sock >= 0) { close(sock); errx(-1, "socket(PF_LOCAL, SOCK_RAW, 0) returned %d", sock); } if (errno != EPROTONOSUPPORT) err(-1, "socket(PF_LOCAL, SOCK_RAW, 0)"); if (socketpair(PF_LOCAL, SOCK_STREAM, 0, socks) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_STREAM, 0, socks)"); if (socks[0] < 0) errx(-1, "socketpair(PF_LOCAL, SOCK_STREAM, 0, socks) [0] < 0"); if (socks[1] < 0) errx(-1, "socketpair(PF_LOCAL, SOCK_STREAM, 0, socks) [1] < 1"); close(socks[0]); close(socks[1]); if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks) < 0) err(-1, "socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks)"); if (socks[0] < 0) errx(-1, "socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks) [0] < 0"); if (socks[1] < 0) errx(-1, "socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks) [1] < 1"); close(socks[0]); close(socks[1]); return (0); } Index: stable/10/tools/regression/sockets/unix_sorflush/Makefile =================================================================== --- stable/10/tools/regression/sockets/unix_sorflush/Makefile (revision 281973) +++ stable/10/tools/regression/sockets/unix_sorflush/Makefile (revision 281974) @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= unix_sorflush MAN= -WARNS?= 3 +WARNS?= 6 .include Index: stable/10/tools/regression/sockets/unix_sorflush/unix_sorflush.c =================================================================== --- stable/10/tools/regression/sockets/unix_sorflush/unix_sorflush.c (revision 281973) +++ stable/10/tools/regression/sockets/unix_sorflush/unix_sorflush.c (revision 281974) @@ -1,99 +1,99 @@ /*- * Copyright (c) 2008 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Reproduce a race in which: * * - Process (a) is blocked in read on a socket waiting on data. * - Process (b) is blocked in shutdown() on a socket waiting on (a). * - Process (c) delivers a signal to (b) interrupting its wait. * * This race is premised on shutdown() not interrupting (a) properly, and the * signal to (b) causing problems in the kernel. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include static void receive_and_exit(int s) { ssize_t ssize; char ch; ssize = recv(s, &ch, sizeof(ch), 0); if (ssize < 0) err(-1, "receive_and_exit: recv"); exit(0); } static void shutdown_and_exit(int s) { if (shutdown(s, SHUT_RD) < 0) err(-1, "shutdown_and_exit: shutdown"); exit(0); } int -main(int argc, char *argv[]) +main(void) { pid_t pida, pidb; int sv[2]; if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) < 0) err(-1, "socketpair"); pida = fork(); if (pida < 0) err(-1, "fork"); if (pida == 0) receive_and_exit(sv[1]); sleep(1); pidb = fork(); if (pidb < 0) { warn("fork"); (void)kill(pida, SIGKILL); exit(-1); } if (pidb == 0) shutdown_and_exit(sv[1]); sleep(1); if (kill(pidb, SIGKILL) < 0) err(-1, "kill"); sleep(1); printf("ok 1 - unix_sorflush\n"); exit(0); } Index: stable/10/tools/regression/sockets/zerosend/zerosend.c =================================================================== --- stable/10/tools/regression/sockets/zerosend/zerosend.c (revision 281973) +++ stable/10/tools/regression/sockets/zerosend/zerosend.c (revision 281974) @@ -1,290 +1,290 @@ /*- * Copyright (c) 2007 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #define PORT1 10001 #define PORT2 10002 static void try_0send(const char *test, int fd) { ssize_t len; char ch; ch = 0; len = send(fd, &ch, 0, 0); if (len < 0) err(-1, "%s: try_0send", test); if (len != 0) errx(-1, "%s: try_0send: returned %zd", test, len); } static void try_0write(const char *test, int fd) { ssize_t len; char ch; ch = 0; len = write(fd, &ch, 0); if (len < 0) err(-1, "%s: try_0write", test); if (len != 0) errx(-1, "%s: try_0write: returned %zd", test, len); } static void setup_udp(const char *test, int *fdp) { struct sockaddr_in sin; int sock1, sock2; bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = htons(PORT1); sock1 = socket(PF_INET, SOCK_DGRAM, 0); if (sock1 < 0) err(-1, "%s: setup_udp: socket", test); if (bind(sock1, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "%s: setup_udp: bind(%s, %d)", test, inet_ntoa(sin.sin_addr), PORT1); sin.sin_port = htons(PORT2); if (connect(sock1, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "%s: setup_udp: connect(%s, %d)", test, inet_ntoa(sin.sin_addr), PORT2); sock2 = socket(PF_INET, SOCK_DGRAM, 0); if (sock2 < 0) err(-1, "%s: setup_udp: socket", test); if (bind(sock2, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "%s: setup_udp: bind(%s, %d)", test, inet_ntoa(sin.sin_addr), PORT2); sin.sin_port = htons(PORT1); if (connect(sock2, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "%s: setup_udp: connect(%s, %d)", test, inet_ntoa(sin.sin_addr), PORT1); fdp[0] = sock1; fdp[1] = sock2; } static void setup_tcp(const char *test, int *fdp) { fd_set writefds, exceptfds; struct sockaddr_in sin; int ret, sock1, sock2, sock3; struct timeval tv; bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* * First set up the listen socket. */ sin.sin_port = htons(PORT1); sock1 = socket(PF_INET, SOCK_STREAM, 0); if (sock1 < 0) err(-1, "%s: setup_tcp: socket", test); if (bind(sock1, (struct sockaddr *)&sin, sizeof(sin)) < 0) err(-1, "%s: bind(%s, %d)", test, inet_ntoa(sin.sin_addr), PORT1); if (listen(sock1, -1) < 0) err(-1, "%s: listen", test); /* * Now connect to it, non-blocking so that we don't deadlock against * ourselves. */ sock2 = socket(PF_INET, SOCK_STREAM, 0); if (sock2 < 0) err(-1, "%s: setup_tcp: socket", test); if (fcntl(sock2, F_SETFL, O_NONBLOCK) < 0) err(-1, "%s: setup_tcp: fcntl(O_NONBLOCK)", test); if (connect(sock2, (struct sockaddr *)&sin, sizeof(sin)) < 0 && errno != EINPROGRESS) err(-1, "%s: setup_tcp: connect(%s, %d)", test, inet_ntoa(sin.sin_addr), PORT1); /* * Now pick up the connection after sleeping a moment to make sure * there's been time for some packets to go back and forth. */ if (sleep(1) < 0) err(-1, "%s: sleep(1)", test); sock3 = accept(sock1, NULL, NULL); if (sock3 < 0) err(-1, "%s: accept", test); if (sleep(1) < 0) err(-1, "%s: sleep(1)", test); FD_ZERO(&writefds); FD_SET(sock2, &writefds); FD_ZERO(&exceptfds); FD_SET(sock2, &exceptfds); tv.tv_sec = 1; tv.tv_usec = 0; ret = select(sock2 + 1, NULL, &writefds, &exceptfds, &tv); if (ret < 0) err(-1, "%s: setup_tcp: select", test); if (FD_ISSET(sock2, &exceptfds)) errx(-1, "%s: setup_tcp: select: exception", test); if (!FD_ISSET(sock2, &writefds)) errx(-1, "%s: setup_tcp: select: not writable", test); close(sock1); fdp[0] = sock2; fdp[1] = sock3; } static void setup_udsstream(const char *test, int *fdp) { if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fdp) < 0) err(-1, "%s: setup_udsstream: socketpair", test); } static void setup_udsdgram(const char *test, int *fdp) { if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fdp) < 0) err(-1, "%s: setup_udsdgram: socketpair", test); } static void setup_pipe(const char *test, int *fdp) { if (pipe(fdp) < 0) err(-1, "%s: setup_pipe: pipe", test); } static void setup_fifo(const char *test, int *fdp) { - char path[PATH_MAX]; + char path[] = "0send_fifo.XXXXXXX"; int fd1, fd2; - strcpy(path, "/tmp/0send_fifo.XXXXXXX"); - if (mktemp(path) == NULL) + if (mkstemp(path) == -1) err(-1, "%s: setup_fifo: mktemp", test); + unlink(path); if (mkfifo(path, 0600) < 0) err(-1, "%s: setup_fifo: mkfifo(%s)", test, path); fd1 = open(path, O_RDONLY | O_NONBLOCK); if (fd1 < 0) err(-1, "%s: setup_fifo: open(%s, O_RDONLY)", test, path); fd2 = open(path, O_WRONLY | O_NONBLOCK); if (fd2 < 0) err(-1, "%s: setup_fifo: open(%s, O_WRONLY)", test, path); fdp[0] = fd2; fdp[1] = fd1; } static void close_both(int *fdp) { close(fdp[0]); fdp[0] = -1; close(fdp[1]); fdp[1] = -1; } int main(int argc, char *argv[]) { int fd[2]; setup_udp("udp_0send", fd); try_0send("udp_0send", fd[0]); close_both(fd); setup_udp("udp_0write", fd); try_0write("udp_0write", fd[0]); close_both(fd); setup_tcp("tcp_0send", fd); try_0send("tcp_0send", fd[0]); close_both(fd); setup_tcp("tcp_0write", fd); try_0write("tcp_0write", fd[0]); close_both(fd); setup_udsstream("udsstream_0send", fd); try_0send("udsstream_0send", fd[0]); close_both(fd); setup_udsstream("udsstream_0write", fd); try_0write("udsstream_0write", fd[0]); close_both(fd); setup_udsdgram("udsdgram_0send", fd); try_0send("udsdgram_0send", fd[0]); close_both(fd); setup_udsdgram("udsdgram_0write", fd); try_0write("udsdgram_0write", fd[0]); close_both(fd); setup_pipe("pipe_0write", fd); try_0write("pipd_0write", fd[0]); close_both(fd); setup_fifo("fifo_0write", fd); try_0write("fifo_0write", fd[0]); close_both(fd); return (0); } Index: stable/10 =================================================================== --- stable/10 (revision 281973) +++ stable/10 (revision 281974) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r261550,281354-281356,281358-281362,281391-281395,281397-281404,281407-281411