Merge commit 'e94c9ffa' from origin/upstream/master
Change-Id: I529c6cb0b6b8b1bcd105d03a92ba2b80e0dce57d
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..9ff1c29
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,73 @@
+# Copyright 2016 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("lwip_config") {
+ include_dirs = [
+ "ports/fuchsia/include",
+ "src/include",
+ ]
+}
+
+static_library("lwip") {
+ sources = [
+ "ports/fuchsia/include/netif/ethernetif.h",
+ "ports/fuchsia/netif/ethernetif.c",
+ "ports/fuchsia/sys_arch.c",
+ "src/api/api_lib.c",
+ "src/api/api_msg.c",
+ "src/api/err.c",
+ "src/api/netbuf.c",
+ "src/api/netdb.c",
+ "src/api/netifapi.c",
+ "src/api/sockets.c",
+ "src/api/tcpip.c",
+ "src/core/def.c",
+ "src/core/dns.c",
+ "src/core/inet_chksum.c",
+ "src/core/init.c",
+ "src/core/ip.c",
+ "src/core/ipv4/autoip.c",
+ "src/core/ipv4/dhcp.c",
+ "src/core/ipv4/etharp.c",
+ "src/core/ipv4/icmp.c",
+ "src/core/ipv4/igmp.c",
+ "src/core/ipv4/ip4.c",
+ "src/core/ipv4/ip4_addr.c",
+ "src/core/ipv4/ip4_frag.c",
+ "src/core/ipv6/dhcp6.c",
+ "src/core/ipv6/ethip6.c",
+ "src/core/ipv6/icmp6.c",
+ "src/core/ipv6/ip6.c",
+ "src/core/ipv6/ip6_addr.c",
+ "src/core/ipv6/ip6_frag.c",
+ "src/core/ipv6/mld6.c",
+ "src/core/ipv6/nd6.c",
+ "src/core/mem.c",
+ "src/core/memp.c",
+ "src/core/netif.c",
+ "src/core/pbuf.c",
+ "src/core/raw.c",
+ "src/core/stats.c",
+ "src/core/sys.c",
+ "src/core/tcp.c",
+ "src/core/tcp_in.c",
+ "src/core/tcp_out.c",
+ "src/core/timeouts.c",
+ "src/core/udp.c",
+ "src/netif/ethernet.c",
+ "src/netif/slipif.c",
+ ]
+
+ public_configs = [ ":lwip_config" ]
+
+ if (is_debug) {
+ sources += [
+ "ports/fuchsia/debug_flags.c",
+ ]
+ cflags = [
+ "-DLWIP_DEBUG",
+ "-Wno-address-of-packed-member",
+ ]
+ }
+}
diff --git a/ports/fuchsia/AUTHORS b/ports/fuchsia/AUTHORS
new file mode 100644
index 0000000..c2a4eac
--- /dev/null
+++ b/ports/fuchsia/AUTHORS
@@ -0,0 +1,8 @@
+# This is the list of Fuchsia Authors.
+
+# Names should be added to this file as one of
+# Organization's name
+# Individual's name <submission email address>
+# Individual's name <submission email address> <email2> <emailN>
+
+Google Inc.
diff --git a/ports/fuchsia/LICENSE b/ports/fuchsia/LICENSE
new file mode 100644
index 0000000..ac6402f
--- /dev/null
+++ b/ports/fuchsia/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * 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.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
diff --git a/ports/fuchsia/debug_flags.c b/ports/fuchsia/debug_flags.c
new file mode 100644
index 0000000..1fd5ca7
--- /dev/null
+++ b/ports/fuchsia/debug_flags.c
@@ -0,0 +1,29 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "lwip/opt.h"
+
+/*
+ * debug_flags dynamically controls what LWIP_DEBUGF() prints.
+ *
+ * LWIP_DEBUGF(debug, message) prints if (debug & debug_flags) is true
+ * because:
+ * lwipopts.h defines LWIP_DBG_TYPES_ON as debug_flags
+ * lwip/debug.h defines LWIP_DEBUGF() to test (debug & LWIP_DBG_TYPS)
+ *
+ * You should also check lwipopts.h to understand how 'debug's are defined.
+ *
+ * You can enable/disable the debug messages with these flags:
+ *
+ * LWIP_DBG_ON - enables all debug messages
+ * LWIP_DBG_OFF - disables all debug messages
+ *
+ * You can also selectively enable the debug messages by types:
+ *
+ * LWIP_DBG_TRACE - enables if debug includes LWP_DBG_TRACE
+ * LWIP_DBG_STATE - enables if debug includes LWP_DBG_STATE
+ * LWIP_DBG_FRESH - enables if debug includes LWP_DBG_FRESH
+ */
+
+unsigned char lwip_debug_flags = LWIP_DBG_OFF;
diff --git a/ports/fuchsia/include/arch/cc.h b/ports/fuchsia/include/arch/cc.h
new file mode 100644
index 0000000..82f5328
--- /dev/null
+++ b/ports/fuchsia/include/arch/cc.h
@@ -0,0 +1,85 @@
+/*
+ * 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: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
+
+/* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */
+#if defined __linux__
+#define LWIP_UNIX_LINUX
+#elif defined __APPLE__
+#define LWIP_UNIX_MACH
+#elif defined __OpenBSD__
+#define LWIP_UNIX_OPENBSD
+#elif defined __CYGWIN__
+#define LWIP_UNIX_CYGWIN
+#endif
+
+/* Include some files for defining library routines */
+#include <string.h>
+#include <sys/time.h>
+#include <limits.h>
+
+#define LWIP_TIMEVAL_PRIVATE 0
+
+/* Define platform endianness */
+#ifndef BYTE_ORDER
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif /* BYTE_ORDER */
+
+/* Compiler hints for packing structures */
+#define PACK_STRUCT_FIELD(x) x
+#define PACK_STRUCT_STRUCT __attribute__((packed))
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_END
+
+/* prototypes for printf() and abort() */
+#include <stdio.h>
+#include <stdlib.h>
+/* Plaform specific diagnostic output */
+#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
+
+#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
+ x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
+
+#ifdef LWIP_NOASSERT_ON_ERROR
+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
+ handler;}} while(0)
+#endif
+
+#define LWIP_RAND() ((u32_t)rand())
+
+struct sio_status_s;
+typedef struct sio_status_s sio_status_t;
+#define sio_fd_t sio_status_t*
+#define __sio_fd_t_defined
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/ports/fuchsia/include/arch/sys_arch.h b/ports/fuchsia/include/arch/sys_arch.h
new file mode 100644
index 0000000..438806e
--- /dev/null
+++ b/ports/fuchsia/include/arch/sys_arch.h
@@ -0,0 +1,60 @@
+/*
+ * 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: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef LWIP_ARCH_SYS_ARCH_H
+#define LWIP_ARCH_SYS_ARCH_H
+
+#include <errno.h>
+
+#define SYS_MBOX_NULL NULL
+#define SYS_SEM_NULL NULL
+
+typedef u32_t sys_prot_t;
+
+struct sys_sem;
+typedef struct sys_sem * sys_sem_t;
+#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL))
+#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0)
+
+struct sys_mutex;
+typedef struct sys_mutex * sys_mutex_t;
+#define sys_mutex_valid(mutex) sys_sem_valid(mutex)
+#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex)
+
+struct sys_mbox;
+typedef struct sys_mbox * sys_mbox_t;
+#define sys_mbox_valid(mbox) sys_sem_valid(mbox)
+#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox)
+
+struct sys_thread;
+typedef struct sys_thread * sys_thread_t;
+
+#endif /* LWIP_ARCH_SYS_ARCH_H */
diff --git a/ports/fuchsia/include/lwipopts.h b/ports/fuchsia/include/lwipopts.h
new file mode 100644
index 0000000..4a0114c
--- /dev/null
+++ b/ports/fuchsia/include/lwipopts.h
@@ -0,0 +1,358 @@
+/*
+ * 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: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef LWIP_LWIPOPTS_H
+#define LWIP_LWIPOPTS_H
+
+#include "lwip/arch.h"
+
+#define LWIP_NETIF_LOOPBACK 1
+#define LWIP_LOOPBACK_MAX_PBUFS 20
+
+#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1
+
+#define LWIP_IPV4 1
+#define LWIP_IPV6 1
+
+#define LWIP_COMPAT_SOCKETS 0
+
+#define LWIP_DBG_MIN_LEVEL 0
+
+#define TAPIF_DEBUG LWIP_DBG_OFF
+#define TUNIF_DEBUG LWIP_DBG_OFF
+#define UNIXIF_DEBUG LWIP_DBG_OFF
+#define DELIF_DEBUG LWIP_DBG_OFF
+#define SIO_FIFO_DEBUG LWIP_DBG_OFF
+#define TCPDUMP_DEBUG LWIP_DBG_OFF
+
+#define SLIP_DEBUG LWIP_DBG_OFF
+#define PPP_DEBUG LWIP_DBG_OFF
+#define MEM_DEBUG LWIP_DBG_OFF
+#define MEMP_DEBUG LWIP_DBG_OFF
+#define PBUF_DEBUG LWIP_DBG_OFF
+#define API_LIB_DEBUG LWIP_DBG_OFF
+#define API_MSG_DEBUG LWIP_DBG_OFF
+#define TCPIP_DEBUG LWIP_DBG_OFF
+#define NETIF_DEBUG LWIP_DBG_OFF
+#define SOCKETS_DEBUG LWIP_DBG_OFF
+#define DEMO_DEBUG LWIP_DBG_OFF
+#define IP_DEBUG LWIP_DBG_OFF
+#define IP_REASS_DEBUG LWIP_DBG_OFF
+#define RAW_DEBUG LWIP_DBG_OFF
+#define ICMP_DEBUG LWIP_DBG_OFF
+#define UDP_DEBUG LWIP_DBG_OFF
+#define TCP_DEBUG LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
+#define TCP_RTO_DEBUG LWIP_DBG_OFF
+#define TCP_CWND_DEBUG LWIP_DBG_OFF
+#define TCP_WND_DEBUG LWIP_DBG_OFF
+#define TCP_FR_DEBUG LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG LWIP_DBG_OFF
+#define TCP_RST_DEBUG LWIP_DBG_OFF
+
+extern unsigned char lwip_debug_flags;
+#define LWIP_DBG_TYPES_ON lwip_debug_flags
+
+#define NO_SYS 0
+#define LWIP_SOCKET (NO_SYS==0)
+#define LWIP_NETCONN (NO_SYS==0)
+#define SO_REUSE 1
+#define IP_SOF_BROADCAST_RECV 1
+#define IP_SOF_BROADCAST 1
+#define SO_REUSE_RXTOALL 1
+
+/* ---------- Memory options ---------- */
+/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
+ lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
+ byte alignment -> define MEM_ALIGNMENT to 2. */
+/* MSVC port: intel processors don't need 4-byte alignment,
+ but are faster that way! */
+#define MEM_ALIGNMENT 4
+
+/* MEM_SIZE: the size of the heap memory. If the application will send
+a lot of data that needs to be copied, this should be set high. */
+#define MEM_SIZE 24000
+
+/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
+ sends a lot of data out of ROM (or other static memory), this
+ should be set high. */
+#define MEMP_NUM_PBUF 16
+/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One
+ per active RAW "connection". */
+#define MEMP_NUM_RAW_PCB 3
+/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+ per active UDP "connection". */
+#define MEMP_NUM_UDP_PCB 64
+/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
+ connections. */
+#define MEMP_NUM_TCP_PCB 64
+/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
+ connections. */
+#define MEMP_NUM_TCP_PCB_LISTEN 64
+/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
+ segments. */
+#define MEMP_NUM_TCP_SEG 360
+/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
+ timeouts. */
+#define MEMP_NUM_SYS_TIMEOUT 120
+
+/* The following four are used only with the sequential API and can be
+ set to 0 if the application only will use the raw API. */
+/* MEMP_NUM_NETBUF: the number of struct netbufs. */
+#define MEMP_NUM_NETBUF 2
+/* MEMP_NUM_NETCONN: the number of struct netconns. */
+#define MEMP_NUM_NETCONN 100
+/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
+ for sequential API communication and incoming packets. Used in
+ src/api/tcpip.c. */
+#define MEMP_NUM_TCPIP_MSG_API 120
+#define MEMP_NUM_TCPIP_MSG_INPKT 120
+
+/* ---------- Pbuf options ---------- */
+/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
+#define PBUF_POOL_SIZE 3600
+
+/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
+#define PBUF_POOL_BUFSIZE 128
+
+/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
+ link level header. */
+#define PBUF_LINK_HLEN 16
+
+/** SYS_LIGHTWEIGHT_PROT
+ * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
+ * for certain critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT 1
+
+#define LWIP_TCPIP_TIMEOUT 1
+
+/* ---------- TCP options ---------- */
+#define LWIP_TCP 1
+#define TCP_TTL 255
+
+#define TCP_LISTEN_BACKLOG 1
+
+/* Controls if TCP should queue segments that arrive out of
+ order. Define to 0 if your device is low on memory. */
+#define TCP_QUEUE_OOSEQ 1
+
+/* TCP Maximum segment size. */
+#define TCP_MSS 1024
+
+/* TCP sender buffer space (bytes). */
+#define TCP_SND_BUF 2048
+
+/* TCP sender buffer space (pbufs). This must be at least = 2 *
+ TCP_SND_BUF/TCP_MSS for things to work. */
+#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS)
+
+/* TCP writable space (bytes). This must be less than or equal
+ to TCP_SND_BUF. It is the amount of space which must be
+ available in the tcp snd_buf for select to return writable */
+#define TCP_SNDLOWAT (TCP_SND_BUF/2)
+
+/* TCP receive window. */
+#define TCP_WND 8096
+
+/* Maximum number of retransmissions of data segments. */
+#define TCP_MAXRTX 12
+
+/* Maximum number of retransmissions of SYN segments. */
+#define TCP_SYNMAXRTX 4
+
+/* ---------- ARP options ---------- */
+#define LWIP_ARP 1
+#define ARP_TABLE_SIZE 10
+#define ARP_QUEUEING 1
+
+/* ---------- IP options ---------- */
+/* Define IP_FORWARD to 1 if you wish to have the ability to forward
+ IP packets across network interfaces. If you are going to run lwIP
+ on a device with only one network interface, define this to 0. */
+#define IP_FORWARD 1
+
+
+/* IP reassembly and segmentation.These are orthogonal even
+ * if they both deal with IP fragments */
+#define IP_REASSEMBLY 1
+#define IP_REASS_MAX_PBUFS 10
+#define MEMP_NUM_REASSDATA 10
+#define IP_FRAG 1
+#define IPV6_FRAG_COPYHEADER 1
+
+#define LWIP_IGMP 1
+
+/* ---------- ICMP options ---------- */
+#define ICMP_TTL 255
+
+/* ---------- DHCP options ---------- */
+/* Define LWIP_DHCP to 1 if you want DHCP configuration of
+ interfaces. */
+#define LWIP_DHCP 1
+
+#define LWIP_DHCP_GET_NTP_SRV 0
+
+/* 1 if you want to do an ARP check on the offered address
+ (recommended if using DHCP). */
+#define DHCP_DOES_ARP_CHECK (LWIP_DHCP)
+
+/* ---------- AUTOIP options ------- */
+#define LWIP_AUTOIP (LWIP_DHCP)
+
+/* ---------- SNTP options --------- */
+extern void sntp_set_system_time(u32_t sec);
+#define SNTP_SET_SYSTEM_TIME(s) sntp_set_system_time(s)
+
+/* ---------- SNMP options ---------- */
+#define LWIP_SNMP 1
+#define MIB2_STATS LWIP_SNMP
+#define SNMP_USE_NETCONN LWIP_NETCONN
+#define SNMP_USE_RAW (!LWIP_NETCONN)
+
+/* ---------- DNS options ---------- */
+#define LWIP_DNS 1
+
+/* ---------- UDP options ---------- */
+#define LWIP_UDP 1
+#define UDP_TTL 255
+
+/* ---------- RAW options ---------- */
+#define LWIP_RAW 0
+#define RAW_TTL 255
+
+/* ---------- Statistics options ---------- */
+/* individual STATS options can be turned off by defining them to 0
+ * (e.g #define TCP_STATS 0). All of them are turned off if LWIP_STATS
+ * is 0
+ * */
+
+#define LWIP_STATS 1
+#define LWIP_STATS_DISPLAY 1
+
+#define LWIP_NETIF_API 1
+#define LWIP_NETIF_STATUS_CALLBACK 1
+#define LWIP_NETIF_HOSTNAME 0
+
+/* ---------- SLIP options ---------- */
+
+#define LWIP_HAVE_SLIPIF 1 /* Set > 0 for SLIP */
+
+/* Maximum packet size that is received by this netif */
+#define SLIP_MAX_SIZE 1500
+#define sio_tryread sio_read
+
+/* ---------- 6LoWPAN options ---------- */
+#define LWIP_6LOWPAN 1
+
+/* ---------- PPP options ---------- */
+
+#define PPP_SUPPORT 0 /* Set > 0 for PPP */
+#define MPPE_SUPPORT PPP_SUPPORT
+#define PPPOE_SUPPORT PPP_SUPPORT
+#define PPPOL2TP_SUPPORT PPP_SUPPORT
+#define PPPOS_SUPPORT PPP_SUPPORT
+
+#if PPP_SUPPORT > 0
+
+#define NUM_PPP 1 /* Max PPP sessions. */
+
+
+/* Select modules to enable. Ideally these would be set in the makefile but
+ * we're limited by the command line length so you need to modify the settings
+ * in this file.
+ */
+#define PAP_SUPPORT 1 /* Set > 0 for PAP. */
+#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */
+#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */
+#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */
+#define CCP_SUPPORT 0 /* Set > 0 for CCP (NOT FUNCTIONAL!) */
+#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */
+#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */
+
+
+/*
+ * Timeouts.
+ */
+#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */
+#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
+#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
+#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
+
+#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */
+#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
+
+#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */
+#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */
+
+
+/* Interval in seconds between keepalive echo requests, 0 to disable. */
+#if 1
+#define LCP_ECHOINTERVAL 0
+#else
+#define LCP_ECHOINTERVAL 10
+#endif
+
+/* Number of unanswered echo requests before failure. */
+#define LCP_MAXECHOFAILS 3
+
+/* Max Xmit idle time (in jiffies) before resend flag char. */
+#define PPP_MAXIDLEFLAG 100
+
+/*
+ * Packet sizes
+ *
+ * Note - lcp shouldn't be allowed to negotiate stuff outside these
+ * limits. See lcp.h in the pppd directory.
+ * (XXX - these constants should simply be shared by lcp.c instead
+ * of living in lcp.h)
+ */
+#define PPP_MTU 1500 /* Default MTU (size of Info field) */
+#if 0
+#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN)
+#else
+#define PPP_MAXMTU 1500 /* Largest MTU we allow */
+#endif
+#define PPP_MINMTU 64
+#define PPP_MRU 1500 /* default MRU = max length of info field */
+#define PPP_MAXMRU 1500 /* Largest MRU we allow */
+#define PPP_DEFMRU 296 /* Try for this */
+#define PPP_MINMRU 128 /* No MRUs below this */
+
+
+#define MAXNAMELEN 256 /* max length of hostname or name for auth */
+#define MAXSECRETLEN 256 /* max length of password or secret */
+
+#endif /* PPP_SUPPORT > 0 */
+
+#endif /* LWIP_LWIPOPTS_H */
diff --git a/ports/fuchsia/include/netif/ethernetif.h b/ports/fuchsia/include/netif/ethernetif.h
new file mode 100644
index 0000000..c810bef
--- /dev/null
+++ b/ports/fuchsia/include/netif/ethernetif.h
@@ -0,0 +1,12 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LWIP_ETHERNETIF_H
+#define LWIP_ETHERNETIF_H
+
+#include "lwip/netif.h"
+
+err_t ethernetif_init(struct netif *netif);
+
+#endif /* LWIP_ETHERNETIF_H */
diff --git a/ports/fuchsia/netif/ethernetif.c b/ports/fuchsia/netif/ethernetif.c
new file mode 100644
index 0000000..24ce7d1
--- /dev/null
+++ b/ports/fuchsia/netif/ethernetif.c
@@ -0,0 +1,340 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <dirent.h>
+
+#include <magenta/types.h>
+#include <magenta/syscalls.h>
+#include <magenta/processargs.h>
+#include <mxio/io.h>
+#include <mxio/util.h>
+
+#include "lwip/opt.h"
+
+#include "lwip/debug.h"
+#include "lwip/def.h"
+#include "lwip/ip.h"
+#include "lwip/mem.h"
+#include "lwip/stats.h"
+#include "lwip/snmp.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include "lwip/timeouts.h"
+#include "netif/etharp.h"
+#include "lwip/ethip6.h"
+
+#include "netif/ethernetif.h"
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 'e'
+#define IFNAME1 'n'
+
+#define IO_TYPE_FD 1
+#define IO_TYPE_CHANNEL 2
+
+struct ethernetif {
+ /* Add whatever per-interface state that is needed here. */
+ int io_type;
+ union {
+ int fd;
+ mx_handle_t h;
+ } io;
+};
+
+/* Forward declarations. */
+static void ethernetif_input(struct netif *netif);
+static void ethernetif_thread(void *arg);
+
+/*-----------------------------------------------------------------------------------*/
+static int read_packet(struct netif *netif, void *buf, size_t count)
+{
+ struct ethernetif *ethernetif = (struct ethernetif *)netif->state;
+
+ if (ethernetif->io_type == IO_TYPE_FD) {
+ return read(ethernetif->io.fd, buf, count);
+ }
+ if (ethernetif->io_type == IO_TYPE_CHANNEL) {
+ uint32_t sz = count;
+ mx_status_t r;
+ if ((r = mx_channel_read(ethernetif->io.h, 0, buf, sz, &sz, NULL, 0, NULL)) < 0)
+ return -1;
+ return sz;
+ }
+ printf("ethernetif: not initialized correctly\n");
+ return ERR_INTERNAL;
+}
+
+static int write_packet(struct netif *netif, const void *buf, size_t count)
+{
+ struct ethernetif *ethernetif = (struct ethernetif *)netif->state;
+
+ if (ethernetif->io_type == IO_TYPE_FD) {
+ return write(ethernetif->io.fd, buf, count);
+ }
+ if (ethernetif->io_type == IO_TYPE_CHANNEL) {
+ ssize_t r;
+ if ((r = mx_channel_write(ethernetif->io.h, 0, buf, count, NULL, 0)) < 0)
+ return -1;
+ return count;
+ }
+ printf("ethernetif: not initialized correctly\n");
+ return -1;
+}
+
+static int
+open_ethernet_device(u8_t *hwaddr, u8_t *hwaddr_len)
+{
+ DIR* dir;
+ struct dirent* de;
+ int fd = -1;
+
+ if ((dir = opendir("/dev/class/ethernet")) == NULL) {
+ printf("ethernetif_init: cannot open /dev/class/ethernet\n");
+ return -1;
+ }
+ while ((de = readdir(dir)) != NULL) {
+ if (de->d_name[0] == '.') {
+ continue;
+ }
+ if ((fd = openat(dirfd(dir), de->d_name, O_RDWR)) >= 0) {
+ break;
+ }
+ }
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: fd %d\n", fd));
+ closedir(dir);
+
+ if (*hwaddr_len < 6 || read(fd, hwaddr, 6) != 6) {
+ printf("ethernetif_init: cannot read MAC address\n");
+ close(fd);
+ return -1;
+ }
+ LWIP_DEBUGF(NETIF_DEBUG,
+ ("ethernetif_init: mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ hwaddr[0], hwaddr[1], hwaddr[2],
+ hwaddr[3], hwaddr[4], hwaddr[5]));
+ *hwaddr_len = 6;
+
+ return fd;
+}
+
+static void
+low_level_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif = (struct ethernetif *)netif->state;
+
+ mx_handle_t h;
+ int fd;
+
+ netif->hwaddr_len = 6u;
+
+ if ((h = mxio_get_startup_handle(MX_HND_INFO(MX_HND_TYPE_USER0, 0))) !=
+ MX_HANDLE_INVALID) {
+ ethernetif->io_type = IO_TYPE_CHANNEL;
+ ethernetif->io.h = h;
+ printf("ethernetif_init: using a startup handle\n");
+ } else if ((fd = open_ethernet_device(netif->hwaddr,
+ &netif->hwaddr_len)) >= 0) {
+ ethernetif->io_type = IO_TYPE_FD;
+ ethernetif->io.fd = fd;
+ printf("ethernetif_init: opened an ethernet devie\n");
+ } else {
+ printf("ethernetif_init: initialization failed\n");
+ return;
+ }
+
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
+
+ /* if the io type is fd, link up now */
+ if (ethernetif->io_type == IO_TYPE_FD)
+ netif_set_link_up(netif);
+
+ sys_thread_new("ethernetif_thread", ethernetif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
+}
+
+static err_t
+low_level_output(struct netif *netif, struct pbuf *p)
+{
+ char buf[1514]; /* MTU (1500) + header (14) */
+ ssize_t written;
+
+ pbuf_copy_partial(p, buf, p->tot_len, 0);
+
+ /*
+ * Pad spaces toward the minimum packet size (60 bytes without FCS)
+ * as the driver doesn't do it for us.
+ */
+#define MIN_WRITE_SIZE 60
+
+ int write_len = p->tot_len;
+ if (write_len < MIN_WRITE_SIZE) {
+ memset(buf + write_len, 0, MIN_WRITE_SIZE - write_len);
+ write_len = MIN_WRITE_SIZE;
+ }
+ written = write_packet(netif, buf, write_len);
+ if (written == -1) {
+ MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
+ printf("ethernetif: write %d bytes returned -1\n", p->tot_len);
+ }
+ else {
+ MIB2_STATS_NETIF_ADD(netif, ifoutoctets, written);
+ }
+ return ERR_OK;
+}
+
+#define TIMER_MS(n) (((uint64_t)(n)) * 1000000ULL)
+
+static struct pbuf *
+low_level_input(struct netif *netif)
+{
+ struct pbuf *p;
+ int len;
+ /* TODO(toshik)
+ * The driver expects at least 2048 bytes for the buffer size. Reading less
+ * than that would fail (Currently 2048 is a magic number)
+ */
+ char buf[2048];
+
+ len = read_packet(netif, buf, sizeof(buf));
+ if (len < 0) {
+ /* TODO(toshik)
+ * Currently read() often fails because ethernetif_input() is called even
+ * if the fd is not readable.
+ */
+ /* LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: read returned %d\n", len)); */
+ return NULL;
+ }
+ if (len == 8) {
+ /* status message: mac (6 bytes) + mtu (2 bytes) */
+ unsigned int mtu = *(unsigned short int*)(buf+6);
+ if (mtu > 0) {
+ /* link up */
+ memcpy(netif->hwaddr, buf, 6);
+ printf("ethernetif: link up (mac %02x:%02x:%02x:%02x:%02x:%02x,"
+ " mtu %u)\n",
+ (uint8_t)buf[0], (uint8_t)buf[1], (uint8_t)buf[2], (uint8_t)buf[3],
+ (uint8_t)buf[4], (uint8_t)buf[5], mtu);
+ netif_set_link_up(netif);
+ } else {
+ /* link down */
+ printf("ethernetif: link down\n");
+ netif_set_link_down(netif);
+ }
+ }
+
+ MIB2_STATS_NETIF_ADD(netif, ifinoctets, len);
+
+ /* We allocate a pbuf chain of pbufs from the pool. */
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p != NULL) {
+ pbuf_take(p, buf, len);
+ /* acknowledge that packet has been read(); */
+ } else {
+ /* drop packet(); */
+ MIB2_STATS_NETIF_INC(netif, ifindiscards);
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: could not allocate pbuf\n"));
+ }
+
+ return p;
+}
+
+static void
+ethernetif_input(struct netif *netif)
+{
+ struct pbuf *p = low_level_input(netif);
+
+ if (p == NULL) {
+ /* TODO(toshik)
+ * Currently low_level_input() may return NULL often because
+ * ethernetif_input() is called even if the fd is not readable.
+ * Disable the following code for now.
+ */
+#if 0
+#if LINK_STATS
+ LINK_STATS_INC(link.recv);
+#endif /* LINK_STATS */
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: low_level_input returned NULL\n"));
+#endif
+ return;
+ }
+
+ if (netif->input(p, netif) != ERR_OK) {
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: netif input error\n"));
+ pbuf_free(p);
+ }
+}
+
+err_t
+ethernetif_init(struct netif *netif)
+{
+ struct ethernetif *ethernetif = (struct ethernetif *)mem_malloc(sizeof(struct ethernetif));
+
+ if (ethernetif == NULL) {
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory for ethernetif\n"));
+ return ERR_MEM;
+ }
+ ethernetif->io_type = -1;
+
+ netif->state = ethernetif;
+ MIB2_INIT_NETIF(netif, snmp_ifType_other, 100000000);
+
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = etharp_output;
+ netif->output_ip6 = ethip6_output;
+ netif->linkoutput = low_level_output;
+ netif->mtu = 1500;
+
+ low_level_init(netif);
+
+ return ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------*/
+
+static void
+ethernetif_thread(void *arg)
+{
+ struct netif *netif;
+ struct ethernetif *ethernetif;
+
+ netif = (struct netif *)arg;
+ ethernetif = (struct ethernetif *)netif->state;
+
+ while(1) {
+ if (ethernetif->io_type == IO_TYPE_FD) {
+ mxio_wait_fd(ethernetif->io.fd, MXIO_EVT_READABLE, NULL,
+ MX_TIME_INFINITE);
+ } else if (ethernetif->io_type == IO_TYPE_CHANNEL) {
+ mx_status_t r;
+ mx_signals_t pending;
+ r = mx_handle_wait_one(ethernetif->io.h,
+ MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED,
+ MX_TIME_INFINITE, &pending);
+ if (r < 0) {
+ printf("ethernetif: handle wait error (%d)\n", r);
+ return;
+ }
+ if (pending & MX_SIGNAL_PEER_CLOSED) {
+ printf("ethernetif: handle closed\n");
+ return;
+ }
+ }
+ /* TODO(toshik) mxio_wait_fd() might return even if the fd is not readable.
+ * we should check why it returned, but it is not possible as errno is not
+ * set currently.
+ */
+ ethernetif_input(netif);
+ }
+}
diff --git a/ports/fuchsia/sys_arch.c b/ports/fuchsia/sys_arch.c
new file mode 100644
index 0000000..98eb21d
--- /dev/null
+++ b/ports/fuchsia/sys_arch.c
@@ -0,0 +1,648 @@
+/*
+ * 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: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/*
+ * Wed Apr 17 16:05:29 EDT 2002 (James Roth)
+ *
+ * - Fixed an unlikely sys_thread_new() race condition.
+ *
+ * - Made current_thread() work with threads which where
+ * not created with sys_thread_new(). This includes
+ * the main thread and threads made with pthread_create().
+ *
+ * - Catch overflows where more than SYS_MBOX_SIZE messages
+ * are waiting to be read. The sys_mbox_post() routine
+ * will block until there is more room instead of just
+ * leaking messages.
+ */
+#include "lwip/debug.h"
+
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "lwip/def.h"
+
+#ifdef LWIP_UNIX_MACH
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#endif
+
+#include "lwip/sys.h"
+#include "lwip/opt.h"
+#include "lwip/stats.h"
+
+static void
+get_monotonic_time(struct timespec *ts)
+{
+#ifdef LWIP_UNIX_MACH
+ /* darwin impl (no CLOCK_MONOTONIC) */
+ uint64_t t = mach_absolute_time();
+ mach_timebase_info_data_t timebase_info = {0, 0};
+ mach_timebase_info(&timebase_info);
+ uint64_t nano = (t * timebase_info.numer) / (timebase_info.denom);
+ uint64_t sec = nano/1000000000L;
+ nano -= sec * 1000000000L;
+ ts->tv_sec = sec;
+ ts->tv_nsec = nano;
+#else
+ clock_gettime(CLOCK_MONOTONIC, ts);
+#endif
+}
+
+#if !NO_SYS
+
+static struct sys_thread *threads = NULL;
+static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+struct sys_mbox_msg {
+ struct sys_mbox_msg *next;
+ void *msg;
+};
+
+#define SYS_MBOX_SIZE 128
+
+struct sys_mbox {
+ int first, last;
+ void *msgs[SYS_MBOX_SIZE];
+ struct sys_sem *not_empty;
+ struct sys_sem *not_full;
+ struct sys_sem *mutex;
+ int wait_send;
+};
+
+struct sys_sem {
+ unsigned int c;
+ pthread_condattr_t condattr;
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+};
+
+struct sys_mutex {
+ pthread_mutex_t mutex;
+};
+
+struct sys_thread {
+ struct sys_thread *next;
+ pthread_t pthread;
+};
+
+#if SYS_LIGHTWEIGHT_PROT
+static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t lwprot_thread = (pthread_t)0xDEAD;
+static int lwprot_count = 0;
+#endif /* SYS_LIGHTWEIGHT_PROT */
+
+static struct sys_sem *sys_sem_new_internal(u8_t count);
+static void sys_sem_free_internal(struct sys_sem *sem);
+
+static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ u32_t timeout);
+
+/*-----------------------------------------------------------------------------------*/
+/* Threads */
+static struct sys_thread *
+introduce_thread(pthread_t id)
+{
+ struct sys_thread *thread;
+
+ thread = (struct sys_thread *)malloc(sizeof(struct sys_thread));
+
+ if (thread != NULL) {
+ pthread_mutex_lock(&threads_mutex);
+ thread->next = threads;
+ thread->pthread = id;
+ threads = thread;
+ pthread_mutex_unlock(&threads_mutex);
+ }
+
+ return thread;
+}
+
+sys_thread_t
+sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
+{
+ int code;
+ pthread_t tmp;
+ struct sys_thread *st = NULL;
+ LWIP_UNUSED_ARG(name);
+ LWIP_UNUSED_ARG(stacksize);
+ LWIP_UNUSED_ARG(prio);
+
+ code = pthread_create(&tmp,
+ NULL,
+ (void *(*)(void *))
+ function,
+ arg);
+
+ if (0 == code) {
+ st = introduce_thread(tmp);
+ }
+
+ if (NULL == st) {
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%lx",
+ code, (unsigned long)st));
+ abort();
+ }
+ return st;
+}
+
+/*-----------------------------------------------------------------------------------*/
+/* Mailbox */
+err_t
+sys_mbox_new(struct sys_mbox **mb, int size)
+{
+ struct sys_mbox *mbox;
+ LWIP_UNUSED_ARG(size);
+
+ mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox));
+ if (mbox == NULL) {
+ return ERR_MEM;
+ }
+ mbox->first = mbox->last = 0;
+ mbox->not_empty = sys_sem_new_internal(0);
+ mbox->not_full = sys_sem_new_internal(0);
+ mbox->mutex = sys_sem_new_internal(1);
+ mbox->wait_send = 0;
+
+ SYS_STATS_INC_USED(mbox);
+ *mb = mbox;
+ return ERR_OK;
+}
+
+void
+sys_mbox_free(struct sys_mbox **mb)
+{
+ if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) {
+ struct sys_mbox *mbox = *mb;
+ SYS_STATS_DEC(mbox.used);
+ sys_arch_sem_wait(&mbox->mutex, 0);
+
+ sys_sem_free_internal(mbox->not_empty);
+ sys_sem_free_internal(mbox->not_full);
+ sys_sem_free_internal(mbox->mutex);
+ mbox->not_empty = mbox->not_full = mbox->mutex = NULL;
+ /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
+ free(mbox);
+ }
+}
+
+err_t
+sys_mbox_trypost(struct sys_mbox **mb, void *msg)
+{
+ u8_t first;
+ struct sys_mbox *mbox;
+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
+ mbox = *mb;
+
+ sys_arch_sem_wait(&mbox->mutex, 0);
+
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
+ (void *)mbox, (void *)msg));
+
+ if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
+ sys_sem_signal(&mbox->mutex);
+ return ERR_MEM;
+ }
+
+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
+
+ if (mbox->last == mbox->first) {
+ first = 1;
+ } else {
+ first = 0;
+ }
+
+ mbox->last++;
+
+ if (first) {
+ sys_sem_signal(&mbox->not_empty);
+ }
+
+ sys_sem_signal(&mbox->mutex);
+
+ return ERR_OK;
+}
+
+void
+sys_mbox_post(struct sys_mbox **mb, void *msg)
+{
+ u8_t first;
+ struct sys_mbox *mbox;
+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
+ mbox = *mb;
+
+ sys_arch_sem_wait(&mbox->mutex, 0);
+
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
+
+ while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
+ mbox->wait_send++;
+ sys_sem_signal(&mbox->mutex);
+ sys_arch_sem_wait(&mbox->not_full, 0);
+ sys_arch_sem_wait(&mbox->mutex, 0);
+ mbox->wait_send--;
+ }
+
+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
+
+ if (mbox->last == mbox->first) {
+ first = 1;
+ } else {
+ first = 0;
+ }
+
+ mbox->last++;
+
+ if (first) {
+ sys_sem_signal(&mbox->not_empty);
+ }
+
+ sys_sem_signal(&mbox->mutex);
+}
+
+u32_t
+sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg)
+{
+ struct sys_mbox *mbox;
+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
+ mbox = *mb;
+
+ sys_arch_sem_wait(&mbox->mutex, 0);
+
+ if (mbox->first == mbox->last) {
+ sys_sem_signal(&mbox->mutex);
+ return SYS_MBOX_EMPTY;
+ }
+
+ if (msg != NULL) {
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
+ }
+ else{
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
+ }
+
+ mbox->first++;
+
+ if (mbox->wait_send) {
+ sys_sem_signal(&mbox->not_full);
+ }
+
+ sys_sem_signal(&mbox->mutex);
+
+ return 0;
+}
+
+u32_t
+sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout)
+{
+ u32_t time_needed = 0;
+ struct sys_mbox *mbox;
+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
+ mbox = *mb;
+
+ /* The mutex lock is quick so we don't bother with the timeout
+ stuff here. */
+ sys_arch_sem_wait(&mbox->mutex, 0);
+
+ while (mbox->first == mbox->last) {
+ sys_sem_signal(&mbox->mutex);
+
+ /* We block while waiting for a mail to arrive in the mailbox. We
+ must be prepared to timeout. */
+ if (timeout != 0) {
+ time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout);
+
+ if (time_needed == SYS_ARCH_TIMEOUT) {
+ return SYS_ARCH_TIMEOUT;
+ }
+ } else {
+ sys_arch_sem_wait(&mbox->not_empty, 0);
+ }
+
+ sys_arch_sem_wait(&mbox->mutex, 0);
+ }
+
+ if (msg != NULL) {
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
+ }
+ else{
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
+ }
+
+ mbox->first++;
+
+ if (mbox->wait_send) {
+ sys_sem_signal(&mbox->not_full);
+ }
+
+ sys_sem_signal(&mbox->mutex);
+
+ return time_needed;
+}
+
+/*-----------------------------------------------------------------------------------*/
+/* Semaphore */
+static struct sys_sem *
+sys_sem_new_internal(u8_t count)
+{
+ struct sys_sem *sem;
+
+ sem = (struct sys_sem *)malloc(sizeof(struct sys_sem));
+ if (sem != NULL) {
+ sem->c = count;
+ pthread_condattr_init(&(sem->condattr));
+#ifndef LWIP_UNIX_MACH
+ pthread_condattr_setclock(&(sem->condattr), CLOCK_MONOTONIC);
+#endif
+ pthread_cond_init(&(sem->cond), &(sem->condattr));
+ pthread_mutex_init(&(sem->mutex), NULL);
+ }
+ return sem;
+}
+
+err_t
+sys_sem_new(struct sys_sem **sem, u8_t count)
+{
+ SYS_STATS_INC_USED(sem);
+ *sem = sys_sem_new_internal(count);
+ if (*sem == NULL) {
+ return ERR_MEM;
+ }
+ return ERR_OK;
+}
+
+static u32_t
+cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout)
+{
+ struct timespec rtime1, rtime2, ts;
+ int ret;
+
+ if (timeout == 0) {
+ pthread_cond_wait(cond, mutex);
+ return 0;
+ }
+
+ /* Get a timestamp and add the timeout value. */
+ get_monotonic_time(&rtime1);
+#ifdef LWIP_UNIX_MACH
+ ts.tv_sec = timeout / 1000L;
+ ts.tv_nsec = (timeout % 1000L) * 1000000L;
+ ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
+#else
+ ts.tv_sec = rtime1.tv_sec + timeout / 1000L;
+ ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L;
+ if (ts.tv_nsec >= 1000000000L) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000L;
+ }
+
+ ret = pthread_cond_timedwait(cond, mutex, &ts);
+#endif
+ if (ret == ETIMEDOUT) {
+ return SYS_ARCH_TIMEOUT;
+ }
+
+ /* Calculate for how long we waited for the cond. */
+ get_monotonic_time(&rtime2);
+ ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec;
+ ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec;
+ if (ts.tv_nsec < 0) {
+ ts.tv_sec--;
+ ts.tv_nsec += 1000000000L;
+ }
+ return ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
+}
+
+u32_t
+sys_arch_sem_wait(struct sys_sem **s, u32_t timeout)
+{
+ u32_t time_needed = 0;
+ struct sys_sem *sem;
+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL));
+ sem = *s;
+
+ pthread_mutex_lock(&(sem->mutex));
+ while (sem->c <= 0) {
+ if (timeout > 0) {
+ time_needed = cond_wait(&(sem->cond), &(sem->mutex), timeout);
+
+ if (time_needed == SYS_ARCH_TIMEOUT) {
+ pthread_mutex_unlock(&(sem->mutex));
+ return SYS_ARCH_TIMEOUT;
+ }
+ /* pthread_mutex_unlock(&(sem->mutex));
+ return time_needed; */
+ } else {
+ cond_wait(&(sem->cond), &(sem->mutex), 0);
+ }
+ }
+ sem->c--;
+ pthread_mutex_unlock(&(sem->mutex));
+ return (u32_t)time_needed;
+}
+
+void
+sys_sem_signal(struct sys_sem **s)
+{
+ struct sys_sem *sem;
+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL));
+ sem = *s;
+
+ pthread_mutex_lock(&(sem->mutex));
+ sem->c++;
+
+ if (sem->c > 1) {
+ sem->c = 1;
+ }
+
+ pthread_cond_broadcast(&(sem->cond));
+ pthread_mutex_unlock(&(sem->mutex));
+}
+
+static void
+sys_sem_free_internal(struct sys_sem *sem)
+{
+ pthread_cond_destroy(&(sem->cond));
+ pthread_condattr_destroy(&(sem->condattr));
+ pthread_mutex_destroy(&(sem->mutex));
+ free(sem);
+}
+
+void
+sys_sem_free(struct sys_sem **sem)
+{
+ if ((sem != NULL) && (*sem != SYS_SEM_NULL)) {
+ SYS_STATS_DEC(sem.used);
+ sys_sem_free_internal(*sem);
+ }
+}
+
+/*-----------------------------------------------------------------------------------*/
+/* Mutex */
+/** Create a new mutex
+ * @param mutex pointer to the mutex to create
+ * @return a new mutex */
+err_t
+sys_mutex_new(struct sys_mutex **mutex)
+{
+ struct sys_mutex *mtx;
+
+ mtx = (struct sys_mutex *)malloc(sizeof(struct sys_mutex));
+ if (mtx != NULL) {
+ pthread_mutex_init(&(mtx->mutex), NULL);
+ *mutex = mtx;
+ return ERR_OK;
+ }
+ else {
+ return ERR_MEM;
+ }
+}
+
+/** Lock a mutex
+ * @param mutex the mutex to lock */
+void
+sys_mutex_lock(struct sys_mutex **mutex)
+{
+ pthread_mutex_lock(&((*mutex)->mutex));
+}
+
+/** Unlock a mutex
+ * @param mutex the mutex to unlock */
+void
+sys_mutex_unlock(struct sys_mutex **mutex)
+{
+ pthread_mutex_unlock(&((*mutex)->mutex));
+}
+
+/** Delete a mutex
+ * @param mutex the mutex to delete */
+void
+sys_mutex_free(struct sys_mutex **mutex)
+{
+ pthread_mutex_destroy(&((*mutex)->mutex));
+ free(*mutex);
+}
+
+#endif /* !NO_SYS */
+
+/*-----------------------------------------------------------------------------------*/
+/* Time */
+u32_t
+sys_now(void)
+{
+ struct timespec ts;
+
+ get_monotonic_time(&ts);
+ return ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
+}
+
+u32_t
+sys_jiffies(void)
+{
+ struct timespec ts;
+
+ get_monotonic_time(&ts);
+ return ts.tv_sec * 1000000000L + ts.tv_nsec;
+}
+
+/*-----------------------------------------------------------------------------------*/
+/* Init */
+
+void
+sys_init(void)
+{
+}
+
+/*-----------------------------------------------------------------------------------*/
+/* Critical section */
+#if SYS_LIGHTWEIGHT_PROT
+/** sys_prot_t sys_arch_protect(void)
+
+This optional function does a "fast" critical region protection and returns
+the previous protection level. This function is only called during very short
+critical regions. An embedded system which supports ISR-based drivers might
+want to implement this function by disabling interrupts. Task-based systems
+might want to implement this by using a mutex or disabling tasking. This
+function should support recursive calls from the same task or interrupt. In
+other words, sys_arch_protect() could be called while already protected. In
+that case the return value indicates that it is already protected.
+
+sys_arch_protect() is only required if your port is supporting an operating
+system.
+*/
+sys_prot_t
+sys_arch_protect(void)
+{
+ /* Note that for the UNIX port, we are using a lightweight mutex, and our
+ * own counter (which is locked by the mutex). The return code is not actually
+ * used. */
+ if (lwprot_thread != pthread_self())
+ {
+ /* We are locking the mutex where it has not been locked before *
+ * or is being locked by another thread */
+ pthread_mutex_lock(&lwprot_mutex);
+ lwprot_thread = pthread_self();
+ lwprot_count = 1;
+ }
+ else
+ /* It is already locked by THIS thread */
+ lwprot_count++;
+ return 0;
+}
+
+/** void sys_arch_unprotect(sys_prot_t pval)
+
+This optional function does a "fast" set of critical region protection to the
+value specified by pval. See the documentation for sys_arch_protect() for
+more information. This function is only required if your port is supporting
+an operating system.
+*/
+void
+sys_arch_unprotect(sys_prot_t pval)
+{
+ LWIP_UNUSED_ARG(pval);
+ if (lwprot_thread == pthread_self())
+ {
+ if (--lwprot_count == 0)
+ {
+ lwprot_thread = (pthread_t) 0xDEAD;
+ pthread_mutex_unlock(&lwprot_mutex);
+ }
+ }
+}
+#endif /* SYS_LIGHTWEIGHT_PROT */
diff --git a/src/netif/ethernet.c b/src/netif/ethernet.c
index 9b76e85..eeca11a 100644
--- a/src/netif/ethernet.c
+++ b/src/netif/ethernet.c
@@ -94,10 +94,10 @@
ethhdr = (struct eth_hdr *)p->payload;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n",
- (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
- (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
- (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
- (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
+ (unsigned char)ethhdr->dest.addr[0], (unsigned char)ethhdr->dest.addr[1], (unsigned char)ethhdr->dest.addr[2],
+ (unsigned char)ethhdr->dest.addr[3], (unsigned char)ethhdr->dest.addr[4], (unsigned char)ethhdr->dest.addr[5],
+ (unsigned char)ethhdr->src.addr[0], (unsigned char)ethhdr->src.addr[1], (unsigned char)ethhdr->src.addr[2],
+ (unsigned char)ethhdr->src.addr[3], (unsigned char)ethhdr->src.addr[4], (unsigned char)ethhdr->src.addr[5],
lwip_htons(ethhdr->type)));
type = ethhdr->type;