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;