bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Update patches


From: Joan Lledó
Subject: [PATCH] Update patches
Date: Sat, 22 Jun 2019 11:50:58 +0200

* debian/patches/max_sockets:
  * Update required after making changes in debian/patches/port
* debian/patches/patch9807:
  * New patch: Add new function tcpip_callback_wait() in tcpip.c
    * To call a function inside the tcpip thread and wait
      for it to return
* debian/patches/port:
  * Fix bug: Don't abort the whole stack on error
  * Fix some locking issues
  * Rename macro HURD_LWIP_LWIPOPTS_H to UNIX_LWIP_LWIPOPTS_H
  * Add all Unix port interface files
    * To make compilation of userspace programs in Linux easier
  * Detect 64bit systems
    * Macros in lwipopts.h must have different values in
      64bit systems
* debian/patches/series:
  * Add new patch debian/patches/patch9807
---
 debian/patches/max_sockets |    6 +-
 debian/patches/patch9807   |   98 ++
 debian/patches/port        | 1743 +++++++++++++++++++++++++++++++++++-
 debian/patches/series      |    1 +
 4 files changed, 1829 insertions(+), 19 deletions(-)
 create mode 100644 debian/patches/patch9807

diff --git a/debian/patches/max_sockets b/debian/patches/max_sockets
index 672a831..fbc8851 100644
--- a/debian/patches/max_sockets
+++ b/debian/patches/max_sockets
@@ -302,8 +302,8 @@ Won't get to upstream
  #define LWIP_SOCKET_EXTERNAL_HEADERS            1
 --- a/port/include/arch/cc.h
 +++ b/port/include/arch/cc.h
-@@ -47,6 +47,13 @@
- #define LWIP_UNIX_HURD
+@@ -52,6 +52,13 @@
+ #define IPV6_FRAG_COPYHEADER     1
  #endif
  
 +#if defined(LWIP_UNIX_LINUX) || defined(LWIP_UNIX_HURD)
@@ -316,7 +316,7 @@ Won't get to upstream
  #define LWIP_TIMEVAL_PRIVATE 0
  #include <sys/time.h>
  
-@@ -68,7 +75,7 @@
+@@ -73,7 +80,7 @@
  typedef __kernel_fd_set fd_set;
  #endif
  
diff --git a/debian/patches/patch9807 b/debian/patches/patch9807
new file mode 100644
index 0000000..894f8dc
--- /dev/null
+++ b/debian/patches/patch9807
@@ -0,0 +1,98 @@
+--- a/src/api/tcpip.c
++++ b/src/api/tcpip.c
+@@ -166,6 +166,11 @@
+       msg->msg.api_call.arg->err = 
msg->msg.api_call.function(msg->msg.api_call.arg);
+       sys_sem_signal(msg->msg.api_call.sem);
+       break;
++    case TCPIP_MSG_CALLBACK_STATIC_WAIT:
++      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK WAIT message %p\n", 
(void *)msg));
++      msg->msg.cb_wait.function(msg->msg.cb_wait.ctx);
++      sys_sem_signal(msg->msg.cb_wait.sem);
++      break;
+ #endif /* !LWIP_TCPIP_CORE_LOCKING */
+ 
+ #if !LWIP_TCPIP_CORE_LOCKING_INPUT
+@@ -590,6 +595,49 @@
+ }
+ 
+ /**
++ * Sends a message to TCPIP thread to call a function. Caller thread blocks
++ * until the function returns.
++ * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or
++ * LWIP_NETCONN_SEM_PER_THREAD.
++ * If not, a semaphore is created and destroyed on every call which is usually
++ * an expensive/slow operation.
++ *
++ * @param function the function to call
++ * @param ctx parameter passed to f
++ * @return ERR_OK if the function was called, another err_t if not
++ */
++err_t
++tcpip_callback_wait(tcpip_callback_fn function, void *ctx)
++{
++#if LWIP_TCPIP_CORE_LOCKING
++  LOCK_TCPIP_CORE();
++  function(ctx);
++  UNLOCK_TCPIP_CORE();
++  return ERR_OK;
++#else /* LWIP_TCPIP_CORE_LOCKING */
++  err_t err;
++  sys_sem_t sem;
++  struct tcpip_msg msg;
++
++  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
++
++  err = sys_sem_new(&sem, 0);
++  if (err != ERR_OK) {
++    return err;
++  }
++
++  msg.type = TCPIP_MSG_CALLBACK_STATIC_WAIT;
++  msg.msg.cb_wait.function = function;
++  msg.msg.cb_wait.ctx = ctx;
++  msg.msg.cb_wait.sem = &sem;
++  sys_mbox_post(&tcpip_mbox, &msg);
++  sys_arch_sem_wait(&sem, 0);
++  sys_sem_free(&sem);
++  return ERR_OK;
++#endif /* LWIP_TCPIP_CORE_LOCKING */
++}
++
++/**
+  * @ingroup lwip_os
+  * Initialize this module:
+  * - initialize all sub modules
+--- a/src/include/lwip/priv/tcpip_priv.h
++++ b/src/include/lwip/priv/tcpip_priv.h
+@@ -123,7 +123,8 @@
+   TCPIP_MSG_UNTIMEOUT,
+ #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
+   TCPIP_MSG_CALLBACK,
+-  TCPIP_MSG_CALLBACK_STATIC
++  TCPIP_MSG_CALLBACK_STATIC,
++  TCPIP_MSG_CALLBACK_STATIC_WAIT
+ };
+ 
+ struct tcpip_msg {
+@@ -139,6 +140,11 @@
+       struct tcpip_api_call_data *arg;
+       sys_sem_t *sem;
+     } api_call;
++    struct {
++      tcpip_callback_fn function;
++      void *ctx;
++      sys_sem_t *sem;
++    } cb_wait;
+ #endif /* LWIP_TCPIP_CORE_LOCKING */
+ #if !LWIP_TCPIP_CORE_LOCKING_INPUT
+     struct {
+--- a/src/include/lwip/tcpip.h
++++ b/src/include/lwip/tcpip.h
+@@ -81,6 +81,7 @@
+ 
+ err_t  tcpip_try_callback(tcpip_callback_fn function, void *ctx);
+ err_t  tcpip_callback(tcpip_callback_fn function, void *ctx);
++err_t  tcpip_callback_wait(tcpip_callback_fn function, void *ctx);
+ /**  @ingroup lwip_os
+  * @deprecated use tcpip_try_callback() or tcpip_callback() instead
+  */
diff --git a/debian/patches/port b/debian/patches/port
index 494be51..a45bd3f 100644
--- a/debian/patches/port
+++ b/debian/patches/port
@@ -2,7 +2,7 @@ Not intended to be upstream
 
 --- /dev/null
 +++ b/port/include/arch/cc.h
-@@ -0,0 +1,86 @@
+@@ -0,0 +1,91 @@
 +/*
 + * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
 + * All rights reserved. 
@@ -52,6 +52,11 @@ Not intended to be upstream
 +#define LWIP_UNIX_HURD
 +#endif
 +
++/* If the system is 64 bit */
++#if defined __LP64__
++#define IPV6_FRAG_COPYHEADER     1
++#endif
++
 +#define LWIP_TIMEVAL_PRIVATE 0
 +#include <sys/time.h>
 +
@@ -91,7 +96,7 @@ Not intended to be upstream
 +#endif /* LWIP_ARCH_CC_H */
 --- /dev/null
 +++ b/port/include/arch/sys_arch.h
-@@ -0,0 +1,63 @@
+@@ -0,0 +1,66 @@
 +/*
 + * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
 + * All rights reserved. 
@@ -129,6 +134,9 @@ Not intended to be upstream
 +#define SYS_MBOX_NULL NULL
 +#define SYS_SEM_NULL  NULL
 +
++/* Return code for an interrupted timed wait */
++#define SYS_ARCH_INTR 0xfffffffeUL
++
 +/*typedef u32_t sys_prot_t;*/
 +
 +struct sys_sem;
@@ -157,7 +165,7 @@ Not intended to be upstream
 +
 --- /dev/null
 +++ b/port/include/lwipopts.h
-@@ -0,0 +1,160 @@
+@@ -0,0 +1,169 @@
 +/*
 +   Copyright (C) 2017 Free Software Foundation, Inc.
 +   Written by Joan Lledó.
@@ -177,8 +185,8 @@ Not intended to be upstream
 +   You should have received a copy of the GNU General Public License
 +   along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.  */
 +
-+#ifndef HURD_LWIP_LWIPOPTS_H
-+#define HURD_LWIP_LWIPOPTS_H
++#ifndef UNIX_LWIP_LWIPOPTS_H
++#define UNIX_LWIP_LWIPOPTS_H
 +
 +/* An OS is present */
 +#define NO_SYS    0
@@ -197,7 +205,6 @@ Not intended to be upstream
 +#define MEM_LIBC_MALLOC   1
 +#define MEMP_MEM_MALLOC   1
 +#define MEM_USE_POOLS     0
-+#define MEM_ALIGNMENT     4
 +
 +/* Only send complete packets to the device */
 +#define LWIP_NETIF_TX_SINGLE_PBUF 1
@@ -264,9 +271,19 @@ Not intended to be upstream
 +#define LWIP_ICMP6            1
 +#define LWIP_IPV6_MLD         1
 +
++/* Don't abort the whole stack when an error is detected */
++#define LWIP_NOASSERT_ON_ERROR   1
++
 +/* Threading options */
 +#define LWIP_TCPIP_CORE_LOCKING   1
 +
++/* If the system is 64 bit */
++#if defined __LP64__
++#define MEM_ALIGNMENT            8
++#else
++#define MEM_ALIGNMENT            4
++#endif
++
 +#if !NO_SYS
 +void sys_check_core_locking(void);
 +#define LWIP_ASSERT_CORE_LOCKED()  sys_check_core_locking()
@@ -317,10 +334,10 @@ Not intended to be upstream
 +#define IP6_DEBUG         LWIP_DBG_OFF
 +#endif
 +
-+#endif
++#endif /* UNIX_LWIP_LWIPOPTS_H */
 --- /dev/null
 +++ b/port/sys_arch.c
-@@ -0,0 +1,722 @@
+@@ -0,0 +1,739 @@
 +/*
 + * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
 + * All rights reserved. 
@@ -806,8 +823,14 @@ Not intended to be upstream
 +#endif
 +
 +  if (timeout == 0) {
-+    pthread_cond_wait(cond, mutex);
-+    return 0;
++    ret = pthread_cond_wait(cond, mutex);
++    return
++#ifdef LWIP_UNIX_HURD
++    /* On the Hurd, ret == 1 means the RPC has been cancelled.
++     * The thread is awakened (not terminated) and execution must continue */
++    ret == 1 ? SYS_ARCH_INTR :
++#endif
++    (u32_t)ret;
 +  }
 +
 +  /* Get a timestamp and add the timeout value. */
@@ -828,6 +851,12 @@ Not intended to be upstream
 +#endif
 +  if (ret == ETIMEDOUT) {
 +    return SYS_ARCH_TIMEOUT;
++#ifdef LWIP_UNIX_HURD
++    /* On the Hurd, ret == 1 means the RPC has been cancelled.
++     * The thread is awakened (not terminated) and execution must continue */
++  } else if (ret == 1) {
++    return SYS_ARCH_INTR;
++#endif
 +  }
 +
 +  /* Calculate for how long we waited for the cond. */
@@ -846,6 +875,7 @@ Not intended to be upstream
 +{
 +  u32_t time_needed = 0;
 +  struct sys_sem *sem;
++  u32_t ret;
 +  LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL));
 +  sem = *s;
 +
@@ -857,14 +887,18 @@ Not intended to be upstream
 +      if (time_needed == SYS_ARCH_TIMEOUT) {
 +        pthread_mutex_unlock(&(sem->mutex));
 +        return SYS_ARCH_TIMEOUT;
++#ifdef LWIP_UNIX_HURD
++      } else if(time_needed == SYS_ARCH_INTR) {
++        pthread_mutex_unlock(&(sem->mutex));
++        return SYS_ARCH_INTR;
++#endif
 +      }
 +      /*      pthread_mutex_unlock(&(sem->mutex));
 +              return time_needed; */
-+    } else {
-+      cond_wait(&(sem->cond), &(sem->mutex), 0);
-+#ifdef LWIP_UNIX_HURD
-+      return 0;
-+#endif
++    } else if((ret = cond_wait(&(sem->cond), &(sem->mutex), 0))) {
++      /* Some error happened or the thread has been awakened but not by lwip 
*/
++      pthread_mutex_unlock(&(sem->mutex));
++      return ret;
 +    }
 +  }
 +  sem->c--;
@@ -1045,7 +1079,7 @@ Not intended to be upstream
 +#endif /* SYS_LIGHTWEIGHT_PROT */
 --- /dev/null
 +++ b/port/Filelists.cmake
-@@ -0,0 +1,17 @@
+@@ -0,0 +1,22 @@
 +# This file is indended to be included in end-user CMakeLists.txt
 +# include(/path/to/Filelists.cmake)
 +# It assumes the variable LWIP_DIR is defined pointing to the
@@ -1062,6 +1096,11 @@ Not intended to be upstream
 +
 +set(lwipportunix_SRCS
 +    ${LWIP_DIR}/port/sys_arch.c
++    ${LWIP_DIR}/port/netif/fifo.c
++    ${LWIP_DIR}/port/netif/list.c
++    ${LWIP_DIR}/port/netif/pcapif.c
++    ${LWIP_DIR}/port/netif/sio.c
++    ${LWIP_DIR}/port/netif/tapif.c
 +)
 --- /dev/null
 +++ b/port/include/posix/inet.h
@@ -1376,3 +1415,1675 @@ Not intended to be upstream
    }
    MEMCPY(name, &saddr, *namelen);
  
+--- /dev/null
++++ b/port/include/netif/fifo.h
+@@ -0,0 +1,54 @@
++#ifndef FIFO_H
++#define FIFO_H
++
++#include "lwip/sys.h"
++
++/** How many bytes in fifo */
++#define FIFOSIZE 2048
++
++/** fifo data structure, this one is passed to all fifo functions */
++typedef struct fifo_t {
++  u8_t data[FIFOSIZE+10]; /* data segment, +10 is a hack probably not 
needed.. FIXME! */
++  int dataslot;                         /* index to next char to be read */
++  int emptyslot;                /* index to next empty slot */
++  int len;                              /* len probably not needed, may be 
calculated from dataslot and emptyslot in conjunction with FIFOSIZE */
++
++  sys_sem_t sem;              /* semaphore protecting simultaneous data 
manipulation */
++  sys_sem_t getSem;           /* sepaphore used to signal new data if 
getWaiting is set */
++  u8_t getWaiting;            /* flag used to indicate that fifoget is 
waiting for data. fifoput is suposed to clear */
++                                              /* this flag prior to signaling 
the getSem semaphore */
++} fifo_t;
++
++
++/**
++*   Get a character from fifo
++*   Blocking call.
++*     @param  fifo pointer to fifo data structure
++*     @return character read from fifo
++*/
++u8_t fifoGet(fifo_t * fifo);
++
++/**
++*   Get a character from fifo
++*   Non blocking call.
++*     @param  fifo pointer to fifo data structure
++*     @return character read from fifo, or < zero if non was available
++*/
++s16_t fifoGetNonBlock(fifo_t * fifo);
++
++/**
++*     fifoput is called by the signalhandler when new data has arrived (or 
some other event is indicated)
++*   fifoput reads directly from the serialport and is thus highly dependent 
on unix arch at this moment
++*     @param  fifo pointer to fifo data structure
++*     @param  fd      unix file descriptor
++*/
++void fifoPut(fifo_t * fifo, int fd);
++
++/**
++*   fifoinit initiate fifo
++*     @param  fifo    pointer to fifo data structure, allocated by the user
++*/
++void fifoInit(fifo_t * fifo);
++
++#endif
++
+--- /dev/null
++++ b/port/include/netif/list.h
+@@ -0,0 +1,26 @@
++
++#ifndef LWIP_LIST_H
++#define LWIP_LIST_H
++
++struct elem;
++
++struct list {
++  struct elem *first, *last;
++  int size, elems;
++};
++
++struct elem {
++  struct elem *next;
++  void *data;
++};
++
++struct list *list_new(int size);
++int list_push(struct list *list, void *data);
++void *list_pop(struct list *list);
++void *list_first(struct list *list);
++int list_elems(struct list *list);
++void list_delete(struct list *list);
++int list_remove(struct list *list, void *elem);
++void list_map(struct list *list, void (* func)(void *arg));
++
++#endif
+--- /dev/null
++++ b/port/include/netif/pcapif.h
+@@ -0,0 +1,39 @@
++/*
++ * 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_PCAPIF_H
++#define LWIP_PCAPIF_H
++
++#include "lwip/netif.h"
++
++err_t pcapif_init(struct netif *netif);
++
++#endif /* LWIP_PCAPIF_H */
+--- /dev/null
++++ b/port/include/netif/sio.h
+@@ -0,0 +1,60 @@
++#ifndef SIO_UNIX_H
++#define SIO_UNIX_H
++
++#include "lwip/sys.h"
++#include "lwip/netif.h"
++#include "netif/fifo.h"
++/*#include "netif/pppif.h"*/
++
++struct sio_status_s {
++      int fd;
++      fifo_t myfifo;
++};
++
++/* BAUDRATE is defined in sio.c as it is implementation specific */
++/** Baudrates */
++typedef enum sioBaudrates {
++      SIO_BAUD_9600,
++      SIO_BAUD_19200,
++      SIO_BAUD_38400,
++      SIO_BAUD_57600, 
++      SIO_BAUD_115200 
++} sioBaudrates;
++
++/**
++* Poll for a new character from incoming data stream
++* @param      siostat siostatus struct, contains sio instance data, given by 
sio_open
++* @return     char read from input stream, or < 0 if no char was available
++*/
++s16_t sio_poll(sio_status_t * siostat);
++
++/**
++*     Parse incoming characters until a string str is recieved, blocking call
++* @param      str             zero terminated string to expect
++* @param      siostat siostatus struct, contains sio instance data, given by 
sio_open
++*/
++void sio_expect_string(u8_t *str, sio_status_t * siostat);
++
++/**
++* Write a char to output data stream
++* @param      str             pointer to a zero terminated string
++* @param      siostat siostatus struct, contains sio instance data, given by 
sio_open
++*/
++void sio_send_string(u8_t *str, sio_status_t * siostat);
++
++/**
++*     Flush outbuffer (send everything in buffer now), useful if some layer 
below is 
++*     holding on to data, waitng to fill a buffer
++* @param      siostat siostatus struct, contains sio instance data, given by 
sio_open
++*/
++void sio_flush( sio_status_t * siostat );
++
++/**
++*     Change baudrate of port, may close and reopen port
++* @param      baud    new baudrate
++* @param      siostat siostatus struct, contains sio instance data, given by 
sio_open
++*/
++void sio_change_baud( sioBaudrates baud, sio_status_t * siostat );
++
++#endif
++
+--- /dev/null
++++ b/port/include/netif/tapif.h
+@@ -0,0 +1,43 @@
++/*
++ * 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_TAPIF_H
++#define LWIP_TAPIF_H
++
++#include "lwip/netif.h"
++
++err_t tapif_init(struct netif *netif);
++void tapif_poll(struct netif *netif);
++#if NO_SYS
++int tapif_select(struct netif *netif);
++#endif /* NO_SYS */
++
++#endif /* LWIP_TAPIF_H */
+--- /dev/null
++++ b/port/netif/fifo.c
+@@ -0,0 +1,139 @@
++/* Author: Magnus Ivarsson <magnus.ivarsson@volvo.com> */
++
++/* ---------------------------------------------- */
++/* --- fifo 4 unix ------------------------------ */
++/* ---------------------------------------------- */
++#include "lwip/err.h"
++#include "netif/fifo.h"
++#include "lwip/debug.h"
++#include "lwip/def.h"
++#include "lwip/sys.h"
++#include "lwip/arch.h"
++#include <unistd.h>
++
++#ifndef TRUE
++#define TRUE  1
++#endif
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef SIO_FIFO_DEBUG
++#define SIO_FIFO_DEBUG LWIP_DBG_OFF
++#endif
++
++u8_t fifoGet(fifo_t * fifo)
++{
++      u8_t c;
++
++      sys_sem_wait(&fifo->sem);      /* enter critical section */
++
++      if (fifo->dataslot == fifo->emptyslot)
++      {
++            fifo->getWaiting = TRUE;    /* tell putFifo to signal us when 
data is available */
++            sys_sem_signal(&fifo->sem);  /* leave critical section (allow 
input from serial port..) */
++            sys_sem_wait(&fifo->getSem); /* wait 4 data */
++            sys_sem_wait(&fifo->sem);    /* reenter critical section */
++      }
++
++      c = fifo->data[fifo->dataslot++];
++      fifo->len--;
++
++      if (fifo->dataslot == FIFOSIZE)
++      {
++              fifo->dataslot = 0;
++      }
++      sys_sem_signal(&fifo->sem);    /* leave critical section */
++      return c;
++}
++
++
++s16_t fifoGetNonBlock(fifo_t * fifo)
++{
++      u16_t c;
++
++      sys_sem_wait(&fifo->sem);      /* enter critical section */
++
++      if (fifo->dataslot == fifo->emptyslot)
++      {
++            /* empty fifo */
++              c = -1;
++      }
++      else
++      {
++              c = fifo->data[fifo->dataslot++];
++              fifo->len--;
++
++              if (fifo->dataslot == FIFOSIZE)
++              {
++                      fifo->dataslot = 0;
++              }
++      }
++      sys_sem_signal(&fifo->sem);    /* leave critical section */
++      return c;
++}
++
++
++void fifoPut(fifo_t * fifo, int fd)
++{
++      /* FIXME: mutex around struct data.. */
++      int cnt=0;
++
++      sys_sem_wait(&fifo->sem ); /* enter critical */
++
++      LWIP_DEBUGF( SIO_FIFO_DEBUG,("fifoput: len%d dat%d empt%d --> ", 
fifo->len, fifo->dataslot, fifo->emptyslot ) );
++
++      if ( fifo->emptyslot < fifo->dataslot )
++      {
++              cnt = read( fd, &fifo->data[fifo->emptyslot], fifo->dataslot - 
fifo->emptyslot );
++      }
++      else
++      {
++              cnt = read( fd, &fifo->data[fifo->emptyslot], 
FIFOSIZE-fifo->emptyslot );
++      }
++      fifo->emptyslot += cnt;
++      fifo->len += cnt;
++
++      LWIP_DEBUGF( SIO_FIFO_DEBUG,("len%d dat%d empt%d\n", fifo->len, 
fifo->dataslot, fifo->emptyslot ) );
++
++      if ( fifo->len > FIFOSIZE )
++      {
++              printf( "ERROR: fifo overrun detected len=%d, flushing\n", 
fifo->len );
++              fifo->dataslot  = 0;
++              fifo->emptyslot = 0;
++              fifo->len = 0;
++      }
++
++      if ( fifo->emptyslot == FIFOSIZE )
++      {
++              fifo->emptyslot = 0;
++              LWIP_DEBUGF( SIO_FIFO_DEBUG, ("(WRAP) ") );
++
++              sys_sem_signal(&fifo->sem ); /* leave critical */
++              fifoPut( fifo, fd );
++              return;
++      }
++      if ( fifo->getWaiting )
++      {
++              fifo->getWaiting = FALSE;
++              sys_sem_signal(&fifo->getSem );
++      }
++
++      sys_sem_signal(&fifo->sem ); /* leave critical */
++      return;
++}
++
++
++void fifoInit(fifo_t * fifo)
++{
++  fifo->dataslot  = 0;
++  fifo->emptyslot = 0;
++  fifo->len       = 0;
++  if(sys_sem_new(&fifo->sem, 1) != ERR_OK) {  /* critical section 1=free to 
enter */
++    LWIP_ASSERT("Failed to create semaphore", 0);
++  }
++  if(sys_sem_new(&fifo->getSem, 0) != ERR_OK) {  /* 0 = no one waiting */
++    LWIP_ASSERT("Failed to create semaphore", 0);
++  }
++  fifo->getWaiting = FALSE;
++}
+--- /dev/null
++++ b/port/netif/list.c
+@@ -0,0 +1,152 @@
++/*
++ * 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>
++ *
++ */
++
++
++
++#include <stdlib.h>
++#include <netif/list.h>
++
++
++/*-----------------------------------------------------------------------------------*/
++struct list *
++list_new(int size)
++{
++  struct list *list;
++  list = (struct list *)malloc(sizeof(struct list));
++  list->first = list->last = NULL;
++  list->size = size;
++  list->elems = 0;
++  return list;
++}
++/*-----------------------------------------------------------------------------------*/
++int
++list_push(struct list *list, void *data)
++{
++  struct elem *elem;
++
++  if (list->elems < list->size) {
++    elem = (struct elem *)malloc(sizeof(struct elem));
++    elem->data = data;
++    elem->next = NULL;
++    if (list->last != NULL) {
++      list->last->next = elem;
++    }
++    list->last = elem;
++    if (list->first == NULL) {
++      list->first = elem;
++    }
++    list->elems++;
++    return 1;
++  }
++  return 0;
++}
++/*-----------------------------------------------------------------------------------*/
++void *
++list_pop(struct list *list)
++{
++  struct elem *elem;
++  void *data;
++
++  if (list->elems > 0) {
++    elem = list->first;
++    if (elem == list->last) {
++      list->last = elem->next;
++    }
++    list->first = elem->next;
++
++    list->elems--;
++
++    data = elem->data;
++    free(elem);
++
++    return data;
++  }
++  return NULL;
++}
++/*-----------------------------------------------------------------------------------*/
++void *
++list_first(struct list *list)
++{
++  return list->first;
++}
++/*-----------------------------------------------------------------------------------*/
++int
++list_elems(struct list *list)
++{
++  return list->elems;
++}
++/*-----------------------------------------------------------------------------------*/
++void
++list_delete(struct list *list)
++{
++  while (list_pop(list) != NULL);
++  free(list);
++}
++/*-----------------------------------------------------------------------------------*/
++int
++list_remove(struct list *list, void *elem)
++{
++  struct elem *e, *p;
++
++  p = NULL;
++  for(e = list->first; e != NULL; e = e->next) {
++    if (e->data == elem) {
++      if (p != NULL) {
++        p->next = e->next;
++      } else {
++        list->first = e->next;
++      }
++      if (list->last == e) {
++        list->last = p;
++        if (p != NULL) {
++          p->next = NULL;
++        }
++      }
++      free(e);
++      list->elems--;
++      return 1;
++    }
++    p = e;
++  }
++  return 0;
++}
++/*-----------------------------------------------------------------------------------*/
++void
++list_map(struct list *list, void (* func)(void *arg))
++{
++  struct elem *e;
++
++  for(e = list->first; e != NULL; e = e->next) {
++    func(e->data);
++  }
++}
++/*-----------------------------------------------------------------------------------*/
+--- /dev/null
++++ b/port/netif/pcapif.c
+@@ -0,0 +1,209 @@
++/*
++ * 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 linux  /* Apparently, this doesn't work under Linux. */
++
++#include "lwip/debug.h"
++
++#include <fcntl.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/uio.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <sys/stat.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++
++#include <pcap.h>
++
++#include "netif/etharp.h"
++
++#include "lwip/stats.h"
++
++#include "lwip/def.h"
++#include "lwip/mem.h"
++#include "lwip/pbuf.h"
++#include "lwip/sys.h"
++
++#include "lwip/ip.h"
++
++
++struct pcapif {
++  pcap_t *pd;
++  sys_sem_t sem;
++  u8_t pkt[2048];
++  u32_t len;
++  u32_t lasttime;
++  struct pbuf *p;
++  struct eth_addr *ethaddr;
++};
++
++static char errbuf[PCAP_ERRBUF_SIZE];
++
++/*-----------------------------------------------------------------------------------*/
++static err_t
++pcapif_output(struct netif *netif, struct pbuf *p,
++            ip_addr_t *ipaddr)
++{
++  return ERR_OK;
++}
++/*-----------------------------------------------------------------------------------*/
++static void
++timeout(void *arg)
++{
++  struct netif *netif;
++  struct pcapif *pcapif;
++  struct pbuf *p;
++  struct eth_hdr *ethhdr;
++
++  netif = (struct netif *)arg;
++  pcapif = netif->state;
++  ethhdr = (struct eth_hdr *)pcapif->pkt;
++
++
++  if (lwip_htons(ethhdr->type) != ETHTYPE_IP ||
++     ip_lookup(pcapif->pkt + 14, netif)) {
++
++    /* We allocate a pbuf chain of pbufs from the pool. */
++    p = pbuf_alloc(PBUF_LINK, pcapif->len, PBUF_POOL);
++
++    if (p != NULL) {
++      pbuf_take(p, pcapif->pkt, pcapif->len);
++
++      ethhdr = p->payload;
++      switch (lwip_htons(ethhdr->type)) {
++      /* IP or ARP packet? */
++      case ETHTYPE_IP:
++      case ETHTYPE_ARP:
++#if PPPOE_SUPPORT
++      /* PPPoE packet? */
++      case ETHTYPE_PPPOEDISC:
++      case ETHTYPE_PPPOE:
++#endif /* PPPOE_SUPPORT */
++        /* full packet send to tcpip_thread to process */
++        if (netif->input(p, netif) != ERR_OK) {
++          LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
++          pbuf_free(p);
++          p = NULL;
++        }
++        break;
++      default:
++        pbuf_free(p);
++        break;
++      }
++    }
++  } else {
++    printf("ip_lookup dropped\n");
++  }
++
++  sys_sem_signal(&pcapif->sem);
++}
++/*-----------------------------------------------------------------------------------*/
++static void
++callback(u_char *arg, const struct pcap_pkthdr *hdr, const u_char *pkt)
++{
++  struct netif *netif;
++  struct pcapif *pcapif;
++  u32_t time, lasttime;
++
++  netif = (struct netif *)arg;
++  pcapif = netif->state;
++
++  pcapif->len = hdr->len;
++
++  bcopy(pkt, pcapif->pkt, hdr->len);
++
++  time = hdr->ts.tv_sec * 1000 + hdr->ts.tv_usec / 1000;
++
++  lasttime = pcapif->lasttime;
++  pcapif->lasttime = time;
++
++
++  if (lasttime == 0) {
++    sys_timeout(1000, timeout, netif);
++  } else {
++    sys_timeout(time - lasttime, timeout, netif);
++  }
++}
++/*-----------------------------------------------------------------------------------*/
++static void
++pcapif_thread(void *arg)
++{
++  struct netif *netif;
++  struct pcapif *pcapif;
++  netif = arg;
++  pcapif = netif->state;
++
++  while (1) {
++    pcap_loop(pcapif->pd, 1, callback, (u_char *)netif);
++    sys_sem_wait(&pcapif->sem);
++    if (pcapif->p != NULL) {
++      netif->input(pcapif->p, netif);
++    }
++  }
++}
++/*-----------------------------------------------------------------------------------*/
++err_t
++pcapif_init(struct netif *netif)
++{
++  struct pcapif *p;
++
++  p = malloc(sizeof(struct pcapif));
++  if (p == NULL)
++      return ERR_MEM;
++  netif->state = p;
++  netif->name[0] = 'p';
++  netif->name[1] = 'c';
++  netif->output = pcapif_output;
++
++  p->pd = pcap_open_offline("pcapdump", errbuf);
++  if (p->pd == NULL) {
++    printf("pcapif_init: failed %s\n", errbuf);
++    return ERR_IF;
++  }
++
++  if(sys_sem_new(&p->sem, 0) != ERR_OK) {
++    LWIP_ASSERT("Failed to create semaphore", 0);
++  }
++  p->p = NULL;
++  p->lasttime = 0;
++
++  sys_thread_new("pcapif_thread", pcapif_thread, netif, 
DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
++  return ERR_OK;
++}
++/*-----------------------------------------------------------------------------------*/
++#else /* linux */
++typedef int avoid_empty_compilation_unit;
++#endif /* linux */
+--- /dev/null
++++ b/port/netif/sio.c
+@@ -0,0 +1,488 @@
++/* Author: Magnus Ivarsson <magnus.ivarsson@volvo.com> */
++
++/* to get rid of implicit function declarations */
++#define _XOPEN_SOURCE 600
++#define _GNU_SOURCE
++
++/* build with Darwin C extensions not part of POSIX, i.e. FASYNC, SIGIO.
++   we can't use LWIP_UNIX_MACH because extensions need to be turned
++   on before any system headers (which are pulled in through cc.h)
++   are included */
++#if defined(__APPLE__)
++#define _DARWIN_C_SOURCE
++#endif
++
++#include "netif/sio.h"
++#include "netif/fifo.h"
++#include "lwip/debug.h"
++#include "lwip/def.h"
++#include "lwip/sys.h"
++#include "lwip/arch.h"
++#include "lwip/sio.h"
++#include "netif/ppp/ppp_opts.h"
++
++/* Following #undefs are here to keep compiler from issuing warnings
++   about them being double defined. (They are defined in lwip/inet.h
++   as well as the Unix #includes below.) */
++#undef htonl
++#undef ntohl
++#undef htons
++#undef ntohs
++#undef HTONL
++#undef NTOHL
++#undef HTONS
++#undef NTOHS
++
++#include <stdlib.h>
++#include <stdio.h>
++#if defined(LWIP_UNIX_OPENBSD)
++#include <util.h>
++#endif
++#include <termios.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <string.h>
++#include <sys/signal.h>
++#include <sys/types.h>
++
++#ifndef LWIP_HAVE_SLIPIF
++#define LWIP_HAVE_SLIPIF 0
++#endif
++
++#if (PPP_SUPPORT || LWIP_HAVE_SLIPIF) && defined(LWIP_UNIX_LINUX)
++#include <pty.h>
++#endif
++
++/*#define BAUDRATE B19200 */
++/*#define BAUDRATE B57600 */
++#define BAUDRATE B115200
++
++#ifndef TRUE
++#define TRUE  1
++#endif
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++/* for all of you who dont define SIO_DEBUG in debug.h */
++#ifndef SIO_DEBUG
++#define SIO_DEBUG 0
++#endif
++
++
++/*  typedef struct siostruct_t */
++/*  {  */
++/*    sio_status_t *sio; */
++/*  } siostruct_t; */
++
++/** array of ((siostruct*)netif->state)->sio structs */
++static sio_status_t statusar[4];
++
++#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
++/* 
--private-functions-----------------------------------------------------------------
 */
++/**
++ * Signal handler for ttyXX0 to indicate bytes received
++ * one per interface is needed since we cannot send a instance number / 
pointer as callback argument (?)
++ */
++static void   signal_handler_IO_0( int status )
++{
++      LWIP_UNUSED_ARG(status);
++      LWIP_DEBUGF(SIO_DEBUG, ("SigHand: rxSignal channel 0\n"));
++      fifoPut( &statusar[0].myfifo, statusar[0].fd );
++}
++
++/**
++ * Signal handler for ttyXX1 to indicate bytes received
++ * one per interface is needed since we cannot send a instance number / 
pointer as callback argument (?)
++ */
++static void signal_handler_IO_1( int status )
++{
++      LWIP_UNUSED_ARG(status);
++      LWIP_DEBUGF(SIO_DEBUG, ("SigHand: rxSignal channel 1\n"));
++      fifoPut( &statusar[1].myfifo, statusar[1].fd );
++}
++#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
++
++/**
++* Initiation of serial device
++* @param device string with the device name and path, eg. "/dev/ttyS0"
++* @param devnum device number
++* @param siostat status
++* @return file handle to serial dev.
++*/
++static int sio_init( char * device, int devnum, sio_status_t * siostat )
++{
++      struct termios oldtio,newtio;
++#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
++      struct sigaction saio;           /* definition of signal action */
++#endif
++      int fd;
++      LWIP_UNUSED_ARG(siostat);
++      LWIP_UNUSED_ARG(devnum);
++
++      /* open the device to be non-blocking (read will return immediately) */
++      fd = open( device, O_RDWR | O_NOCTTY | O_NONBLOCK );
++      if ( fd < 0 )
++      {
++              perror( device );
++              exit( -1 );
++      }
++
++#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
++      /* install the signal handler before making the device asynchronous */
++      switch ( devnum )
++      {
++              case 0:
++                      LWIP_DEBUGF( SIO_DEBUG, ("sioinit, 
signal_handler_IO_0\n") );
++                      saio.sa_handler = signal_handler_IO_0;
++                      break;
++              case 1:
++                      LWIP_DEBUGF( SIO_DEBUG, ("sioinit, 
signal_handler_IO_1\n") );
++                      saio.sa_handler = signal_handler_IO_1;
++                      break;
++              default:
++                      LWIP_DEBUGF( SIO_DEBUG,("sioinit, devnum not 
allowed\n") );
++                      break;
++      }
++
++      saio.sa_flags = 0;
++#if defined(LWIP_UNIX_LINUX)
++      saio.sa_restorer = NULL;
++#endif /* LWIP_UNIX_LINUX */
++      sigaction( SIGIO,&saio,NULL );
++
++      /* allow the process to receive SIGIO */
++              if ( fcntl( fd, F_SETOWN, getpid( ) ) != 0)
++      {
++              perror( device );
++              exit( -1 );
++      }
++      /* Make the file descriptor asynchronous (the manual page says only
++      O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
++              if ( fcntl( fd, F_SETFL, FASYNC ) != 0)
++      {
++              perror( device );
++              exit( -1 );
++      }
++#else
++              if ( fcntl( fd, F_SETFL, 0 ) != 0)
++      {
++              perror( device );
++              exit( -1 );
++      }
++
++#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
++
++      tcgetattr( fd,&oldtio ); /* save current port settings */
++      /* set new port settings */
++      /* see 'man termios' for further settings */
++        memset(&newtio, 0, sizeof(newtio));
++      newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD | CRTSCTS;
++      newtio.c_iflag = 0;
++      newtio.c_oflag = 0;
++      newtio.c_lflag = 0; /*ECHO; */
++      newtio.c_cc[VMIN] = 1; /* Read 1 byte at a time, no timer */
++      newtio.c_cc[VTIME] = 0;
++
++      tcsetattr( fd,TCSANOW,&newtio );
++      tcflush( fd, TCIOFLUSH );
++
++      return fd;
++}
++
++/**
++*
++*/
++static void sio_speed( int fd, int speed )
++{
++      struct termios oldtio,newtio;
++      /*  int fd; */
++
++      LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: baudcode:%d enter\n", fd, 
speed));
++
++      if ( fd < 0 )
++      {
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: fd ERROR\n", fd));
++              exit( -1 );
++      }
++
++      tcgetattr( fd,&oldtio ); /* get current port settings */
++
++      /* set new port settings
++      * see 'man termios' for further settings */
++        memset(&newtio, 0, sizeof(newtio));
++      newtio.c_cflag = speed | CS8 | CLOCAL | CREAD; /* | CRTSCTS; */
++      newtio.c_iflag = 0;
++      newtio.c_oflag = 0;
++      newtio.c_lflag = 0; /*ECHO; */
++      newtio.c_cc[VMIN] = 1; /* Read 1 byte at a time, no timer */
++      newtio.c_cc[VTIME] = 0;
++
++      tcsetattr( fd,TCSANOW,&newtio );
++      tcflush( fd, TCIOFLUSH );
++
++      LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: leave\n", fd));
++}
++
++/* 
--public-functions-----------------------------------------------------------------------------
 */
++void sio_send( u8_t c, sio_status_t * siostat )
++{
++    /*        sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
++
++      if ( write( siostat->fd, &c, 1 ) <= 0 )
++      {
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_send[%d]: write refused\n", 
siostat->fd));
++      }
++}
++
++void sio_send_string( u8_t *str, sio_status_t * siostat )
++{
++    /*        sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
++      int len = strlen( (const char *)str );
++
++      if ( write( siostat->fd, str, len ) <= 0 )
++      {
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_send_string[%d]: write refused\n", 
siostat->fd));
++      }
++      LWIP_DEBUGF(SIO_DEBUG, ("sio_send_string[%d]: sent: %s\n", siostat->fd, 
str));
++}
++
++
++void sio_flush( sio_status_t * siostat )
++{
++      LWIP_UNUSED_ARG(siostat);
++      /* not implemented in unix as it is not needed */
++      /*sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
++}
++
++
++#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
++/*u8_t sio_recv( struct netif * netif )*/
++u8_t sio_recv( sio_status_t * siostat )
++{
++    /*        sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */
++      return fifoGet( &(siostat->myfifo) );
++}
++
++s16_t sio_poll(sio_status_t * siostat)
++{
++    /*        sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/
++      return fifoGetNonBlock( &(siostat->myfifo) );
++}
++
++
++void sio_expect_string( u8_t *str, sio_status_t * siostat )
++{
++    /*        sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/
++      u8_t c;
++      int finger=0;
++
++      LWIP_DEBUGF(SIO_DEBUG, ("sio_expect_string[%d]: %s\n", siostat->fd, 
str));
++      while ( 1 )
++      {
++              c=fifoGet( &(siostat->myfifo) );
++              LWIP_DEBUGF(SIO_DEBUG, ("_%c", c));
++              if ( c==str[finger] )
++              {
++                      finger++;
++              } else if ( finger > 0 )
++              {
++                    /*it might fit in the beginning? */
++                      if ( str[0] == c )
++                      {
++                              finger = 1;
++                      }
++              }
++              if ( 0 == str[finger] )
++                    break;    /* done, we have a match */
++      }
++      LWIP_DEBUGF(SIO_DEBUG, ("sio_expect_string[%d]: [match]\n", 
siostat->fd));
++}
++#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
++
++#if (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
++u32_t sio_write(sio_status_t * siostat, u8_t *buf, u32_t size)
++{
++    ssize_t wsz = write( siostat->fd, buf, size );
++    return wsz < 0 ? 0 : wsz;
++}
++
++u32_t sio_read(sio_status_t * siostat, u8_t *buf, u32_t size)
++{
++    ssize_t rsz = read( siostat->fd, buf, size );
++    return rsz < 0 ? 0 : rsz;
++}
++
++void sio_read_abort(sio_status_t * siostat)
++{
++    LWIP_UNUSED_ARG(siostat);
++    printf("sio_read_abort[%d]: not yet implemented for unix\n", siostat->fd);
++}
++#endif /* (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */
++
++sio_fd_t sio_open(u8_t devnum)
++{
++      char dev[20];
++
++      /* would be nice with dynamic memory alloc */
++      sio_status_t * siostate = &statusar[ devnum ];
++/*    siostruct_t * tmp; */
++
++
++/*    tmp = (siostruct_t*)(netif->state); */
++/*    tmp->sio = siostate; */
++
++/*    tmp = (siostruct_t*)(netif->state); */
++
++/*    ((sio_status_t*)(tmp->sio))->fd = 0; */
++
++      LWIP_DEBUGF(SIO_DEBUG, ("sio_open: for devnum %d\n", devnum));
++
++#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF)
++      fifoInit( &siostate->myfifo );
++#endif /* ! PPP_SUPPORT */
++
++      snprintf( dev, sizeof(dev), "/dev/ttyS%d", devnum );
++
++      if ( (devnum == 1) || (devnum == 0) )
++      {
++              if ( ( siostate->fd = sio_init( dev, devnum, siostate ) ) == 0 )
++              {
++                      LWIP_DEBUGF(SIO_DEBUG, ("sio_open: ERROR opening serial 
device dev=%s\n", dev));
++                      abort( );
++                      return NULL;
++              }
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: dev=%s open.\n", 
siostate->fd, dev));
++      }
++#if PPP_SUPPORT
++      else if (devnum == 2) {
++          pid_t childpid;
++          char name[256];
++          childpid = forkpty(&siostate->fd, name, NULL, NULL);
++          if(childpid < 0) {
++              perror("forkpty");
++              exit (1);
++          }
++          if(childpid == 0) {
++              execl("/usr/sbin/pppd", "pppd",
++                      "ms-dns", "198.168.100.7",
++                      "local", "crtscts",
++                      "debug",
++#ifdef LWIP_PPP_CHAP_TEST
++                      "auth",
++                      "require-chap",
++                      "remotename", "lwip",
++#else
++                      "noauth",
++#endif
++#if LWIP_IPV6
++                      "+ipv6",
++#endif
++                      "192.168.1.1:192.168.1.2",
++                      NULL);
++              perror("execl pppd");
++              exit (1);
++          } else {
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: spawned pppd pid %d on 
%s\n",
++                      siostate->fd, childpid, name));
++          }
++
++      }
++#endif
++#if LWIP_HAVE_SLIPIF
++      else if (devnum == 3) {
++          pid_t childpid;
++          /* create PTY pair */
++          siostate->fd = posix_openpt(O_RDWR | O_NOCTTY);
++          if (siostate->fd < 0) {
++              perror("open pty master");
++              exit (1);
++          }
++          if (grantpt(siostate->fd) != 0) {
++              perror("grant pty master");
++              exit (1);
++          }
++          if (unlockpt(siostate->fd) != 0) {
++              perror("unlock pty master");
++              exit (1);
++          }
++          LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: for %s\n",
++                  siostate->fd, ptsname(siostate->fd)));
++          /* fork for slattach */
++          childpid = fork();
++          if(childpid < 0) {
++              perror("fork");
++              exit (1);
++          }
++          if(childpid == 0) {
++              /* esteblish SLIP interface on host side connected to PTY slave 
*/
++              execl("/sbin/slattach", "slattach",
++                      "-d", "-v", "-L", "-p", "slip",
++                      ptsname(siostate->fd),
++                      NULL);
++              perror("execl slattach");
++              exit (1);
++          } else {
++              int ret;
++              char buf[1024];
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: spawned slattach pid %d 
on %s\n",
++                      siostate->fd, childpid, ptsname(siostate->fd)));
++              /* wait a moment for slattach startup */
++              sleep(1);
++              /* configure SLIP interface on host side as P2P interface */
++              snprintf(buf, sizeof(buf),
++                      "/sbin/ifconfig sl0 mtu %d %s pointopoint %s up",
++                      SLIP_MAX_SIZE, "192.168.2.1", "192.168.2.2");
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: system(\"%s\");\n", 
siostate->fd, buf));
++              ret = system(buf);
++              if (ret < 0) {
++                  perror("ifconfig failed");
++                  exit(1);
++              }
++          }
++      }
++#endif /* LWIP_HAVE_SLIPIF */
++      else
++      {
++              LWIP_DEBUGF(SIO_DEBUG, ("sio_open: device %s (%d) is not 
supported\n", dev, devnum));
++              return NULL;
++      }
++
++      return siostate;
++}
++
++/**
++*
++*/
++void sio_change_baud( sioBaudrates baud, sio_status_t * siostat )
++{
++    /*        sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/
++
++      LWIP_DEBUGF(SIO_DEBUG, ("sio_change_baud[%d]\n", siostat->fd));
++
++      switch ( baud )
++      {
++              case SIO_BAUD_9600:
++                      sio_speed( siostat->fd, B9600 );
++                      break;
++              case SIO_BAUD_19200:
++                      sio_speed( siostat->fd, B19200 );
++                      break;
++              case SIO_BAUD_38400:
++                      sio_speed( siostat->fd, B38400 );
++                      break;
++              case SIO_BAUD_57600:
++                      sio_speed( siostat->fd, B57600 );
++                      break;
++              case SIO_BAUD_115200:
++                      sio_speed( siostat->fd, B115200 );
++                      break;
++
++              default:
++                      LWIP_DEBUGF(SIO_DEBUG, ("sio_change_baud[%d]: Unknown 
baudrate, code:%d\n",
++                                      siostat->fd, baud));
++                      break;
++      }
++}
+--- /dev/null
++++ b/port/netif/tapif.c
+@@ -0,0 +1,432 @@
++/*
++ * 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>
++ *
++ */
++
++#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 "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/tapif.h"
++
++#define IFCONFIG_BIN "/sbin/ifconfig "
++
++#if defined(LWIP_UNIX_LINUX)
++#include <sys/ioctl.h>
++#include <linux/if.h>
++#include <linux/if_tun.h>
++/*
++ * Creating a tap interface requires special privileges. If the interfaces
++ * is created in advance with `tunctl -u <user>` it can be opened as a regular
++ * user. The network must already be configured. If DEVTAP_IF is defined it
++ * will be opened instead of creating a new tap device.
++ *
++ * You can also use PRECONFIGURED_TAPIF environment variable to do so.
++ */
++#ifndef DEVTAP_DEFAULT_IF
++#define DEVTAP_DEFAULT_IF "tap0"
++#endif
++#ifndef DEVTAP
++#define DEVTAP "/dev/net/tun"
++#endif
++#define NETMASK_ARGS "netmask %d.%d.%d.%d"
++#define IFCONFIG_ARGS "tap0 inet %d.%d.%d.%d " NETMASK_ARGS
++#elif defined(LWIP_UNIX_OPENBSD)
++#define DEVTAP "/dev/tun0"
++#define NETMASK_ARGS "netmask %d.%d.%d.%d"
++#define IFCONFIG_ARGS "tun0 inet %d.%d.%d.%d " NETMASK_ARGS " link0"
++#else /* others */
++#define DEVTAP "/dev/tap0"
++#define NETMASK_ARGS "netmask %d.%d.%d.%d"
++#define IFCONFIG_ARGS "tap0 inet %d.%d.%d.%d " NETMASK_ARGS
++#endif
++
++/* Define those to better describe your network interface. */
++#define IFNAME0 't'
++#define IFNAME1 'p'
++
++#ifndef TAPIF_DEBUG
++#define TAPIF_DEBUG LWIP_DBG_OFF
++#endif
++
++struct tapif {
++  /* Add whatever per-interface state that is needed here. */
++  int fd;
++};
++
++/* Forward declarations. */
++static void tapif_input(struct netif *netif);
++#if !NO_SYS
++static void tapif_thread(void *arg);
++#endif /* !NO_SYS */
++
++/*-----------------------------------------------------------------------------------*/
++static void
++low_level_init(struct netif *netif)
++{
++  struct tapif *tapif;
++#if LWIP_IPV4
++  int ret;
++  char buf[1024];
++#endif /* LWIP_IPV4 */
++  char *preconfigured_tapif = getenv("PRECONFIGURED_TAPIF");
++
++  tapif = (struct tapif *)netif->state;
++
++  /* Obtain MAC address from network interface. */
++
++  /* (We just fake an address...) */
++  netif->hwaddr[0] = 0x02;
++  netif->hwaddr[1] = 0x12;
++  netif->hwaddr[2] = 0x34;
++  netif->hwaddr[3] = 0x56;
++  netif->hwaddr[4] = 0x78;
++  netif->hwaddr[5] = 0xab;
++  netif->hwaddr_len = 6;
++
++  /* device capabilities */
++  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
++
++  tapif->fd = open(DEVTAP, O_RDWR);
++  LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_init: fd %d\n", tapif->fd));
++  if (tapif->fd == -1) {
++#ifdef LWIP_UNIX_LINUX
++    perror("tapif_init: try running \"modprobe tun\" or rebuilding your 
kernel with CONFIG_TUN; cannot open "DEVTAP);
++#else /* LWIP_UNIX_LINUX */
++    perror("tapif_init: cannot open "DEVTAP);
++#endif /* LWIP_UNIX_LINUX */
++    exit(1);
++  }
++
++#ifdef LWIP_UNIX_LINUX
++  {
++    struct ifreq ifr;
++    memset(&ifr, 0, sizeof(ifr));
++
++    if (preconfigured_tapif) {
++      strncpy(ifr.ifr_name, preconfigured_tapif, sizeof(ifr.ifr_name));
++    } else {
++      strncpy(ifr.ifr_name, DEVTAP_DEFAULT_IF, sizeof(ifr.ifr_name));
++    }
++    ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0; /* ensure \0 termination */
++
++    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
++    if (ioctl(tapif->fd, TUNSETIFF, (void *) &ifr) < 0) {
++      perror("tapif_init: "DEVTAP" ioctl TUNSETIFF");
++      exit(1);
++    }
++  }
++#endif /* LWIP_UNIX_LINUX */
++
++  netif_set_link_up(netif);
++
++  if (preconfigured_tapif == NULL) {
++#if LWIP_IPV4
++    snprintf(buf, 1024, IFCONFIG_BIN IFCONFIG_ARGS,
++             ip4_addr1(netif_ip4_gw(netif)),
++             ip4_addr2(netif_ip4_gw(netif)),
++             ip4_addr3(netif_ip4_gw(netif)),
++             ip4_addr4(netif_ip4_gw(netif))
++#ifdef NETMASK_ARGS
++             ,
++             ip4_addr1(netif_ip4_netmask(netif)),
++             ip4_addr2(netif_ip4_netmask(netif)),
++             ip4_addr3(netif_ip4_netmask(netif)),
++             ip4_addr4(netif_ip4_netmask(netif))
++#endif /* NETMASK_ARGS */
++             );
++
++    LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_init: system(\"%s\");\n", buf));
++    ret = system(buf);
++    if (ret < 0) {
++      perror("ifconfig failed");
++      exit(1);
++    }
++    if (ret != 0) {
++      printf("ifconfig returned %d\n", ret);
++    }
++#else /* LWIP_IPV4 */
++    perror("todo: support IPv6 support for non-preconfigured tapif");
++    exit(1);
++#endif /* LWIP_IPV4 */
++  }
++
++#if !NO_SYS
++  sys_thread_new("tapif_thread", tapif_thread, netif, 
DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
++#endif /* !NO_SYS */
++}
++/*-----------------------------------------------------------------------------------*/
++/*
++ * low_level_output():
++ *
++ * Should do the actual transmission of the packet. The packet is
++ * contained in the pbuf that is passed to the function. This pbuf
++ * might be chained.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++
++static err_t
++low_level_output(struct netif *netif, struct pbuf *p)
++{
++  struct tapif *tapif = (struct tapif *)netif->state;
++  char buf[1518]; /* max packet size including VLAN excluding CRC */
++  ssize_t written;
++
++#if 0
++  if (((double)rand()/(double)RAND_MAX) < 0.2) {
++    printf("drop output\n");
++    return ERR_OK; /* ERR_OK because we simulate packet loss on cable */
++  }
++#endif
++
++  if (p->tot_len > sizeof(buf)) {
++    MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
++    perror("tapif: packet too large");
++    return ERR_IF;
++  }
++
++  /* initiate transfer(); */
++  pbuf_copy_partial(p, buf, p->tot_len, 0);
++
++  /* signal that packet should be sent(); */
++  written = write(tapif->fd, buf, p->tot_len);
++  if (written < p->tot_len) {
++    MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
++    perror("tapif: write");
++    return ERR_IF;
++  } else {
++    MIB2_STATS_NETIF_ADD(netif, ifoutoctets, (u32_t)written);
++    return ERR_OK;
++  }
++}
++/*-----------------------------------------------------------------------------------*/
++/*
++ * low_level_input():
++ *
++ * Should allocate a pbuf and transfer the bytes of the incoming
++ * packet from the interface into the pbuf.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++static struct pbuf *
++low_level_input(struct netif *netif)
++{
++  struct pbuf *p;
++  u16_t len;
++  ssize_t readlen;
++  char buf[1518]; /* max packet size including VLAN excluding CRC */
++  struct tapif *tapif = (struct tapif *)netif->state;
++
++  /* Obtain the size of the packet and put it into the "len"
++     variable. */
++  readlen = read(tapif->fd, buf, sizeof(buf));
++  if (readlen < 0) {
++    perror("read returned -1");
++    exit(1);
++  }
++  len = (u16_t)readlen;
++
++  MIB2_STATS_NETIF_ADD(netif, ifinoctets, len);
++
++#if 0
++  if (((double)rand()/(double)RAND_MAX) < 0.2) {
++    printf("drop\n");
++    return NULL;
++  }
++#endif
++
++  /* 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, ("tapif_input: could not allocate pbuf\n"));
++  }
++
++  return p;
++}
++
++/*-----------------------------------------------------------------------------------*/
++/*
++ * tapif_input():
++ *
++ * This function should be called when a packet is ready to be read
++ * from the interface. It uses the function low_level_input() that
++ * should handle the actual reception of bytes from the network
++ * interface.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++static void
++tapif_input(struct netif *netif)
++{
++  struct pbuf *p = low_level_input(netif);
++
++  if (p == NULL) {
++#if LINK_STATS
++    LINK_STATS_INC(link.recv);
++#endif /* LINK_STATS */
++    LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_input: low_level_input returned 
NULL\n"));
++    return;
++  }
++
++  if (netif->input(p, netif) != ERR_OK) {
++    LWIP_DEBUGF(NETIF_DEBUG, ("tapif_input: netif input error\n"));
++    pbuf_free(p);
++  }
++}
++/*-----------------------------------------------------------------------------------*/
++/*
++ * tapif_init():
++ *
++ * Should be called at the beginning of the program to set up the
++ * network interface. It calls the function low_level_init() to do the
++ * actual setup of the hardware.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++err_t
++tapif_init(struct netif *netif)
++{
++  struct tapif *tapif = (struct tapif *)mem_malloc(sizeof(struct tapif));
++
++  if (tapif == NULL) {
++    LWIP_DEBUGF(NETIF_DEBUG, ("tapif_init: out of memory for tapif\n"));
++    return ERR_MEM;
++  }
++  netif->state = tapif;
++  MIB2_INIT_NETIF(netif, snmp_ifType_other, 100000000);
++
++  netif->name[0] = IFNAME0;
++  netif->name[1] = IFNAME1;
++#if LWIP_IPV4
++  netif->output = etharp_output;
++#endif /* LWIP_IPV4 */
++#if LWIP_IPV6
++  netif->output_ip6 = ethip6_output;
++#endif /* LWIP_IPV6 */
++  netif->linkoutput = low_level_output;
++  netif->mtu = 1500;
++
++  low_level_init(netif);
++
++  return ERR_OK;
++}
++
++
++/*-----------------------------------------------------------------------------------*/
++void
++tapif_poll(struct netif *netif)
++{
++  tapif_input(netif);
++}
++
++#if NO_SYS
++
++int
++tapif_select(struct netif *netif)
++{
++  fd_set fdset;
++  int ret;
++  struct timeval tv;
++  struct tapif *tapif;
++  u32_t msecs = sys_timeouts_sleeptime();
++
++  tapif = (struct tapif *)netif->state;
++
++  tv.tv_sec = msecs / 1000;
++  tv.tv_usec = (msecs % 1000) * 1000;
++
++  FD_ZERO(&fdset);
++  FD_SET(tapif->fd, &fdset);
++
++  ret = select(tapif->fd + 1, &fdset, NULL, NULL, &tv);
++  if (ret > 0) {
++    tapif_input(netif);
++  }
++  return ret;
++}
++
++#else /* NO_SYS */
++
++static void
++tapif_thread(void *arg)
++{
++  struct netif *netif;
++  struct tapif *tapif;
++  fd_set fdset;
++  int ret;
++
++  netif = (struct netif *)arg;
++  tapif = (struct tapif *)netif->state;
++
++  while(1) {
++    FD_ZERO(&fdset);
++    FD_SET(tapif->fd, &fdset);
++
++    /* Wait for a packet to arrive. */
++    ret = select(tapif->fd + 1, &fdset, NULL, NULL, NULL);
++
++    if(ret == 1) {
++      /* Handle incoming packet. */
++      tapif_input(netif);
++    } else if(ret == -1) {
++      perror("tapif_thread: select");
++    }
++  }
++}
++
++#endif /* NO_SYS */
diff --git a/debian/patches/series b/debian/patches/series
index 1cc04ed..b5e6d33 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,4 +1,5 @@
 patch9350 --binary
+patch9807
 port
 max_sockets
 cmake
-- 
2.17.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]