/* * Copyright (c) 2013 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 * 82178 Puchheim * Germany * * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TEST_NAME "LIBBSD SYSCALLS 1" typedef void (*no_mem_test_body)(int fd); typedef struct { no_mem_test_body body; int fd; rtems_id master_task; } no_mem_test; typedef struct { int domain; int type; int protocol; int expect_errno; } socket_test; static socket_test socket_tests[] = { { -1, SOCK_RAW, 0, EAFNOSUPPORT }, { PF_UNSPEC, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_UNIX, SOCK_STREAM, 0, 0 }, { PF_UNIX, SOCK_DGRAM, 0, 0 }, { PF_UNIX, SOCK_SEQPACKET, 0, 0 }, { PF_INET, -1, 0, EPROTOTYPE }, { PF_INET, SOCK_RAW, -1, EPROTONOSUPPORT }, { PF_INET, SOCK_STREAM, 0, 0 }, { PF_INET, SOCK_DGRAM, 0, 0 }, { PF_INET, SOCK_SEQPACKET, 0, EPROTOTYPE }, { PF_INET, SOCK_RAW, IPPROTO_3PC, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ADFS, 0 }, { PF_INET, SOCK_RAW, IPPROTO_AH, 0 }, { PF_INET, SOCK_RAW, IPPROTO_AHIP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_APES, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ARGUS, 0 }, { PF_INET, SOCK_RAW, IPPROTO_AX25, 0 }, { PF_INET, SOCK_RAW, IPPROTO_BHA, 0 }, { PF_INET, SOCK_RAW, IPPROTO_BLT, 0 }, { PF_INET, SOCK_RAW, IPPROTO_BRSATMON, 0 }, { PF_INET, SOCK_RAW, IPPROTO_CARP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_CFTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_CHAOS, 0 }, { PF_INET, SOCK_RAW, IPPROTO_CMTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_CPHB, 0 }, { PF_INET, SOCK_RAW, IPPROTO_CPNX, 0 }, { PF_INET, SOCK_RAW, IPPROTO_DDP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_DGP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_DSTOPTS, 0 }, { PF_INET, SOCK_RAW, IPPROTO_EGP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_EMCON, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ENCAP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_EON, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ESP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ETHERIP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_FRAGMENT, 0 }, { PF_INET, SOCK_RAW, IPPROTO_GGP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_GMTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_GRE, 0 }, { PF_INET, SOCK_RAW, IPPROTO_HELLO, 0 }, { PF_INET, SOCK_RAW, IPPROTO_HMP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ICMP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ICMPV6, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IDP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IDPR, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IDRP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IGMP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IGP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IGRP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IL, 0 }, { PF_INET, SOCK_RAW, IPPROTO_INLSP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_INP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IPCOMP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IPCV, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IPEIP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IPIP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IPPC, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IPV4, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IPV6, 0 }, { PF_INET, SOCK_RAW, IPPROTO_IRTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_KRYPTOLAN, 0 }, { PF_INET, SOCK_RAW, IPPROTO_LARP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_LEAF1, 0 }, { PF_INET, SOCK_RAW, IPPROTO_LEAF2, 0 }, { PF_INET, SOCK_RAW, IPPROTO_MEAS, 0 }, { PF_INET, SOCK_RAW, IPPROTO_MHRP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_MICP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_MOBILE, 0 }, { PF_INET, SOCK_RAW, IPPROTO_MTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_MUX, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ND, 0 }, { PF_INET, SOCK_RAW, IPPROTO_NHRP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_NONE, 0 }, { PF_INET, SOCK_RAW, IPPROTO_NSP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_NVPII, 0 }, { PF_INET, SOCK_RAW, IPPROTO_OLD_DIVERT, 0 }, { PF_INET, SOCK_RAW, IPPROTO_OSPFIGP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_PFSYNC, 0 }, { PF_INET, SOCK_RAW, IPPROTO_PGM, 0 }, { PF_INET, SOCK_RAW, IPPROTO_PIGP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_PIM, 0 }, { PF_INET, SOCK_RAW, IPPROTO_PRM, 0 }, { PF_INET, SOCK_RAW, IPPROTO_PUP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_PVP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_RCCMON, 0 }, { PF_INET, SOCK_RAW, IPPROTO_RDP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ROUTING, 0 }, { PF_INET, SOCK_RAW, IPPROTO_RSVP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_RVD, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SATEXPAK, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SATMON, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SCCSP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SCTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SDRP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SEP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SKIP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SRPC, 0 }, { PF_INET, SOCK_RAW, IPPROTO_ST, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SVMTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_SWIPE, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TCF, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TCP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TLSP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TPXX, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TRUNK1, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TRUNK2, 0 }, { PF_INET, SOCK_RAW, IPPROTO_TTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_UDP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_VINES, 0 }, { PF_INET, SOCK_RAW, IPPROTO_VISA, 0 }, { PF_INET, SOCK_RAW, IPPROTO_VMTP, 0 }, { PF_INET, SOCK_RAW, IPPROTO_WBEXPAK, 0 }, { PF_INET, SOCK_RAW, IPPROTO_WBMON, 0 }, { PF_INET, SOCK_RAW, IPPROTO_WSN, 0 }, { PF_INET, SOCK_RAW, IPPROTO_XNET, 0 }, { PF_INET, SOCK_RAW, IPPROTO_XTP, 0 }, { PF_IMPLINK, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_PUP, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_CHAOS, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_NETBIOS, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_ISO, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_ECMA, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_DATAKIT, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_CCITT, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_SNA, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_DECnet, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_DLI, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_LAT, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_HYLINK, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_APPLETALK, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_ROUTE, SOCK_DGRAM, 0, EPROTOTYPE }, { PF_LINK, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_XTP, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_COIP, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_CNT, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_RTIP, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_IPX, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_SIP, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_PIP, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_ISDN, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_KEY, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_INET6, SOCK_DGRAM, 0, 0 }, { PF_NATM, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_ATM, SOCK_DGRAM, 0, EAFNOSUPPORT }, { pseudo_AF_HDRCMPLT, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_NETGRAPH, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_SLOW, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_SCLUSTER, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_ARP, SOCK_DGRAM, 0, EAFNOSUPPORT }, { PF_BLUETOOTH, SOCK_DGRAM, 0, EAFNOSUPPORT }, { AF_IEEE80211, SOCK_DGRAM, 0, EAFNOSUPPORT } }; static void init_addr(struct sockaddr_in *addr) { int ok; memset(addr, 0, sizeof(*addr)); addr->sin_family = AF_INET; addr->sin_port = htons(1234); ok = inet_aton("127.0.0.1", &addr->sin_addr); assert(ok != 0); } static void init_msg(struct msghdr *msg, struct sockaddr_in *addr, struct iovec *iov, void *buf, size_t n) { memset(msg, 0, sizeof(*msg)); memset(iov, 0, sizeof(*iov)); iov->iov_base = buf; iov->iov_len = n; msg->msg_name = addr; msg->msg_namelen = sizeof(*addr); msg->msg_iov = iov; msg->msg_iovlen = 1; } static void no_mem_task(rtems_task_argument arg) { const no_mem_test *self = (const no_mem_test *) arg; rtems_status_code sc; void *greedy; assert(rtems_configuration_get_unified_work_area()); greedy = rtems_workspace_greedy_allocate(NULL, 0); (*self->body)(self->fd); rtems_workspace_greedy_free(greedy); sc = rtems_event_transient_send(self->master_task); assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_suspend(RTEMS_SELF); assert(sc == RTEMS_SUCCESSFUL); } static void do_no_mem_test(no_mem_test_body body, int fd) { no_mem_test test = { .body = body, .fd = fd, .master_task = rtems_task_self() }; rtems_status_code sc; rtems_id id; rtems_resource_snapshot snapshot; rtems_resource_snapshot_take(&snapshot); sc = rtems_task_create( rtems_build_name('N', 'M', 'E', 'M'), RTEMS_MINIMUM_PRIORITY, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_FLOATING_POINT, &id ); assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start(id, no_mem_task, (rtems_task_argument) &test); assert(sc == RTEMS_SUCCESSFUL); sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_delete(id); assert(sc == RTEMS_SUCCESSFUL); assert(rtems_resource_snapshot_check(&snapshot)); } static void test_socket(const socket_test *st) { int sd; int rv; errno = 0; sd = socket(st->domain, st->type, st->protocol); if (st->expect_errno == 0) { assert(sd >= 0); rv = close(sd); assert(rv == 0); } else { assert(st->expect_errno == errno); } } static void test_sockets(void) { size_t n = sizeof(socket_tests) / sizeof(socket_tests[0]); size_t i; puts("test sockets"); for (i = 0; i < n; ++i) { const socket_test *st = &socket_tests[i]; test_socket(st); } puts("test sockets and check resources"); for (i = 0; i < n; ++i) { const socket_test *st = &socket_tests[i]; rtems_resource_snapshot snapshot; rtems_resource_snapshot_take(&snapshot); test_socket(st); assert(rtems_resource_snapshot_check(&snapshot)); } } static void test_socket_unsupported_ops(void) { rtems_resource_snapshot snapshot; int sd; int rv; off_t off; puts("test socket unsupported ops"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); errno = 0; off = lseek(sd, 0, SEEK_CUR); assert(off == -1); assert(errno == ESPIPE); errno = 0; rv = ftruncate(sd, 0); assert(rv == -1); assert(errno == EINVAL); errno = 0; rv = fsync(sd); assert(rv == -1); assert(errno == EINVAL); errno = 0; rv = fdatasync(sd); assert(rv == -1); assert(errno == EINVAL); rv = close(sd); assert(rv == 0); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_fstat(int fd) { struct stat st; int rv; rv = fstat(fd, &st); assert(rv == 0); } static void no_mem_socket_shutdown(int fd) { int rv; rv = shutdown(fd, SHUT_RDWR); assert(rv == 0); } static void test_socket_fstat_and_shutdown(void) { mode_t canrecv = S_IRUSR | S_IRGRP | S_IROTH; mode_t cansend = S_IWUSR | S_IWGRP | S_IWOTH; rtems_resource_snapshot snapshot; struct stat st; int sd; int rv; puts("test socket fstat and shutdown"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_fstat, sd); rv = fstat(sd, &st); assert(rv == 0); assert(st.st_mode == (S_IFSOCK | canrecv | cansend)); rv = shutdown(sd, SHUT_RD); assert(rv == 0); rv = fstat(sd, &st); assert(rv == 0); assert(st.st_mode == (S_IFSOCK | cansend)); rv = shutdown(sd, SHUT_WR); assert(rv == 0); rv = fstat(sd, &st); assert(rv == 0); assert(st.st_mode == S_IFSOCK); errno = 0; rv = shutdown(sd, ~SHUT_RDWR); assert(rv == -1); assert(errno == EINVAL); rv = close(sd); assert(rv == 0); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_shutdown, sd); rv = close(sd); assert(rv == 0); errno = 0; rv = shutdown(sd, SHUT_RDWR); assert(rv == -1); assert(errno == EBADF); errno = 0; rv = shutdown(0, SHUT_RDWR); assert(rv == -1); assert(errno == ENOTSOCK); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_ioctl(int fd) { int rv; int data; errno = 0; rv = ioctl(fd, FIONREAD, &data); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_ioctl(void) { rtems_resource_snapshot snapshot; int sd; int rv; int data; puts("test socket ioctl"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_ioctl, sd); errno = 0; rv = ioctl(sd, 0xffffffff); assert(rv == -1); assert(errno == EADDRNOTAVAIL); data = -1; rv = ioctl(sd, FIONREAD, &data); assert(rv == 0); assert(data == 0); rv = close(sd); assert(rv == 0); errno = 0; rv = ioctl(sd, 0); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_bind(int fd) { struct sockaddr_in addr; int rv; errno = 0; rv = bind(fd, (const struct sockaddr *) &addr, sizeof(addr)); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_bind(void) { rtems_resource_snapshot snapshot; struct sockaddr_in addr; int sd; int rv; puts("test socket bind"); rtems_resource_snapshot_take(&snapshot); init_addr(&addr); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_bind, sd); errno = 0; rv = bind(sd, (const struct sockaddr *) &addr, SOCK_MAXADDRLEN + 1); assert(rv == -1); assert(errno == ENAMETOOLONG); errno = 0; rv = bind(sd, (const struct sockaddr *) &addr, 0); assert(rv == -1); assert(errno == EINVAL); errno = 0; rv = bind(sd, (const struct sockaddr *) &addr, sizeof(addr)); assert(rv == -1); assert(errno == EADDRNOTAVAIL); rv = close(sd); assert(rv == 0); errno = 0; rv = bind(sd, (struct sockaddr *) &addr, sizeof(addr)); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_connect(int fd) { struct sockaddr_in addr; int rv; errno = 0; rv = connect(fd, (const struct sockaddr *) &addr, sizeof(addr)); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_connect(void) { rtems_resource_snapshot snapshot; struct sockaddr_in addr; int sd; int rv; puts("test socket connect"); rtems_resource_snapshot_take(&snapshot); init_addr(&addr); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_connect, sd); errno = 0; rv = connect(sd, (const struct sockaddr *) &addr, SOCK_MAXADDRLEN + 1); assert(rv == -1); assert(errno == ENAMETOOLONG); errno = 0; rv = connect(sd, (const struct sockaddr *) &addr, 0); assert(rv == -1); assert(errno == EINVAL); errno = 0; rv = connect(sd, (const struct sockaddr *) &addr, sizeof(addr)); assert(rv == -1); assert(errno == ENETUNREACH); rv = close(sd); assert(rv == 0); errno = 0; rv = connect(sd, (struct sockaddr *) &addr, sizeof(addr)); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_listen(int fd) { int rv; errno = 0; rv = listen(fd, 0); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_listen(void) { rtems_resource_snapshot snapshot; int sd; int rv; puts("test socket listen"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_listen, sd); errno = 0; rv = listen(sd, 0); assert(rv == -1); assert(errno == EOPNOTSUPP); rv = close(sd); assert(rv == 0); errno = 0; rv = listen(sd, 0); assert(rv == -1); assert(errno == EBADF); sd = socket(PF_INET, SOCK_STREAM, 0); assert(sd >= 0); errno = 0; rv = listen(sd, 0); assert(rv == -1); assert(errno == EADDRNOTAVAIL); rv = close(sd); assert(rv == 0); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_accept(int fd) { struct sockaddr_in addr; socklen_t addr_len; int rv; errno = 0; addr_len = sizeof(addr); rv = accept(fd, (struct sockaddr *) &addr, &addr_len); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_accept(void) { rtems_resource_snapshot snapshot; struct sockaddr_in addr; socklen_t addr_len; int sd; int ad; int rv; puts("test socket accept"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_STREAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_accept, sd); errno = 0; addr_len = sizeof(addr); ad = accept(sd, (struct sockaddr *) &addr, &addr_len); assert(ad == -1); assert(errno == EINVAL); rv = close(sd); assert(rv == 0); errno = 0; addr_len = sizeof(addr); ad = accept(sd, (struct sockaddr *) &addr, &addr_len); assert(ad == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_getsockopt_and_setsockopt(int fd) { int rv; int optval; socklen_t optlen; errno = 0; optlen = sizeof(optval); rv = getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); assert(rv == -1); assert(errno == ENOMEM); errno = 0; optlen = sizeof(optval); rv = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_getsockopt_and_setsockopt(void) { rtems_resource_snapshot snapshot; int optval; socklen_t optlen; int sd; int rv; puts("test socket getsockopt and setsockopt"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_STREAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_getsockopt_and_setsockopt, sd); errno = 0; optlen = sizeof(optval); rv = getsockopt(sd, SOL_SOCKET, -1, &optval, &optlen); assert(rv == -1); assert(errno == ENOPROTOOPT); errno = 0; optlen = sizeof(optval); rv = setsockopt(sd, SOL_SOCKET, -1, &optval, optlen); assert(rv == -1); assert(errno == ENOPROTOOPT); errno = 0; optlen = sizeof(optval); rv = getsockopt(sd, -1, SO_REUSEADDR, &optval, &optlen); assert(rv == -1); assert(errno == EINVAL); errno = 0; optlen = sizeof(optval); rv = setsockopt(sd, -1, SO_REUSEADDR, &optval, optlen); assert(rv == -1); assert(errno == EINVAL); optval = -1; optlen = sizeof(optval); rv = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); assert(rv == 0); assert(optval == 0); assert(optlen == sizeof(optval)); optval = 1; optlen = sizeof(optval); rv = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen); assert(rv == 0); optval = 0; optlen = sizeof(optval); rv = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); assert(rv == 0); assert(optval != 0); assert(optlen == sizeof(optval)); rv = close(sd); assert(rv == 0); errno = 0; optlen = sizeof(optval); rv = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen); assert(rv == -1); assert(errno == EBADF); errno = 0; optval = 0; optlen = sizeof(optval); rv = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_getpeername(int fd) { struct sockaddr_in addr; socklen_t addr_len; int rv; errno = 0; addr_len = sizeof(addr); rv = getpeername(fd, (struct sockaddr *) &addr, &addr_len); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_getpeername(void) { rtems_resource_snapshot snapshot; struct sockaddr_in addr; socklen_t addr_len; int sd; int rv; puts("test socket getpeername"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_STREAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_getpeername, sd); errno = 0; addr_len = sizeof(addr); rv = getpeername(sd, (struct sockaddr *) &addr, &addr_len); assert(rv == -1); assert(errno == ENOTCONN); rv = close(sd); assert(rv == 0); errno = 0; addr_len = sizeof(addr); rv = getpeername(sd, (struct sockaddr *) &addr, &addr_len); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_getsockname(int fd) { struct sockaddr_in addr; socklen_t addr_len; int rv; errno = 0; addr_len = sizeof(addr); rv = getsockname(fd, (struct sockaddr *) &addr, &addr_len); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_getsockname(void) { rtems_resource_snapshot snapshot; struct sockaddr_in addr; struct sockaddr_in expected_addr; socklen_t addr_len; int sd; int rv; puts("test socket getsockname"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_STREAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_getsockname, sd); memset(&addr, 0xff, sizeof(addr)); addr_len = sizeof(addr); rv = getsockname(sd, (struct sockaddr *) &addr, &addr_len); assert(rv == 0); memset(&expected_addr, 0, sizeof(expected_addr)); expected_addr.sin_len = sizeof(expected_addr); expected_addr.sin_family = AF_INET; assert(memcmp(&addr, &expected_addr, sizeof(addr)) == 0); rv = close(sd); assert(rv == 0); errno = 0; addr_len = sizeof(addr); rv = getsockname(sd, (struct sockaddr *) &addr, &addr_len); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_read_and_write(int fd) { ssize_t n; char buf[1]; errno = 0; n = read(fd, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == ENOMEM); errno = 0; n = write(fd, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == ENOMEM); } static void test_socket_read_and_write(void) { rtems_resource_snapshot snapshot; int sd; int rv; ssize_t n; char buf[1]; int enable = 1; puts("test socket read and write"); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); rv = ioctl(sd, FIONBIO, &enable); assert(rv == 0); do_no_mem_test(no_mem_socket_read_and_write, sd); errno = 0; n = read(sd, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == EAGAIN); errno = 0; n = write(sd, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == EDESTADDRREQ); rv = close(sd); assert(rv == 0); errno = 0; n = read(sd, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == EBADF); errno = 0; n = write(sd, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_send_and_sendto_and_sendmsg(int fd) { struct sockaddr_in addr; struct iovec iov; struct msghdr msg; ssize_t n; char buf[1]; init_addr(&addr); init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); errno = 0; n = send(fd, &buf[0], sizeof(buf), 0); assert(n == -1); assert(errno == ENOMEM); errno = 0; n = sendto(fd, &buf[0], sizeof(buf), 0, (const struct sockaddr *) &addr, sizeof(addr)); assert(n == -1); assert(errno == ENOMEM); errno = 0; n = sendmsg(fd, &msg, 0); assert(n == -1); assert(errno == ENOMEM); } static void test_socket_send_and_sendto_and_sendmsg(void) { rtems_resource_snapshot snapshot; struct sockaddr_in addr; struct iovec iov; struct msghdr msg; int sd; int rv; ssize_t n; char buf[1]; puts("test socket send, sendto and sendmsg"); rtems_resource_snapshot_take(&snapshot); init_addr(&addr); init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_send_and_sendto_and_sendmsg, sd); errno = 0; n = send(sd, &buf[0], sizeof(buf), 0); assert(n == -1); assert(errno == EDESTADDRREQ); errno = 0; n = sendto(sd, &buf[0], sizeof(buf), 0, (const struct sockaddr *) &addr, sizeof(addr)); assert(n == -1); assert(errno == ENETUNREACH); errno = 0; n = sendmsg(sd, &msg, 0); assert(n == -1); assert(errno == ENETUNREACH); rv = close(sd); assert(rv == 0); errno = 0; n = send(sd, &buf[0], sizeof(buf), 0); assert(n == -1); assert(errno == EBADF); errno = 0; n = sendto(sd, &buf[0], sizeof(buf), 0, (const struct sockaddr *) &addr, sizeof(addr)); assert(n == -1); assert(errno == EBADF); errno = 0; n = sendmsg(sd, &msg, 0); assert(n == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_recv_and_recvfrom_and_recvmsg(int fd) { struct sockaddr_in addr; socklen_t addr_len; struct iovec iov; struct msghdr msg; ssize_t n; char buf[1]; init_addr(&addr); init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); errno = 0; n = recv(fd, &buf[0], sizeof(buf), 0); assert(n == -1); assert(errno == ENOMEM); errno = 0; addr_len = sizeof(addr); n = recvfrom(fd, &buf[0], sizeof(buf), 0, (struct sockaddr *) &addr, &addr_len); assert(n == -1); assert(errno == ENOMEM); errno = 0; n = recvmsg(fd, &msg, 0); assert(n == -1); assert(errno == ENOMEM); } static void test_socket_recv_and_recvfrom_and_recvmsg(void) { rtems_resource_snapshot snapshot; struct sockaddr_in addr; socklen_t addr_len; struct iovec iov; struct msghdr msg; int sd; int rv; ssize_t n; char buf[1]; int enable = 1; puts("test socket recv, recvfrom and recvmsg"); rtems_resource_snapshot_take(&snapshot); init_addr(&addr); init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); rv = ioctl(sd, FIONBIO, &enable); assert(rv == 0); do_no_mem_test(no_mem_socket_recv_and_recvfrom_and_recvmsg, sd); errno = 0; n = recv(sd, &buf[0], sizeof(buf), 0); assert(n == -1); assert(errno == EAGAIN); errno = 0; addr_len = sizeof(addr); n = recvfrom(sd, &buf[0], sizeof(buf), 0, (struct sockaddr *) &addr, &addr_len); assert(n == -1); assert(errno == EAGAIN); errno = 0; n = recvmsg(sd, &msg, 0); assert(n == -1); assert(errno == EAGAIN); rv = close(sd); assert(rv == 0); errno = 0; n = recv(sd, &buf[0], sizeof(buf), 0); assert(n == -1); assert(errno == EBADF); errno = 0; addr_len = sizeof(addr); n = recvfrom(sd, &buf[0], sizeof(buf), 0, (struct sockaddr *) &addr, &addr_len); assert(n == -1); assert(errno == EBADF); errno = 0; n = recvmsg(sd, &msg, 0); assert(n == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_select(int fd) { struct fd_set set; int nfds; int rv; FD_ZERO(&set); FD_SET(fd, &set); nfds = fd + 1; errno = 0; rv = select(nfds, &set, NULL, NULL, NULL); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_select(void) { rtems_resource_snapshot snapshot; struct fd_set set; int nfds; int sd; int rv; puts("test socket select"); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); rv = close(sd); assert(rv == 0); FD_ZERO(&set); FD_SET(sd, &set); nfds = sd + 1; errno = 0; rv = select(nfds, &set, NULL, NULL, NULL); assert(rv == -1); assert(errno == EBADF); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_select, sd); FD_ZERO(&set); nfds = -1; errno = 0; rv = select(nfds, &set, NULL, NULL, NULL); assert(rv == -1); assert(errno == EINVAL); rv = close(sd); assert(rv == 0); FD_ZERO(&set); FD_SET(sd, &set); nfds = sd + 1; errno = 0; rv = select(nfds, &set, NULL, NULL, NULL); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_poll(int fd) { struct pollfd pfd; int timeout = -1; int rv; pfd.fd = fd; pfd.events = POLLIN; pfd.revents = 0; errno = 0; rv = poll(&pfd, 1, timeout); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_poll(void) { rtems_resource_snapshot snapshot; struct pollfd pfd; int timeout = -1; int sd; int rv; puts("test socket poll"); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); rv = close(sd); assert(rv == 0); pfd.fd = sd; pfd.events = POLLIN; pfd.revents = 0; rv = poll(&pfd, 1, timeout); assert(rv == 1); assert(pfd.revents == POLLNVAL); rtems_resource_snapshot_take(&snapshot); sd = socket(PF_INET, SOCK_DGRAM, 0); assert(sd >= 0); do_no_mem_test(no_mem_socket_poll, sd); pfd.fd = sd; pfd.events = POLLIN; pfd.revents = 0; errno = 0; rv = poll(NULL, UINT_MAX, timeout); assert(rv == -1); assert(errno == EINVAL); rv = close(sd); assert(rv == 0); pfd.fd = sd; pfd.events = POLLIN; pfd.revents = 0; rv = poll(&pfd, 1, timeout); assert(rv == 1); assert(pfd.revents == POLLNVAL); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_socket_pair(int fd) { int sd[2]; int rv; errno = 0; rv = socketpair(PF_UNIX, SOCK_DGRAM, 0, &sd[0]); assert(rv == -1); assert(errno == ENOMEM); } static void test_socket_pair(void) { rtems_resource_snapshot snapshot; int sd[2]; int rv; char in[] = { 'x' }; char out[] = { 'o' }; ssize_t n; puts("test socket pair"); rtems_resource_snapshot_take(&snapshot); rv = socketpair(PF_UNIX, SOCK_DGRAM, 0, &sd[0]); assert(rv == 0); n = write(sd[0], &out[0], sizeof(out)); assert(n == (ssize_t)sizeof(out)); n = read(sd[1], &in[0], sizeof(in)); assert(n == (ssize_t)sizeof(in)); assert(memcmp(&in[0], &out[0], sizeof(in)) == 0); rv = close(sd[0]); assert(rv == 0); rv = close(sd[1]); assert(rv == 0); do_no_mem_test(no_mem_socket_pair, -1); assert(rtems_resource_snapshot_check(&snapshot)); } static void test_kqueue_unsupported_ops(void) { rtems_resource_snapshot snapshot; int kq; int rv; off_t off; ssize_t n; char buf[1]; puts("test kqueue unsupported ops"); rtems_resource_snapshot_take(&snapshot); kq = kqueue(); assert(kq >= 0); errno = 0; n = read(kq, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == ENOTSUP); errno = 0; n = write(kq, &buf[0], sizeof(buf)); assert(n == -1); assert(errno == ENOTSUP); errno = 0; rv = ioctl(kq, 0); assert(rv == -1); assert(errno == ENOTTY); errno = 0; off = lseek(kq, 0, SEEK_CUR); assert(off == -1); assert(errno == ESPIPE); errno = 0; rv = ftruncate(kq, 0); assert(rv == -1); assert(errno == EINVAL); errno = 0; rv = fsync(kq); assert(rv == -1); assert(errno == EINVAL); errno = 0; rv = fdatasync(kq); assert(rv == -1); assert(errno == EINVAL); rv = close(kq); assert(rv == 0); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_kqueue_fstat(int fd) { struct stat st; int rv; rv = fstat(fd, &st); assert(rv == 0); } static void test_kqueue_fstat(void) { static const struct stat expected_st = { .st_mode = S_IFIFO }; rtems_resource_snapshot snapshot; struct stat st; int kq; int rv; puts("test kqueue fstat"); rtems_resource_snapshot_take(&snapshot); kq = kqueue(); assert(kq >= 0); do_no_mem_test(no_mem_kqueue_fstat, kq); rv = fstat(kq, &st); assert(rv == 0); assert(memcmp(&expected_st, &st, sizeof(st)) == 0); rv = close(kq); assert(rv == 0); assert(rtems_resource_snapshot_check(&snapshot)); } static void no_mem_kqueue_kevent(int fd) { int rv; errno = 0; rv = kevent(fd, NULL, 0, NULL, 0, NULL); assert(rv == -1); assert(errno == ENOMEM); } static void test_kqueue_kevent(void) { rtems_resource_snapshot snapshot; int kq; int rv; puts("test kqueue kevent"); rtems_resource_snapshot_take(&snapshot); kq = kqueue(); assert(kq >= 0); do_no_mem_test(no_mem_kqueue_kevent, kq); rv = kevent(kq, NULL, 0, NULL, 0, NULL); assert(rv == 0); rv = close(kq); assert(rv == 0); errno = 0; rv = kevent(kq, NULL, 0, NULL, 0, NULL); assert(rv == -1); assert(errno == EBADF); errno = 0; rv = kevent(0, NULL, 0, NULL, 0, NULL); assert(rv == -1); assert(errno == EBADF); assert(rtems_resource_snapshot_check(&snapshot)); } static void test_syslog(void) { puts("test syslog"); errno = 0; syslog(LOG_ERR, "%m"); syslog(LOG_ERR, "b%m"); syslog(LOG_ERR, "%me"); errno = ENXIO; syslog(LOG_ERR, "<%m><%m><%m>"); syslog(LOG_INFO, "%m%m%m%m%m%m%m%m%m%m%m%m%m%m"); syslog(LOG_EMERG, "emerg"); syslog(LOG_ALERT, "alert"); syslog(LOG_CRIT, "crit"); syslog(LOG_ERR, "err"); syslog(LOG_WARNING, "warning"); syslog(LOG_NOTICE, "notice"); syslog(LOG_INFO, "info"); syslog(LOG_DEBUG, "debug"); } static void test_setgethostname(void) { int rv; char out[] = { 'f', 'o', 'o', 'b', 'a', 'r' }; char in[] = { '?', '?', '?', '?', '?', '?', '?' }; puts("test set/get hostname"); rv = sethostname(&out[0], sizeof(out)); assert(rv == 0); rv = gethostname(&in[0], sizeof(in)); assert(rv == 0); assert(memcmp(&in[0], &out[0], sizeof(in) - 1) == 0); assert(in[sizeof(in) - 1] == '\0'); } static void test_main(void) { /* Must be first test to ensure resource checks work */ test_sockets(); test_socket_unsupported_ops(); test_socket_fstat_and_shutdown(); test_socket_ioctl(); test_socket_bind(); test_socket_connect(); test_socket_listen(); test_socket_accept(); test_socket_getsockopt_and_setsockopt(); test_socket_getpeername(); test_socket_getsockname(); test_socket_read_and_write(); test_socket_send_and_sendto_and_sendmsg(); test_socket_recv_and_recvfrom_and_recvmsg(); test_socket_select(); test_socket_poll(); test_socket_pair(); test_kqueue_unsupported_ops(); test_kqueue_fstat(); test_kqueue_kevent(); test_syslog(); test_setgethostname(); exit(0); } #include