Date: Sat, 11 Apr 2015 08:57:32 +0000 (UTC) From: Garrett Cooper <ngie@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r281424 - in user/ngie/more-tests: etc/mtree tests/sys/sockets tests/sys/sockets/accept_fd_leak tests/sys/sockets/accf_data_attach tests/sys/sockets/fstat tests/sys/sockets/kqueue tests... Message-ID: <201504110857.t3B8vWI4087015@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ngie Date: Sat Apr 11 08:57:31 2015 New Revision: 281424 URL: https://svnweb.freebsd.org/changeset/base/281424 Log: Start integrating tools/regression/sockets into tests/sys/sockets Added: user/ngie/more-tests/tests/sys/sockets/ - copied from r281415, user/ngie/more-tests/tools/regression/sockets/ user/ngie/more-tests/tests/sys/sockets/Makefile (contents, props changed) user/ngie/more-tests/tests/sys/sockets/README.unix_cmsg - copied unchanged from r281404, head/tools/regression/sockets/unix_cmsg/README user/ngie/more-tests/tests/sys/sockets/accept_fd_leak_test.c - copied unchanged from r281415, user/ngie/more-tests/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c user/ngie/more-tests/tests/sys/sockets/accf_data_attach_test.c - copied unchanged from r281404, head/tools/regression/sockets/accf_data_attach/accf_data_attach.c user/ngie/more-tests/tests/sys/sockets/fstat_test.c - copied unchanged from r281404, head/tools/regression/sockets/fstat/fstat.c user/ngie/more-tests/tests/sys/sockets/kqueue_test.c - copied unchanged from r281404, head/tools/regression/sockets/kqueue/kqueue.c user/ngie/more-tests/tests/sys/sockets/listen_backlog_test.c - copied unchanged from r281404, head/tools/regression/sockets/listen_backlog/listen_backlog.c user/ngie/more-tests/tests/sys/sockets/listenclose_test.c - copied unchanged from r281404, head/tools/regression/sockets/listenclose/listenclose.c user/ngie/more-tests/tests/sys/sockets/pr_atomic_test.c - copied unchanged from r281409, head/tools/regression/sockets/pr_atomic/pr_atomic.c user/ngie/more-tests/tests/sys/sockets/reconnect_test.c - copied unchanged from r281411, head/tools/regression/sockets/reconnect/reconnect.c user/ngie/more-tests/tests/sys/sockets/rtsocket_test.c - copied unchanged from r281404, head/tools/regression/sockets/rtsocket/rtsocket.c user/ngie/more-tests/tests/sys/sockets/sblock_test.c - copied unchanged from r281404, head/tools/regression/sockets/sblock/sblock.c user/ngie/more-tests/tests/sys/sockets/sendfile_test.c - copied unchanged from r281404, head/tools/regression/sockets/sendfile/sendfile.c user/ngie/more-tests/tests/sys/sockets/shutdown_test.c - copied unchanged from r281404, head/tools/regression/sockets/shutdown/shutdown.c user/ngie/more-tests/tests/sys/sockets/sigpipe_test.c - copied unchanged from r281404, head/tools/regression/sockets/sigpipe/sigpipe.c user/ngie/more-tests/tests/sys/sockets/so_setfib_test.c - copied unchanged from r281408, head/tools/regression/sockets/so_setfib/so_setfib.c user/ngie/more-tests/tests/sys/sockets/socketpair_test.c - copied unchanged from r281404, head/tools/regression/sockets/socketpair/socketpair.c user/ngie/more-tests/tests/sys/sockets/unix_bindconnect_test.c - copied unchanged from r281404, head/tools/regression/sockets/unix_bindconnect/unix_bindconnect.c user/ngie/more-tests/tests/sys/sockets/unix_close_race_test.c - copied unchanged from r281404, head/tools/regression/sockets/unix_close_race/unix_close_race.c user/ngie/more-tests/tests/sys/sockets/unix_cmsg.c - copied unchanged from r281404, head/tools/regression/sockets/unix_cmsg/unix_cmsg.c user/ngie/more-tests/tests/sys/sockets/unix_cmsg_test.sh - copied, changed from r281404, head/tools/regression/sockets/unix_cmsg/unix_cmsg.t user/ngie/more-tests/tests/sys/sockets/unix_gc_test.c - copied unchanged from r281404, head/tools/regression/sockets/unix_gc/unix_gc.c user/ngie/more-tests/tests/sys/sockets/unix_passfd_test.c - copied unchanged from r281404, head/tools/regression/sockets/unix_passfd/unix_passfd.c user/ngie/more-tests/tests/sys/sockets/unix_sendtorace_test.c - copied unchanged from r281404, head/tools/regression/sockets/unix_sendtorace/unix_sendtorace.c user/ngie/more-tests/tests/sys/sockets/unix_socket_test.c - copied unchanged from r281404, head/tools/regression/sockets/unix_socket/unix_socket.c user/ngie/more-tests/tests/sys/sockets/unix_sorflush_test.c - copied unchanged from r281404, head/tools/regression/sockets/unix_sorflush/unix_sorflush.c user/ngie/more-tests/tests/sys/sockets/zerosend_test.c - copied unchanged from r281404, head/tools/regression/sockets/zerosend/zerosend.c Deleted: user/ngie/more-tests/tests/sys/sockets/accept_fd_leak/ user/ngie/more-tests/tests/sys/sockets/accf_data_attach/ user/ngie/more-tests/tests/sys/sockets/fstat/ user/ngie/more-tests/tests/sys/sockets/kqueue/ user/ngie/more-tests/tests/sys/sockets/listen_backlog/ user/ngie/more-tests/tests/sys/sockets/listenclose/ user/ngie/more-tests/tests/sys/sockets/pr_atomic/ user/ngie/more-tests/tests/sys/sockets/reconnect/ user/ngie/more-tests/tests/sys/sockets/rtsocket/ user/ngie/more-tests/tests/sys/sockets/sblock/ user/ngie/more-tests/tests/sys/sockets/sendfile/ user/ngie/more-tests/tests/sys/sockets/shutdown/ user/ngie/more-tests/tests/sys/sockets/sigpipe/ user/ngie/more-tests/tests/sys/sockets/so_setfib/ user/ngie/more-tests/tests/sys/sockets/socketpair/ user/ngie/more-tests/tests/sys/sockets/unix_bindconnect/ user/ngie/more-tests/tests/sys/sockets/unix_close_race/ user/ngie/more-tests/tests/sys/sockets/unix_cmsg/ user/ngie/more-tests/tests/sys/sockets/unix_gc/ user/ngie/more-tests/tests/sys/sockets/unix_passfd/ user/ngie/more-tests/tests/sys/sockets/unix_sendtorace/ user/ngie/more-tests/tests/sys/sockets/unix_socket/ user/ngie/more-tests/tests/sys/sockets/unix_sorflush/ user/ngie/more-tests/tests/sys/sockets/zerosend/ user/ngie/more-tests/tools/regression/sockets/ Modified: user/ngie/more-tests/etc/mtree/BSD.tests.dist Modified: user/ngie/more-tests/etc/mtree/BSD.tests.dist ============================================================================== --- user/ngie/more-tests/etc/mtree/BSD.tests.dist Sat Apr 11 08:55:56 2015 (r281423) +++ user/ngie/more-tests/etc/mtree/BSD.tests.dist Sat Apr 11 08:57:31 2015 (r281424) @@ -392,6 +392,8 @@ unlink .. .. + socket + .. .. usr.bin apply Added: user/ngie/more-tests/tests/sys/sockets/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ngie/more-tests/tests/sys/sockets/Makefile Sat Apr 11 08:57:31 2015 (r281424) @@ -0,0 +1,54 @@ +# $FreeBSD$ +# +# Some of these tests fail on 11.0-CURRENT @ r280355 with DEBUG bits on + +TESTSDIR= ${TESTSBASE}/sys/socket + +BINDIR= ${TESTSDIR} + +PROGS+= unix_cmsg + +TAP_TESTS_C+= accept_fd_leak_test +# accf_data_attach: not ok 9 - setsockopt() after listen() failed with 2 (No such file or directory) +TAP_TESTS_C+= accf_data_attach_test +PLAIN_TESTS_C+= fstat_test +PLAIN_TESTS_C+= kqueue_test +PLAIN_TESTS_C+= listen_backlog_test +PLAIN_TESTS_C+= listenclose_test +PLAIN_TESTS_C+= pr_atomic_test +PLAIN_TESTS_C+= reconnect_test +# rtsocket: socket(PF_ROUTE, SOCK_STREAM, 0): Protocol wrong type for socket +PLAIN_TESTS_C+= rtsocket_test +PLAIN_TESTS_C+= sblock_test +TAP_TESTS_C+= sendfile_test +PLAIN_TESTS_C+= shutdown_test +PLAIN_TESTS_C+= sigpipe_test +TAP_TESTS_C+= so_setfib_test +PLAIN_TESTS_C+= socketpair_test +PLAIN_TESTS_C+= unix_bindconnect_test +PLAIN_TESTS_C+= unix_close_race_test +# Lots of failures +TAP_TESTS_SH+= unix_cmsg_test +# unix_gc: twosome_drop1: sendfd: before 0 after 0 +PLAIN_TESTS_C+= unix_gc_test +# unix_passfd: test8-rights+creds+payload: recvmsg: 24 bytes received +PLAIN_TESTS_C+= unix_passfd_test +PLAIN_TESTS_C+= unix_sendtorace_test +# unix_socket: socket(PF_LOCAL, SOCK_RAW, 0): Protocol wrong type for socket +PLAIN_TESTS_C+= unix_socket_test +PLAIN_TESTS_C+= unix_sorflush_test +# zerosend: tcp_0write: bind(127.0.0.1, 10001): Address already in use +PLAIN_TESTS_C+= zerosend_test + +DPADD.sendfile_test+= ${LIBMD} +LDADD.sendfile_test+= -lmd + +# XXX: this doesn't work..? +#WARNS.unix_cmsg= 3 +#WARNS.unix_gc= 3 +#WARNS.unix_passfd= 3 +#WARNS.zerosend= 2 + +WARNS= 2 + +.include <bsd.test.mk> Copied: user/ngie/more-tests/tests/sys/sockets/README.unix_cmsg (from r281404, head/tools/regression/sockets/unix_cmsg/README) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ngie/more-tests/tests/sys/sockets/README.unix_cmsg Sat Apr 11 08:57:31 2015 (r281424, copy of r281404, head/tools/regression/sockets/unix_cmsg/README) @@ -0,0 +1,160 @@ +$FreeBSD$ + +About unix_cmsg +=============== + +This program is a collection of regression tests for ancillary data +(control information) for PF_LOCAL sockets (local domain or Unix domain +sockets). There are tests for stream and datagram sockets. + +Usually each test does following steps: creates Server, forks Client, +Client sends something to Server, Server verifies whether everything is +correct in received message(s). + +It is better to change the owner of unix_cmsg to some safe user +(eg. nobody:nogroup) and set SUID and SGID bits, else some tests that +check credentials can give correct results for wrong implementation. + +It is better to run this program by a user that belongs to more +than 16 groups. + +Available options +================= + +usage: unix_cmsg [-dh] [-n num] [-s size] [-t type] [-z value] [testno] + + Options are: + -d Output debugging information + -h Output the help message and exit + -n num Number of messages to send + -s size Specify size of data for IPC + -t type Specify socket type (stream, dgram) for tests + -z value Do not send data in a message (bit 0x1), do not send + data array associated with a cmsghdr structure (bit 0x2) + testno Run one test by its number (require the -t option) + +Description +=========== + +If Client sends something to Server, then it sends 5 messages by default. +Number of messages can be changed in the -n command line option. Number +of messages will be given as N in the following descriptions. + +If Client sends something to Server, then it sends some data (few bytes) +in each message by default. The size of this data can be changed by the -s +command line option. The "-s 0" command line option means, that Client will +send zero bytes represented by { NULL, 0 } value of struct iovec{}, referenced +by the msg_iov field from struct msghdr{}. The "-z 1" or "-z 3" command line +option means, that Client will send zero bytes represented by the NULL value +in the msg_iov field from struct msghdr{}. + +If Client sends some ancillary data object, then this ancillary data object +always has associated data array by default. The "-z 2" or "-z 3" option +means, that Client will not send associated data array if possible. + +For SOCK_STREAM sockets: +----------------------- + + 1: Sending, receiving cmsgcred + + Client connects to Server and sends N messages with SCM_CREDS ancillary + data object. Server should receive N messages, each message should + have SCM_CREDS ancillary data object followed by struct cmsgcred{}. + + 2: Receiving sockcred (listening socket) + + Server creates a listening stream socket and sets the LOCAL_CREDS + socket option for it. Client connects to Server two times, each time + it sends N messages. Server accepts two connections and receives N + messages from each connection. The first message from each connection + should have SCM_CREDS ancillary data object followed by struct sockcred{}, + next messages from the same connection should not have ancillary data. + + 3: Receiving sockcred (accepted socket) + + Client connects to Server. Server accepts connection and sets the + LOCAL_CREDS socket option for just accepted socket. Client sends N + messages to Server. Server should receive N messages, the first + message should have SCM_CREDS ancillary data object followed by + struct sockcred{}, next messages should not have ancillary data. + + 4: Sending cmsgcred, receiving sockcred + + Server creates a listening stream socket and sets the LOCAL_CREDS + socket option for it. Client connects to Server and sends N messages + with SCM_CREDS ancillary data object. Server should receive N messages, + the first message should have SCM_CREDS ancillary data object followed + by struct sockcred{}, each of next messages should have SCM_CREDS + ancillary data object followed by struct cmsgcred{}. + + 5: Sending, receiving timeval + + Client connects to Server and sends message with SCM_TIMESTAMP ancillary + data object. Server should receive one message with SCM_TIMESTAMP + ancillary data object followed by struct timeval{}. + + 6: Sending, receiving bintime + + Client connects to Server and sends message with SCM_BINTIME ancillary + data object. Server should receive one message with SCM_BINTIME + ancillary data object followed by struct bintime{}. + + 7: Checking cmsghdr.cmsg_len + + Client connects to Server and tries to send several messages with + SCM_CREDS ancillary data object that has wrong cmsg_len field in its + struct cmsghdr{}. All these attempts should fail, since cmsg_len + in all requests is less than CMSG_LEN(0). + + 8: Check LOCAL_PEERCRED socket option + + This test does not use ancillary data, but can be implemented here. + Client connects to Server. Both Client and Server verify that + credentials of the peer are correct using LOCAL_PEERCRED socket option. + +For SOCK_DGRAM sockets: +---------------------- + + 1: Sending, receiving cmsgcred + + Client connects to Server and sends N messages with SCM_CREDS ancillary + data object. Server should receive N messages, each message should + have SCM_CREDS ancillary data object followed by struct cmsgcred{}. + + 2: Receiving sockcred + + Server creates datagram socket and sets the LOCAL_CREDS socket option + for it. Client sends N messages to Server. Server should receive N + messages, each message should have SCM_CREDS ancillary data object + followed by struct sockcred{}. + + 3: Sending cmsgcred, receiving sockcred + + Server creates datagram socket and sets the LOCAL_CREDS socket option + for it. Client sends N messages with SCM_CREDS ancillary data object + to Server. Server should receive N messages, the first message should + have SCM_CREDS ancillary data object followed by struct sockcred{}, + each of next messages should have SCM_CREDS ancillary data object + followed by struct cmsgcred{}. + + 4: Sending, receiving timeval + + Client sends one message with SCM_TIMESTAMP ancillary data object + to Server. Server should receive one message with SCM_TIMESTAMP + ancillary data object followed by struct timeval{}. + + 5: Sending, receiving bintime + + Client sends one message with SCM_BINTIME ancillary data object + to Server. Server should receive one message with SCM_BINTIME + ancillary data object followed by struct bintime{}. + + 6: Checking cmsghdr.cmsg_len + + Client tries to send Server several messages with SCM_CREDS ancillary + data object that has wrong cmsg_len field in its struct cmsghdr{}. + All these attempts should fail, since cmsg_len in all requests is less + than CMSG_LEN(0). + +- Andrey Simonenko +andreysimonenko@users.sourceforge.net Copied: user/ngie/more-tests/tests/sys/sockets/accept_fd_leak_test.c (from r281415, user/ngie/more-tests/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ngie/more-tests/tests/sys/sockets/accept_fd_leak_test.c Sat Apr 11 08:57:31 2015 (r281424, copy of r281415, user/ngie/more-tests/tools/regression/sockets/accept_fd_leak/accept_fd_leak.c) @@ -0,0 +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 <sys/param.h> +#include <sys/socket.h> +#include <sys/wait.h> + +#include <netinet/in.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define BIND_ATTEMPTS 10 +#define LOOPS 500 +#define NUM_ATTEMPTS 1000 + +static volatile int quit; + +static void +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(void) +{ + struct sockaddr_in sin; + socklen_t size; + pid_t child; + 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); + + 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 `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(listen_port); + + 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); + } + + /* 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 `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); +} Copied: user/ngie/more-tests/tests/sys/sockets/accf_data_attach_test.c (from r281404, head/tools/regression/sockets/accf_data_attach/accf_data_attach.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ngie/more-tests/tests/sys/sockets/accf_data_attach_test.c Sat Apr 11 08:57:31 2015 (r281424, copy of r281404, head/tools/regression/sockets/accf_data_attach/accf_data_attach.c) @@ -0,0 +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 <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> + +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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(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); +} Copied: user/ngie/more-tests/tests/sys/sockets/fstat_test.c (from r281404, head/tools/regression/sockets/fstat/fstat.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ngie/more-tests/tests/sys/sockets/fstat_test.c Sat Apr 11 08:57:31 2015 (r281424, copy of r281404, head/tools/regression/sockets/fstat/fstat.c) @@ -0,0 +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 <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <err.h> +#include <unistd.h> + +/* + * 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(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); +} Copied: user/ngie/more-tests/tests/sys/sockets/kqueue_test.c (from r281404, head/tools/regression/sockets/kqueue/kqueue.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ngie/more-tests/tests/sys/sockets/kqueue_test.c Sat Apr 11 08:57:31 2015 (r281424, copy of r281404, head/tools/regression/sockets/kqueue/kqueue.c) @@ -0,0 +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 <sys/types.h> +#include <sys/event.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +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(void) +{ + int kq, sv[2]; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504110857.t3B8vWI4087015>