From: Chris Johns <chr...@rtems.org> --- rtems/rtems_socketpair.c | 133 ++++++++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 28 deletions(-)
diff --git a/rtems/rtems_socketpair.c b/rtems/rtems_socketpair.c index 1dcaf6e..5b8bac3 100644 --- a/rtems/rtems_socketpair.c +++ b/rtems/rtems_socketpair.c @@ -1,53 +1,130 @@ #include <machine/rtems-bsd-kernel-space.h> /* - * socketpair() for RTEMS * - * This file exists primarily to document what is required to provide - * a functional implementation of socketpair() for RTEMS. + * RTEMS Project (https://www.rtems.org/) * - * The socketpair() service requires that the "local domain" sockets - * be functional. This is denoted by the domain constants AF_LOCAL - * and AF_UNIX and the protocol constants PF_LOCAL and PF_UNIX. The - * local domain functionality is implemented in the file kern/uipc_usrreq.c - * which was not part of the initial port of the FreeBSD stack to - * RTEMS. + * Copyright (c) 2021 Vijay Kumar Banerjee <vi...@rtems.org>. + * All rights reserved. * - * The FreeBSD socketpair implementation appears to be dependent on - * file system features which are not available currently in RTEMS. + * 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. * - * COPYRIGHT (c) 1989-2007. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include <rtems.h> +#include <rtems/error.h> +#include <rtems/rtems_bsdnet.h> + +#include <rtems/rtems_bsdnet_internal.h> + #include <unistd.h> +#include <netinet/in.h> #include <sys/socket.h> #include <errno.h> #include "rtems_syscall.h" -int socketpair (int domain, int type, int protocol, int *rsv) +static int setup_socketpair(int listener, int *socket_vector) +{ + union { + struct sockaddr addr; + struct sockaddr_in inaddr; + } a; + int reuse = 1; + socklen_t addrlen = sizeof(a.inaddr); + + memset(&a, 0, sizeof(a)); + a.inaddr.sin_family = AF_INET; + a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + a.inaddr.sin_port = 0; + + if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, + (char*) &reuse, (socklen_t) sizeof(reuse)) == -1) { + return 1; + } + + if (bind(listener, &a.addr, sizeof(a.inaddr)) == -1) { + return 1; + } + + memset(&a, 0, sizeof(a)); + if (getsockname(listener, &a.addr, &addrlen) == -1) { + return 1; + } + + a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + a.inaddr.sin_family = AF_INET; + + if (listen(listener, 1) == -1) { + return 1; + } + + socket_vector[0] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (socket_vector[0] == -1) { + return 1; + } + + if (connect(socket_vector[0], &a.addr, sizeof(a.inaddr)) == -1) { + return 1; + } + + socket_vector[1] = accept(listener, NULL, NULL); + if (socket_vector[1] == -1) { + return 1; + } + + close(listener); + return 0; +} + +/* Fake socketpair() support with a loopback TCP socket */ +int +socketpair(int domain, int type, int protocol, int *socket_vector) { - if ( !rsv ) { - errno = EFAULT; + int listener; + int saved_errno; + + if (socket_vector == NULL) { + errno = EINVAL; return -1; } + socket_vector[0] = socket_vector[1] = -1; + + listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listener == -1) + return -1; + + if (setup_socketpair(listener, socket_vector) == 0) { + return 0; + } - /* - * Yes, we do not support socketpair() so this is really paranoid. - * But it ensures that someone calling this routine and ignoring - * the return status will get errors from subsequent socket calls. - */ - rsv[ 0 ] = -1; - rsv[ 1 ] = -1; - errno = ENOSYS; + saved_errno = errno; + close(listener); + close(socket_vector[0]); + close(socket_vector[1]); + errno = saved_errno; + socket_vector[0] = socket_vector[1] = -1; return -1; } -- 2.37.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel