From b63196d62ad4d9e377b550c61842e03d1133e84c Mon Sep 17 00:00:00 2001 From: jani Date: Sat, 18 Jan 2003 18:18:02 +0000 Subject: [PATCH] Add Unix port --- ports/unix/include/arch/cc.h | 51 +++ ports/unix/include/arch/cpu.h | 39 +++ ports/unix/include/arch/init.h | 41 +++ ports/unix/include/arch/lib.h | 43 +++ ports/unix/include/arch/perf.h | 63 ++++ ports/unix/include/arch/sys_arch.h | 48 +++ ports/unix/include/netif/delif.h | 42 +++ ports/unix/include/netif/dropif.h | 41 +++ ports/unix/include/netif/fifo.h | 54 ++++ ports/unix/include/netif/pcapif.h | 39 +++ ports/unix/include/netif/sio.h | 82 +++++ ports/unix/include/netif/tapif.h | 39 +++ ports/unix/include/netif/tcpdump.h | 40 +++ ports/unix/include/netif/tunif.h | 42 +++ ports/unix/include/netif/unixif.h | 40 +++ ports/unix/lwip_chksum.c | 73 +++++ ports/unix/netif/delif.c | 310 +++++++++++++++++++ ports/unix/netif/fifo.c | 131 ++++++++ ports/unix/netif/list.c | 162 ++++++++++ ports/unix/netif/pcapif.c | 214 +++++++++++++ ports/unix/netif/sio.c | 319 +++++++++++++++++++ ports/unix/netif/tapif.c | 361 ++++++++++++++++++++++ ports/unix/netif/tcpdump.c | 186 +++++++++++ ports/unix/netif/tunif.c | 298 ++++++++++++++++++ ports/unix/netif/unixif.c | 480 +++++++++++++++++++++++++++++ ports/unix/perf.c | 64 ++++ ports/unix/sys_arch.c | 453 +++++++++++++++++++++++++++ 27 files changed, 3755 insertions(+) create mode 100644 ports/unix/include/arch/cc.h create mode 100644 ports/unix/include/arch/cpu.h create mode 100644 ports/unix/include/arch/init.h create mode 100644 ports/unix/include/arch/lib.h create mode 100644 ports/unix/include/arch/perf.h create mode 100644 ports/unix/include/arch/sys_arch.h create mode 100644 ports/unix/include/netif/delif.h create mode 100644 ports/unix/include/netif/dropif.h create mode 100644 ports/unix/include/netif/fifo.h create mode 100644 ports/unix/include/netif/pcapif.h create mode 100644 ports/unix/include/netif/sio.h create mode 100644 ports/unix/include/netif/tapif.h create mode 100644 ports/unix/include/netif/tcpdump.h create mode 100644 ports/unix/include/netif/tunif.h create mode 100644 ports/unix/include/netif/unixif.h create mode 100644 ports/unix/lwip_chksum.c create mode 100644 ports/unix/netif/delif.c create mode 100644 ports/unix/netif/fifo.c create mode 100644 ports/unix/netif/list.c create mode 100644 ports/unix/netif/pcapif.c create mode 100644 ports/unix/netif/sio.c create mode 100644 ports/unix/netif/tapif.c create mode 100644 ports/unix/netif/tcpdump.c create mode 100644 ports/unix/netif/tunif.c create mode 100644 ports/unix/netif/unixif.c create mode 100644 ports/unix/perf.c create mode 100644 ports/unix/sys_arch.c diff --git a/ports/unix/include/arch/cc.h b/ports/unix/include/arch/cc.h new file mode 100644 index 0000000..8c77a17 --- /dev/null +++ b/ports/unix/include/arch/cc.h @@ -0,0 +1,51 @@ +/* + * 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 + * + */ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +typedef unsigned char u8_t; +typedef signed char s8_t; +/*typedef unsigned short u8_t; + typedef signed short s8_t; */ +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned long u32_t; +typedef signed long s32_t; + +typedef u32_t mem_ptr_t; + +#define PACK_STRUCT_FIELD(x) x __attribute__((packed)) +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +#endif /* __ARCH_CC_H__ */ diff --git a/ports/unix/include/arch/cpu.h b/ports/unix/include/arch/cpu.h new file mode 100644 index 0000000..b05112f --- /dev/null +++ b/ports/unix/include/arch/cpu.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 + * + */ +#ifndef __ARCH_CPU_H__ +#define __ARCH_CPU_H__ + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif /* BYTE_ORDER */ + +#endif /* __ARCH_CPU_H__ */ diff --git a/ports/unix/include/arch/init.h b/ports/unix/include/arch/init.h new file mode 100644 index 0000000..5f9277a --- /dev/null +++ b/ports/unix/include/arch/init.h @@ -0,0 +1,41 @@ +/* + * 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 + * + */ +#ifndef __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) sys_sem_signal(*(sys_sem_t *)arg) + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/ports/unix/include/arch/lib.h b/ports/unix/include/arch/lib.h new file mode 100644 index 0000000..4c0d3fb --- /dev/null +++ b/ports/unix/include/arch/lib.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 + * + */ +#ifndef __ARCH_LIB_H__ +#define __ARCH_LIB_H__ +#include + +#ifndef _STRING_H_ +#ifndef _STRING_H +int strlen(const char *str); +int strncmp(const char *str1, const char *str2, int len); +#endif /* _STRING_H */ +#endif /* _STRING_H_ */ + +#endif /* __ARCH_LIB_H__ */ diff --git a/ports/unix/include/arch/perf.h b/ports/unix/include/arch/perf.h new file mode 100644 index 0000000..9fbcf60 --- /dev/null +++ b/ports/unix/include/arch/perf.h @@ -0,0 +1,63 @@ +/* + * 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 + * + */ +#ifndef __ARCH_PERF_H__ +#define __ARCH_PERF_H__ + +#include + +#ifdef PERF +#define PERF_START { \ + unsigned long __c1l, __c1h, __c2l, __c2h; \ + __asm__(".byte 0x0f, 0x31" : "=a" (__c1l), "=d" (__c1h)) +#define PERF_STOP(x) __asm__(".byte 0x0f, 0x31" : "=a" (__c2l), "=d" (__c2h)); \ + perf_print(__c1l, __c1h, __c2l, __c2h, x);} + +/*#define PERF_START do { \ + struct tms __perf_start, __perf_end; \ + times(&__perf_start) +#define PERF_STOP(x) times(&__perf_end); \ + perf_print_times(&__perf_start, &__perf_end, x);\ + } while(0)*/ +#else /* PERF */ +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ +#endif /* PERF */ + +void perf_print(unsigned long c1l, unsigned long c1h, + unsigned long c2l, unsigned long c2h, + char *key); + +void perf_print_times(struct tms *start, struct tms *end, char *key); + +void perf_init(char *fname); + +#endif /* __ARCH_PERF_H__ */ diff --git a/ports/unix/include/arch/sys_arch.h b/ports/unix/include/arch/sys_arch.h new file mode 100644 index 0000000..d9bdb29 --- /dev/null +++ b/ports/unix/include/arch/sys_arch.h @@ -0,0 +1,48 @@ +/* + * 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 + * + */ +#ifndef __ARCH_SYS_ARCH_H__ +#define __ARCH_SYS_ARCH_H__ + +#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL + +struct sys_sem; +typedef struct sys_sem * sys_sem_t; + +struct sys_mbox; +typedef struct sys_mbox *sys_mbox_t; + +struct sys_thread; +typedef struct sys_thread * sys_thread_t; + +#endif /* __ARCH_SYS_ARCH_H__ */ + diff --git a/ports/unix/include/netif/delif.h b/ports/unix/include/netif/delif.h new file mode 100644 index 0000000..cf06631 --- /dev/null +++ b/ports/unix/include/netif/delif.h @@ -0,0 +1,42 @@ +/* + * 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 + * + */ +#ifndef __DELIF_H__ +#define __DELIF_H__ + +#include "lwip/netif.h" + +#include "lwip/pbuf.h" + +void delif_init(struct netif *netif); +void delif_init_thread(struct netif *netif); + +#endif /* __DELIF_H__ */ diff --git a/ports/unix/include/netif/dropif.h b/ports/unix/include/netif/dropif.h new file mode 100644 index 0000000..11cb33d --- /dev/null +++ b/ports/unix/include/netif/dropif.h @@ -0,0 +1,41 @@ +/* + * 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 + * + */ +#ifndef __DROPIF_H__ +#define __DROPIF_H__ + +#include "lwip/netif.h" + +#include "lwip/pbuf.h" + +void dropif_init(struct netif *netif); + +#endif /* __DROPIF_H__ */ diff --git a/ports/unix/include/netif/fifo.h b/ports/unix/include/netif/fifo.h new file mode 100644 index 0000000..415cf01 --- /dev/null +++ b/ports/unix/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 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 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 + diff --git a/ports/unix/include/netif/pcapif.h b/ports/unix/include/netif/pcapif.h new file mode 100644 index 0000000..54f9472 --- /dev/null +++ b/ports/unix/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 + * + */ +#ifndef __PCAPIF_H__ +#define __PCAPIF_H__ + +#include "lwip/netif.h" + +void pcapif_init(struct netif *netif); + +#endif /* __PCAPIF_H__ */ diff --git a/ports/unix/include/netif/sio.h b/ports/unix/include/netif/sio.h new file mode 100644 index 0000000..24a6555 --- /dev/null +++ b/ports/unix/include/netif/sio.h @@ -0,0 +1,82 @@ +#ifndef SIO_H +#define SIO_H + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "netif/fifo.h" +//#include "netif/pppif.h" +/* BAUDRATE is defined in sio.c as it is implementation specific */ + +typedef struct sio_status_t { + int fd; + fifo_t myfifo; +} sio_status_t; + + +/** Baudrates */ +typedef enum sioBaudrates { + SIO_BAUD_9600, + SIO_BAUD_19200, + SIO_BAUD_38400, + SIO_BAUD_57600, + SIO_BAUD_115200 +} sioBaudrates; + +/** +* Read a char from incoming data stream, this call blocks until data has arrived +* @param siostat siostatus struct, contains sio instance data, given by sio_open +* @return char read from input stream +*/ +u8_t sio_recv( sio_status_t * siostat ); + +/** +* 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 c char to write to output stream +* @param siostat siostatus struct, contains sio instance data, given by sio_open +*/ +void sio_send( u8_t c, 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 ); + +/** +* Open serial port entry point from serial protocol (slipif, pppif) +* @param devnum the device number to use, i.e. ttySx, comx:, etc. there x = devnum +* @return siostatus struct, contains sio instance data, use when calling sio functions +*/ +sio_status_t * sio_open( int devnum ); + +/** +* 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 + diff --git a/ports/unix/include/netif/tapif.h b/ports/unix/include/netif/tapif.h new file mode 100644 index 0000000..3e1aa9d --- /dev/null +++ b/ports/unix/include/netif/tapif.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 + * + */ +#ifndef __TAPIF_H__ +#define __TAPIF_H__ + +#include "lwip/netif.h" + +void tapif_init(struct netif *netif); + +#endif /* __TAPIF_H__ */ diff --git a/ports/unix/include/netif/tcpdump.h b/ports/unix/include/netif/tcpdump.h new file mode 100644 index 0000000..4542de8 --- /dev/null +++ b/ports/unix/include/netif/tcpdump.h @@ -0,0 +1,40 @@ +/* + * 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 + * + */ +#ifndef __NETIF_TCPDUMP_H__ +#define __NETIF_TCPDUMP_H__ + +#include "lwip/pbuf.h" + +void tcpdump_init(void); +void tcpdump(struct pbuf *p); + +#endif /* __NETIF_TCPDUMP_H__ */ diff --git a/ports/unix/include/netif/tunif.h b/ports/unix/include/netif/tunif.h new file mode 100644 index 0000000..1b53405 --- /dev/null +++ b/ports/unix/include/netif/tunif.h @@ -0,0 +1,42 @@ +/* + * 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 + * + */ +#ifndef __TUNIF_H__ +#define __TUNIF_H__ + +#include "lwip/netif.h" + +#include "lwip/pbuf.h" + +void tunif_init(struct netif *netif); +void tunif_init_thread(struct netif *netif); + +#endif /* __TUNIF_H__ */ diff --git a/ports/unix/include/netif/unixif.h b/ports/unix/include/netif/unixif.h new file mode 100644 index 0000000..384fb54 --- /dev/null +++ b/ports/unix/include/netif/unixif.h @@ -0,0 +1,40 @@ +/* + * 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 + * + */ +#ifndef __UNIXIF_H__ +#define __UNIXIF_H__ + +#include "lwip/netif.h" + +void unixif_init_server(struct netif *netif); +void unixif_init_client(struct netif *netif); + +#endif /* __UNIXIF_H__ */ diff --git a/ports/unix/lwip_chksum.c b/ports/unix/lwip_chksum.c new file mode 100644 index 0000000..bbc8973 --- /dev/null +++ b/ports/unix/lwip_chksum.c @@ -0,0 +1,73 @@ +/* + * 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 + * + */ + +#include "lwip/debug.h" + +#include "lwip/arch.h" + +#include "lwip/def.h" +#include "lwip/inet.h" + + +/*-----------------------------------------------------------------------------------*/ +/* lwip_chksum: + * + * Sums up all 16 bit words in a memory portion. Also includes any odd byte. + * This function is used by the other checksum functions. + * + */ +/*-----------------------------------------------------------------------------------*/ +#if 0 +u16_t +lwip_chksum(void *dataptr, int len) +{ + u32_t acc; + + for(acc = 0; len > 1; len -= 2) { + acc += *((u16_t *)dataptr)++; + } + + /* add up any odd byte */ + if(len == 1) { + acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8); + DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", *(u8_t *)dataptr)); + } + acc = (acc >> 16) + (acc & 0xffffUL); + + if(acc & 0xffff0000 != 0) { + acc = (acc >> 16) + (acc & 0xffffUL); + } + + return (u16_t)acc; +} +/*-----------------------------------------------------------------------------------*/ +#endif diff --git a/ports/unix/netif/delif.c b/ports/unix/netif/delif.c new file mode 100644 index 0000000..5f7005d --- /dev/null +++ b/ports/unix/netif/delif.c @@ -0,0 +1,310 @@ +/* + * 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 + * + */ + +#include "lwip/debug.h" + +#include + +#include "lwip/def.h" +#include "netif/delif.h" + +#ifdef linux +#include "netif/tapif.h" +#else /* linux */ +#include "netif/tunif.h" +#endif /* linux */ + +#include "lwip/sys.h" + + +#define DELIF_INPUT_DROPRATE 0.1 +#define DELIF_OUTPUT_DROPRATE 0.1 + +#define DELIF_INPUT_DELAY 500 /* Miliseconds. */ +#define DELIF_OUTPUT_DELAY 500 /* Miliseconds. */ + +#define DELIF_TIMEOUT 10 + +struct delif { + err_t (* input)(struct pbuf *p, struct netif *inp); + struct netif *netif; +}; + +struct delif_pbuf { + struct delif_pbuf *next; + struct pbuf *p; + struct ip_addr *ipaddr; + unsigned int time; +}; + +static struct delif_pbuf *input_list = NULL; +static struct delif_pbuf *output_list = NULL; +/*-----------------------------------------------------------------------------------*/ +static void +delif_input_timeout(void *arg) +{ + struct netif *netif; + struct delif *delif; + struct delif_pbuf *dp; + unsigned int timeout, now; + + timeout = DELIF_TIMEOUT; + + netif = arg; + delif = netif->state; + + + /* Check if there is anything on the input list. */ + dp = input_list; + while(dp != NULL) { + now = sys_now(); + + if(dp->time <= now) { + delif->input(dp->p, netif); + if(dp->next != NULL) { + if(dp->next->time > now) { + timeout = dp->next->time - now; + } else { + timeout = 0; + } + DEBUGF(DELIF_DEBUG, ("delif_output_timeout: timeout %u.\n", timeout)); + + } + input_list = dp->next; + free(dp); + dp = input_list; + } else { + dp = dp->next; + } + } + + sys_timeout(timeout, delif_input_timeout, arg); +} +/*-----------------------------------------------------------------------------------*/ +static void +delif_output_timeout(void *arg) +{ + struct netif *netif; + struct delif *delif; + struct delif_pbuf *dp; + unsigned int timeout, now; + + timeout = DELIF_TIMEOUT; + + netif = arg; + delif = netif->state; + + /* Check if there is anything on the output list. */ + dp = output_list; + while(dp != NULL) { + now = sys_now(); + if(dp->time <= now) { + DEBUGF(DELIF_DEBUG, ("delif_output_timeout: now %u dp->time %u\n", + now, dp->time)); + delif->netif->output(delif->netif, dp->p, dp->ipaddr); + if(dp->next != NULL) { + if(dp->next->time > now) { + timeout = dp->next->time - now; + } else { + timeout = 0; + } + DEBUGF(DELIF_DEBUG, ("delif_output_timeout: timeout %u.\n", timeout)); + + } + pbuf_free(dp->p); + + output_list = dp->next; + free(dp); + dp = output_list; + } else { + dp = dp->next; + } + } + + + sys_timeout(timeout, delif_output_timeout, arg); +} +/*-----------------------------------------------------------------------------------*/ +static err_t +delif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) +{ + struct delif_pbuf *dp, *np; + struct pbuf *q; + int i, j; + char *data; + + DEBUGF(DELIF_DEBUG, ("delif_output\n")); + +#ifdef DELIF_OUTPUT_DROPRATE + if(((double)rand()/(double)RAND_MAX) < DELIF_OUTPUT_DROPRATE) { + DEBUGF(DELIF_DEBUG, ("delif_output: Packet dropped\n")); + return 0; + } +#endif /* DELIF_OUTPUT_DROPRATE */ + + + DEBUGF(DELIF_DEBUG, ("delif_output\n")); + + + dp = malloc(sizeof(struct delif_pbuf)); + data = malloc(p->tot_len); + + i = 0; + for(q = p; q != NULL; q = q->next) { + for(j = 0; j < q->len; j++) { + data[i] = ((char *)q->payload)[j]; + i++; + } + } + + + dp->p = pbuf_alloc(PBUF_LINK, 0, PBUF_ROM); + dp->p->payload = data; + dp->p->len = p->tot_len; + dp->p->tot_len = p->tot_len; + dp->ipaddr = ipaddr; + dp->time = sys_now() + DELIF_OUTPUT_DELAY; + dp->next = NULL; + if(output_list == NULL) { + output_list = dp; + } else { + for(np = output_list; np->next != NULL; np = np->next); + np->next = dp; + } + + + return ERR_OK; + + +} +/*-----------------------------------------------------------------------------------*/ +static err_t +delif_input(struct pbuf *p, struct netif *inp) +{ + struct delif_pbuf *dp, *np; + + DEBUGF(DELIF_DEBUG, ("delif_input\n")); +#ifdef DELIF_INPUT_DROPRATE + if(((double)rand()/(double)RAND_MAX) < DELIF_INPUT_DROPRATE) { + DEBUGF(DELIF_DEBUG, ("delif_input: Packet dropped\n")); + pbuf_free(p); + return ERR_OK; + } +#endif /* DELIF_INPUT_DROPRATE */ + + + dp = malloc(sizeof(struct delif_pbuf)); + dp->p = p; + dp->time = sys_now() + DELIF_INPUT_DELAY; + dp->next = NULL; + if(input_list == NULL) { + input_list = dp; + } else { + for(np = input_list; np->next != NULL; np = np->next); + np->next = dp; + } + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +void +delif_init(struct netif *netif) +{ + struct delif *del; + + del = malloc(sizeof(struct delif)); + netif->state = del; + netif->name[0] = 'd'; + netif->name[1] = 'e'; + netif->output = delif_output; + + del->netif = malloc(sizeof(struct netif)); +#ifdef linux + /* tapif_init(del->netif);*/ + tunif_init(del->netif); +#else /* linux */ + tunif_init(del->netif); +#endif /* linux */ + del->input = netif->input; + del->netif->input = delif_input; + sys_timeout(DELIF_TIMEOUT, delif_input_timeout, netif); + sys_timeout(DELIF_TIMEOUT, delif_output_timeout, netif); +} + +/*-----------------------------------------------------------------------------------*/ +static void +delif_thread(void *arg) +{ + struct netif *netif = arg; + struct delif *del; + sys_sem_t sem; + + del = netif->state; +#ifdef linux + tapif_init(del->netif); +#else /* linux */ + tunif_init(del->netif); +#endif /* linux */ + + sys_timeout(DELIF_TIMEOUT, delif_input_timeout, netif); + sys_timeout(DELIF_TIMEOUT, delif_output_timeout, netif); + + sem = sys_sem_new(0); + sys_sem_wait(sem); + +} +/*-----------------------------------------------------------------------------------*/ +void +delif_init_thread(struct netif *netif) +{ + struct delif *del; + + DEBUGF(DELIF_DEBUG, ("delif_init_thread\n")); + + del = malloc(sizeof(struct delif)); + netif->state = del; + netif->name[0] = 'd'; + netif->name[1] = 'e'; + netif->output = delif_output; + + del->netif = malloc(sizeof(struct netif)); + del->netif->ip_addr = netif->ip_addr; + del->netif->gw = netif->gw; + del->netif->netmask = netif->netmask; + del->input = netif->input; + del->netif->input = delif_input; + sys_thread_new(delif_thread, netif); +} + +/*-----------------------------------------------------------------------------------*/ + + + diff --git a/ports/unix/netif/fifo.c b/ports/unix/netif/fifo.c new file mode 100644 index 0000000..99122c2 --- /dev/null +++ b/ports/unix/netif/fifo.c @@ -0,0 +1,131 @@ +/* Author: Magnus Ivarsson */ + +/* ---------------------------------------------- */ +/* --- fifo 4 unix ------------------------------ */ +/* ---------------------------------------------- */ +#include "netif/fifo.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/arch.h" +#include + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#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 + + 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; + + 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; + 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; + fifo->sem = sys_sem_new(1); // critical section 1=free to enter + fifo->getSem = sys_sem_new(0); // 0 = no one waiting + fifo->getWaiting = FALSE; +} diff --git a/ports/unix/netif/list.c b/ports/unix/netif/list.c new file mode 100644 index 0000000..f4f95d1 --- /dev/null +++ b/ports/unix/netif/list.c @@ -0,0 +1,162 @@ +/* + * 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 + * + */ + + +#include "lwip/list.h" + +#include + +struct list { + struct elem *first, *last; + int size, elems; +}; + +struct elem { + struct elem *next; + void *data; +}; + +/*-----------------------------------------------------------------------------------*/ +struct list * +list_new(int size) +{ + struct list *list; + 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 = 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); + } +} +/*-----------------------------------------------------------------------------------*/ + diff --git a/ports/unix/netif/pcapif.c b/ports/unix/netif/pcapif.c new file mode 100644 index 0000000..1550940 --- /dev/null +++ b/ports/unix/netif/pcapif.c @@ -0,0 +1,214 @@ +/* + * 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 + * + */ + +#ifndef linux /* Apparently, this doesn't work under Linux. */ + +#include "lwip/debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "netif/etharp.h" + +#include "lwip/stats.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "netif/unixif.h" +#include "lwip/sys.h" + +#include "lwip/ip.h" + +#include "lwip/list.h" + +#include "netif/tcpdump.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, + struct ip_addr *ipaddr) +{ + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +static void +timeout(void *arg) +{ + struct netif *netif; + struct pcapif *pcapif; + struct pbuf *p, *q; + u8_t *bufptr; + struct eth_hdr *ethhdr; + + netif = (struct netif *)arg; + pcapif = netif->state; + ethhdr = (struct eth_hdr *)pcapif->pkt; + + + if(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) { + /* We iterate over the pbuf chain until we have read the entire + packet into the pbuf. */ + bufptr = (u_char *)pcapif->pkt; + for(q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + available data in the pbuf is given by the q->len + variable. */ + /* read data into(q->payload, q->len); */ + bcopy(bufptr, q->payload, q->len); + bufptr += q->len; + } + + ethhdr = p->payload; + switch(htons(ethhdr->type)) { + case ETHTYPE_IP: + arp_ip_input(netif, p); + pbuf_header(p, -14); + netif->input(p, netif); + break; + case ETHTYPE_ARP: + p = arp_arp_input(netif, pcapif->ethaddr, p); + if(p != NULL) { + printf("ARP outout\n"); + pbuf_free(p); + } + 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); + } + } +} +/*-----------------------------------------------------------------------------------*/ +void +pcapif_init(struct netif *netif) +{ + struct pcapif *p; + + p = malloc(sizeof(struct pcapif)); + 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; + } + + p->sem = sys_sem_new(0); + p->p = NULL; + p->lasttime = 0; + + sys_thread_new(pcapif_thread, netif); +} +/*-----------------------------------------------------------------------------------*/ +#endif /* linux */ diff --git a/ports/unix/netif/sio.c b/ports/unix/netif/sio.c new file mode 100644 index 0000000..6375d07 --- /dev/null +++ b/ports/unix/netif/sio.c @@ -0,0 +1,319 @@ +/* Author: Magnus Ivarsson */ + +#include "netif/sio.h" +#include "netif/fifo.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/arch.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 +#include +#include +#include +#include +#include +#include +#include + +//#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[2]; + +/* --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 ) +{ + DEBUGF(SIO_DEBUG, ("SigHand: rxSignal chanel 0")); + 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 ) +{ + DEBUGF(SIO_DEBUG, ("SigHand: rxSignal channel 1")); + fifoPut( &statusar[1].myfifo, statusar[1].fd ); +} + +/** +* Initiation of serial device +* @param device : string with the device name and path, eg. "/dev/ttyS0" +* @param netif : netinterface struct, contains interface instance data +* @return file handle to serial dev. +*/ +static int sio_init( char * device, int devnum, sio_status_t * siostat ) +{ + struct termios oldtio,newtio; + struct sigaction saio; /* definition of signal action */ + int fd; + + /* open the device to be non-blocking (read will return immediatly) */ + fd = open( device, O_RDWR | O_NOCTTY | O_NONBLOCK ); + if ( fd < 0 ) + { + perror( device ); + exit( -1 ); + } + + /* install the signal handler before making the device asynchronous */ + switch ( devnum ) + { + case 0: + DEBUGF( SIO_DEBUG, ("sioinit, signal_handler_IO_0\r\n") ); + saio.sa_handler = signal_handler_IO_0; + break; + case 1: + DEBUGF( SIO_DEBUG, ("sioinit, signal_handler_IO_1\r\n") ); + saio.sa_handler = signal_handler_IO_1; + break; + default: + DEBUGF( SIO_DEBUG,("sioinit, devnum not allowed\r\n") ); + break; + } + + saio.sa_flags = 0; +#if linux + saio.sa_restorer = NULL; +#endif /* linux */ + sigaction( SIGIO,&saio,NULL ); + + /* allow the process to receive SIGIO */ + fcntl( fd, F_SETOWN, getpid( ) ); + /* Make the file descriptor asynchronous (the manual page says only + O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ + fcntl( fd, F_SETFL, FASYNC ); + + tcgetattr( fd,&oldtio ); /* save current port settings */ + /* set new port settings */ + /* see 'man termios' for further settings */ + 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; + + DEBUGF( 1,("sio_speed: baudcode:%d enter\n",speed ) ); + + if ( fd < 0 ) + { + DEBUGF(SIO_DEBUG, ( "sio_speed: fd ERROR\n" )); + exit( -1 ); + } + + tcgetattr( fd,&oldtio ); /* get current port settings */ + + /* set new port settings + * see 'man termios' for further settings */ + 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 ); + + DEBUGF( SIO_DEBUG ,("sio_speed: leave\n" )); +} + +/* --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 ) + { + DEBUGF( SIO_DEBUG,("sio_send: write refused") ); + } +} + +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 ) + { + DEBUGF( SIO_DEBUG,("sio_send_string: write refused") ); + } + DEBUGF( (PPP_DEBUG | SIO_DEBUG),("sent:%s",str ) ); +} + + +void sio_flush( sio_status_t * siostat ) +{ + /* not implemented in unix as it is not needed */ + //sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; +} + + +//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; + + DEBUGF( (PPP_DEBUG | SIO_DEBUG), ("expect:%s\n",str) ); + while ( 1 ) + { + c=fifoGet( &(siostat->myfifo) ); + DEBUGF( (PPP_DEBUG | 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 + } + DEBUGF( (PPP_DEBUG | SIO_DEBUG), ("[match]\n") ); +} + + +sio_status_t * sio_open( int 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; + + fifoInit( &siostate->myfifo ); + + sprintf( dev, "/dev/ttyS%d", devnum ); + + if ( (devnum == 1) || (devnum == 0) ) + { + if ( ( siostate->fd = sio_init( dev, devnum, siostate ) ) == 0 ) + { + DEBUGF(SIO_DEBUG, ( "sio_open: ERROR opening serial device" )); + abort( ); + return NULL; + } + } + else + { + DEBUGF(SIO_DEBUG, ( "sio_open: device %s (%d) is not supported", dev, devnum )); + return NULL; + } + DEBUGF( 1,("sio_open: dev=%s open.\n", dev )); + + return siostate; +} + +/** +* +*/ +void sio_change_baud( sioBaudrates baud, sio_status_t * siostat ) +{ +// sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; + + DEBUGF( 1,("sio_change_baud\n" )); + + 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: + DEBUGF( 1,("sio_change_baud: Unknown baudrate, code:%d", baud )); + break; + } +} + diff --git a/ports/unix/netif/tapif.c b/ports/unix/netif/tapif.c new file mode 100644 index 0000000..525f39d --- /dev/null +++ b/ports/unix/netif/tapif.c @@ -0,0 +1,361 @@ +/* + * 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 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "lwip/debug.h" + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" + +#include "netif/etharp.h" + +#ifdef linux +#include +#include +#include +#define DEVTAP "/dev/net/tun" +#else /* linux */ +#define DEVTAP "/dev/tap0" +#endif /* linux */ + +#define IFNAME0 't' +#define IFNAME1 'p' + +static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; + +struct tapif { + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ + int fd; +}; + +/* Forward declarations. */ +static void tapif_input(struct netif *netif); +static err_t tapif_output(struct netif *netif, struct pbuf *p, + struct ip_addr *ipaddr); + +static void tapif_thread(void *data); + +/*-----------------------------------------------------------------------------------*/ +static void +low_level_init(struct netif *netif) +{ + struct tapif *tapif; + char buf[100]; + + tapif = netif->state; + + /* Obtain MAC address from network interface. */ + + /* (We just fake an address...) */ + tapif->ethaddr->addr[0] = 0x1; + tapif->ethaddr->addr[1] = 0x2; + tapif->ethaddr->addr[2] = 0x3; + tapif->ethaddr->addr[3] = 0x4; + tapif->ethaddr->addr[4] = 0x5; + tapif->ethaddr->addr[5] = 0x6; + + /* Do whatever else is needed to initialize interface. */ + + tapif->fd = open(DEVTAP, O_RDWR); + DEBUGF(TAPIF_DEBUG, ("tapif_init: fd %d\n", tapif->fd)); + if(tapif->fd == -1) { + perror("tapif_init"); + exit(1); + } + +#ifdef linux + { + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP|IFF_NO_PI; + if (ioctl(tapif->fd, TUNSETIFF, (void *) &ifr) < 0) { + perror(buf); + exit(1); + } + } +#endif /* Linux */ + + snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d", + ip4_addr1(&(netif->gw)), + ip4_addr2(&(netif->gw)), + ip4_addr3(&(netif->gw)), + ip4_addr4(&(netif->gw))); + + DEBUGF(TAPIF_DEBUG, ("tapif_init: system(\"%s\");\n", buf)); + system(buf); + sys_thread_new(tapif_thread, netif); + +} +/*-----------------------------------------------------------------------------------*/ +/* + * 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 pbuf *q; + char buf[1514]; + char *bufptr; + struct tapif *tapif; + + tapif = netif->state; +#if 0 + if(((double)rand()/(double)RAND_MAX) < 0.2) { + printf("drop output\n"); + return ERR_OK; + } +#endif + /* initiate transfer(); */ + + bufptr = &buf[0]; + + for(q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + /* send data from(q->payload, q->len); */ + memcpy(bufptr, q->payload, q->len); + bufptr += q->len; + } + + /* signal that packet should be sent(); */ + if(write(tapif->fd, buf, p->tot_len) == -1) { + perror("tapif: write"); + } + 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 tapif *tapif) +{ + struct pbuf *p, *q; + u16_t len; + char buf[1514]; + char *bufptr; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + len = read(tapif->fd, buf, sizeof(buf)); +#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) { + /* We iterate over the pbuf chain until we have read the entire + packet into the pbuf. */ + bufptr = &buf[0]; + for(q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + available data in the pbuf is given by the q->len + variable. */ + /* read data into(q->payload, q->len); */ + memcpy(q->payload, bufptr, q->len); + bufptr += q->len; + } + /* acknowledge that packet has been read(); */ + } else { + /* drop packet(); */ + } + + return p; +} +/*-----------------------------------------------------------------------------------*/ +static void +tapif_thread(void *arg) +{ + struct netif *netif; + struct tapif *tapif; + fd_set fdset; + int ret; + + netif = arg; + 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"); + } + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * tapif_output(): + * + * This function is called by the TCP/IP stack when an IP packet + * should be sent. It calls the function called low_level_output() to + * do the actuall transmission of the packet. + * + */ +/*-----------------------------------------------------------------------------------*/ +static err_t +tapif_output(struct netif *netif, struct pbuf *p, + struct ip_addr *ipaddr) +{ + p = etharp_output(netif, ipaddr, p); + if(p != NULL) { + low_level_output(netif, p); + p = NULL; + } + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* + * 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 tapif *tapif; + struct eth_hdr *ethhdr; + struct pbuf *p, *q; + + + tapif = netif->state; + + p = low_level_input(tapif); + + if(p == NULL) { + DEBUGF(TAPIF_DEBUG, ("tapif_input: low_level_input returned NULL\n")); + return; + } + ethhdr = p->payload; + + q = NULL; + switch(htons(ethhdr->type)) { + case ETHTYPE_IP: + DEBUGF(TAPIF_DEBUG, ("tapif_input: IP packet\n")); + q = etharp_ip_input(netif, p); + pbuf_header(p, -14); + netif->input(p, netif); + break; + case ETHTYPE_ARP: + DEBUGF(TAPIF_DEBUG, ("tapif_input: ARP packet\n")); + q = etharp_arp_input(netif, tapif->ethaddr, p); + break; + default: + pbuf_free(p); + break; + } + if(q != NULL) { + low_level_output(netif, q); + pbuf_free(q); + } + +} +/*-----------------------------------------------------------------------------------*/ +static void +arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL); +} +/*-----------------------------------------------------------------------------------*/ +/* + * 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. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +tapif_init(struct netif *netif) +{ + struct tapif *tapif; + + tapif = mem_malloc(sizeof(struct tapif)); + netif->state = tapif; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + netif->output = tapif_output; + netif->linkoutput = low_level_output; + netif->mtu = 1500; + + tapif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); + low_level_init(netif); + etharp_init(); + + sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL); +} +/*-----------------------------------------------------------------------------------*/ diff --git a/ports/unix/netif/tcpdump.c b/ports/unix/netif/tcpdump.c new file mode 100644 index 0000000..7e3264b --- /dev/null +++ b/ports/unix/netif/tcpdump.c @@ -0,0 +1,186 @@ +/* + * 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 + * + */ + +#include + +#include "netif/tcpdump.h" +#include "lwip/ip.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include "lwip/inet.h" + +static FILE *file = NULL; + +/*-----------------------------------------------------------------------------------*/ +void +tcpdump_init(void) +{ + char *fname; + + fname = "/tmp/tcpdump"; + file = fopen(fname, "w"); + if(file == NULL) { + perror("tcpdump_init: fopen"); + } + DEBUGF(TCPDUMP_DEBUG, ("tcpdump: file %s\n", fname)); +} +/*-----------------------------------------------------------------------------------*/ +void +tcpdump(struct pbuf *p) +{ + struct ip_hdr *iphdr; + struct tcp_hdr *tcphdr; + struct udp_hdr *udphdr; + char flags[5]; + int i; + int len; + int offset; + + if(file == NULL) { + return; + } +#ifdef IPv4 + iphdr = p->payload; + switch(IPH_PROTO(iphdr)) { + case IP_PROTO_TCP: + tcphdr = (struct tcp_hdr *)((char *)iphdr + IP_HLEN); + + pbuf_header(p, -IP_HLEN); + if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), + (struct ip_addr *)&(iphdr->dest), + IP_PROTO_TCP, p->tot_len) != 0) { + DEBUGF(TCPDUMP_DEBUG, ("tcpdump: IP checksum failed!\n")); + /* fprintf(file, "chksum 0x%lx ", tcphdr->chksum); + tcphdr->chksum = 0; + fprintf(file, "should be 0x%lx ", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), + (struct ip_addr *)&(iphdr->dest), + IP_PROTO_TCP, p->tot_len));*/ + fprintf(file, "!chksum "); + } + + i = 0; + if(TCPH_FLAGS(tcphdr) & TCP_SYN) { + flags[i++] = 'S'; + } + if(TCPH_FLAGS(tcphdr) & TCP_PSH) { + flags[i++] = 'P'; + } + if(TCPH_FLAGS(tcphdr) & TCP_FIN) { + flags[i++] = 'F'; + } + if(TCPH_FLAGS(tcphdr) & TCP_RST) { + flags[i++] = 'R'; + } + if(i == 0) { + flags[i++] = '.'; + } + flags[i++] = 0; + + + + fprintf(file, "%d.%d.%d.%d.%u > %d.%d.%d.%d.%u: ", + (int)(ntohl(iphdr->src.addr) >> 24) & 0xff, + (int)(ntohl(iphdr->src.addr) >> 16) & 0xff, + (int)(ntohl(iphdr->src.addr) >> 8) & 0xff, + (int)(ntohl(iphdr->src.addr) >> 0) & 0xff, + ntohs(tcphdr->src), + (int)(ntohl(iphdr->dest.addr) >> 24) & 0xff, + (int)(ntohl(iphdr->dest.addr) >> 16) & 0xff, + (int)(ntohl(iphdr->dest.addr) >> 8) & 0xff, + (int)(ntohl(iphdr->dest.addr) >> 0) & 0xff, + ntohs(tcphdr->dest)); + offset = TCPH_OFFSET(tcphdr) >> 4; + + len = ntohs(IPH_LEN(iphdr)) - offset * 4 - IP_HLEN; + if(len != 0 || flags[0] != '.') { + fprintf(file, "%s %lu:%lu(%u) ", + flags, + ntohl(tcphdr->seqno), + ntohl(tcphdr->seqno) + len, + len); + } + if(TCPH_FLAGS(tcphdr) & TCP_ACK) { + fprintf(file, "ack %lu ", + ntohl(tcphdr->ackno)); + } + fprintf(file, "wnd %u\n", + ntohs(tcphdr->wnd)); + + fflush(file); + + pbuf_header(p, IP_HLEN); + break; + + case IP_PROTO_UDP: + udphdr = (struct udp_hdr *)((char *)iphdr + IP_HLEN); + + pbuf_header(p, -IP_HLEN); + if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), + (struct ip_addr *)&(iphdr->dest), + IP_PROTO_UDP, p->tot_len) != 0) { + DEBUGF(TCPDUMP_DEBUG, ("tcpdump: IP checksum failed!\n")); + /* fprintf(file, "chksum 0x%lx ", tcphdr->chksum); + tcphdr->chksum = 0; + fprintf(file, "should be 0x%lx ", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), + (struct ip_addr *)&(iphdr->dest), + IP_PROTO_TCP, p->tot_len));*/ + fprintf(file, "!chksum "); + } + + fprintf(file, "%d.%d.%d.%d.%u > %d.%d.%d.%d.%u: ", + (int)(ntohl(iphdr->src.addr) >> 24) & 0xff, + (int)(ntohl(iphdr->src.addr) >> 16) & 0xff, + (int)(ntohl(iphdr->src.addr) >> 8) & 0xff, + (int)(ntohl(iphdr->src.addr) >> 0) & 0xff, + ntohs(udphdr->src), + (int)(ntohl(iphdr->dest.addr) >> 24) & 0xff, + (int)(ntohl(iphdr->dest.addr) >> 16) & 0xff, + (int)(ntohl(iphdr->dest.addr) >> 8) & 0xff, + (int)(ntohl(iphdr->dest.addr) >> 0) & 0xff, + ntohs(udphdr->dest)); + fprintf(file, "U "); + len = ntohs(IPH_LEN(iphdr)) - sizeof(struct udp_hdr) - IP_HLEN; + fprintf(file, " %d\n", len); + + fflush(file); + + pbuf_header(p, IP_HLEN); + break; + + } +#endif /* IPv4 */ +} +/*-----------------------------------------------------------------------------------*/ + + + + diff --git a/ports/unix/netif/tunif.c b/ports/unix/netif/tunif.c new file mode 100644 index 0000000..0d061b4 --- /dev/null +++ b/ports/unix/netif/tunif.c @@ -0,0 +1,298 @@ +/* + * 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 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "lwip/debug.h" + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" + + +#define IFNAME0 't' +#define IFNAME1 'n' + +struct tunif { + /* Add whatever per-interface state that is needed here. */ + int fd; +}; + +/* Forward declarations. */ +static void tunif_input(struct netif *netif); +static err_t tunif_output(struct netif *netif, struct pbuf *p, + struct ip_addr *ipaddr); + +static void tunif_thread(void *data); + +/*-----------------------------------------------------------------------------------*/ +static void +low_level_init(struct netif *netif) +{ + struct tunif *tunif; + char buf[100]; + + tunif = netif->state; + + /* Obtain MAC address from network interface. */ + + /* Do whatever else is needed to initialize interface. */ + + tunif->fd = open("/dev/tun0", O_RDWR); + DEBUGF(TUNIF_DEBUG, ("tunif_init: fd %d\n", tunif->fd)); + if(tunif->fd == -1) { + perror("tunif_init"); + exit(1); + } + snprintf(buf, sizeof(buf), "ifconfig tun0 inet %d.%d.%d.%d %d.%d.%d.%d", + ip4_addr1(&(netif->gw)), + ip4_addr2(&(netif->gw)), + ip4_addr3(&(netif->gw)), + ip4_addr4(&(netif->gw)), + ip4_addr1(&(netif->ip_addr)), + ip4_addr2(&(netif->ip_addr)), + ip4_addr3(&(netif->ip_addr)), + ip4_addr4(&(netif->ip_addr))); + + DEBUGF(TUNIF_DEBUG, ("tunif_init: system(\"%s\");\n", buf)); + system(buf); + sys_thread_new(tunif_thread, netif); + +} +/*-----------------------------------------------------------------------------------*/ +/* + * 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 tunif *tunif, struct pbuf *p) +{ + struct pbuf *q; + char buf[1500]; + char *bufptr; + + /* initiate transfer(); */ + + if(((double)rand()/(double)RAND_MAX) < 0.4) { + printf("drop\n"); + return ERR_OK; + } + + + bufptr = &buf[0]; + + for(q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + /* send data from(q->payload, q->len); */ + bcopy(q->payload, bufptr, q->len); + bufptr += q->len; + } + + /* signal that packet should be sent(); */ + if(write(tunif->fd, buf, p->tot_len) == -1) { + perror("tunif: write"); + } + 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 tunif *tunif) +{ + struct pbuf *p, *q; + u16_t len; + char buf[1500]; + char *bufptr; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + len = read(tunif->fd, buf, sizeof(buf)); + + /* if(((double)rand()/(double)RAND_MAX) < 0.1) { + printf("drop\n"); + return NULL; + }*/ + + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL); + + if(p != NULL) { + /* We iterate over the pbuf chain until we have read the entire + packet into the pbuf. */ + bufptr = &buf[0]; + for(q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + available data in the pbuf is given by the q->len + variable. */ + /* read data into(q->payload, q->len); */ + bcopy(bufptr, q->payload, q->len); + bufptr += q->len; + } + /* acknowledge that packet has been read(); */ + } else { + /* drop packet(); */ + } + + return p; +} +/*-----------------------------------------------------------------------------------*/ +static void +tunif_thread(void *arg) +{ + struct netif *netif; + struct tunif *tunif; + fd_set fdset; + int ret; + + netif = arg; + tunif = netif->state; + + while(1) { + FD_ZERO(&fdset); + FD_SET(tunif->fd, &fdset); + + /* Wait for a packet to arrive. */ + ret = select(tunif->fd + 1, &fdset, NULL, NULL, NULL); + + if(ret == 1) { + /* Handle incoming packet. */ + tunif_input(netif); + } else if(ret == -1) { + perror("tunif_thread: select"); + } + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * tunif_output(): + * + * This function is called by the TCP/IP stack when an IP packet + * should be sent. It calls the function called low_level_output() to + * do the actuall transmission of the packet. + * + */ +/*-----------------------------------------------------------------------------------*/ +static err_t +tunif_output(struct netif *netif, struct pbuf *p, + struct ip_addr *ipaddr) +{ + struct tunif *tunif; + + tunif = netif->state; + + return low_level_output(tunif, p); + +} +/*-----------------------------------------------------------------------------------*/ +/* + * tunif_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 +tunif_input(struct netif *netif) +{ + struct tunif *tunif; + struct pbuf *p; + + + tunif = netif->state; + + p = low_level_input(tunif); + + if(p == NULL) { + DEBUGF(TUNIF_DEBUG, ("tunif_input: low_level_input returned NULL\n")); + return; + } + + if(ip_lookup(p->payload, netif)) { + netif->input(p, netif); + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * tunif_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. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +tunif_init(struct netif *netif) +{ + struct tunif *tunif; + + tunif = mem_malloc(sizeof(struct tunif)); + netif->state = tunif; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + netif->output = tunif_output; + + + low_level_init(netif); +} +/*-----------------------------------------------------------------------------------*/ diff --git a/ports/unix/netif/unixif.c b/ports/unix/netif/unixif.c new file mode 100644 index 0000000..742f200 --- /dev/null +++ b/ports/unix/netif/unixif.c @@ -0,0 +1,480 @@ +/* + * 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 + * + */ + +#include "lwip/debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "lwip/stats.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "netif/unixif.h" +#include "lwip/sys.h" + +#include "lwip/list.h" + +#include "netif/tcpdump.h" + +#define UNIXIF_BPS 512000 +#define UNIXIF_QUEUELEN 6 +/*#define UNIXIF_DROP_FIRST */ + +struct unixif_buf { + struct pbuf *p; + unsigned short len, tot_len; + void *payload; +}; + +struct unixif { + int fd; + sys_sem_t sem; + struct list *q; +}; + + +/*-----------------------------------------------------------------------------------*/ +static int +unix_socket_client(char *name) +{ + int fd, len; + struct sockaddr_un unix_addr; + + /* create a Unix domain stream socket */ + if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + + /* fill socket address structure w/our address */ + memset(&unix_addr, 0, sizeof(unix_addr)); + unix_addr.sun_family = AF_UNIX; + sprintf(unix_addr.sun_path, "%s%05d", "/var/tmp/", getpid()); +#ifndef linux + len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; + unix_addr.sun_len = len; +#else + len = sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; +#endif /* linux */ + + unlink(unix_addr.sun_path); /* in case it already exists */ + if(bind(fd, (struct sockaddr *) &unix_addr, + sizeof(struct sockaddr_un)) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + if(chmod(unix_addr.sun_path, S_IRWXU | S_IRWXO) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + + /* fill socket address structure w/server's addr */ + memset(&unix_addr, 0, sizeof(unix_addr)); + unix_addr.sun_family = AF_UNIX; + strcpy(unix_addr.sun_path, name); +#ifndef linux + len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; + unix_addr.sun_len = len; +#else + len = sizeof(unix_addr.sun_family) + strlen(unix_addr.sun_path) + 1; +#endif /* linux */ + if(connect(fd, (struct sockaddr *) &unix_addr, + sizeof(struct sockaddr_un)) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + return(fd); +} + +/*-----------------------------------------------------------------------------------*/ +static int +unix_socket_server(char *name) +{ + int fd, len; + struct sockaddr_un unix_addr; + + /* create a Unix domain stream socket */ + if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("unixif: unix_socket_server: socket"); + return(-1); + } + + unlink(name); /* in case it already exists */ + + /* fill in socket address structure */ + memset(&unix_addr, 0, sizeof(unix_addr)); + unix_addr.sun_family = AF_UNIX; + strcpy(unix_addr.sun_path, name); +#ifndef linux + len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; + unix_addr.sun_len = len; +#else + len = sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; +#endif /* linux */ + + /* bind the name to the descriptor */ + if(bind(fd, (struct sockaddr *) &unix_addr, + sizeof(struct sockaddr_un)) < 0) { + perror("unixif: unix_socket_server: bind"); + return(-1); + } + + if(chmod(unix_addr.sun_path, S_IRWXU | S_IRWXO) < 0) { + perror("unixif: unix_socket_server: chmod"); + return(-1); + } + + + if(listen(fd, 5) < 0) { /* tell kernel we're a server */ + perror("unixif: unix_socket_server: listen"); + return(-1); + } + + return(fd); +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_input_handler(void *data) +{ + struct netif *netif; + struct unixif *unixif; + char buf[4096], *bufptr; + int len, plen, rlen; + struct pbuf *p, *q; + + netif = data; + unixif = netif->state; + + len = read(unixif->fd, &plen, sizeof(int)); + if(len == -1) { + perror("unixif_irq_handler: read"); + abort(); + } + + DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: len == %d plen == %d bytes\n", len, plen)); + if(len == sizeof(int)) { + + if(plen < 20 || plen > 1500) { + DEBUGF(UNIXIF_DEBUG, ("plen %d!\n", plen)); + return; + } + + len = read(unixif->fd, buf, plen); + if(len == -1) { + perror("unixif_irq_handler: read"); + abort(); + } + DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: read %d bytes\n", len)); + p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL); + + if(p != NULL) { + rlen = len; + bufptr = buf; + q = p; + while(rlen > 0) { + bcopy(bufptr, q->payload, rlen > q->len? q->len: rlen); + rlen -= q->len; + bufptr += q->len; + q = q->next; + } + pbuf_realloc(p, len); +#ifdef LINK_STATS + lwip_stats.link.recv++; +#endif /* LINK_STATS */ + tcpdump(p); + netif->input(p, netif); + } else { + DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: could not allocate pbuf\n")); + } + + + } +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_thread(void *arg) +{ + struct netif *netif; + struct unixif *unixif; + + DEBUGF(UNIXIF_DEBUG, ("unixif_thread: started.\n")); + + netif = arg; + unixif = netif->state; + + + while(1) { + sys_sem_wait(unixif->sem); + unixif_input_handler(netif); + } + +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_thread2(void *arg) +{ + struct netif *netif; + struct unixif *unixif; + fd_set fdset; + + DEBUGF(UNIXIF_DEBUG, ("unixif_thread2: started.\n")); + + netif = arg; + unixif = netif->state; + + while(1) { + FD_ZERO(&fdset); + FD_SET(unixif->fd, &fdset); + + if(select(unixif->fd + 1, &fdset, NULL, NULL, NULL) > 0) { + sys_sem_signal(unixif->sem); + } + } +} +/*-----------------------------------------------------------------------------------*/ +static void unixif_output_timeout(void *arg); + +static err_t +unixif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) +{ + struct unixif *unixif; + struct unixif_buf *buf; + unixif = netif->state; + + buf = malloc(sizeof(struct unixif_buf)); + buf->p = p; + buf->len = p->len; + buf->tot_len = p->tot_len; + buf->payload = p->payload; + + if(list_elems(unixif->q) == 0) { + pbuf_ref(p); + list_push(unixif->q, buf); + sys_timeout((double)p->tot_len * 8000.0 / UNIXIF_BPS, unixif_output_timeout, + netif); + + DEBUGF(UNIXIF_DEBUG, ("unixif_output: first on list\n")); + + } else { + pbuf_ref(p); + if(list_push(unixif->q, buf) == 0) { +#ifdef UNIXIF_DROP_FIRST + struct unixif_buf *buf2; + + buf2 = list_pop(unixif->q); + pbuf_free(buf2->p); + free(buf2); + list_push(unixif->q, buf); +#else + free(buf); + pbuf_free(p); + + DEBUGF(UNIXIF_DEBUG, ("unixif_output: drop\n")); + +#endif /* UNIXIF_DROP_FIRST */ +#ifdef LINK_STATS + lwip_stats.link.drop++; +#endif /* LINK_STATS */ + + } else { + DEBUGF(UNIXIF_DEBUG, ("unixif_output: on list\n")); + } + + } + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_output_timeout(void *arg) +{ + struct pbuf *p, *q; + int i, j, len; + unsigned short plen, ptot_len; + struct unixif_buf *buf; + void *payload; + struct netif *netif; + struct unixif *unixif; + char *data; + + netif = arg; + unixif = netif->state; + + DEBUGF(UNIXIF_DEBUG, ("unixif_output_timeout\n")); + + /* buf = unixif->q[0]; + unixif->q[0] = unixif->q[1]; + unixif->q[1] = NULL;*/ + buf = list_pop(unixif->q); + + p = buf->p; + + plen = p->len; + ptot_len = p->tot_len; + payload = p->payload; + + p->len = buf->len; + p->tot_len = buf->tot_len; + p->payload = buf->payload; + + + if(p->tot_len == 0) { + + DEBUGF(UNIXIF_DEBUG, ("p->len!\n")); + abort(); + } + data = malloc(p->tot_len); + + i = 0; + for(q = p; q != NULL; q = q->next) { + for(j = 0; j < q->len; j++) { + data[i] = ((char *)q->payload)[j]; + i++; + } + } + + DEBUGF(UNIXIF_DEBUG, ("unixif_output: sending %d (%d) bytes\n", + p->len, p->tot_len)); + + len = p->tot_len; + if(write(unixif->fd, &len, sizeof(int)) == -1) { + perror("unixif_output: write"); + abort(); + } + + if(write(unixif->fd, data, p->tot_len) == -1) { + perror("unixif_output: write"); + abort(); + } + tcpdump(p); +#ifdef LINK_STATS + lwip_stats.link.xmit++; +#endif /* LINK_STATS */ + + free(data); + free(buf); + p->len = plen; + p->tot_len = ptot_len; + p->payload = payload; + + pbuf_free(p); + + /* if(unixif->q[0] != NULL) { + sys_timeout(unixif->q[0]->tot_len * 8000 / UNIXIF_BPS, + unixif_output_timeout, netif); + }*/ + if(list_elems(unixif->q) > 0) { + sys_timeout(((struct unixif_buf *)list_first(unixif->q))->tot_len * + 8000.0 / UNIXIF_BPS, + unixif_output_timeout, netif); + } +} +/*-----------------------------------------------------------------------------------*/ +void +unixif_init_server(struct netif *netif) +{ + int fd, fd2; + struct sockaddr_un addr; + socklen_t len; + struct unixif *unixif; + + fd = unix_socket_server("/tmp/unixif"); + + if(fd == -1) { + perror("unixif_server"); + abort(); + } + DEBUGF(UNIXIF_DEBUG, ("unixif_server: fd %d\n", fd)); + + unixif = malloc(sizeof(struct unixif)); + netif->state = unixif; + netif->name[0] = 'u'; + netif->name[1] = 'n'; + netif->output = unixif_output; + unixif->q = list_new(UNIXIF_QUEUELEN); + + printf("Now run ./simnode.\n"); + len = sizeof(addr); + fd2 = accept(fd, (struct sockaddr *)&addr, &len); + + if(fd2 == -1) { + perror("unixif_accept"); + abort(); + } + + DEBUGF(UNIXIF_DEBUG, ("unixif_accept: %d\n", fd2)); + + unixif->fd = fd2; + unixif->sem = sys_sem_new(0); + sys_thread_new(unixif_thread, netif); + sys_thread_new(unixif_thread2, netif); +} +/*-----------------------------------------------------------------------------------*/ +void +unixif_init_client(struct netif *netif) +{ + struct unixif *unixif; + unixif = malloc(sizeof(struct unixif)); + netif->state = unixif; + netif->name[0] = 'u'; + netif->name[1] = 'n'; + netif->output = unixif_output; + + unixif->fd = unix_socket_client("/tmp/unixif"); + if(unixif->fd == -1) { + perror("unixif_init"); + abort(); + } + unixif->q = list_new(UNIXIF_QUEUELEN); + unixif->sem = sys_sem_new(0); + sys_thread_new(unixif_thread, netif); + sys_thread_new(unixif_thread2, netif); +} +/*-----------------------------------------------------------------------------------*/ + + diff --git a/ports/unix/perf.c b/ports/unix/perf.c new file mode 100644 index 0000000..ec494a9 --- /dev/null +++ b/ports/unix/perf.c @@ -0,0 +1,64 @@ +/* + * 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 + * + */ + +#include "arch/perf.h" + +#include + +static FILE *f; + +void +perf_print(unsigned long c1l, unsigned long c1h, + unsigned long c2l, unsigned long c2h, + char *key) +{ + unsigned long long start, end; + + start = (unsigned long long)c2h << 32 | c2l; + end = (unsigned long long)c1h << 32 | c1l; + fprintf(f, "%s: %llu\n", key, start - end); + fflush(NULL); +} + +void +perf_print_times(struct tms *start, struct tms *end, char *key) +{ + fprintf(f, "%s: %lu\n", key, end->tms_stime - start->tms_stime); + fflush(NULL); +} + +void +perf_init(char *fname) +{ + f = fopen(fname, "w"); +} + diff --git a/ports/unix/sys_arch.c b/ports/unix/sys_arch.c new file mode 100644 index 0000000..4609898 --- /dev/null +++ b/ports/unix/sys_arch.c @@ -0,0 +1,453 @@ +/* + * 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 + * + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include "lwip/sys.h" +#include "lwip/opt.h" +#include "lwip/stats.h" + +#define UMAX(a, b) ((a) > (b) ? (a) : (b)) + +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 *mail; + struct sys_sem *mutex; + int wait_send; +}; + +struct sys_sem { + unsigned int c; + pthread_cond_t cond; + pthread_mutex_t mutex; +}; + +struct sys_thread { + struct sys_thread *next; + struct sys_timeouts timeouts; + pthread_t pthread; +}; + + +static struct timeval starttime; + +static struct sys_sem *sys_sem_new_(u8_t count); +static void sys_sem_free_(struct sys_sem *sem); + +static u16_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex, + u16_t timeout); + +/*-----------------------------------------------------------------------------------*/ +static struct sys_thread * +introduce_thread(pthread_t id) +{ + struct sys_thread *thread; + + thread = malloc(sizeof(struct sys_thread)); + + if(thread) { + pthread_mutex_lock(&threads_mutex); + thread->next = threads; + thread->timeouts.next = NULL; + thread->pthread = id; + threads = thread; + pthread_mutex_unlock(&threads_mutex); + } + + return thread; +} +/*-----------------------------------------------------------------------------------*/ +static struct sys_thread * +current_thread(void) +{ + struct sys_thread *st; + pthread_t pt; + pt = pthread_self(); + pthread_mutex_lock(&threads_mutex); + + for(st = threads; st != NULL; st = st->next) { + if(pthread_equal(st->pthread, pt)) { + pthread_mutex_unlock(&threads_mutex); + + return st; + } + } + + pthread_mutex_unlock(&threads_mutex); + + st = introduce_thread(pt); + + if(!st) { + printf("current_thread???\n"); + abort(); + } + + return st; +} +/*-----------------------------------------------------------------------------------*/ +void +sys_thread_new(void (*function)(void *arg), void *arg) +{ + int code; + pthread_t tmp; + struct sys_thread *st = NULL; + + code = pthread_create(&tmp, + NULL, + (void *(*)(void *)) + function, + arg); + + if(0 == code) { + st = introduce_thread(tmp); + } + + if(NULL == st) { + DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%x", + code, (int)st)); + abort(); + } +} +/*-----------------------------------------------------------------------------------*/ +struct sys_mbox * +sys_mbox_new() +{ + struct sys_mbox *mbox; + + mbox = malloc(sizeof(struct sys_mbox)); + mbox->first = mbox->last = 0; + mbox->mail = sys_sem_new_(0); + mbox->mutex = sys_sem_new_(1); + mbox->wait_send = 0; + +#ifdef SYS_STATS + lwip_stats.sys.mbox.used++; + if(lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + + return mbox; +} +/*-----------------------------------------------------------------------------------*/ +void +sys_mbox_free(struct sys_mbox *mbox) +{ + if(mbox != SYS_MBOX_NULL) { +#ifdef SYS_STATS + lwip_stats.sys.mbox.used--; +#endif /* SYS_STATS */ + sys_sem_wait(mbox->mutex); + + sys_sem_free_(mbox->mail); + sys_sem_free_(mbox->mutex); + mbox->mail = mbox->mutex = NULL; + /* DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */ + free(mbox); + } +} + +/*-----------------------------------------------------------------------------------*/ +void +sys_mbox_post(struct sys_mbox *mbox, void *msg) +{ + u8_t first; + + sys_sem_wait(mbox->mutex); + + DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", mbox, msg)); + + while((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { + mbox->wait_send++; + sys_sem_signal(mbox->mutex); + sys_arch_sem_wait(mbox->mail, 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->mail); + } + + sys_sem_signal(mbox->mutex); +} +/*-----------------------------------------------------------------------------------*/ +u16_t +sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u16_t timeout) +{ + u16_t time = 1; + + /* 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 = sys_arch_sem_wait(mbox->mail, timeout); + + /* If time == 0, the sem_wait timed out, and we return 0. */ + if(time == 0) { + return 0; + } + } else { + sys_arch_sem_wait(mbox->mail, 0); + } + + sys_arch_sem_wait(mbox->mutex, 0); + } + + DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", mbox, *msg)); + + if(msg != NULL) { + *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; + } + + mbox->first++; + + if(mbox->wait_send) { + sys_sem_signal(mbox->mail); + } + + sys_sem_signal(mbox->mutex); + + return time; +} +/*-----------------------------------------------------------------------------------*/ +struct sys_sem * +sys_sem_new(u8_t count) +{ +#ifdef SYS_STATS + lwip_stats.sys.sem.used++; + if(lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + return sys_sem_new_(count); +} + +/*-----------------------------------------------------------------------------------*/ +static struct sys_sem * +sys_sem_new_(u8_t count) +{ + struct sys_sem *sem; + + sem = malloc(sizeof(struct sys_sem)); + sem->c = count; + + pthread_cond_init(&(sem->cond), NULL); + pthread_mutex_init(&(sem->mutex), NULL); + + return sem; +} + +/*-----------------------------------------------------------------------------------*/ +static u16_t +cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u16_t timeout) +{ + int tdiff; + unsigned long sec, usec; + struct timeval rtime1, rtime2; + struct timespec ts; + struct timezone tz; + int retval; + + if(timeout > 0) { + /* Get a timestamp and add the timeout value. */ + gettimeofday(&rtime1, &tz); + sec = rtime1.tv_sec; + usec = rtime1.tv_usec; + usec += timeout % 1000 * 1000; + sec += (int)(timeout / 1000) + (int)(usec / 1000000); + usec = usec % 1000000; + ts.tv_nsec = usec * 1000; + ts.tv_sec = sec; + + retval = pthread_cond_timedwait(cond, mutex, &ts); + + if(retval == ETIMEDOUT) { + return 0; + } else { + /* Calculate for how long we waited for the cond. */ + gettimeofday(&rtime2, &tz); + tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 + + (rtime2.tv_usec - rtime1.tv_usec) / 1000; + + if(tdiff <= 0) { + return 1; + } + + return tdiff; + } + } else { + pthread_cond_wait(cond, mutex); + return 0; + } +} +/*-----------------------------------------------------------------------------------*/ +u16_t +sys_arch_sem_wait(struct sys_sem *sem, u16_t timeout) +{ + u16_t time = 1; + + pthread_mutex_lock(&(sem->mutex)); + while(sem->c <= 0) { + if(timeout > 0) { + time = cond_wait(&(sem->cond), &(sem->mutex), timeout); + + if(time == 0) { + pthread_mutex_unlock(&(sem->mutex)); + return 0; + } + /* pthread_mutex_unlock(&(sem->mutex)); + return time; */ + } else { + cond_wait(&(sem->cond), &(sem->mutex), 0); + } + } + sem->c--; + pthread_mutex_unlock(&(sem->mutex)); + return time; +} +/*-----------------------------------------------------------------------------------*/ +void +sys_sem_signal(struct sys_sem *sem) +{ + pthread_mutex_lock(&(sem->mutex)); + sem->c++; + + if(sem->c > 1) { + sem->c = 1; + } + + pthread_cond_broadcast(&(sem->cond)); + pthread_mutex_unlock(&(sem->mutex)); +} +/*-----------------------------------------------------------------------------------*/ +void +sys_sem_free(struct sys_sem *sem) +{ + if(sem != SYS_SEM_NULL) { +#ifdef SYS_STATS + lwip_stats.sys.sem.used--; +#endif /* SYS_STATS */ + sys_sem_free_(sem); + } +} + +/*-----------------------------------------------------------------------------------*/ +static void +sys_sem_free_(struct sys_sem *sem) +{ + pthread_cond_destroy(&(sem->cond)); + pthread_mutex_destroy(&(sem->mutex)); + free(sem); +} +/*-----------------------------------------------------------------------------------*/ +unsigned long +sys_unix_now() +{ + struct timeval tv; + struct timezone tz; + long sec, usec; + unsigned long msec; + gettimeofday(&tv, &tz); + + sec = tv.tv_sec - starttime.tv_sec; + usec = tv.tv_usec - starttime.tv_usec; + msec = sec * 1000 + usec / 1000; + + return msec; +} +/*-----------------------------------------------------------------------------------*/ +void +sys_init() +{ + struct timezone tz; + gettimeofday(&starttime, &tz); +} +/*-----------------------------------------------------------------------------------*/ +struct sys_timeouts * +sys_arch_timeouts(void) +{ + struct sys_thread *thread; + + thread = current_thread(); + return &thread->timeouts; +} +/*-----------------------------------------------------------------------------------*/