summaryrefslogtreecommitdiff
path: root/rtemslwip
diff options
context:
space:
mode:
authorVijay Kumar Banerjee <vijay@rtems.org>2021-06-14 18:42:56 -0600
committerKinsey Moore <kinsey.moore@oarcorp.com>2022-07-08 16:14:55 -0500
commit5857da3fa8f88d7028d80fe270d03e779706e533 (patch)
treed660fc757b82de55573b0358525f6bf536ec623e /rtemslwip
parentb9f8a984bef5861b79dbfaddc68dfc1ab1ec32e9 (diff)
lwip: Add bbb and tms570 drivers
+ Add networking01 and telnetd01 tests
Diffstat (limited to 'rtemslwip')
-rw-r--r--rtemslwip/beaglebone/lwipopts.h276
-rw-r--r--rtemslwip/common/rtems_lwip_io.c1323
-rw-r--r--rtemslwip/common/rtems_lwip_sysdefs.c185
-rw-r--r--rtemslwip/common/syslog.c89
-rw-r--r--rtemslwip/include/rtems_lwip_int.h92
-rw-r--r--rtemslwip/include/sys/sysctl.h1
-rw-r--r--rtemslwip/test/buffer_test_io.h21
-rw-r--r--rtemslwip/test/networking01/sample_app.c159
-rw-r--r--rtemslwip/test/telnetd01/init.c149
-rw-r--r--rtemslwip/test/telnetd01/telnetd01.doc24
-rw-r--r--rtemslwip/test/telnetd01/telnetd01.scn11
-rw-r--r--rtemslwip/test/tmacros.h283
12 files changed, 2613 insertions, 0 deletions
diff --git a/rtemslwip/beaglebone/lwipopts.h b/rtemslwip/beaglebone/lwipopts.h
new file mode 100644
index 0000000..888fae4
--- /dev/null
+++ b/rtemslwip/beaglebone/lwipopts.h
@@ -0,0 +1,276 @@
+#if 0
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef LWIP_HDR_LWIPOPTS_H__
+#define LWIP_HDR_LWIPOPTS_H__
+
+/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
+#define NO_SYS 0
+#define LWIP_NETCONN 1
+#define LWIP_SOCKET 1
+#define LWIP_DNS 1
+
+#define LWIP_IPV6 1
+#define LWIP_IPV4 1
+
+#define LWIP_ETHERNET 1
+#define LWIP_NETIF_API 1
+#define LWIP_AUTOIP 1
+/* Enable DHCP to test it, disable UDP checksum to easier inject packets */
+#define LWIP_DHCP 1
+#define LWIP_TIMEVAL_PRIVATE 0
+#define LWIP_POSIX_SOCKETS_IO_NAMES 1
+//#define LWIP_COMPAT_SOCKETS 2
+#ifndef FIONREAD
+#define FIONREAD 1
+#endif
+#ifndef FIONBIO
+#define FIONBIO 1
+#endif
+#define THREAD_STACK_SIZE 4096
+
+#define LWIP_TIMERS 1
+/* Minimal changes to opt.h required for tcp unit tests: */
+
+#define MEM_SIZE 16000
+#define TCP_SND_QUEUELEN 40
+#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN
+#define TCP_SND_BUF (12 * TCP_MSS)
+#define TCP_WND (10 * TCP_MSS)
+#define LWIP_WND_SCALE 1
+#define TCP_RCV_SCALE 0
+#define PBUF_POOL_SIZE 400 // pbuf tests need ~200KByte
+
+/* Minimal changes to opt.h required for etharp unit tests: */
+#define ETHARP_SUPPORT_STATIC_ENTRIES 1
+
+#endif /* LWIP_HDR_LWIPOPTS_H__ */
+
+#endif /* 0 */
+
+/**
+ * \file lwipopts.h - Configuration options for lwIP
+ *
+ * Copyright (c) 2010 Texas Instruments Incorporated
+ */
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __LWIPOPTS_H__
+#define __LWIPOPTS_H__
+
+/*****************************************************************************
+** CONFIGURATIONS
+*****************************************************************************/
+
+/*
+** The macro CPSW_DUAL_MAC_MODE shall be defined for using CPSW ports in
+** Dual MAC mode.
+*/
+#define CPSW_DUAL_MAC_MODE
+
+/*
+** The below macro should be defined for using lwIP with cache. For cache
+** enabling, pbuf pool shall be cache line aligned. This is done by using
+** separate pool for each memory. The alignment of pbuf pool to cache line
+** size is done in /ports/cpsw/include/arch/cc.h.
+*/
+/*#define LWIP_CACHE_ENABLED*/
+
+#define SOC_CACHELINE_SIZE_BYTES 64 /* Number of bytes in
+ a cache line */
+/*
+** The timeout for DHCP completion. lwIP library will wait for DHCP
+** completion for (LWIP_DHCP_TIMEOUT / 100) seconds.
+*/
+#define LWIP_DHCP_TIMEOUT 1000
+
+/*
+** The number of times DHCP is attempted. Each time, the library will wait
+** for (LWIP_DHCP_TIMEOUT / 100) seconds for DHCP completion.
+*/
+#define NUM_DHCP_TRIES 5
+
+#define LWIP_ETHERNET 1
+#define LWIP_ARP 1
+#define LWIP_DNS 1
+
+/*****************************************************************************
+** lwIP SPECIFIC DEFINITIONS - To be used by lwIP stack
+*****************************************************************************/
+#define HOST_TMR_INTERVAL 0
+#define DYNAMIC_HTTP_HEADERS
+
+/*****************************************************************************
+** Platform specific locking
+*****************************************************************************/
+#define SYS_LIGHTWEIGHT_PROT 1
+#define NO_SYS 0
+#define NO_SYS_NO_TIMERS 0
+
+/*****************************************************************************
+** Memory Options
+*****************************************************************************/
+#define MEM_ALIGNMENT 4
+#define MEM_SIZE (1024 * 1024) /* 4K */
+
+#define MEMP_NUM_PBUF 96
+#define MEMP_NUM_TCP_PCB 32
+#define MEMP_NUM_TCP_SEG 32
+#define PBUF_POOL_SIZE 512
+#define MEMP_MEM_MALLOC 1
+#define MEMP_MEM_INIT 1
+#define MEMP_OVERFLOW_CHECK 0
+
+#ifdef LWIP_CACHE_ENABLED
+#define MEMP_SEPARATE_POOLS 1 /* We want the pbuf
+ pool cache line
+ aligned*/
+#endif
+
+//#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)
+
+/*****************************************************************************
+** IP Options
+*****************************************************************************/
+#define IP_REASSEMBLY 0
+#define IP_FRAG 0
+#define LWIP_IPV4 1
+#define LWIP_IPV6 1
+
+/*****************************************************************************
+** DHCP Options
+*****************************************************************************/
+#define LWIP_DHCP 1
+#define DHCP_DOES_ARP_CHECK 0
+
+/*****************************************************************************
+** Auto IP Options
+*****************************************************************************/
+#define LWIP_AUTOIP 1
+#define LWIP_DHCP_AUTOIP_COOP ((LWIP_DHCP) && (LWIP_AUTOIP))
+
+/*****************************************************************************
+** TCP Options
+*****************************************************************************/
+#define TCP_MSS 1500
+#define TCP_WND (8 * TCP_MSS)
+#define TCP_SND_BUF (8 * TCP_MSS)
+#define TCP_OVERSIZE TCP_MSS
+#define LWIP_TCPIP_CORE_LOCKING 1
+
+/*****************************************************************************
+** PBUF Options
+*****************************************************************************/
+#define PBUF_LINK_HLEN 14
+#define PBUF_POOL_BUFSIZE 1520 /* + size of struct pbuf
+ shall be cache line
+ aligned be enabled */
+#define ETH_PAD_SIZE 0
+#define LWIP_NETCONN 1
+
+/*****************************************************************************
+** Socket Options
+*****************************************************************************/
+#define LWIP_SOCKET 1
+#define SO_REUSE 1
+
+/*****************************************************************************
+** Debugging options
+*****************************************************************************/
+#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_OFF
+#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON | LWIP_DBG_TRACE \
+ |LWIP_DBG_STATE | LWIP_DBG_FRESH)
+#define DHCP_DEBUG LWIP_DBG_OFF
+#define NETIF_DEBUG LWIP_DBG_OFF
+#define IP_DEBUG LWIP_DBG_OFF
+#define UDP_DEBUG LWIP_DBG_OFF
+#define ETHARP_DEBUG LWIP_DBG_OFF
+#define SYS_DEBUG LWIP_DBG_OFF
+#define RAW_DEBUG LWIP_DBG_OFF
+#define MEM_DEBUG LWIP_DBG_OFF
+#define MEMP_DEBUG LWIP_DBG_OFF
+#define PBUF_DEBUG LWIP_DBG_OFF
+#define TCPIP_DEBUG LWIP_DBG_OFF
+#define APP_DEBUG LWIP_DBG_OFF
+#define SOCKETS_DEBUG LWIP_DBG_OFF
+#define LWIP_STATS 0
+#define LWIP_STATS_DISPLAY 0
+#define LWIP_STATS_POSIX 0
+#define LWIP_DNS_API_DEFINE_ERRORS 1
+
+
+
+/**
+ * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names.
+ * (only used if you use sockets.c)
+ */
+#define LWIP_COMPAT_SOCKETS 1
+
+ #define LWIP_TIMEVAL_PRIVATE 0
+
+ #define LWIP_RAW 0
+
+#define tskIDLE_PRIORITY RTEMS_MAXIMUM_PRIORITY
+#define portTICK_RATE_MS (rtems_clock_get_ticks_per_second() * 1000)
+#define vTaskDelay(x) sys_arch_delay(x)
+
+#endif /* __LWIPOPTS_H__ */
diff --git a/rtemslwip/common/rtems_lwip_io.c b/rtemslwip/common/rtems_lwip_io.c
new file mode 100644
index 0000000..8aa28b5
--- /dev/null
+++ b/rtemslwip/common/rtems_lwip_io.c
@@ -0,0 +1,1323 @@
+/*
+ *
+ * RTEMS Project (https://www.rtems.org/)
+ *
+ * Copyright (c) 2021 Vijay Kumar Banerjee <vijay@rtems.org>.
+ * 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 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.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define LWIP_COMPAT_SOCKETS 0
+
+#include <string.h>
+#include <stdarg.h>
+/* #include <stdlib.h> */
+#include <stdio.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/error.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#include <sys/sysctl.h>
+
+#include <rtems/thread.h>
+
+#include <lwip/tcpip.h>
+#include <lwip/api.h>
+#include <lwip/netbuf.h>
+#include <lwip/netdb.h>
+#include <lwip/netifapi.h>
+#include <lwip/sockets.h>
+#include <lwip/sys.h>
+#include <sys/errno.h>
+
+#include <lwip/init.h>
+#include "lwip/err.h"
+#include "lwip/tcp.h"
+#include <netif/etharp.h>
+
+#include <string.h>
+
+#include "lwip/tcpip.h"
+//#include "arch/eth_lwip.h"
+#include "lwip/api.h"
+#include "lwip/netbuf.h"
+#include "lwip/netdb.h"
+#include "lwip/netifapi.h"
+#include "lwip/sockets.h"
+#include "lwip/sys.h"
+
+#include "rtems_lwip_int.h"
+
+static const rtems_filesystem_file_handlers_r rtems_lwip_socket_handlers;
+
+static rtems_recursive_mutex rtems_lwip_mutex =
+ RTEMS_RECURSIVE_MUTEX_INITIALIZER( "_LWIP" );
+
+void rtems_lwip_semaphore_obtain( void )
+{
+ rtems_recursive_mutex_lock( &rtems_lwip_mutex );
+}
+
+/*
+ * Release network mutex
+ */
+void rtems_lwip_semaphore_release( void )
+{
+ rtems_recursive_mutex_unlock( &rtems_lwip_mutex );
+}
+
+static inline int rtems_lwip_iop_to_lwipfd( rtems_libio_t *iop )
+{
+ if ( iop == NULL ) {
+ errno = EBADF;
+
+ return -1;
+ }
+
+/*
+ if ((rtems_libio_iop_flags(iop) & LIBIO_FLAGS_OPEN) == 0) {
+ errno = EBADF;
+ return -1;
+ }
+ */
+
+ if ( iop->pathinfo.handlers != &rtems_lwip_socket_handlers ) {
+ errno = ENOTSOCK;
+
+ return -1;
+ }
+
+ return iop->data0;
+}
+
+/*
+ * Convert an RTEMS file descriptor to a LWIP socket pointer.
+ */
+int rtems_lwip_sysfd_to_lwipfd( int fd )
+{
+ if ( (uint32_t) fd >= rtems_libio_number_iops ) {
+ errno = EBADF;
+
+ return -1;
+ }
+
+ return rtems_lwip_iop_to_lwipfd( rtems_libio_iop( fd ) );
+}
+
+/*
+ * Create an RTEMS file descriptor for a socket
+ */
+static int rtems_lwip_make_sysfd_from_lwipfd( int lfwipfd )
+{
+ rtems_libio_t *iop;
+ int fd;
+
+ iop = rtems_libio_allocate();
+
+ if ( iop == 0 )
+ rtems_set_errno_and_return_minus_one( ENFILE );
+
+ fd = rtems_libio_iop_to_descriptor( iop );
+ iop->data0 = lfwipfd;
+ iop->data1 = NULL;
+ iop->pathinfo.handlers = &rtems_lwip_socket_handlers;
+ iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
+ rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo );
+ rtems_libio_iop_flags_set( iop, LIBIO_FLAGS_READ_WRITE | LIBIO_FLAGS_OPEN );
+
+ return fd;
+}
+
+/*
+ *********************************************************************
+ * BSD-style entry points *
+ *********************************************************************
+ */
+int socket(
+ int domain,
+ int type,
+ int protocol
+)
+{
+ int fd;
+ int lwipfd;
+
+ if ( domain == rtems_lwip_sysdefs_PF_UNSPEC ) {
+ domain = PF_UNSPEC;
+ } else if ( domain == rtems_lwip_sysdefs_PF_INET ) {
+ domain = PF_INET;
+ } else if ( domain == rtems_lwip_sysdefs_PF_INET6 ) {
+ domain = PF_INET6;
+ } else {
+ errno = EINVAL;
+
+ return -1;
+ }
+
+ if ( type == rtems_lwip_sysdefs_SOCK_STREAM ) {
+ type = SOCK_STREAM;
+ } else if ( type == rtems_lwip_sysdefs_SOCK_DGRAM ) {
+ type = SOCK_DGRAM;
+ } else {
+ errno = EINVAL;
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_obtain();
+
+ lwipfd = lwip_socket( domain, type, 0 );
+
+ if ( lwipfd < 0 ) {
+ fd = -1;
+ } else {
+ fd = rtems_lwip_make_sysfd_from_lwipfd( lwipfd );
+
+ if ( fd < 0 ) {
+ lwip_close( lwipfd );
+ }
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return fd;
+}
+
+int bind(
+ int s,
+ const struct sockaddr *name,
+ socklen_t namelen
+)
+{
+ int ret = -1;
+ int lwipfd;
+ int family;
+ struct sockaddr *lwipname;
+ socklen_t lwipnamelen;
+ struct sockaddr_in so_in;
+
+ #if LWIP_IPV6
+ struct sockaddr_in6 so_in6;
+ #endif
+
+ family = rtems_lwip_sysdefs_sockaddr_get_family( name );
+
+ if ( ( family == rtems_lwip_sysdefs_AF_INET ) &&
+ ( namelen >= rtems_lwip_sysdefs_sockaddr_in_size ) ) {
+ so_in.sin_len = sizeof( so_in );
+ so_in.sin_family = PF_INET;
+ so_in.sin_port = rtems_lwip_sysdefs_sockaddr_in_get_sin_port( name );
+ so_in.sin_addr.s_addr =
+ rtems_lwip_sysdefs_sockaddr_in_get_sin_addr( name );
+ lwipname = (struct sockaddr *) &so_in;
+ lwipnamelen = so_in.sin_len;
+ #if LWIP_IPV6
+ } else if ( ( family == rtems_lwip_sysdefs_AF_INET6 ) &&
+ ( namelen >= rtems_lwip_sysdefs_sockaddr_in6_size ) ) {
+ so_in6.sin6_len = sizeof( so_in6 );
+ so_in6.sin6_family = PF_INET6;
+ so_in6.sin6_port = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_port( name );
+ memcpy( &so_in6.sin6_addr,
+ rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr_const( name ),
+ sizeof( so_in6.sin6_addr ) );
+ so_in6.sin6_flowinfo = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_flowinfo(
+ name );
+ so_in6.sin6_scope_id = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_scope_id(
+ name );
+ lwipname = (struct sockaddr *) &so_in6;
+ lwipnamelen = so_in6.sin6_len;
+ #endif
+ } else {
+ errno = EINVAL;
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ ret = lwip_bind( lwipfd, lwipname, lwipnamelen );
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+int connect(
+ int s,
+ const struct sockaddr *name,
+ socklen_t namelen
+)
+{
+ int ret = -1;
+ int lwipfd;
+ int family;
+ struct sockaddr *lwipname;
+ socklen_t lwipnamelen;
+ struct sockaddr_in so_in;
+
+ #if LWIP_IPV6
+ struct sockaddr_in6 so_in6;
+ #endif
+
+ family = rtems_lwip_sysdefs_sockaddr_get_family( name );
+
+ if ( ( family == rtems_lwip_sysdefs_AF_INET ) &&
+ ( namelen >= rtems_lwip_sysdefs_sockaddr_in_size ) ) {
+ so_in.sin_len = sizeof( so_in );
+ so_in.sin_family = AF_INET;
+ so_in.sin_port = rtems_lwip_sysdefs_sockaddr_in_get_sin_port( name );
+ so_in.sin_addr.s_addr =
+ rtems_lwip_sysdefs_sockaddr_in_get_sin_addr( name );
+ lwipname = (struct sockaddr *) &so_in;
+ lwipnamelen = so_in.sin_len;
+ #if LWIP_IPV6
+ } else if ( ( family == rtems_lwip_sysdefs_AF_INET6 ) &&
+ ( namelen >= rtems_lwip_sysdefs_sockaddr_in6_size ) ) {
+ so_in6.sin6_len = sizeof( so_in6 );
+ so_in6.sin6_family = AF_INET6;
+ so_in6.sin6_port = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_port( name );
+ memcpy( &so_in6.sin6_addr,
+ rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr_const( name ),
+ sizeof( so_in6.sin6_addr ) );
+ so_in6.sin6_flowinfo = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_flowinfo(
+ name );
+ so_in6.sin6_scope_id = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_scope_id(
+ name );
+ lwipname = (struct sockaddr *) &so_in6;
+ lwipnamelen = so_in6.sin6_len;
+ #endif
+ } else {
+ errno = EINVAL;
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ ret = lwip_connect( lwipfd, lwipname, lwipnamelen );
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+int listen(
+ int s,
+ int backlog
+)
+{
+ int ret = -1;
+ int lwipfd;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ ret = lwip_listen( lwipfd, backlog );
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+int accept(
+ int s,
+ struct sockaddr *name,
+ socklen_t *namelen
+)
+{
+ int ret = -1;
+ int lwipfd;
+ struct sockaddr *lwipname = name;
+ socklen_t lwipnamelen = *namelen;
+ struct sockaddr_in so_in;
+
+ #if LWIP_IPV6
+ struct sockaddr_in6 so_in6;
+ #endif
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+
+ rtems_lwip_semaphore_release();
+ lwipfd = lwip_accept( lwipfd, lwipname, &lwipnamelen );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ if ( lwipfd < 0 )
+ return lwipfd;
+
+ if ( lwipname->sa_family == AF_INET ) {
+ memcpy( &so_in, lwipname, sizeof( so_in ) );
+ rtems_lwip_sysdefs_sockaddr_set_len( name,
+ rtems_lwip_sysdefs_sockaddr_in_size );
+ rtems_lwip_sysdefs_sockaddr_set_family( name, rtems_lwip_sysdefs_AF_INET );
+ rtems_lwip_sysdefs_sockaddr_in_set_sin_port( name, so_in.sin_port );
+ rtems_lwip_sysdefs_sockaddr_in_set_sin_addr( name, so_in.sin_addr.s_addr );
+ #if LWIP_IPV6
+ } else if ( lwipname->sa_family == AF_INET6 ) {
+ memcpy( &so_in6, lwipname, sizeof( so_in6 ) );
+ rtems_lwip_sysdefs_sockaddr_set_len( name,
+ rtems_lwip_sysdefs_sockaddr_in6_size );
+ rtems_lwip_sysdefs_sockaddr_set_family( name,
+ rtems_lwip_sysdefs_AF_INET6 );
+
+ rtems_lwip_sysdefs_sockaddr_in6_set_sin6_port( name, so_in6.sin6_port );
+ memcpy( rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr( name ),
+ &so_in6.sin6_addr,
+ sizeof( so_in6.sin6_addr ) );
+ rtems_lwip_sysdefs_sockaddr_in6_set_sin6_flowinfo( name,
+ so_in6.sin6_flowinfo );
+ rtems_lwip_sysdefs_sockaddr_in6_set_sin6_scope_id( name,
+ so_in6.sin6_scope_id );
+ #endif
+ } else {
+ lwip_close( lwipfd );
+ errno = EINVAL;
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_obtain();
+ ret = rtems_lwip_make_sysfd_from_lwipfd( lwipfd );
+
+ if ( ret < 0 ) {
+ rtems_lwip_semaphore_release();
+ lwip_close( lwipfd );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ *namelen = rtems_lwip_sysdefs_sockaddr_get_len( name );
+
+ return ret;
+}
+
+/*
+ * Shutdown routine
+ */
+
+int shutdown(
+ int s,
+ int how
+)
+{
+ int ret = -1;
+ int lwipfd;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ rtems_lwip_semaphore_release();
+ ret = lwip_shutdown( lwipfd, how );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+ssize_t recv(
+ int s,
+ void *buf,
+ size_t len,
+ int flags
+)
+{
+ int ret = -1;
+ int lwipfd;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ rtems_lwip_semaphore_release();
+ ret = lwip_recv( lwipfd, buf, len, flags );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+ssize_t send(
+ int s,
+ const void *buf,
+ size_t len,
+ int flags
+)
+{
+ int ret = -1;
+ int lwipfd;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ rtems_lwip_semaphore_release();
+ ret = lwip_send( lwipfd, buf, len, flags );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+ssize_t recvfrom(
+ int s,
+ void *buf,
+ size_t len,
+ int flags,
+ struct sockaddr *name,
+ socklen_t *namelen
+)
+{
+ int ret = -1;
+ int lwipfd;
+ struct sockaddr *lwipname = name;
+ socklen_t lwipnamelen = *namelen;
+ struct sockaddr_in so_in;
+
+ #if LWIP_IPV6
+ struct sockaddr_in6 so_in6;
+ #endif
+
+ if ( name == NULL )
+ return recv( s, buf, len, flags );
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ rtems_lwip_semaphore_release();
+ lwipfd = lwip_recvfrom( lwipfd, buf, len, flags, lwipname, &lwipnamelen );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ if ( lwipfd < 0 )
+ return lwipfd;
+
+ if ( lwipname->sa_family == AF_INET ) {
+ memcpy( &so_in, lwipname, sizeof( so_in ) );
+ rtems_lwip_sysdefs_sockaddr_set_len( name,
+ rtems_lwip_sysdefs_sockaddr_in_size );
+ rtems_lwip_sysdefs_sockaddr_set_family( name, rtems_lwip_sysdefs_AF_INET );
+ rtems_lwip_sysdefs_sockaddr_in_set_sin_port( name, so_in.sin_port );
+ rtems_lwip_sysdefs_sockaddr_in_set_sin_addr( name, so_in.sin_addr.s_addr );
+ #if LWIP_IPV6
+ } else if ( lwipname->sa_family == AF_INET6 ) {
+ memcpy( &so_in6, lwipname, sizeof( so_in6 ) );
+ rtems_lwip_sysdefs_sockaddr_set_len( name,
+ rtems_lwip_sysdefs_sockaddr_in6_size );
+ rtems_lwip_sysdefs_sockaddr_set_family( name,
+ rtems_lwip_sysdefs_AF_INET6 );
+
+ rtems_lwip_sysdefs_sockaddr_in6_set_sin6_port( name, so_in6.sin6_port );
+ memcpy( rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr( name ),
+ &so_in6.sin6_addr,
+ sizeof( so_in6.sin6_addr ) );
+ rtems_lwip_sysdefs_sockaddr_in6_set_sin6_flowinfo( name,
+ so_in6.sin6_flowinfo );
+ rtems_lwip_sysdefs_sockaddr_in6_set_sin6_scope_id( name,
+ so_in6.sin6_scope_id );
+ #endif
+ } else {
+ lwip_close( lwipfd );
+ errno = EINVAL;
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_obtain();
+ ret = rtems_lwip_make_sysfd_from_lwipfd( lwipfd );
+
+ if ( ret < 0 ) {
+ lwip_close( lwipfd );
+ }
+
+ rtems_lwip_semaphore_release();
+
+ *namelen = rtems_lwip_sysdefs_sockaddr_get_len( name );
+
+ return ret;
+}
+
+ssize_t sendto(
+ int s,
+ const void *buf,
+ size_t len,
+ int flags,
+ const struct sockaddr *name,
+ socklen_t namelen
+)
+{
+ int ret = -1;
+ int lwipfd;
+ int family;
+ struct sockaddr *lwipname;
+ socklen_t lwipnamelen;
+ struct sockaddr_in so_in;
+
+ #if LWIP_IPV6
+ struct sockaddr_in6 so_in6;
+ #endif
+
+ if ( name == NULL )
+ return send( s, buf, len, flags );
+
+ family = rtems_lwip_sysdefs_sockaddr_get_family( name );
+
+ if ( ( family == rtems_lwip_sysdefs_AF_INET ) &&
+ ( namelen >= rtems_lwip_sysdefs_sockaddr_in_size ) ) {
+ so_in.sin_len = sizeof( so_in );
+ so_in.sin_family = AF_INET;
+ so_in.sin_port = rtems_lwip_sysdefs_sockaddr_in_get_sin_port( name );
+ so_in.sin_addr.s_addr =
+ rtems_lwip_sysdefs_sockaddr_in_get_sin_addr( name );
+ lwipname = (struct sockaddr *) &so_in;
+ lwipnamelen = so_in.sin_len;
+ #if LWIP_IPV6
+ } else if ( ( family == rtems_lwip_sysdefs_AF_INET6 ) &&
+ ( namelen >= rtems_lwip_sysdefs_sockaddr_in6_size ) ) {
+ so_in6.sin6_len = sizeof( so_in6 );
+ so_in6.sin6_family = AF_INET6;
+ so_in6.sin6_port = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_port( name );
+ memcpy( &so_in6.sin6_addr,
+ rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr_const( name ),
+ sizeof( so_in6.sin6_addr ) );
+ so_in6.sin6_flowinfo = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_flowinfo(
+ name );
+ so_in6.sin6_scope_id = rtems_lwip_sysdefs_sockaddr_in6_get_sin6_scope_id(
+ name );
+ lwipname = (struct sockaddr *) &so_in6;
+ lwipnamelen = so_in6.sin6_len;
+ #endif
+ } else {
+ errno = EINVAL;
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) >= 0 ) {
+ rtems_lwip_semaphore_release();
+ ret = lwip_sendto( lwipfd, buf, len, flags, lwipname, lwipnamelen );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+#if 0
+
+/*
+ * All `transmit' operations end up calling this routine.
+ */
+ssize_t sendmsg(
+ int s,
+ const struct msghdr *mp,
+ int flags
+)
+{
+ int ret = -1;
+ int error;
+ struct uio auio;
+ struct iovec *iov;
+ int lwipfd;
+ struct mbuf *to;
+ struct mbuf *control = NULL;
+ int i;
+ int len;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( so = rtems_lwip_sysfd_to_lwipfd( s ) ) == NULL ) {
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_offset = 0;
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+
+ for ( i = 0; i < mp->msg_iovlen; i++, iov++ ) {
+ if ( ( auio.uio_resid += iov->iov_len ) < 0 ) {
+ errno = EINVAL;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+ }
+
+ if ( mp->msg_name ) {
+ error = sockargstombuf( &to, mp->msg_name, mp->msg_namelen, MT_SONAME );
+
+ if ( error ) {
+ errno = error;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+ } else {
+ to = NULL;
+ }
+
+ if ( mp->msg_control ) {
+ if ( mp->msg_controllen < sizeof( struct cmsghdr ) ) {
+ errno = EINVAL;
+
+ if ( to )
+ m_freem( to );
+
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ sockargstombuf( &control, mp->msg_control, mp->msg_controllen,
+ MT_CONTROL );
+ } else {
+ control = NULL;
+ }
+
+ len = auio.uio_resid;
+ error = sosend( so, to, &auio, (struct mbuf *) 0, control, flags );
+
+ if ( error ) {
+ if ( auio.uio_resid != len && ( error == EINTR || error == EWOULDBLOCK ) )
+ error = 0;
+ }
+
+ if ( error )
+ errno = error;
+ else
+ ret = len - auio.uio_resid;
+
+ if ( to )
+ m_freem( to );
+
+ rtems_lwip_semaphore_release();
+
+ return ( ret );
+}
+
+/*
+ * All `receive' operations end up calling this routine.
+ */
+ssize_t recvmsg(
+ int s,
+ struct msghdr *mp,
+ int flags
+)
+{
+ int ret = -1;
+ int error;
+ struct uio auio;
+ struct iovec *iov;
+ int lwipfd;
+ struct mbuf *from = NULL, *control = NULL;
+ int i;
+ int len;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( so = rtems_lwip_sysfd_to_lwipfd( s ) ) == NULL ) {
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_READ;
+ auio.uio_offset = 0;
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+
+ for ( i = 0; i < mp->msg_iovlen; i++, iov++ ) {
+ if ( ( auio.uio_resid += iov->iov_len ) < 0 ) {
+ errno = EINVAL;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+ }
+
+ len = auio.uio_resid;
+ mp->msg_flags = flags;
+ error = soreceive( so, &from, &auio, (struct mbuf **) NULL,
+ mp->msg_control ? &control : (struct mbuf **) NULL,
+ &mp->msg_flags );
+
+ if ( error ) {
+ if ( auio.uio_resid != len && ( error == EINTR || error == EWOULDBLOCK ) )
+ error = 0;
+ }
+
+ if ( error ) {
+ errno = error;
+ } else {
+ ret = len - auio.uio_resid;
+
+ if ( mp->msg_name ) {
+ len = mp->msg_namelen;
+
+ if ( ( len <= 0 ) || ( from == NULL ) ) {
+ len = 0;
+ } else {
+ if ( len > from->m_len )
+ len = from->m_len;
+
+ memcpy( mp->msg_name, mtod( from, caddr_t ), len );
+ }
+
+ mp->msg_namelen = len;
+ }
+
+ if ( mp->msg_control ) {
+ struct mbuf *m;
+ void *ctlbuf;
+
+ len = mp->msg_controllen;
+ m = control;
+ mp->msg_controllen = 0;
+ ctlbuf = mp->msg_control;
+
+ while ( m && ( len > 0 ) ) {
+ unsigned int tocopy;
+
+ if ( len >= m->m_len )
+ tocopy = m->m_len;
+ else {
+ mp->msg_flags |= MSG_CTRUNC;
+ tocopy = len;
+ }
+
+ memcpy( ctlbuf, mtod( m, caddr_t ), tocopy );
+ ctlbuf += tocopy;
+ len -= tocopy;
+ m = m->m_next;
+ }
+
+ mp->msg_controllen = ctlbuf - mp->msg_control;
+ }
+ }
+
+ if ( from )
+ m_freem( from );
+
+ if ( control )
+ m_freem( control );
+
+ rtems_lwip_semaphore_release();
+
+ return ( ret );
+}
+
+#endif
+
+int setsockopt(
+ int s,
+ int level,
+ int name,
+ const void *val,
+ socklen_t len
+)
+{
+
+#if 0
+ int lwipfd;
+ struct mbuf *m = NULL;
+ int error;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( so = rtems_lwip_sysfd_to_lwipfd( s ) ) == NULL ) {
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ if ( len > MLEN ) {
+ errno = EINVAL;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ if ( val ) {
+ error = sockargstombuf( &m, val, len, MT_SOOPTS );
+
+ if ( error ) {
+ errno = error;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+ }
+
+ error = sosetopt( so, level, name, m );
+
+ if ( error ) {
+ errno = error;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_release();
+#endif
+ return 0;
+}
+
+#if 0
+
+int getsockopt(
+ int s,
+ int level,
+ int name,
+ void *aval,
+ socklen_t *avalsize
+)
+{
+ int lwipfd;
+ struct mbuf *m = NULL, *m0;
+ char *val = aval;
+ int i, op, valsize;
+ int error;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( so = rtems_lwip_sysfd_to_lwipfd( s ) ) == NULL ) {
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ if ( val )
+ valsize = *avalsize;
+ else
+ valsize = 0;
+
+ if ( ( ( error =
+ sogetopt( so, level, name,
+ &m ) ) == 0 ) && val && valsize && m ) {
+ op = 0;
+
+ while ( m && op < valsize ) {
+ i = valsize - op;
+
+ if ( i > m->m_len )
+ i = m->m_len;
+
+ memcpy( val, mtod( m, caddr_t ), i );
+ op += i;
+ val += i;
+ m0 = m;
+ MFREE( m0, m );
+ }
+
+ *avalsize = op;
+ }
+
+ if ( m != NULL )
+ (void) m_free( m );
+
+ if ( error ) {
+ errno = error;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return 0;
+}
+
+static int getpeersockname(
+ int s,
+ struct sockaddr *name,
+ socklen_t *namelen,
+ int pflag
+)
+{
+ int lwipfd;
+ struct mbuf *m;
+ int len = *namelen;
+ int error;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( so = rtems_lwip_sysfd_to_lwipfd( s ) ) == NULL ) {
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ m = m_getclr( M_WAIT, MT_SONAME );
+
+ if ( m == NULL ) {
+ errno = ENOBUFS;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ if ( pflag )
+ error = ( *so->so_proto->pr_usrreqs->pru_peeraddr )( so, m );
+ else
+ error = ( *so->so_proto->pr_usrreqs->pru_sockaddr )( so, m );
+
+ if ( error ) {
+ m_freem( m );
+ errno = error;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ if ( len > m->m_len ) {
+ len = m->m_len;
+ *namelen = len;
+ }
+
+ memcpy( name, mtod( m, caddr_t ), len );
+ m_freem( m );
+ rtems_lwip_semaphore_release();
+
+ return 0;
+}
+
+#endif
+
+int getpeername(
+ int s,
+ struct sockaddr *name,
+ socklen_t *namelen
+)
+{
+ int lwipfd;
+ int error;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( lwipfd = rtems_lwip_sysfd_to_lwipfd( s ) ) < 0 ) {
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ error = lwip_getpeername(lwipfd, name, namelen);
+
+ rtems_lwip_semaphore_release();
+
+ return error;
+}
+
+#if 0
+
+int getsockname(
+ int s,
+ struct sockaddr *name,
+ socklen_t *namelen
+)
+{
+ return getpeersockname( s, name, namelen, 0 );
+}
+
+int sysctl(
+ const int *name,
+ u_int namelen,
+ void *oldp,
+ size_t *oldlenp,
+ const void *newp,
+ size_t newlen
+)
+{
+ int error;
+ size_t j;
+
+ rtems_lwip_semaphore_obtain();
+ error =
+ userland_sysctl( 0, name, namelen, oldp, oldlenp, 1, newp, newlen, &j );
+ rtems_lwip_semaphore_release();
+
+ if ( oldlenp )
+ *oldlenp = j;
+
+ if ( error ) {
+ errno = error;
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+
+/*
+ ************************************************************************
+ * RTEMS I/O HANDLER ROUTINES *
+ ************************************************************************
+ */
+static int rtems_lwip_close( rtems_libio_t *iop )
+{
+ int lwipfd;
+ int ret;
+
+ rtems_lwip_semaphore_obtain();
+ lwipfd = rtems_lwip_iop_to_lwipfd( iop );
+
+ if ( lwipfd < 0 ) {
+ ret = -1;
+ } else {
+ rtems_lwip_semaphore_release();
+ ret = lwip_close( lwipfd );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+static ssize_t rtems_lwip_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ size_t count
+)
+{
+ int lwipfd;
+ int ret;
+
+ rtems_lwip_semaphore_obtain();
+ lwipfd = rtems_lwip_iop_to_lwipfd( iop );
+
+ if ( lwipfd < 0 ) {
+ ret = -1;
+ } else {
+ rtems_lwip_semaphore_release();
+ ret = lwip_read( lwipfd, buffer, count );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+static ssize_t rtems_lwip_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ size_t count
+)
+{
+ int lwipfd;
+ int ret;
+
+ rtems_lwip_semaphore_obtain();
+ lwipfd = rtems_lwip_iop_to_lwipfd( iop );
+
+ if ( lwipfd < 0 ) {
+ ret = -1;
+ } else {
+ rtems_lwip_semaphore_release();
+ ret = lwip_write( lwipfd, buffer, count );
+ rtems_lwip_semaphore_obtain();
+ }
+
+ rtems_lwip_semaphore_release();
+
+ return ret;
+}
+
+int so_ioctl(
+ rtems_libio_t *iop,
+ int lwipfd,
+ uint32_t command,
+ void *buffer
+)
+{
+#if 0
+
+ switch ( command ) {
+ case FIONBIO:
+
+ if ( *(int *) buffer ) {
+ iop->flags |= O_NONBLOCK;
+ so->so_state |= SS_NBIO;
+ } else {
+ iop->flags &= ~O_NONBLOCK;
+ so->so_state &= ~SS_NBIO;
+ }
+
+ return 0;
+
+ case FIONREAD:
+ *(int *) buffer = so->so_rcv.sb_cc;
+
+ return 0;
+ }
+
+ if ( IOCGROUP( command ) == 'i' )
+ return ifioctl( so, command, buffer, NULL );
+
+ if ( IOCGROUP( command ) == 'r' )
+ return rtioctl( command, buffer, NULL );
+
+ return ( *so->so_proto->pr_usrreqs->pru_control )( so, command, buffer, 0 );
+#endif
+
+ return -1;
+}
+
+static int rtems_lwip_ioctl(
+ rtems_libio_t *iop,
+ ioctl_command_t command,
+ void *buffer
+)
+{
+#if 0
+ int lwipfd;
+ int error;
+
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( so = iop->data1 ) == NULL ) {
+ errno = EBADF;
+ rtems_lwip_semaphore_release();
+
+ return -1;
+ }
+
+ error = so_ioctl( iop, so, command, buffer );
+ rtems_lwip_semaphore_release();
+
+ if ( error ) {
+ errno = error;
+
+ return -1;
+ }
+
+ return 0;
+#endif
+
+ return -1;
+}
+
+static int rtems_lwip_fcntl(
+ rtems_libio_t *iop,
+ int cmd
+)
+{
+#if 0
+ int lwipfd;
+
+ if ( cmd == F_SETFL ) {
+ rtems_lwip_semaphore_obtain();
+
+ if ( ( so = iop->data1 ) == NULL ) {
+ rtems_lwip_semaphore_release();
+
+ return EBADF;
+ }
+
+ if ( rtems_libio_iop_is_no_delay( iop ) )
+ so->so_state |= SS_NBIO;
+ else
+ so->so_state &= ~SS_NBIO;
+
+ rtems_lwip_semaphore_release();
+ }
+
+ return 0;
+#endif
+
+ return -1;
+}
+
+static int rtems_lwip_fstat(
+ const rtems_filesystem_location_info_t *loc,
+ struct stat *sp
+)
+{
+ sp->st_mode = S_IFSOCK;
+
+ return 0;
+}
+
+static const rtems_filesystem_file_handlers_r rtems_lwip_socket_handlers = {
+ .open_h = rtems_filesystem_default_open,
+ .close_h = rtems_lwip_close,
+ .read_h = rtems_lwip_read,
+ .write_h = rtems_lwip_write,
+ .ioctl_h = rtems_lwip_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek,
+ .fstat_h = rtems_lwip_fstat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fcntl_h = rtems_lwip_fcntl,
+ .kqfilter_h = rtems_filesystem_default_kqfilter,
+ .mmap_h = rtems_filesystem_default_mmap,
+ .poll_h = rtems_filesystem_default_poll,
+ .readv_h = rtems_filesystem_default_readv,
+ .writev_h = rtems_filesystem_default_writev
+};
+
+const char *
+inet_ntop(int af, const void *src, char *dst, socklen_t size){
+ return lwip_inet_ntop(af, src, dst, size);
+}
diff --git a/rtemslwip/common/rtems_lwip_sysdefs.c b/rtemslwip/common/rtems_lwip_sysdefs.c
new file mode 100644
index 0000000..3877811
--- /dev/null
+++ b/rtemslwip/common/rtems_lwip_sysdefs.c
@@ -0,0 +1,185 @@
+/*
+ *
+ * RTEMS Project (https://www.rtems.org/)
+ *
+ * Copyright (c) 2021 Vijay Kumar Banerjee <vijay@rtems.org>.
+ * 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 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.
+ */
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "rtems_lwip_int.h"
+
+int rtems_lwip_sysdefs_AF_UNSPEC = AF_UNSPEC;
+int rtems_lwip_sysdefs_AF_UNIX = AF_UNIX;
+int rtems_lwip_sysdefs_AF_INET = AF_INET;
+int rtems_lwip_sysdefs_AF_INET6 = AF_INET6;
+int rtems_lwip_sysdefs_PF_UNSPEC = PF_UNSPEC;
+int rtems_lwip_sysdefs_PF_UNIX = PF_UNIX;
+int rtems_lwip_sysdefs_PF_INET = PF_INET;
+int rtems_lwip_sysdefs_PF_INET6 = PF_INET6;
+int rtems_lwip_sysdefs_SOCK_STREAM = SOCK_STREAM;
+int rtems_lwip_sysdefs_SOCK_DGRAM = SOCK_DGRAM;
+int rtems_lwip_sysdefs_SOCK_RAW = SOCK_RAW;
+int rtems_lwip_sysdefs_sockaddr_in_size = sizeof( struct sockaddr_in );
+int rtems_lwip_sysdefs_sockaddr_in6_size = sizeof( struct sockaddr_in6 );
+
+int rtems_lwip_sysdefs_sockaddr_get_len( const void *sockaddr )
+{
+ const struct sockaddr *so = sockaddr;
+
+ return so->sa_len;
+}
+
+int rtems_lwip_sysdefs_sockaddr_get_family( const void *sockaddr )
+{
+ const struct sockaddr *so = sockaddr;
+
+ return so->sa_family;
+}
+
+uint16_t rtems_lwip_sysdefs_sockaddr_in_get_sin_port( const void *sockaddr )
+{
+ const struct sockaddr_in *so = sockaddr;
+
+ return so->sin_port;
+}
+
+uint32_t rtems_lwip_sysdefs_sockaddr_in_get_sin_addr( const void *sockaddr )
+{
+ const struct sockaddr_in *so = sockaddr;
+
+ return so->sin_addr.s_addr;
+}
+
+uint16_t rtems_lwip_sysdefs_sockaddr_in6_get_sin6_port( const void *sockaddr )
+{
+ const struct sockaddr_in6 *so = sockaddr;
+
+ return so->sin6_port;
+}
+
+const uint8_t *rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr_const(
+ const void *sockaddr )
+{
+ const struct sockaddr_in6 *so = sockaddr;
+
+ return (uint8_t *) &so->sin6_addr;
+}
+
+uint8_t *rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr(
+ void *sockaddr )
+{
+ struct sockaddr_in6 *so = sockaddr;
+
+ return (uint8_t *) &so->sin6_addr;
+}
+
+uint32_t rtems_lwip_sysdefs_sockaddr_in6_get_sin6_flowinfo(
+ const void *sockaddr )
+{
+ const struct sockaddr_in6 *so = sockaddr;
+
+ return so->sin6_flowinfo;
+}
+
+uint32_t rtems_lwip_sysdefs_sockaddr_in6_get_sin6_scope_id(
+ const void *sockaddr )
+{
+ const struct sockaddr_in6 *so = sockaddr;
+
+ return so->sin6_scope_id;
+}
+
+void rtems_lwip_sysdefs_sockaddr_set_len(
+ void *sockaddr,
+ int len
+)
+{
+ struct sockaddr *so = sockaddr;
+
+ so->sa_len = len;
+}
+
+void rtems_lwip_sysdefs_sockaddr_set_family(
+ void *sockaddr,
+ int family
+)
+{
+ struct sockaddr *so = sockaddr;
+
+ so->sa_family = family;
+}
+
+void rtems_lwip_sysdefs_sockaddr_in_set_sin_port(
+ void *sockaddr,
+ uint16_t port
+)
+{
+ struct sockaddr_in *so = sockaddr;
+
+ so->sin_port = port;
+}
+
+void rtems_lwip_sysdefs_sockaddr_in_set_sin_addr(
+ void *sockaddr,
+ uint32_t addr
+)
+{
+ struct sockaddr_in *so = sockaddr;
+
+ so->sin_addr.s_addr = addr;
+}
+
+void rtems_lwip_sysdefs_sockaddr_in6_set_sin6_port(
+ void *sockaddr,
+ uint16_t port
+)
+{
+ struct sockaddr_in6 *so = sockaddr;
+
+ so->sin6_port = port;
+}
+
+void rtems_lwip_sysdefs_sockaddr_in6_set_sin6_flowinfo(
+ void *sockaddr,
+ uint32_t flowinfo
+)
+{
+ struct sockaddr_in6 *so = sockaddr;
+
+ so->sin6_flowinfo = flowinfo;
+}
+
+void rtems_lwip_sysdefs_sockaddr_in6_set_sin6_scope_id(
+ void *sockaddr,
+ uint32_t scope_id
+)
+{
+ struct sockaddr_in6 *so = sockaddr;
+
+ so->sin6_scope_id = scope_id;
+}
diff --git a/rtemslwip/common/syslog.c b/rtemslwip/common/syslog.c
new file mode 100644
index 0000000..e544074
--- /dev/null
+++ b/rtemslwip/common/syslog.c
@@ -0,0 +1,89 @@
+/*
+ * RTEMS version of syslog and associated routines
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/thread.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#include <unistd.h>
+
+static int LogStatus = LOG_CONS;
+static const char *LogTag = "syslog";
+static int LogFacility = LOG_USER;
+static int LogMask = 0xff;
+
+void
+syslog (int pri, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vsyslog (pri, fmt, ap);
+ va_end (ap);
+}
+
+/*
+ * FIXME: Should cbuf be static? Then we wouldn't
+ * have to worry about blowing stacks with a local variable
+ * that large. Could make cbuf bigger, too.
+ */
+void
+vsyslog (int pri, const char *fmt, va_list ap)
+{
+ int cnt;
+ char cbuf[200];
+
+ if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
+ syslog (LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID,
+ "syslog: unknown facility/priority: %#x", pri);
+ pri &= LOG_PRIMASK|LOG_FACMASK;
+ }
+
+ if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
+ return;
+
+ if ((pri & LOG_FACMASK) == 0)
+ pri |= LogFacility;
+
+ cnt = snprintf (cbuf, sizeof (cbuf), "<%d>", pri);
+ if (LogTag && cnt < sizeof (cbuf) - 1)
+ cnt += snprintf (cbuf + cnt, sizeof (cbuf) - cnt, "%s", LogTag);
+ if (LogStatus & LOG_PID && cnt < sizeof (cbuf) - 1) {
+ rtems_id tid;
+ rtems_task_ident (RTEMS_SELF, 0, &tid);
+ cnt += snprintf (cbuf + cnt, sizeof (cbuf) - cnt, "[%#lx]", (unsigned long)tid);
+ }
+ if (LogTag && cnt < sizeof (cbuf) - 1)
+ cnt += snprintf (cbuf + cnt, sizeof (cbuf) - cnt, ": ");
+ cnt += vsnprintf (cbuf + cnt, sizeof (cbuf) - cnt, fmt, ap);
+ if (cnt > sizeof (cbuf) - 1)
+ cnt = sizeof (cbuf) - 1;
+ while (cnt > 0 && cbuf[cnt-1] == '\n')
+ cbuf[--cnt] = '\0';
+
+ if (LogStatus & LOG_PERROR)
+ printf ("%s\n", cbuf);
+}
+
+int
+setlogmask (int pmask)
+{
+ int omask;
+
+ omask = LogMask;
+ if (pmask != 0)
+ LogMask = pmask;
+ return (omask);
+}
diff --git a/rtemslwip/include/rtems_lwip_int.h b/rtemslwip/include/rtems_lwip_int.h
new file mode 100644
index 0000000..9d3d548
--- /dev/null
+++ b/rtemslwip/include/rtems_lwip_int.h
@@ -0,0 +1,92 @@
+/*
+ *
+ * RTEMS Project (https://www.rtems.org/)
+ *
+ * Copyright (c) 2021 Vijay Kumar Banerjee <vijay@rtems.org>.
+ * 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 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.
+ */
+
+#ifndef RTEMS_LWIP_INT_H
+#define RTEMS_LWIP_INT_H
+
+#include <stdint.h>
+
+extern int rtems_lwip_sysdefs_AF_UNSPEC;
+extern int rtems_lwip_sysdefs_AF_UNIX;
+extern int rtems_lwip_sysdefs_AF_INET;
+extern int rtems_lwip_sysdefs_AF_INET6;
+extern int rtems_lwip_sysdefs_PF_UNSPEC;
+extern int rtems_lwip_sysdefs_PF_UNIX;
+extern int rtems_lwip_sysdefs_PF_INET;
+extern int rtems_lwip_sysdefs_PF_INET6;
+extern int rtems_lwip_sysdefs_SOCK_STREAM;
+extern int rtems_lwip_sysdefs_SOCK_DGRAM;
+extern int rtems_lwip_sysdefs_SOCK_RAW;
+extern int rtems_lwip_sysdefs_sockaddr_in_size;
+extern int rtems_lwip_sysdefs_sockaddr_in6_size;
+
+int rtems_lwip_sysdefs_sockaddr_get_len( const void *sockaddr );
+int rtems_lwip_sysdefs_sockaddr_get_family( const void *sockaddr );
+uint16_t rtems_lwip_sysdefs_sockaddr_in_get_sin_port( const void *sockaddr );
+uint32_t rtems_lwip_sysdefs_sockaddr_in_get_sin_addr( const void *sockaddr );
+uint16_t rtems_lwip_sysdefs_sockaddr_in6_get_sin6_port( const void *sockaddr );
+const uint8_t *rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr_const(
+ const void *sockaddr );
+uint8_t *rtems_lwip_sysdefs_sockaddr_in6_get_sin6_addr_ptr(
+ void *sockaddr );
+uint32_t rtems_lwip_sysdefs_sockaddr_in6_get_sin6_flowinfo(
+ const void *sockaddr );
+uint32_t rtems_lwip_sysdefs_sockaddr_in6_get_sin6_scope_id(
+ const void *sockaddr );
+
+void rtems_lwip_sysdefs_sockaddr_set_len(
+ void *sockaddr,
+ int len
+);
+void rtems_lwip_sysdefs_sockaddr_set_family(
+ void *sockaddr,
+ int family
+);
+void rtems_lwip_sysdefs_sockaddr_in_set_sin_port(
+ void *sockaddr,
+ uint16_t port
+);
+void rtems_lwip_sysdefs_sockaddr_in_set_sin_addr(
+ void *sockaddr,
+ uint32_t addr
+);
+void rtems_lwip_sysdefs_sockaddr_in6_set_sin6_port(
+ void *sockaddr,
+ uint16_t port
+);
+void rtems_lwip_sysdefs_sockaddr_in6_set_sin6_flowinfo(
+ void *sockaddr,
+ uint32_t flowinfo
+);
+void rtems_lwip_sysdefs_sockaddr_in6_set_sin6_scope_id(
+ void *sockaddr,
+ uint32_t scope_id
+);
+
+#endif /*RTEMS_LWIP_INT_H*/
diff --git a/rtemslwip/include/sys/sysctl.h b/rtemslwip/include/sys/sysctl.h
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/rtemslwip/include/sys/sysctl.h
@@ -0,0 +1 @@
+
diff --git a/rtemslwip/test/buffer_test_io.h b/rtemslwip/test/buffer_test_io.h
new file mode 100644
index 0000000..f0eae50
--- /dev/null
+++ b/rtemslwip/test/buffer_test_io.h
@@ -0,0 +1,21 @@
+/*
+ * Support for running the test output through a buffer
+ */
+
+#ifndef __BUFFER_TEST_IO_h
+#define __BUFFER_TEST_IO_h
+
+#include <rtems/test-info.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TEST_BEGIN() rtems_test_begin(rtems_test_name, TEST_STATE)
+#define TEST_END() rtems_test_end(rtems_test_name)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/rtemslwip/test/networking01/sample_app.c b/rtemslwip/test/networking01/sample_app.c
new file mode 100644
index 0000000..576cd6b
--- /dev/null
+++ b/rtemslwip/test/networking01/sample_app.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <compat/posix/sys/socket.h>
+#include "lwip/netdb.h"
+#include <string.h>
+#include <rtems.h>
+#include "tmacros.h"
+
+const char rtems_test_name[] = "NETWORKING 1";
+
+/* forward declarations to avoid warnings */
+static rtems_task Init(rtems_task_argument argument);
+
+static void fill_sa(struct sockaddr *sa, sa_family_t family)
+{
+ memset(sa, 0, sizeof(*sa));
+ sa->sa_len = sizeof(*sa);
+ sa->sa_family = family;
+}
+
+static void fill_sa_in(struct sockaddr_in *sa_in,
+ in_addr_t addr, in_port_t port)
+{
+ fill_sa((struct sockaddr *)sa_in, AF_INET);
+ sa_in->sin_port = htons(port);
+ sa_in->sin_addr.s_addr = htonl(addr);
+}
+
+static void test_getnameinfo(
+ const struct sockaddr *sa,
+ int flags,
+ bool ask_node,
+ bool ask_service,
+ int expected_returnvalue,
+ const char *expected_node,
+ const char *expected_service
+)
+{
+ char node[] = "255.255.255.255";
+ char service[] = "65535";
+ socklen_t salen = sa->sa_len;
+ int rv;
+
+ char *node_p = node;
+ char *service_p = service;
+ size_t node_l = sizeof(node);
+ size_t service_l = sizeof(service);
+
+ if(ask_node == false) {
+ node_p = NULL;
+ node_l = 0;
+ }
+
+ if(ask_service == false) {
+ service_p = NULL;
+ service_l = 0;
+ }
+
+ rv = getnameinfo(sa, salen, node_p, node_l, service_p, service_l, flags);
+ rtems_test_assert(rv == expected_returnvalue);
+
+ if(expected_node != NULL) {
+ rtems_test_assert(strcmp(expected_node, node) == 0);
+ }
+
+ if(expected_service != NULL) {
+ rtems_test_assert(strcmp(expected_service, service) == 0);
+ }
+}
+
+static void test(void)
+{
+ struct sockaddr sa;
+ struct sockaddr_in sa_in;
+ struct sockaddr *sa_in_p = (struct sockaddr *) &sa_in;
+
+ const in_addr_t ip1_num = 0x7F000001u;
+ const char ip1_string[] = "127.0.0.1";
+
+ const in_addr_t ip2_num = 0xC0A86464u;
+ const char ip2_string[] = "192.168.100.100";
+
+ const in_port_t port1_num = 7u;
+ const char port1_string[] = "7";
+
+ const in_port_t port2_num = 65534u;
+ const char port2_string[] = "65534";
+
+
+ puts("Try AF_INET6");
+ fill_sa(&sa, AF_INET6);
+ test_getnameinfo(&sa, 0, true, true, EAI_FAMILY, NULL, NULL);
+
+ puts("force node name");
+ fill_sa_in(&sa_in, ip1_num, port1_num);
+ test_getnameinfo(sa_in_p, NI_NAMEREQD, true, true, EAI_NONAME, NULL, NULL);
+
+ puts("force service name");
+ fill_sa_in(&sa_in, ip1_num, port1_num);
+ test_getnameinfo(sa_in_p, NI_NAMEREQD, true, true, EAI_NONAME, NULL, NULL);
+
+ puts("get node only");
+ fill_sa_in(&sa_in, ip1_num, port1_num);
+ test_getnameinfo(sa_in_p, 0, true, false, 0, ip1_string, NULL);
+
+ puts("get service only");
+ fill_sa_in(&sa_in, ip1_num, port1_num);
+ test_getnameinfo(sa_in_p, 0, false, true, 0, NULL, port1_string);
+
+ puts("get node and service");
+ fill_sa_in(&sa_in, ip1_num, port1_num);
+ test_getnameinfo(sa_in_p, 0, true, true, 0, ip1_string, port1_string);
+
+ puts("get node and service with maximum number of characters for IP");
+ fill_sa_in(&sa_in, ip2_num, port2_num);
+ test_getnameinfo(sa_in_p, 0, true, true, 0, ip2_string, port2_string);
+}
+
+static rtems_task Init(rtems_task_argument argument)
+{
+ TEST_BEGIN();
+ test();
+ TEST_END();
+
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_INIT
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS (1)
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
+
+#include <rtems/confdefs.h>
diff --git a/rtemslwip/test/telnetd01/init.c b/rtemslwip/test/telnetd01/init.c
new file mode 100644
index 0000000..f1fe036
--- /dev/null
+++ b/rtemslwip/test/telnetd01/init.c
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 On-Line Applications Research Corporation (OAR)
+ * Written by Kinsey Moore <kinsey.moore@oarcorp.com>
+ *
+ * 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 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.
+ */
+
+#include <rtems/telnetd.h>
+#include <lwip/dhcp.h>
+#include <lwip/tcpip.h>
+
+#include <tmacros.h>
+
+const char rtems_test_name[] = "TELNETD 1";
+
+//struct rtems_bsdnet_config rtems_bsdnet_config;
+
+rtems_shell_env_t env;
+
+static void telnet_shell( char *name, void *arg )
+{
+ rtems_shell_dup_current_env( &env );
+
+ env.devname = name;
+ env.taskname = "TLNT";
+
+ rtems_shell_main_loop( &env );
+}
+
+rtems_telnetd_config_table rtems_telnetd_config = {
+ .command = telnet_shell,
+ .stack_size = 8 * RTEMS_MINIMUM_STACK_SIZE,
+};
+
+#define print_ip( tag, ip ) \
+ printf( \
+ "%s: %" PRId32 ".%" PRId32 ".%" PRId32 ".%" PRId32 "\n", \
+ tag, \
+ ( ntohl( ip.addr ) >> 24 ) & 0xff, \
+ ( ntohl( ip.addr ) >> 16 ) & 0xff, \
+ ( ntohl( ip.addr ) >> 8 ) & 0xff, \
+ ntohl( ip.addr ) & 0xff \
+ );
+
+static int shell_main_netinfo(
+ int argc,
+ char **argv
+)
+{
+ print_ip( "IP", net_interface.ip_addr.u_addr.ip4 );
+ print_ip( "Mask", net_interface.netmask.u_addr.ip4 );
+ print_ip( "GW", net_interface.gw.u_addr.ip4 );
+ return 0;
+}
+
+rtems_shell_cmd_t shell_NETINFO_Command = {
+ "netinfo", /* name */
+ "netinfo - shows basic network info, no arguments", /* usage */
+ "net", /* topic */
+ shell_main_netinfo, /* command */
+ NULL, /* alias */
+ NULL /* next */
+};
+
+static rtems_task Init( rtems_task_argument argument )
+{
+ rtems_status_code sc;
+
+ TEST_BEGIN();
+
+ lwip_init();
+
+ rtems_shell_init_environment();
+
+ dhcp_start( &net_interface );
+
+ sc = rtems_telnetd_start( &rtems_telnetd_config );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+ sc = rtems_shell_init(
+ "SHLL", /* task name */
+ RTEMS_MINIMUM_STACK_SIZE * 4, /* task stack size */
+ 100, /* task priority */
+ "/dev/console", /* device name */
+ false, /* run forever */
+ true, /* wait for shell to terminate */
+ NULL /* login check function,
+ use NULL to disable a login check */
+ );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+ sys_arch_delay( 300000 );
+
+ TEST_END();
+ rtems_test_exit( 0 );
+}
+
+#define CONFIGURE_INIT
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
+
+#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 32
+
+#define CONFIGURE_SHELL_COMMANDS_INIT
+#define CONFIGURE_SHELL_COMMANDS_ALL
+#define CONFIGURE_SHELL_USER_COMMANDS &shell_NETINFO_Command
+
+#define CONFIGURE_MAXIMUM_TASKS 12
+
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
+#define CONFIGURE_MAXIMUM_SEMAPHORES 20
+#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 10
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
+
+#define CONFIGURE_UNLIMITED_OBJECTS
+#define CONFIGURE_UNIFIED_WORK_AREAS
+
+#include <rtems/shellconfig.h>
+
+#include <rtems/confdefs.h>
diff --git a/rtemslwip/test/telnetd01/telnetd01.doc b/rtemslwip/test/telnetd01/telnetd01.doc
new file mode 100644
index 0000000..fe1a4d3
--- /dev/null
+++ b/rtemslwip/test/telnetd01/telnetd01.doc
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2018 embedded brains GmbH. All rights reserved.
+#
+# embedded brains GmbH
+# Dornierstr. 4
+# 82178 Puchheim
+# Germany
+# <rtems@embedded-brains.de>
+#
+# 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 file describes the directives and concepts tested by this test set.
+
+test set name: telnetd01
+
+directives:
+
+ - rtems_telnetd_start()
+
+concepts:
+
++ Check if Telnet server works.
diff --git a/rtemslwip/test/telnetd01/telnetd01.scn b/rtemslwip/test/telnetd01/telnetd01.scn
new file mode 100644
index 0000000..3e9cc00
--- /dev/null
+++ b/rtemslwip/test/telnetd01/telnetd01.scn
@@ -0,0 +1,11 @@
+*** BEGIN OF TEST TELNETD 1 ***
+*** TEST VERSION: 5.0.0.dc32b6aa0807fb70f9b26bc0bc6e164ddb49bd3a
+*** TEST STATE: EXPECTED_PASS
+*** TEST BUILD: RTEMS_NETWORKING
+*** TEST TOOLS: 7.3.0 20180125 (RTEMS 5, RSB 9670d7541e0621915e521fe76e7bb33de8cee661, Newlib d13c84eb07e35984bf7a974cd786a6cdac29e6b9)
+syslog: telnetd: configuration with invalid command
+syslog: telnetd: cannot create session task
+syslog: telnetd: started successfully on port 23
+syslog: telnetd: cannot bind server socket
+
+*** END OF TEST TELNETD 1 ***
diff --git a/rtemslwip/test/tmacros.h b/rtemslwip/test/tmacros.h
new file mode 100644
index 0000000..8189149
--- /dev/null
+++ b/rtemslwip/test/tmacros.h
@@ -0,0 +1,283 @@
+/**
+ * @file
+ *
+ * This include file contains macros which are useful in the RTEMS
+ * test suites.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2014.
+ * 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.
+ */
+
+#ifndef __TMACROS_h
+#define __TMACROS_h
+
+#include <inttypes.h>
+#include <rtems/inttypes.h>
+#include <bsp.h> /* includes <rtems.h> */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rtems/error.h>
+#include <rtems/test-info.h>
+#include <rtems/score/threaddispatch.h>
+
+#include "buffer_test_io.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FOREVER 1 /* infinite loop */
+
+#ifdef CONFIGURE_INIT
+#define TEST_EXTERN
+#else
+#define TEST_EXTERN extern
+#endif
+
+/*
+ * Check that that the dispatch disable level is proper for the
+ * mode/state of the test. Normally it should be 0 when in task space.
+ */
+#define check_dispatch_disable_level( _expect ) \
+ do { \
+ if ( (_expect) != -1 \
+ && (((!_Thread_Dispatch_is_enabled()) == false && (_expect) != 0) \
+ || ((!_Thread_Dispatch_is_enabled()) && (_expect) == 0)) \
+ ) { \
+ printf( \
+ "\n_Thread_Dispatch_disable_level is (%i)" \
+ " not %d detected at %s:%d\n", \
+ !_Thread_Dispatch_is_enabled(), (_expect), __FILE__, __LINE__ ); \
+ rtems_test_exit( 1 ); \
+ } \
+ } while ( 0 )
+
+/*
+ * Check that that the allocator mutex is not owned by the executing thread.
+ */
+#include <rtems/score/apimutex.h>
+#define check_if_allocator_mutex_is_not_owned() \
+ do { \
+ if ( _RTEMS_Allocator_is_owner() ) { \
+ printf( \
+ "\nRTEMS Allocator Mutex is owned by executing thread " \
+ "and should not be.\n" \
+ "Detected at %s:%d\n", \
+ __FILE__, \
+ __LINE__ \
+ ); \
+ rtems_test_exit( 1 ); \
+ } \
+ } while ( 0 )
+
+/*
+ * These macros properly report errors within the Classic API
+ */
+#define directive_failed( _dirstat, _failmsg ) \
+ fatal_directive_status( _dirstat, RTEMS_SUCCESSFUL, _failmsg )
+
+#define directive_failed_with_level( _dirstat, _failmsg, _level ) \
+ fatal_directive_status_with_level( \
+ _dirstat, RTEMS_SUCCESSFUL, _failmsg, _level )
+
+#define fatal_directive_status( _stat, _desired, _msg ) \
+ fatal_directive_status_with_level( _stat, _desired, _msg, 0 )
+
+#define fatal_directive_check_status_only( _stat, _desired, _msg ) \
+ do { \
+ if ( (_stat) != (_desired) ) { \
+ printf( "\n%s FAILED -- expected (%s) got (%s)\n", \
+ (_msg), rtems_status_text(_desired), rtems_status_text(_stat) ); \
+ rtems_test_exit( _stat ); \
+ } \
+ } while ( 0 )
+
+#define fatal_directive_status_with_level( _stat, _desired, _msg, _level ) \
+ do { \
+ check_dispatch_disable_level( _level ); \
+ check_if_allocator_mutex_is_not_owned(); \
+ fatal_directive_check_status_only( _stat, _desired, _msg ); \
+ } while ( 0 )
+
+/*
+ * These macros properly report errors from the POSIX API
+ */
+
+#define posix_service_failed( _dirstat, _failmsg ) \
+ fatal_posix_service_status( _dirstat, 0, _failmsg )
+
+#define posix_service_failed_with_level( _dirstat, _failmsg, _level ) \
+ fatal_posix_service_status_with_level( _dirstat, 0, _failmsg, _level )
+
+#define fatal_posix_service_status_errno( _stat, _desired, _msg ) \
+ if ( (_stat != -1) && (errno) != (_desired) ) { \
+ long statx = _stat; \
+ check_dispatch_disable_level( 0 ); \
+ check_if_allocator_mutex_is_not_owned(); \
+ printf( "\n%s FAILED -- expected (%d - %s) got (%ld %d - %s)\n", \
+ (_msg), _desired, strerror(_desired), \
+ statx, errno, strerror(errno) ); \
+ rtems_test_exit( _stat ); \
+ }
+
+#define fatal_posix_service_status( _stat, _desired, _msg ) \
+ fatal_posix_service_status_with_level( _stat, _desired, _msg, 0 )
+
+#define fatal_posix_service_status_with_level( _stat, _desired, _msg, _level ) \
+ do { \
+ check_dispatch_disable_level( _level ); \
+ check_if_allocator_mutex_is_not_owned(); \
+ if ( (_stat) != (_desired) ) { \
+ printf( "\n%s FAILED -- expected (%d - %s) got (%d - %s)\n", \
+ (_msg), _desired, strerror(_desired), _stat, strerror(_stat) ); \
+ printf( "\n FAILED -- errno (%d - %s)\n", \
+ errno, strerror(errno) ); \
+ rtems_test_exit( _stat ); \
+ } \
+ } while ( 0 )
+
+/*
+ * This macro evaluates the semaphore id returned.
+ */
+#define fatal_posix_sem( _ptr, _msg ) \
+ if ( (_ptr != SEM_FAILED) ) { \
+ check_dispatch_disable_level( 0 ); \
+ printf( "\n%s FAILED -- expected (-1) got (%p - %d/%s)\n", \
+ (_msg), _ptr, errno, strerror(errno) ); \
+ rtems_test_exit( -1 ); \
+ }
+
+/*
+ * This macro evaluates the message queue id returned.
+ */
+#define fatal_posix_mqd( _ptr, _msg ) \
+ if ( (_ptr != (mqd_t) -1) ) { \
+ check_dispatch_disable_level( 0 ); \
+ printf( "\n%s FAILED -- expected (-1) got (%" PRId32 " - %d/%s)\n", \
+ (_msg), _ptr, errno, strerror(errno) ); \
+ rtems_test_exit( -1 ); \
+ }
+
+/*
+ * Generic integer version of the error reporting
+ */
+
+#define int_service_failed( _dirstat, _failmsg ) \
+ fatal_int_service_status( _dirstat, RTEMS_SUCCESSFUL, _failmsg )
+
+#define int_service_failed_with_level( _dirstat, _failmsg, _level ) \
+ fatal_int_service_status_with_level( \
+ _dirstat, RTEMS_SUCCESSFUL, _failmsg, _level )
+
+#define fatal_int_service_status( _stat, _desired, _msg ) \
+ fatal_int_service_status_with_level( _stat, _desired, _msg, 0 )
+
+#define fatal_int_service_status_with_level( _stat, _desired, _msg, _level ) \
+ do { \
+ check_dispatch_disable_level( _level ); \
+ if ( (_stat) != (_desired) ) { \
+ printf( "\n%s FAILED -- expected (%d) got (%d)\n", \
+ (_msg), (_desired), (_stat) ); \
+ rtems_test_exit( _stat ); \
+ } \
+ } while ( 0 )
+
+
+/*
+ * Print the time
+ */
+
+#define sprint_time(_str, _s1, _tb, _s2) \
+ do { \
+ sprintf( (_str), "%s%02d:%02d:%02d %02d/%02d/%04d%s", \
+ _s1, (_tb)->hour, (_tb)->minute, (_tb)->second, \
+ (_tb)->month, (_tb)->day, (_tb)->year, _s2 ); \
+ } while ( 0 )
+
+#define print_time(_s1, _tb, _s2) \
+ do { \
+ printf( "%s%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 " %02" PRIu32 "/%02" PRIu32 "/%04" PRIu32 "%s", \
+ _s1, (_tb)->hour, (_tb)->minute, (_tb)->second, \
+ (_tb)->month, (_tb)->day, (_tb)->year, _s2 ); \
+ } while ( 0 )
+
+#define put_dot( _c ) \
+ do { \
+ putchar( _c ); \
+ } while ( 0 )
+
+#define new_line puts( "" )
+
+#define puts_nocr printf
+
+#define put_name( name, crlf ) \
+{ int c0, c1, c2, c3; \
+ c0 = (name >> 24) & 0xff; \
+ c1 = (name >> 16) & 0xff; \
+ c2 = (name >> 8) & 0xff; \
+ c3 = name & 0xff; \
+ putchar( (isprint(c0)) ? c0 : '*' ); \
+ if ( c1 ) putchar( (isprint(c1)) ? c1 : '*' ); \
+ if ( c2 ) putchar( (isprint(c2)) ? c2 : '*' ); \
+ if ( c3 ) putchar( (isprint(c3)) ? c3 : '*' ); \
+ if ( crlf ) \
+ putchar( '\n' ); \
+}
+
+#ifndef build_time
+#define build_time( TB, MON, DAY, YR, HR, MIN, SEC, TK ) \
+ { (TB)->year = YR; \
+ (TB)->month = MON; \
+ (TB)->day = DAY; \
+ (TB)->hour = HR; \
+ (TB)->minute = MIN; \
+ (TB)->second = SEC; \
+ (TB)->ticks = TK; }
+#endif
+
+#define task_number( tid ) \
+ ( rtems_object_id_get_index( tid ) - \
+ rtems_configuration_get_rtems_api_configuration()-> \
+ number_of_initialization_tasks )
+
+#define rtems_test_assert(__exp) \
+ do { \
+ if (!(__exp)) { \
+ printf( "%s: %d %s\n", __FILE__, __LINE__, #__exp ); \
+ rtems_test_exit(0); \
+ } \
+ } while (0)
+
+/**
+ * This assists in clearly disabling warnings on GCC in certain very
+ * specific cases.
+ *
+ * + -Wnon-null - If a method is declared as never having a NULL first
+ * parameter. We need to explicitly disable this compiler warning to make
+ * the code warning free.
+ */
+#ifdef __GNUC__
+ #define COMPILER_DIAGNOSTIC_SETTINGS_PUSH _Pragma("GCC diagnostic push")
+ #define COMPILER_DIAGNOSTIC_SETTINGS_POP _Pragma("GCC diagnostic pop")
+ #define COMPILER_DIAGNOSTIC_SETTINGS_DISABLE_NONNULL \
+ _Pragma("GCC diagnostic ignored \"-Wnonnull\"")
+#else
+ #define COMPILER_DIAGNOSTIC_SETTINGS_PUSH
+ #define COMPILER_DIAGNOSTIC_SETTINGS_POP
+ #define COMPILER_DIAGNOSTIC_SETTINGS_DISABLE_NONNULL
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif