#include "lwip/udp.h"
#include "lwip/tcpip.h"
+#include "lwip/arch.h"
+
#include <string.h>
#define NUM_SOCKETS MEMP_NUM_NETCONN
struct lwip_select_cb select_cb;
struct lwip_select_cb *p_selcb;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
- maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
- timeout ? timeout->tv_sec : -1L, timeout ? timeout->tv_usec : -1L));
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, timeout?timeout->tv_sec:-1L, timeout?timeout->tv_usec:-1L));
select_cb.next = 0;
select_cb.readset = readset;
--- /dev/null
+/**
+ * @file
+ * Sockets BSD-Like API module
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
+ *
+ */
+
+#include "lwip/opt.h"
+
+#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/sockets.h"
+#include "lwip/api.h"
+#include "lwip/sys.h"
+#include "lwip/igmp.h"
+#include "lwip/inet.h"
+#include "lwip/tcp.h"
+#include "lwip/raw.h"
+#include "lwip/udp.h"
+#include "lwip/tcpip.h"
+
+#include "lwip/arch.h"
+
+#include <string.h>
+
+#define NUM_SOCKETS MEMP_NUM_NETCONN
+
+/** Contains all internal pointers and states used for a socket */
+struct lwip_socket {
+ /** sockets currently are built on netconns, each socket has one netconn */
+ struct netconn *conn;
+ /** data that was left from the previous read */
+ struct netbuf *lastdata;
+ /** offset in the data that was left from the previous read */
+ u16_t lastoffset;
+ /** number of times data was received, set by event_callback(),
+ tested by the receive and select functions */
+ u16_t rcvevent;
+ /** number of times data was received, set by event_callback(),
+ tested by select */
+ u16_t sendevent;
+ /** socket flags (currently, only used for O_NONBLOCK) */
+ u16_t flags;
+ /** last error that occurred on this socket */
+ int err;
+};
+
+/** Description for a task waiting in select */
+struct lwip_select_cb {
+ /** Pointer to the next waiting task */
+ struct lwip_select_cb *next;
+ /** readset passed to select */
+ fd_set *readset;
+ /** writeset passed to select */
+ fd_set *writeset;
+ /** unimplemented: exceptset passed to select */
+ fd_set *exceptset;
+ /** don't signal the same semaphore twice: set to 1 when signalled */
+ int sem_signalled;
+ /** semaphore to wake up a task waiting for select */
+ sys_sem_t sem;
+};
+
+/** This struct is used to pass data to the set/getsockopt_internal
+ * functions running in tcpip_thread context (only a void* is allowed) */
+struct lwip_setgetsockopt_data {
+ /** socket struct for which to change options */
+ struct lwip_socket *sock;
+ /** socket index for which to change options */
+ int s;
+ /** level of the option to process */
+ int level;
+ /** name of the option to process */
+ int optname;
+ /** set: value to set the option to
+ * get: value of the option is stored here */
+ void *optval;
+ /** size of *optval */
+ socklen_t *optlen;
+ /** if an error occures, it is temporarily stored here */
+ err_t err;
+};
+
+/** The global array of available sockets */
+static struct lwip_socket sockets[NUM_SOCKETS];
+/** The global list of tasks waiting for select */
+static struct lwip_select_cb *select_cb_list;
+
+/** Semaphore protecting the sockets array */
+static sys_sem_t socksem;
+/** Semaphore protecting select_cb_list */
+static sys_sem_t selectsem;
+
+/** Table to quickly map an lwIP error (err_t) to a socket error
+ * by using -err as an index */
+static const int err_to_errno_table[] = {
+ 0, /* ERR_OK 0 No error, everything OK. */
+ ENOMEM, /* ERR_MEM -1 Out of memory error. */
+ ENOBUFS, /* ERR_BUF -2 Buffer error. */
+ EHOSTUNREACH, /* ERR_RTE -3 Routing problem. */
+ ECONNABORTED, /* ERR_ABRT -4 Connection aborted. */
+ ECONNRESET, /* ERR_RST -5 Connection reset. */
+ ESHUTDOWN, /* ERR_CLSD -6 Connection closed. */
+ ENOTCONN, /* ERR_CONN -7 Not connected. */
+ EINVAL, /* ERR_VAL -8 Illegal value. */
+ EIO, /* ERR_ARG -9 Illegal argument. */
+ EADDRINUSE, /* ERR_USE -10 Address in use. */
+ -1, /* ERR_IF -11 Low-level netif error */
+ -1, /* ERR_ISCONN -12 Already connected. */
+ ETIMEDOUT, /* ERR_TIMEOUT -13 Timeout */
+ EINPROGRESS /* ERR_INPROGRESS -14 Operation in progress */
+};
+
+#define ERR_TO_ERRNO_TABLE_SIZE \
+ (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
+
+#define err_to_errno(err) \
+ ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
+ err_to_errno_table[-(err)] : EIO)
+
+#ifdef ERRNO
+#define set_errno(err) errno = (err)
+#else
+#define set_errno(err)
+#endif
+
+#define sock_set_errno(sk, e) do { \
+ sk->err = (e); \
+ set_errno(sk->err); \
+} while (0)
+
+/* Forward delcaration of some functions */
+static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
+static void lwip_getsockopt_internal(void *arg);
+static void lwip_setsockopt_internal(void *arg);
+
+/**
+ * Initialize this module. This function has to be called before any other
+ * functions in this module!
+ */
+void
+lwip_socket_init(void)
+{
+ socksem = sys_sem_new(1);
+ selectsem = sys_sem_new(1);
+}
+
+/**
+ * Map a externally used socket index to the internal socket representation.
+ *
+ * @param s externally used socket index
+ * @return struct lwip_socket for the socket or NULL if not found
+ */
+static struct lwip_socket *
+get_socket(int s)
+{
+ struct lwip_socket *sock;
+
+ if ((s < 0) || (s >= NUM_SOCKETS)) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
+ set_errno(EBADF);
+ return NULL;
+ }
+
+ sock = &sockets[s];
+
+ if (!sock->conn) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
+ set_errno(EBADF);
+ return NULL;
+ }
+
+ return sock;
+}
+
+/**
+ * Allocate a new socket for a given netconn.
+ *
+ * @param newconn the netconn for which to allocate a socket
+ * @return the index of the new socket; -1 on error
+ */
+static int
+alloc_socket(struct netconn *newconn)
+{
+ int i;
+
+ /* Protect socket array */
+ sys_sem_wait(socksem);
+
+ /* allocate a new socket identifier */
+ for (i = 0; i < NUM_SOCKETS; ++i) {
+ if (!sockets[i].conn) {
+ sockets[i].conn = newconn;
+ sockets[i].lastdata = NULL;
+ sockets[i].lastoffset = 0;
+ sockets[i].rcvevent = 0;
+ sockets[i].sendevent = 1; /* TCP send buf is empty */
+ sockets[i].flags = 0;
+ sockets[i].err = 0;
+ sys_sem_signal(socksem);
+ return i;
+ }
+ }
+ sys_sem_signal(socksem);
+ return -1;
+}
+
+/* Below this, the well-known socket functions are implemented.
+ * Use google.com or opengroup.org to get a good description :-)
+ *
+ * Exceptions are documented!
+ */
+
+int
+lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ struct lwip_socket *sock, *nsock;
+ struct netconn *newconn;
+ struct ip_addr naddr;
+ u16_t port;
+ int newsock;
+ struct sockaddr_in sin;
+ err_t err;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ newconn = netconn_accept(sock->conn);
+ if (!newconn) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err));
+ sock_set_errno(sock, err_to_errno(sock->conn->err));
+ return -1;
+ }
+
+ /* get the IP address and port of the remote host */
+ err = netconn_peer(newconn, &naddr, &port);
+ if (err != ERR_OK) {
+ netconn_delete(newconn);
+ sock_set_errno(sock, err_to_errno(err));
+ return -1;
+ }
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = naddr.addr;
+
+ if (*addrlen > sizeof(sin))
+ *addrlen = sizeof(sin);
+
+ SMEMCPY(addr, &sin, *addrlen);
+
+ newsock = alloc_socket(newconn);
+ if (newsock == -1) {
+ netconn_delete(newconn);
+ sock_set_errno(sock, ENFILE);
+ return -1;
+ }
+ LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
+ newconn->callback = event_callback;
+ nsock = &sockets[newsock];
+ LWIP_ASSERT("invalid socket pointer", nsock != NULL);
+
+ sys_sem_wait(socksem);
+ /* See event_callback: If data comes in right away after an accept, even
+ * though the server task might not have created a new socket yet.
+ * In that case, newconn->socket is counted down (newconn->socket--),
+ * so nsock->rcvevent is >= 1 here!
+ */
+ nsock->rcvevent += -1 - newconn->socket;
+ newconn->socket = newsock;
+ sys_sem_signal(socksem);
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
+ ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
+
+ sock_set_errno(sock, 0);
+ return newsock;
+}
+
+int
+lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
+{
+ struct lwip_socket *sock;
+ struct ip_addr local_addr;
+ u16_t local_port;
+ err_t err;
+
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
+ ((((struct sockaddr_in *)name)->sin_family) == AF_INET)),
+ sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
+
+ local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
+ local_port = ((struct sockaddr_in *)name)->sin_port;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
+ ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
+
+ err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
+
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
+ sock_set_errno(sock, err_to_errno(err));
+ return -1;
+ }
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
+ sock_set_errno(sock, 0);
+ return 0;
+}
+
+int
+lwip_close(int s)
+{
+ struct lwip_socket *sock;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
+
+ sock = get_socket(s);
+ if (!sock) {
+ return -1;
+ }
+
+ netconn_delete(sock->conn);
+
+ sys_sem_wait(socksem);
+ if (sock->lastdata) {
+ netbuf_delete(sock->lastdata);
+ }
+ sock->lastdata = NULL;
+ sock->lastoffset = 0;
+ sock->conn = NULL;
+ sock_set_errno(sock, 0);
+ sys_sem_signal(socksem);
+ return 0;
+}
+
+int
+lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ struct lwip_socket *sock;
+ err_t err;
+
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
+ ((((struct sockaddr_in *)name)->sin_family) == AF_INET)),
+ sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
+
+ if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
+ err = netconn_disconnect(sock->conn);
+ } else {
+ struct ip_addr remote_addr;
+ u16_t remote_port;
+
+ remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
+ remote_port = ((struct sockaddr_in *)name)->sin_port;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
+ ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
+
+ err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
+ }
+
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
+ sock_set_errno(sock, err_to_errno(err));
+ return -1;
+ }
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
+ sock_set_errno(sock, 0);
+ return 0;
+}
+
+/**
+ * Set a socket into listen mode.
+ * The socket may not have been used for another connection previously.
+ *
+ * @param s the socket to set to listening mode
+ * @param backlog (ATTENTION: need TCP_LISTEN_BACKLOG=1)
+ * @return 0 on success, non-zero on failure
+ */
+int
+lwip_listen(int s, int backlog)
+{
+ struct lwip_socket *sock;
+ err_t err;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
+
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ /* limit the "backlog" parameter to fit in an u8_t */
+ if (backlog < 0) {
+ backlog = 0;
+ }
+ if (backlog > 0xff) {
+ backlog = 0xff;
+ }
+
+ err = netconn_listen_with_backlog(sock->conn, backlog);
+
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
+ sock_set_errno(sock, err_to_errno(err));
+ return -1;
+ }
+
+ sock_set_errno(sock, 0);
+ return 0;
+}
+
+int
+lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen)
+{
+ struct lwip_socket *sock;
+ struct netbuf *buf;
+ u16_t buflen, copylen, off = 0;
+ struct ip_addr *addr;
+ u16_t port;
+ u8_t done = 0;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ do {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", (void*)sock->lastdata));
+ /* Check if there is data left from the last recv operation. */
+ if (sock->lastdata) {
+ buf = sock->lastdata;
+ } else {
+ /* If this is non-blocking call, then check first */
+ if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
+ sock_set_errno(sock, EWOULDBLOCK);
+ return -1;
+ }
+
+ /* No data was left from the previous operation, so we try to get
+ some from the network. */
+ sock->lastdata = buf = netconn_recv(sock->conn);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", (void*)buf));
+
+ if (!buf) {
+ /* We should really do some error checking here. */
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
+ sock_set_errno(sock, (((sock->conn->pcb.ip!=NULL) && (sock->conn->err==ERR_OK))?ETIMEDOUT:err_to_errno(sock->conn->err)));
+ return 0;
+ }
+ }
+
+ buflen = netbuf_len(buf);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%d len=%d off=%d sock->lastoffset=%d\n", buflen, len, off, sock->lastoffset));
+
+ buflen -= sock->lastoffset;
+
+ if (len > buflen) {
+ copylen = buflen;
+ } else {
+ copylen = len;
+ }
+
+ /* copy the contents of the received buffer into
+ the supplied memory pointer mem */
+ netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset);
+
+ off += copylen;
+
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ len -= copylen;
+ if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent) {
+ done = 1;
+ }
+ } else {
+ done = 1;
+ }
+
+ /* If we don't peek the incoming message... */
+ if ((flags & MSG_PEEK)==0) {
+ /* If this is a TCP socket, check if there is data left in the
+ buffer. If so, it should be saved in the sock structure for next
+ time around. */
+ if ((sock->conn->type == NETCONN_TCP) && (buflen - copylen > 0)) {
+ sock->lastdata = buf;
+ sock->lastoffset += copylen;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
+ } else {
+ sock->lastdata = NULL;
+ sock->lastoffset = 0;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
+ netbuf_delete(buf);
+ }
+ } else {
+ done = 1;
+ }
+ } while (!done);
+
+ /* Check to see from where the data was.*/
+ if (from && fromlen) {
+ struct sockaddr_in sin;
+
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
+ netconn_getaddr(sock->conn, addr, &port, 0);
+ } else {
+ addr = netbuf_fromaddr(buf);
+ port = netbuf_fromport(buf);
+ }
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = addr->addr;
+
+ if (*fromlen > sizeof(sin))
+ *fromlen = sizeof(sin);
+
+ SMEMCPY(from, &sin, *fromlen);
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
+ ip_addr_debug_print(SOCKETS_DEBUG, addr);
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off));
+ } else {
+#if SOCKETS_DEBUG
+ struct sockaddr_in sin;
+
+ if (netconn_type(sock->conn) == NETCONN_TCP) {
+ addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
+ netconn_getaddr(sock->conn, addr, &port, 0);
+ } else {
+ addr = netbuf_fromaddr(buf);
+ port = netbuf_fromport(buf);
+ }
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
+ ip_addr_debug_print(SOCKETS_DEBUG, addr);
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off));
+#endif /* SOCKETS_DEBUG */
+ }
+
+ sock_set_errno(sock, 0);
+ return off;
+}
+
+int
+lwip_read(int s, void *mem, int len)
+{
+ return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
+}
+
+int
+lwip_recv(int s, void *mem, int len, unsigned int flags)
+{
+ return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
+}
+
+int
+lwip_send(int s, const void *data, int size, unsigned int flags)
+{
+ struct lwip_socket *sock;
+ err_t err;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n",
+ s, data, size, flags));
+
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ if (sock->conn->type!=NETCONN_TCP) {
+#if (LWIP_UDP || LWIP_RAW)
+ return lwip_sendto(s, data, size, flags, NULL, 0);
+#else
+ sock_set_errno(sock, err_to_errno(ERR_ARG));
+ return -1;
+#endif /* (LWIP_UDP || LWIP_RAW) */
+ }
+
+ err = netconn_write(sock->conn, data, size, NETCONN_COPY | ((flags & MSG_MORE)?NETCONN_MORE:0));
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%d\n", s, err, size));
+ sock_set_errno(sock, err_to_errno(err));
+ return (err==ERR_OK?size:-1);
+}
+
+int
+lwip_sendto(int s, const void *data, int size, unsigned int flags,
+ struct sockaddr *to, socklen_t tolen)
+{
+ struct lwip_socket *sock;
+ struct ip_addr remote_addr;
+ int err;
+#if !LWIP_TCPIP_CORE_LOCKING
+ struct netbuf buf;
+ u16_t remote_port;
+#endif
+
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ if (sock->conn->type==NETCONN_TCP) {
+#if LWIP_TCP
+ return lwip_send(s, data, size, flags);
+#else
+ sock_set_errno(sock, err_to_errno(ERR_ARG));
+ return -1;
+#endif /* LWIP_TCP */
+ }
+
+ LWIP_ASSERT("lwip_sendto: size must fit in u16_t",
+ ((size >= 0) && (size <= 0xffff)));
+ LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
+ ((tolen == sizeof(struct sockaddr_in)) &&
+ ((((struct sockaddr_in *)to)->sin_family) == AF_INET))),
+ sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
+
+#if LWIP_TCPIP_CORE_LOCKING
+ /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
+ { struct pbuf* p;
+
+ p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
+ if (p == NULL) {
+ err = ERR_MEM;
+ } else {
+ p->payload = (void*)data;
+ p->len = p->tot_len = size;
+
+ remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
+
+ LOCK_TCPIP_CORE();
+ if (sock->conn->type==NETCONN_RAW) {
+ err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
+ } else {
+ err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((struct sockaddr_in *)to)->sin_port));
+ }
+ UNLOCK_TCPIP_CORE();
+
+ pbuf_free(p);
+ }
+ }
+#else
+ /* initialize a buffer */
+ buf.p = buf.ptr = NULL;
+ if (to) {
+ remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
+ remote_port = ntohs(((struct sockaddr_in *)to)->sin_port);
+ buf.addr = &remote_addr;
+ buf.port = remote_port;
+ } else {
+ remote_addr.addr = 0;
+ remote_port = 0;
+ buf.addr = NULL;
+ buf.port = 0;
+ }
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=",
+ s, data, size, flags));
+ ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", remote_port));
+
+ /* make the buffer point to the data that should be sent */
+ if ((err = netbuf_ref(&buf, data, size)) == ERR_OK) {
+ /* send the data */
+ err = netconn_send(sock->conn, &buf);
+ }
+
+ /* deallocated the buffer */
+ if (buf.p != NULL) {
+ pbuf_free(buf.p);
+ }
+#endif /* LWIP_TCPIP_CORE_LOCKING */
+ sock_set_errno(sock, err_to_errno(err));
+ return (err==ERR_OK?size:-1);
+}
+
+int
+lwip_socket(int domain, int type, int protocol)
+{
+ struct netconn *conn;
+ int i;
+
+ LWIP_UNUSED_ARG(domain);
+
+ /* create a netconn */
+ switch (type) {
+ case SOCK_RAW:
+ conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
+ domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
+ break;
+ case SOCK_DGRAM:
+ conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
+ NETCONN_UDPLITE : NETCONN_UDP, event_callback);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
+ domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
+ break;
+ case SOCK_STREAM:
+ conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
+ domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
+ break;
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
+ domain, type, protocol));
+ set_errno(EINVAL);
+ return -1;
+ }
+
+ if (!conn) {
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
+ set_errno(ENOBUFS);
+ return -1;
+ }
+
+ i = alloc_socket(conn);
+
+ if (i == -1) {
+ netconn_delete(conn);
+ set_errno(ENFILE);
+ return -1;
+ }
+ conn->socket = i;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
+ set_errno(0);
+ return i;
+}
+
+int
+lwip_write(int s, const void *data, int size)
+{
+ return lwip_send(s, data, size, 0);
+}
+
+/**
+ * Go through the readset and writeset lists and see which socket of the sockets
+ * set in the sets has events. On return, readset, writeset and exceptset have
+ * the sockets enabled that had events.
+ *
+ * exceptset is not used for now!!!
+ *
+ * @param maxfdp1 the highest socket index in the sets
+ * @param readset in: set of sockets to check for read events;
+ * out: set of sockets that had read events
+ * @param writeset in: set of sockets to check for write events;
+ * out: set of sockets that had write events
+ * @param exceptset not yet implemented
+ * @return number of sockets that had events (read+write)
+ */
+static int
+lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
+{
+ int i, nready = 0;
+ fd_set lreadset, lwriteset, lexceptset;
+ struct lwip_socket *p_sock;
+
+ FD_ZERO(&lreadset);
+ FD_ZERO(&lwriteset);
+ FD_ZERO(&lexceptset);
+
+ /* Go through each socket in each list to count number of sockets which
+ currently match */
+ for(i = 0; i < maxfdp1; i++) {
+ if (FD_ISSET(i, readset)) {
+ /* See if netconn of this socket is ready for read */
+ p_sock = get_socket(i);
+ if (p_sock && (p_sock->lastdata || p_sock->rcvevent)) {
+ FD_SET(i, &lreadset);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
+ nready++;
+ }
+ }
+ if (FD_ISSET(i, writeset)) {
+ /* See if netconn of this socket is ready for write */
+ p_sock = get_socket(i);
+ if (p_sock && p_sock->sendevent) {
+ FD_SET(i, &lwriteset);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
+ nready++;
+ }
+ }
+ }
+ *readset = lreadset;
+ *writeset = lwriteset;
+ FD_ZERO(exceptset);
+
+ return nready;
+}
+
+
+/**
+ * Processing exceptset is not yet implemented.
+ */
+int
+lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+ struct timeval *timeout)
+{
+ int i;
+ int nready;
+ fd_set lreadset, lwriteset, lexceptset;
+ u32_t msectimeout;
+ struct lwip_select_cb select_cb;
+ struct lwip_select_cb *p_selcb;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
+ maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
+ timeout ? timeout->tv_sec : -1L, timeout ? timeout->tv_usec : -1L));
+
+ select_cb.next = 0;
+ select_cb.readset = readset;
+ select_cb.writeset = writeset;
+ select_cb.exceptset = exceptset;
+ select_cb.sem_signalled = 0;
+
+ /* Protect ourselves searching through the list */
+ sys_sem_wait(selectsem);
+
+ if (readset)
+ lreadset = *readset;
+ else
+ FD_ZERO(&lreadset);
+ if (writeset)
+ lwriteset = *writeset;
+ else
+ FD_ZERO(&lwriteset);
+ if (exceptset)
+ lexceptset = *exceptset;
+ else
+ FD_ZERO(&lexceptset);
+
+ /* Go through each socket in each list to count number of sockets which
+ currently match */
+ nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
+
+ /* If we don't have any current events, then suspend if we are supposed to */
+ if (!nready) {
+ if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
+ sys_sem_signal(selectsem);
+ if (readset)
+ FD_ZERO(readset);
+ if (writeset)
+ FD_ZERO(writeset);
+ if (exceptset)
+ FD_ZERO(exceptset);
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
+ set_errno(0);
+
+ return 0;
+ }
+
+ /* add our semaphore to list */
+ /* We don't actually need any dynamic memory. Our entry on the
+ * list is only valid while we are in this function, so it's ok
+ * to use local variables */
+
+ select_cb.sem = sys_sem_new(0);
+ /* Note that we are still protected */
+ /* Put this select_cb on top of list */
+ select_cb.next = select_cb_list;
+ select_cb_list = &select_cb;
+
+ /* Now we can safely unprotect */
+ sys_sem_signal(selectsem);
+
+ /* Now just wait to be woken */
+ if (timeout == 0)
+ /* Wait forever */
+ msectimeout = 0;
+ else {
+ msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
+ if(msectimeout == 0)
+ msectimeout = 1;
+ }
+
+ i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
+
+ /* Take us off the list */
+ sys_sem_wait(selectsem);
+ if (select_cb_list == &select_cb)
+ select_cb_list = select_cb.next;
+ else
+ for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) {
+ if (p_selcb->next == &select_cb) {
+ p_selcb->next = select_cb.next;
+ break;
+ }
+ }
+
+ sys_sem_signal(selectsem);
+
+ sys_sem_free(select_cb.sem);
+ if (i == 0) {
+ /* Timeout */
+ if (readset)
+ FD_ZERO(readset);
+ if (writeset)
+ FD_ZERO(writeset);
+ if (exceptset)
+ FD_ZERO(exceptset);
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
+ set_errno(0);
+
+ return 0;
+ }
+
+ if (readset)
+ lreadset = *readset;
+ else
+ FD_ZERO(&lreadset);
+ if (writeset)
+ lwriteset = *writeset;
+ else
+ FD_ZERO(&lwriteset);
+ if (exceptset)
+ lexceptset = *exceptset;
+ else
+ FD_ZERO(&lexceptset);
+
+ /* See what's set */
+ nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
+ } else
+ sys_sem_signal(selectsem);
+
+ if (readset)
+ *readset = lreadset;
+ if (writeset)
+ *writeset = lwriteset;
+ if (exceptset)
+ *exceptset = lexceptset;
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
+ set_errno(0);
+
+ return nready;
+}
+
+/**
+ * Callback registered in the netconn layer for each socket-netconn.
+ * Processes recvevent (data available) and wakes up tasks waiting for select.
+ */
+static void
+event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
+{
+ int s;
+ struct lwip_socket *sock;
+ struct lwip_select_cb *scb;
+
+ LWIP_UNUSED_ARG(len);
+
+ /* Get socket */
+ if (conn) {
+ s = conn->socket;
+ if (s < 0) {
+ /* Data comes in right away after an accept, even though
+ * the server task might not have created a new socket yet.
+ * Just count down (or up) if that's the case and we
+ * will use the data later. Note that only receive events
+ * can happen before the new socket is set up. */
+ sys_sem_wait(socksem);
+ if (conn->socket < 0) {
+ if (evt == NETCONN_EVT_RCVPLUS) {
+ conn->socket--;
+ }
+ sys_sem_signal(socksem);
+ return;
+ }
+ sys_sem_signal(socksem);
+ }
+
+ sock = get_socket(s);
+ if (!sock) {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ sys_sem_wait(selectsem);
+ /* Set event as required */
+ switch (evt) {
+ case NETCONN_EVT_RCVPLUS:
+ sock->rcvevent++;
+ break;
+ case NETCONN_EVT_RCVMINUS:
+ sock->rcvevent--;
+ break;
+ case NETCONN_EVT_SENDPLUS:
+ sock->sendevent = 1;
+ break;
+ case NETCONN_EVT_SENDMINUS:
+ sock->sendevent = 0;
+ break;
+ default:
+ LWIP_ASSERT("unknown event", 0);
+ break;
+ }
+ sys_sem_signal(selectsem);
+
+ /* Now decide if anyone is waiting for this socket */
+ /* NOTE: This code is written this way to protect the select link list
+ but to avoid a deadlock situation by releasing socksem before
+ signalling for the select. This means we need to go through the list
+ multiple times ONLY IF a select was actually waiting. We go through
+ the list the number of waiting select calls + 1. This list is
+ expected to be small. */
+ while (1) {
+ sys_sem_wait(selectsem);
+ for (scb = select_cb_list; scb; scb = scb->next) {
+ if (scb->sem_signalled == 0) {
+ /* Test this select call for our socket */
+ if (scb->readset && FD_ISSET(s, scb->readset))
+ if (sock->rcvevent)
+ break;
+ if (scb->writeset && FD_ISSET(s, scb->writeset))
+ if (sock->sendevent)
+ break;
+ }
+ }
+ if (scb) {
+ scb->sem_signalled = 1;
+ sys_sem_signal(selectsem);
+ sys_sem_signal(scb->sem);
+ } else {
+ sys_sem_signal(selectsem);
+ break;
+ }
+ }
+}
+
+/**
+ * Unimplemented: Close one end of a full-duplex connection.
+ * Currently, the full connection is closed.
+ */
+int
+lwip_shutdown(int s, int how)
+{
+ LWIP_UNUSED_ARG(how);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
+ return lwip_close(s); /* XXX temporary hack until proper implementation */
+}
+
+static int
+lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
+{
+ struct lwip_socket *sock;
+ struct sockaddr_in sin;
+ struct ip_addr naddr;
+
+ sock = get_socket(s);
+ if (!sock)
+ return -1;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+
+ /* get the IP address and port */
+ netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
+ ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
+
+ sin.sin_port = htons(sin.sin_port);
+ sin.sin_addr.s_addr = naddr.addr;
+
+ if (*namelen > sizeof(sin))
+ *namelen = sizeof(sin);
+
+ SMEMCPY(name, &sin, *namelen);
+ sock_set_errno(sock, 0);
+ return 0;
+}
+
+int
+lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
+{
+ return lwip_getaddrname(s, name, namelen, 0);
+}
+
+int
+lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
+{
+ return lwip_getaddrname(s, name, namelen, 1);
+}
+
+int
+lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+ err_t err = ERR_OK;
+ struct lwip_socket *sock = get_socket(s);
+ struct lwip_setgetsockopt_data data;
+
+ if (!sock)
+ return -1;
+
+ if ((NULL == optval) || (NULL == optlen)) {
+ sock_set_errno(sock, EFAULT);
+ return -1;
+ }
+
+ /* Do length and type checks for the various options first, to keep it readable. */
+ switch (level) {
+
+/* Level: SOL_SOCKET */
+ case SOL_SOCKET:
+ switch (optname) {
+
+ case SO_ACCEPTCONN:
+ case SO_BROADCAST:
+ /* UNIMPL case SO_DEBUG: */
+ /* UNIMPL case SO_DONTROUTE: */
+ case SO_ERROR:
+ case SO_KEEPALIVE:
+ /* UNIMPL case SO_CONTIMEO: */
+ /* UNIMPL case SO_SNDTIMEO: */
+#if LWIP_SO_RCVTIMEO
+ case SO_RCVTIMEO:
+#endif /* LWIP_SO_RCVTIMEO */
+#if LWIP_SO_RCVBUF
+ case SO_RCVBUF:
+#endif /* LWIP_SO_RCVBUF */
+ /* UNIMPL case SO_OOBINLINE: */
+ /* UNIMPL case SO_SNDBUF: */
+ /* UNIMPL case SO_RCVLOWAT: */
+ /* UNIMPL case SO_SNDLOWAT: */
+#if SO_REUSE
+ case SO_REUSEADDR:
+ case SO_REUSEPORT:
+#endif /* SO_REUSE */
+ case SO_TYPE:
+ /* UNIMPL case SO_USELOOPBACK: */
+ if (*optlen < sizeof(int)) {
+ err = EINVAL;
+ }
+ break;
+
+ case SO_NO_CHECK:
+ if (*optlen < sizeof(int)) {
+ err = EINVAL;
+ }
+#if LWIP_UDP
+ if ((sock->conn->type != NETCONN_UDP) ||
+ ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
+ /* this flag is only available for UDP, not for UDP lite */
+ err = EAFNOSUPPORT;
+ }
+#endif /* LWIP_UDP */
+ break;
+
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+
+/* Level: IPPROTO_IP */
+ case IPPROTO_IP:
+ switch (optname) {
+ /* UNIMPL case IP_HDRINCL: */
+ /* UNIMPL case IP_RCVDSTADDR: */
+ /* UNIMPL case IP_RCVIF: */
+ case IP_TTL:
+ case IP_TOS:
+ if (*optlen < sizeof(int)) {
+ err = EINVAL;
+ }
+ break;
+#if LWIP_IGMP
+ case IP_MULTICAST_TTL:
+ if (*optlen < sizeof(u8_t)) {
+ err = EINVAL;
+ }
+ break;
+ case IP_MULTICAST_IF:
+ if (*optlen < sizeof(struct in_addr)) {
+ err = EINVAL;
+ }
+ break;
+#endif /* LWIP_IGMP */
+
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+
+#if LWIP_TCP
+/* Level: IPPROTO_TCP */
+ case IPPROTO_TCP:
+ if (*optlen < sizeof(int)) {
+ err = EINVAL;
+ break;
+ }
+
+ /* If this is no TCP socket, ignore any options. */
+ if (sock->conn->type != NETCONN_TCP)
+ return 0;
+
+ switch (optname) {
+ case TCP_NODELAY:
+ case TCP_KEEPALIVE:
+#if LWIP_TCP_KEEPALIVE
+ case TCP_KEEPIDLE:
+ case TCP_KEEPINTVL:
+ case TCP_KEEPCNT:
+#endif /* LWIP_TCP_KEEPALIVE */
+ break;
+
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_TCP */
+#if LWIP_UDP && LWIP_UDPLITE
+/* Level: IPPROTO_UDPLITE */
+ case IPPROTO_UDPLITE:
+ if (*optlen < sizeof(int)) {
+ err = EINVAL;
+ break;
+ }
+
+ /* If this is no UDP lite socket, ignore any options. */
+ if (sock->conn->type != NETCONN_UDPLITE)
+ return 0;
+
+ switch (optname) {
+ case UDPLITE_SEND_CSCOV:
+ case UDPLITE_RECV_CSCOV:
+ break;
+
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_UDP && LWIP_UDPLITE*/
+/* UNDEFINED LEVEL */
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
+ s, level, optname));
+ err = ENOPROTOOPT;
+ } /* switch */
+
+
+ if (err != ERR_OK) {
+ sock_set_errno(sock, err);
+ return -1;
+ }
+
+ /* Now do the actual option processing */
+ data.sock = sock;
+ data.level = level;
+ data.optname = optname;
+ data.optval = optval;
+ data.optlen = optlen;
+ data.err = err;
+ tcpip_callback(lwip_getsockopt_internal, &data);
+ sys_arch_sem_wait(sock->conn->op_completed, 0);
+ /* maybe lwip_getsockopt_internal has changed err */
+ err = data.err;
+
+ sock_set_errno(sock, err);
+ return err ? -1 : 0;
+}
+
+static void
+lwip_getsockopt_internal(void *arg)
+{
+ struct lwip_socket *sock;
+#ifdef LWIP_DEBUG
+ int s;
+#endif /* LWIP_DEBUG */
+ int level, optname;
+ void *optval;
+ struct lwip_setgetsockopt_data *data;
+
+ LWIP_ASSERT("arg != NULL", arg != NULL);
+
+ data = (struct lwip_setgetsockopt_data*)arg;
+ sock = data->sock;
+#ifdef LWIP_DEBUG
+ s = data->s;
+#endif /* LWIP_DEBUG */
+ level = data->level;
+ optname = data->optname;
+ optval = data->optval;
+
+ switch (level) {
+
+/* Level: SOL_SOCKET */
+ case SOL_SOCKET:
+ switch (optname) {
+
+ /* The option flags */
+ case SO_ACCEPTCONN:
+ case SO_BROADCAST:
+ /* UNIMPL case SO_DEBUG: */
+ /* UNIMPL case SO_DONTROUTE: */
+ case SO_KEEPALIVE:
+ /* UNIMPL case SO_OOBINCLUDE: */
+#if SO_REUSE
+ case SO_REUSEADDR:
+ case SO_REUSEPORT:
+#endif /* SO_REUSE */
+ /*case SO_USELOOPBACK: UNIMPL */
+ *(int*)optval = sock->conn->pcb.ip->so_options & optname;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
+ s, optname, (*(int*)optval?"on":"off")));
+ break;
+
+ case SO_TYPE:
+ switch (NETCONNTYPE_GROUP(sock->conn->type)) {
+ case NETCONN_RAW:
+ *(int*)optval = SOCK_RAW;
+ break;
+ case NETCONN_TCP:
+ *(int*)optval = SOCK_STREAM;
+ break;
+ case NETCONN_UDP:
+ *(int*)optval = SOCK_DGRAM;
+ break;
+ default: /* unrecognized socket type */
+ *(int*)optval = sock->conn->type;
+ LWIP_DEBUGF(SOCKETS_DEBUG,
+ ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
+ s, *(int *)optval));
+ } /* switch (sock->conn->type) */
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
+ s, *(int *)optval));
+ break;
+
+ case SO_ERROR:
+ if (sock->err == 0) {
+ sock_set_errno(sock, err_to_errno(sock->conn->err));
+ }
+ *(int *)optval = sock->err;
+ sock->err = 0;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
+ s, *(int *)optval));
+ break;
+
+#if LWIP_SO_RCVTIMEO
+ case SO_RCVTIMEO:
+ *(int *)optval = sock->conn->recv_timeout;
+ break;
+#endif /* LWIP_SO_RCVTIMEO */
+#if LWIP_SO_RCVBUF
+ case SO_RCVBUF:
+ *(int *)optval = sock->conn->recv_bufsize;
+ break;
+#endif /* LWIP_SO_RCVBUF */
+#if LWIP_UDP
+ case SO_NO_CHECK:
+ *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
+ break;
+#endif /* LWIP_UDP*/
+ } /* switch (optname) */
+ break;
+
+/* Level: IPPROTO_IP */
+ case IPPROTO_IP:
+ switch (optname) {
+ case IP_TTL:
+ *(int*)optval = sock->conn->pcb.ip->ttl;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
+ s, *(int *)optval));
+ break;
+ case IP_TOS:
+ *(int*)optval = sock->conn->pcb.ip->tos;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
+ s, *(int *)optval));
+ break;
+#if LWIP_IGMP
+ case IP_MULTICAST_TTL:
+ *(u8_t*)optval = sock->conn->pcb.ip->ttl;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
+ s, *(int *)optval));
+ break;
+ case IP_MULTICAST_IF:
+ ((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%x\n",
+ s, *(u32_t *)optval));
+ break;
+#endif /* LWIP_IGMP */
+ } /* switch (optname) */
+ break;
+
+#if LWIP_TCP
+/* Level: IPPROTO_TCP */
+ case IPPROTO_TCP:
+ switch (optname) {
+ case TCP_NODELAY:
+ *(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
+ s, (*(int*)optval)?"on":"off") );
+ break;
+ case TCP_KEEPALIVE:
+ *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
+ s, *(int *)optval));
+ break;
+
+#if LWIP_TCP_KEEPALIVE
+ case TCP_KEEPIDLE:
+ *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
+ s, *(int *)optval));
+ break;
+ case TCP_KEEPINTVL:
+ *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
+ s, *(int *)optval));
+ break;
+ case TCP_KEEPCNT:
+ *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
+ s, *(int *)optval));
+ break;
+#endif /* LWIP_TCP_KEEPALIVE */
+
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_TCP */
+#if LWIP_UDP && LWIP_UDPLITE
+ /* Level: IPPROTO_UDPLITE */
+ case IPPROTO_UDPLITE:
+ switch (optname) {
+ case UDPLITE_SEND_CSCOV:
+ *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
+ s, (*(int*)optval)) );
+ break;
+ case UDPLITE_RECV_CSCOV:
+ *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
+ s, (*(int*)optval)) );
+ break;
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_UDP */
+ } /* switch (level) */
+ sys_sem_signal(sock->conn->op_completed);
+}
+
+int
+lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+ struct lwip_socket *sock = get_socket(s);
+ int err = ERR_OK;
+ struct lwip_setgetsockopt_data data;
+
+ if (!sock)
+ return -1;
+
+ if (NULL == optval) {
+ sock_set_errno(sock, EFAULT);
+ return -1;
+ }
+
+ /* Do length and type checks for the various options first, to keep it readable. */
+ switch (level) {
+
+/* Level: SOL_SOCKET */
+ case SOL_SOCKET:
+ switch (optname) {
+
+ case SO_BROADCAST:
+ /* UNIMPL case SO_DEBUG: */
+ /* UNIMPL case SO_DONTROUTE: */
+ case SO_KEEPALIVE:
+ /* UNIMPL case case SO_CONTIMEO: */
+ /* UNIMPL case case SO_SNDTIMEO: */
+#if LWIP_SO_RCVTIMEO
+ case SO_RCVTIMEO:
+#endif /* LWIP_SO_RCVTIMEO */
+#if LWIP_SO_RCVBUF
+ case SO_RCVBUF:
+#endif /* LWIP_SO_RCVBUF */
+ /* UNIMPL case SO_OOBINLINE: */
+ /* UNIMPL case SO_SNDBUF: */
+ /* UNIMPL case SO_RCVLOWAT: */
+ /* UNIMPL case SO_SNDLOWAT: */
+#if SO_REUSE
+ case SO_REUSEADDR:
+ case SO_REUSEPORT:
+#endif /* SO_REUSE */
+ /* UNIMPL case SO_USELOOPBACK: */
+ if (optlen < sizeof(int)) {
+ err = EINVAL;
+ }
+ break;
+ case SO_NO_CHECK:
+ if (optlen < sizeof(int)) {
+ err = EINVAL;
+ }
+#if LWIP_UDP
+ if ((sock->conn->type != NETCONN_UDP) ||
+ ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
+ /* this flag is only available for UDP, not for UDP lite */
+ err = EAFNOSUPPORT;
+ }
+#endif /* LWIP_UDP */
+ break;
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+
+/* Level: IPPROTO_IP */
+ case IPPROTO_IP:
+ switch (optname) {
+ /* UNIMPL case IP_HDRINCL: */
+ /* UNIMPL case IP_RCVDSTADDR: */
+ /* UNIMPL case IP_RCVIF: */
+ case IP_TTL:
+ case IP_TOS:
+ if (optlen < sizeof(int)) {
+ err = EINVAL;
+ }
+ break;
+#if LWIP_IGMP
+ case IP_MULTICAST_TTL:
+ if (optlen < sizeof(u8_t)) {
+ err = EINVAL;
+ }
+ if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
+ err = EAFNOSUPPORT;
+ }
+ break;
+ case IP_MULTICAST_IF:
+ if (optlen < sizeof(struct in_addr)) {
+ err = EINVAL;
+ }
+ if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
+ err = EAFNOSUPPORT;
+ }
+ break;
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ if (optlen < sizeof(struct ip_mreq)) {
+ err = EINVAL;
+ }
+ if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
+ err = EAFNOSUPPORT;
+ }
+ break;
+#endif /* LWIP_IGMP */
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+
+#if LWIP_TCP
+/* Level: IPPROTO_TCP */
+ case IPPROTO_TCP:
+ if (optlen < sizeof(int)) {
+ err = EINVAL;
+ break;
+ }
+
+ /* If this is no TCP socket, ignore any options. */
+ if (sock->conn->type != NETCONN_TCP)
+ return 0;
+
+ switch (optname) {
+ case TCP_NODELAY:
+ case TCP_KEEPALIVE:
+#if LWIP_TCP_KEEPALIVE
+ case TCP_KEEPIDLE:
+ case TCP_KEEPINTVL:
+ case TCP_KEEPCNT:
+#endif /* LWIP_TCP_KEEPALIVE */
+ break;
+
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_TCP */
+#if LWIP_UDP && LWIP_UDPLITE
+/* Level: IPPROTO_UDPLITE */
+ case IPPROTO_UDPLITE:
+ if (optlen < sizeof(int)) {
+ err = EINVAL;
+ break;
+ }
+
+ /* If this is no UDP lite socket, ignore any options. */
+ if (sock->conn->type != NETCONN_UDPLITE)
+ return 0;
+
+ switch (optname) {
+ case UDPLITE_SEND_CSCOV:
+ case UDPLITE_RECV_CSCOV:
+ break;
+
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
+ s, optname));
+ err = ENOPROTOOPT;
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_UDP && LWIP_UDPLITE */
+/* UNDEFINED LEVEL */
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
+ s, level, optname));
+ err = ENOPROTOOPT;
+ } /* switch (level) */
+
+
+ if (err != ERR_OK) {
+ sock_set_errno(sock, err);
+ return -1;
+ }
+
+
+ /* Now do the actual option processing */
+ data.sock = sock;
+ data.level = level;
+ data.optname = optname;
+ data.optval = (void*)optval;
+ data.optlen = &optlen;
+ data.err = err;
+ tcpip_callback(lwip_setsockopt_internal, &data);
+ sys_arch_sem_wait(sock->conn->op_completed, 0);
+ /* maybe lwip_setsockopt_internal has changed err */
+ err = data.err;
+
+ sock_set_errno(sock, err);
+ return err ? -1 : 0;
+}
+
+static void
+lwip_setsockopt_internal(void *arg)
+{
+ struct lwip_socket *sock;
+#ifdef LWIP_DEBUG
+ int s;
+#endif /* LWIP_DEBUG */
+ int level, optname;
+ const void *optval;
+ struct lwip_setgetsockopt_data *data;
+
+ LWIP_ASSERT("arg != NULL", arg != NULL);
+
+ data = (struct lwip_setgetsockopt_data*)arg;
+ sock = data->sock;
+#ifdef LWIP_DEBUG
+ s = data->s;
+#endif /* LWIP_DEBUG */
+ level = data->level;
+ optname = data->optname;
+ optval = data->optval;
+
+ switch (level) {
+
+/* Level: SOL_SOCKET */
+ case SOL_SOCKET:
+ switch (optname) {
+
+ /* The option flags */
+ case SO_BROADCAST:
+ /* UNIMPL case SO_DEBUG: */
+ /* UNIMPL case SO_DONTROUTE: */
+ case SO_KEEPALIVE:
+ /* UNIMPL case SO_OOBINCLUDE: */
+#if SO_REUSE
+ case SO_REUSEADDR:
+ case SO_REUSEPORT:
+#endif /* SO_REUSE */
+ /* UNIMPL case SO_USELOOPBACK: */
+ if (*(int*)optval) {
+ sock->conn->pcb.ip->so_options |= optname;
+ } else {
+ sock->conn->pcb.ip->so_options &= ~optname;
+ }
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
+ s, optname, (*(int*)optval?"on":"off")));
+ break;
+#if LWIP_SO_RCVTIMEO
+ case SO_RCVTIMEO:
+ sock->conn->recv_timeout = ( *(int*)optval );
+ break;
+#endif /* LWIP_SO_RCVTIMEO */
+#if LWIP_SO_RCVBUF
+ case SO_RCVBUF:
+ sock->conn->recv_bufsize = ( *(int*)optval );
+ break;
+#endif /* LWIP_SO_RCVBUF */
+#if LWIP_UDP
+ case SO_NO_CHECK:
+ if (*(int*)optval) {
+ udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
+ } else {
+ udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
+ }
+ break;
+#endif /* LWIP_UDP */
+ } /* switch (optname) */
+ break;
+
+/* Level: IPPROTO_IP */
+ case IPPROTO_IP:
+ switch (optname) {
+ case IP_TTL:
+ sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n",
+ s, sock->conn->pcb.ip->ttl));
+ break;
+ case IP_TOS:
+ sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n",
+ s, sock->conn->pcb.ip->tos));
+ break;
+#if LWIP_IGMP
+ case IP_MULTICAST_TTL:
+ sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
+ break;
+ case IP_MULTICAST_IF:
+ sock->conn->pcb.udp->multicast_ip.addr = ((struct in_addr*) optval)->s_addr;
+ break;
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ {
+ /* If this is a TCP or a RAW socket, ignore these options. */
+ struct ip_mreq *imr = (struct ip_mreq *)optval;
+ if(optname == IP_ADD_MEMBERSHIP){
+ data->err = igmp_joingroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
+ } else {
+ data->err = igmp_leavegroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
+ }
+ if(data->err != ERR_OK) {
+ data->err = EADDRNOTAVAIL;
+ }
+ }
+ break;
+#endif /* LWIP_IGMP */
+ } /* switch (optname) */
+ break;
+
+#if LWIP_TCP
+/* Level: IPPROTO_TCP */
+ case IPPROTO_TCP:
+ switch (optname) {
+ case TCP_NODELAY:
+ if (*(int*)optval) {
+ sock->conn->pcb.tcp->flags |= TF_NODELAY;
+ } else {
+ sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
+ }
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
+ s, (*(int *)optval)?"on":"off") );
+ break;
+ case TCP_KEEPALIVE:
+ sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n",
+ s, sock->conn->pcb.tcp->keep_idle));
+ break;
+
+#if LWIP_TCP_KEEPALIVE
+ case TCP_KEEPIDLE:
+ sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %lu\n",
+ s, sock->conn->pcb.tcp->keep_idle));
+ break;
+ case TCP_KEEPINTVL:
+ sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %lu\n",
+ s, sock->conn->pcb.tcp->keep_intvl));
+ break;
+ case TCP_KEEPCNT:
+ sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %lu\n",
+ s, sock->conn->pcb.tcp->keep_cnt));
+ break;
+#endif /* LWIP_TCP_KEEPALIVE */
+
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_TCP*/
+#if LWIP_UDP && LWIP_UDPLITE
+ /* Level: IPPROTO_UDPLITE */
+ case IPPROTO_UDPLITE:
+ switch (optname) {
+ case UDPLITE_SEND_CSCOV:
+ if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
+ /* don't allow illegal values! */
+ sock->conn->pcb.udp->chksum_len_tx = 8;
+ } else {
+ sock->conn->pcb.udp->chksum_len_tx = *(int*)optval;
+ }
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
+ s, (*(int*)optval)) );
+ break;
+ case UDPLITE_RECV_CSCOV:
+ if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
+ /* don't allow illegal values! */
+ sock->conn->pcb.udp->chksum_len_rx = 8;
+ } else {
+ sock->conn->pcb.udp->chksum_len_rx = *(int*)optval;
+ }
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
+ s, (*(int*)optval)) );
+ break;
+ } /* switch (optname) */
+ break;
+#endif /* LWIP_UDP */
+ } /* switch (level) */
+ sys_sem_signal(sock->conn->op_completed);
+}
+
+int
+lwip_ioctl(int s, long cmd, void *argp)
+{
+ struct lwip_socket *sock = get_socket(s);
+ u16_t buflen = 0;
+
+ if (!sock)
+ return -1;
+
+ switch (cmd) {
+ case FIONREAD:
+ if (!argp) {
+ sock_set_errno(sock, EINVAL);
+ return -1;
+ }
+
+ SYS_ARCH_GET(sock->conn->recv_avail, *((u16_t*)argp));
+
+ /* Check if there is data left from the last recv operation. /maq 041215 */
+ if (sock->lastdata) {
+ buflen = netbuf_len(sock->lastdata);
+ buflen -= sock->lastoffset;
+
+ *((u16_t*)argp) += buflen;
+ }
+
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
+ sock_set_errno(sock, 0);
+ return 0;
+
+ case FIONBIO:
+ if (argp && *(u32_t*)argp)
+ sock->flags |= O_NONBLOCK;
+ else
+ sock->flags &= ~O_NONBLOCK;
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
+ sock_set_errno(sock, 0);
+ return 0;
+
+ default:
+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
+ sock_set_errno(sock, ENOSYS); /* not yet implemented */
+ return -1;
+ } /* switch (cmd) */
+}
+
+#endif /* LWIP_SOCKET */
--- /dev/null
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/*
+ * Wed Apr 17 16:05:29 EDT 2002 (James Roth)
+ *
+ * - Fixed an unlikely sys_thread_new() race condition.
+ *
+ * - Made current_thread() work with threads which where
+ * not created with sys_thread_new(). This includes
+ * the main thread and threads made with pthread_create().
+ *
+ * - Catch overflows where more than SYS_MBOX_SIZE messages
+ * are waiting to be read. The sys_mbox_post() routine
+ * will block until there is more room instead of just
+ * leaking messages.
+ */
+#include "lwip/debug.h"
+
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "lwip/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 pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t lwprot_thread = (pthread_t) 0xDEAD;
+static int lwprot_count = 0;
+
+static struct sys_sem *sys_sem_new_(u8_t count);
+static void sys_sem_free_(struct sys_sem *sem);
+
+static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ u32_t timeout);
+
+/*-----------------------------------------------------------------------------------*/
+static struct sys_thread *
+introduce_thread(pthread_t id)
+{
+ struct sys_thread *thread;
+
+ thread = malloc(sizeof(struct sys_thread));
+
+ if (thread != NULL) {
+ 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;
+}
+/*-----------------------------------------------------------------------------------*/
+sys_thread_t
+sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
+{
+ 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) {
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%x",
+ code, (int)st));
+ abort();
+ }
+ return st;
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_mbox *
+sys_mbox_new(int size)
+{
+ struct sys_mbox *mbox;
+
+ mbox = malloc(sizeof(struct sys_mbox));
+ if (mbox != NULL) {
+ mbox->first = mbox->last = 0;
+ mbox->mail = sys_sem_new_(0);
+ mbox->mutex = sys_sem_new_(1);
+ mbox->wait_send = 0;
+
+#if 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) {
+#if 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;
+ /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
+ free(mbox);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+err_t
+sys_mbox_trypost(struct sys_mbox *mbox, void *msg)
+{
+ u8_t first;
+
+ sys_sem_wait(mbox->mutex);
+
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
+ (void *)mbox, (void *)msg));
+
+ if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE))
+ return ERR_MEM;
+
+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
+
+ if (mbox->last == mbox->first) {
+ first = 1;
+ } else {
+ first = 0;
+ }
+
+ mbox->last++;
+
+ if (first) {
+ sys_sem_signal(mbox->mail);
+ }
+
+ sys_sem_signal(mbox->mutex);
+
+ return ERR_OK;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+sys_mbox_post(struct sys_mbox *mbox, void *msg)
+{
+ u8_t first;
+
+ sys_sem_wait(mbox->mutex);
+
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
+
+ while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
+ mbox->wait_send++;
+ sys_sem_signal(mbox->mutex);
+ sys_arch_sem_wait(mbox->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);
+}
+/*-----------------------------------------------------------------------------------*/
+u32_t
+sys_arch_mbox_tryfetch(struct sys_mbox *mbox, void **msg)
+{
+ sys_arch_sem_wait(mbox->mutex, 0);
+
+ if (mbox->first == mbox->last) {
+ sys_sem_signal(mbox->mutex);
+ return SYS_MBOX_EMPTY;
+ }
+
+ if (msg != NULL) {
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
+ }
+ else{
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
+ }
+
+ mbox->first++;
+
+ if (mbox->wait_send) {
+ sys_sem_signal(mbox->mail);
+ }
+
+ sys_sem_signal(mbox->mutex);
+
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+u32_t
+sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
+{
+ u32_t time = 0;
+
+ /* 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 == SYS_ARCH_TIMEOUT) {
+ return SYS_ARCH_TIMEOUT;
+ }
+ } else {
+ sys_arch_sem_wait(mbox->mail, 0);
+ }
+
+ sys_arch_sem_wait(mbox->mutex, 0);
+ }
+
+ if (msg != NULL) {
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
+ }
+ else{
+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
+ }
+
+ mbox->first++;
+
+ if (mbox->wait_send) {
+ sys_sem_signal(mbox->mail);
+ }
+
+ sys_sem_signal(mbox->mutex);
+
+ return time;
+}
+/*-----------------------------------------------------------------------------------*/
+struct sys_sem *
+sys_sem_new(u8_t count)
+{
+#if 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));
+ if (sem != NULL) {
+ sem->c = count;
+ pthread_cond_init(&(sem->cond), NULL);
+ pthread_mutex_init(&(sem->mutex), NULL);
+ }
+ return sem;
+}
+
+/*-----------------------------------------------------------------------------------*/
+static u32_t
+cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_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 SYS_ARCH_TIMEOUT;
+ } 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 0;
+ }
+
+ return tdiff;
+ }
+ } else {
+ pthread_cond_wait(cond, mutex);
+ return SYS_ARCH_TIMEOUT;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+u32_t
+sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
+{
+ u32_t time = 0;
+
+ pthread_mutex_lock(&(sem->mutex));
+ while (sem->c <= 0) {
+ if (timeout > 0) {
+ time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
+
+ if (time == SYS_ARCH_TIMEOUT) {
+ pthread_mutex_unlock(&(sem->mutex));
+ return SYS_ARCH_TIMEOUT;
+ }
+ /* 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) {
+#if 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;
+}
+/*-----------------------------------------------------------------------------------*/
+/** sys_prot_t sys_arch_protect(void)
+
+This optional function does a "fast" critical region protection and returns
+the previous protection level. This function is only called during very short
+critical regions. An embedded system which supports ISR-based drivers might
+want to implement this function by disabling interrupts. Task-based systems
+might want to implement this by using a mutex or disabling tasking. This
+function should support recursive calls from the same task or interrupt. In
+other words, sys_arch_protect() could be called while already protected. In
+that case the return value indicates that it is already protected.
+
+sys_arch_protect() is only required if your port is supporting an operating
+system.
+*/
+sys_prot_t
+sys_arch_protect(void)
+{
+ /* Note that for the UNIX port, we are using a lightweight mutex, and our
+ * own counter (which is locked by the mutex). The return code is not actually
+ * used. */
+ if (lwprot_thread != pthread_self())
+ {
+ /* We are locking the mutex where it has not been locked before *
+ * or is being locked by another thread */
+ pthread_mutex_lock(&lwprot_mutex);
+ lwprot_thread = pthread_self();
+ lwprot_count = 1;
+ }
+ else
+ /* It is already locked by THIS thread */
+ lwprot_count++;
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+/** void sys_arch_unprotect(sys_prot_t pval)
+
+This optional function does a "fast" set of critical region protection to the
+value specified by pval. See the documentation for sys_arch_protect() for
+more information. This function is only required if your port is supporting
+an operating system.
+*/
+void
+sys_arch_unprotect(sys_prot_t pval)
+{
+ if (lwprot_thread == pthread_self())
+ {
+ if (--lwprot_count == 0)
+ {
+ lwprot_thread = (pthread_t) 0xDEAD;
+ pthread_mutex_unlock(&lwprot_mutex);
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------------*/
+
+#ifndef MAX_JIFFY_OFFSET
+#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
+#endif
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+unsigned long
+sys_jiffies(void)
+{
+ struct timeval tv;
+ unsigned long sec = tv.tv_sec;
+ long usec = tv.tv_usec;
+
+ gettimeofday(&tv,NULL);
+
+ if (sec >= (MAX_JIFFY_OFFSET / HZ))
+ return MAX_JIFFY_OFFSET;
+ usec += 1000000L / HZ - 1;
+ usec /= 1000000L / HZ;
+ return HZ * sec + usec;
+}
+
+#if PPP_DEBUG
+
+#include <stdarg.h>
+
+void ppp_trace(int level, const char *format, ...)
+{
+ va_list args;
+
+ (void)level;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+}
+#endif
--- /dev/null
+mem.o: ../core/mem.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/def.h \
+ ../include/lwip/mem.h ../include/lwip/sys.h ../include/lwip/err.h \
+ ../include/arch/sys_arch.h ../include/lwip/stats.h \
+ ../include/lwip/mem.h ../include/lwip/memp.h ../include/lwip/memp_std.h
+memp.o: ../core/memp.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/lwip/pbuf.h ../include/lwip/err.h \
+ ../include/lwip/udp.h ../include/lwip/pbuf.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/ipv4/lwip/inet.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/def.h ../include/lwip/pbuf.h \
+ ../include/lwip/err.h ../include/lwip/raw.h ../include/lwip/tcp.h \
+ ../include/lwip/sys.h ../include/arch/sys_arch.h ../include/lwip/mem.h \
+ ../include/ipv4/lwip/icmp.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/igmp.h ../include/lwip/api.h \
+ ../include/lwip/netbuf.h ../include/lwip/api_msg.h \
+ ../include/ipv4/lwip/igmp.h ../include/lwip/api.h \
+ ../include/lwip/tcpip.h ../include/lwip/api_msg.h \
+ ../include/lwip/netifapi.h ../include/lwip/sys.h \
+ ../include/lwip/stats.h ../include/lwip/memp.h \
+ ../include/netif/etharp.h ../include/lwip/opt.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip.h ../include/ipv4/lwip/ip_frag.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/memp_std.h
+netif.o: ../core/netif.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/def.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/lwip/netif.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/pbuf.h \
+ ../include/lwip/tcp.h ../include/lwip/sys.h ../include/arch/sys_arch.h \
+ ../include/lwip/mem.h ../include/ipv4/lwip/ip.h ../include/lwip/def.h \
+ ../include/lwip/pbuf.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/icmp.h ../include/lwip/netif.h \
+ ../include/lwip/snmp.h ../include/lwip/netif.h ../include/lwip/udp.h \
+ ../include/ipv4/lwip/igmp.h ../include/netif/etharp.h \
+ ../include/lwip/opt.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip.h
+pbuf.o: ../core/pbuf.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/stats.h \
+ ../include/lwip/mem.h ../include/lwip/memp.h ../include/lwip/memp_std.h \
+ ../include/lwip/def.h ../include/lwip/mem.h ../include/lwip/memp.h \
+ ../include/lwip/pbuf.h ../include/lwip/err.h ../include/lwip/sys.h \
+ ../include/arch/sys_arch.h ../include/arch/perf.h
+stats.o: ../core/stats.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h
+sys.o: ../core/sys.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/sys.h \
+ ../include/lwip/err.h ../include/arch/sys_arch.h ../include/lwip/def.h \
+ ../include/lwip/memp.h ../include/lwip/memp_std.h \
+ ../include/lwip/tcpip.h ../include/lwip/api_msg.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/lwip/sys.h ../include/ipv4/lwip/igmp.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/inet.h ../include/lwip/pbuf.h \
+ ../include/lwip/pbuf.h ../include/lwip/api.h ../include/lwip/netbuf.h \
+ ../include/lwip/netifapi.h
+tcp.o: ../core/tcp.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/def.h \
+ ../include/lwip/mem.h ../include/lwip/memp.h ../include/lwip/memp_std.h \
+ ../include/lwip/snmp.h ../include/lwip/netif.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/ipv4/lwip/inet.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/pbuf.h ../include/lwip/udp.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/def.h ../include/lwip/pbuf.h ../include/lwip/err.h \
+ ../include/lwip/tcp.h ../include/lwip/sys.h ../include/arch/sys_arch.h \
+ ../include/lwip/mem.h ../include/ipv4/lwip/icmp.h \
+ ../include/lwip/netif.h
+tcp_in.o: ../core/tcp_in.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/tcp.h \
+ ../include/lwip/sys.h ../include/lwip/err.h ../include/arch/sys_arch.h \
+ ../include/lwip/mem.h ../include/lwip/pbuf.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/opt.h ../include/lwip/def.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/icmp.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h \
+ ../include/lwip/def.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/netif.h ../include/lwip/mem.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/ipv4/lwip/inet.h \
+ ../include/ipv4/lwip/inet_chksum.h ../include/lwip/stats.h \
+ ../include/lwip/memp.h ../include/lwip/snmp.h ../include/lwip/netif.h \
+ ../include/lwip/udp.h ../include/arch/perf.h
+tcp_out.o: ../core/tcp_out.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/tcp.h \
+ ../include/lwip/sys.h ../include/lwip/err.h ../include/arch/sys_arch.h \
+ ../include/lwip/mem.h ../include/lwip/pbuf.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/opt.h ../include/lwip/def.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/icmp.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h \
+ ../include/lwip/def.h ../include/lwip/mem.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/lwip/sys.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/inet.h ../include/ipv4/lwip/inet_chksum.h \
+ ../include/lwip/stats.h ../include/lwip/memp.h ../include/lwip/snmp.h \
+ ../include/lwip/netif.h ../include/lwip/udp.h
+udp.o: ../core/udp.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/udp.h \
+ ../include/lwip/pbuf.h ../include/lwip/err.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/ipv4/lwip/inet.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/def.h ../include/lwip/pbuf.h \
+ ../include/lwip/err.h ../include/lwip/def.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/ipv4/lwip/inet.h \
+ ../include/ipv4/lwip/inet_chksum.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/netif.h ../include/ipv4/lwip/icmp.h \
+ ../include/lwip/netif.h ../include/lwip/stats.h ../include/lwip/mem.h \
+ ../include/lwip/memp.h ../include/lwip/snmp.h ../include/lwip/udp.h \
+ ../include/arch/perf.h ../include/lwip/dhcp.h
+init.o: ../core/init.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/init.h \
+ ../include/lwip/stats.h ../include/lwip/mem.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/lwip/sys.h ../include/lwip/err.h \
+ ../include/arch/sys_arch.h ../include/lwip/mem.h ../include/lwip/memp.h \
+ ../include/lwip/pbuf.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/ipv4/lwip/inet.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/pbuf.h ../include/lwip/sockets.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/def.h ../include/lwip/pbuf.h \
+ ../include/lwip/err.h ../include/lwip/raw.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/udp.h ../include/lwip/netif.h ../include/lwip/tcp.h \
+ ../include/lwip/sys.h ../include/ipv4/lwip/icmp.h \
+ ../include/lwip/netif.h ../include/ipv4/lwip/autoip.h \
+ ../include/ipv4/lwip/igmp.h ../include/lwip/dns.h \
+ ../include/netif/etharp.h ../include/lwip/opt.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip.h
+icmp.o: ../core/ipv4/icmp.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h \
+ ../include/ipv4/lwip/icmp.h ../include/lwip/opt.h \
+ ../include/lwip/pbuf.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h \
+ ../include/lwip/pbuf.h ../include/ipv4/lwip/inet.h \
+ ../include/ipv4/lwip/inet_chksum.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/def.h ../include/lwip/err.h ../include/lwip/def.h \
+ ../include/lwip/stats.h ../include/lwip/mem.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/lwip/snmp.h \
+ ../include/lwip/netif.h ../include/lwip/udp.h ../include/ipv4/lwip/ip.h
+ip.o: ../core/ipv4/ip.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/opt.h ../include/lwip/def.h ../include/lwip/pbuf.h \
+ ../include/lwip/err.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/err.h ../include/lwip/def.h ../include/lwip/mem.h \
+ ../include/ipv4/lwip/ip_frag.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h \
+ ../include/lwip/pbuf.h ../include/ipv4/lwip/ip.h \
+ ../include/ipv4/lwip/inet.h ../include/ipv4/lwip/inet_chksum.h \
+ ../include/lwip/netif.h ../include/ipv4/lwip/icmp.h \
+ ../include/ipv4/lwip/igmp.h ../include/lwip/raw.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/udp.h ../include/lwip/netif.h \
+ ../include/lwip/tcp.h ../include/lwip/sys.h ../include/arch/sys_arch.h \
+ ../include/lwip/mem.h ../include/ipv4/lwip/icmp.h \
+ ../include/lwip/snmp.h ../include/lwip/udp.h ../include/lwip/dhcp.h \
+ ../include/lwip/stats.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/arch/perf.h
+inet.o: ../core/ipv4/inet.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h \
+ ../include/ipv4/lwip/inet.h ../include/lwip/opt.h \
+ ../include/ipv4/lwip/ip_addr.h
+ip_addr.o: ../core/ipv4/ip_addr.c ../include/lwip/opt.h \
+ ../include/lwipopts.h ../include/lwipopts.h ../include/lwip/debug.h \
+ ../include/lwip/arch.h ../include/arch/cc.h \
+ ../../../include/libc/string.h ../include/lwip/opt.h \
+ ../include/lwip/debug.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/opt.h ../include/ipv4/lwip/inet.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/lwip/err.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/ipv4/lwip/inet.h ../include/lwip/pbuf.h
+inet_chksum.o: ../core/ipv4/inet_chksum.c ../include/lwip/opt.h \
+ ../include/lwipopts.h ../include/lwipopts.h ../include/lwip/debug.h \
+ ../include/lwip/arch.h ../include/arch/cc.h \
+ ../../../include/libc/string.h ../include/lwip/opt.h \
+ ../include/lwip/debug.h ../include/ipv4/lwip/inet_chksum.h \
+ ../include/lwip/opt.h ../include/lwip/pbuf.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h
+api_lib.o: ../api/api_lib.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/api.h \
+ ../include/lwip/netbuf.h ../include/lwip/pbuf.h ../include/lwip/err.h \
+ ../include/lwip/sys.h ../include/arch/sys_arch.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/lwip/tcpip.h ../include/lwip/api_msg.h \
+ ../include/ipv4/lwip/igmp.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/netif.h ../include/ipv4/lwip/inet.h \
+ ../include/lwip/pbuf.h ../include/lwip/api.h ../include/lwip/netifapi.h \
+ ../include/lwip/memp.h ../include/lwip/memp_std.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/def.h ../include/lwip/err.h \
+ ../include/lwip/raw.h ../include/ipv4/lwip/ip.h ../include/lwip/udp.h \
+ ../include/lwip/netif.h ../include/lwip/tcp.h ../include/lwip/mem.h \
+ ../include/ipv4/lwip/icmp.h
+api_msg.o: ../api/api_msg.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/api_msg.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/lwip/err.h ../include/lwip/sys.h ../include/arch/sys_arch.h \
+ ../include/ipv4/lwip/igmp.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/netif.h ../include/ipv4/lwip/inet.h \
+ ../include/lwip/pbuf.h ../include/lwip/pbuf.h ../include/lwip/api.h \
+ ../include/lwip/netbuf.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/def.h ../include/lwip/err.h ../include/lwip/udp.h \
+ ../include/lwip/netif.h ../include/ipv4/lwip/ip.h ../include/lwip/tcp.h \
+ ../include/lwip/mem.h ../include/ipv4/lwip/icmp.h ../include/lwip/raw.h \
+ ../include/lwip/memp.h ../include/lwip/memp_std.h \
+ ../include/lwip/tcpip.h ../include/lwip/api_msg.h \
+ ../include/lwip/netifapi.h ../include/ipv4/lwip/igmp.h \
+ ../include/lwip/dns.h
+tcpip.o: ../api/tcpip.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/sys.h \
+ ../include/lwip/err.h ../include/arch/sys_arch.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip_frag.h ../include/lwip/opt.h \
+ ../include/lwip/err.h ../include/lwip/pbuf.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/def.h ../include/lwip/tcp.h \
+ ../include/lwip/sys.h ../include/lwip/mem.h ../include/ipv4/lwip/ip.h \
+ ../include/ipv4/lwip/icmp.h ../include/ipv4/lwip/autoip.h \
+ ../include/lwip/dhcp.h ../include/ipv4/lwip/igmp.h \
+ ../include/lwip/dns.h ../include/lwip/tcpip.h ../include/lwip/api_msg.h \
+ ../include/ipv4/lwip/igmp.h ../include/lwip/api.h \
+ ../include/lwip/netbuf.h ../include/lwip/netifapi.h \
+ ../include/lwip/init.h ../include/netif/etharp.h ../include/lwip/opt.h \
+ ../include/lwip/pbuf.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/netif.h ../include/ipv4/lwip/ip.h \
+ ../include/netif/ppp_oe.h
+err.o: ../api/err.c ../include/lwip/err.h ../include/lwip/opt.h \
+ ../include/lwipopts.h ../include/lwipopts.h ../include/lwip/debug.h \
+ ../include/lwip/arch.h ../include/arch/cc.h \
+ ../../../include/libc/string.h ../include/lwip/debug.h
+sockets.o: ../api/sockets.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/sockets.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/opt.h \
+ ../include/ipv4/lwip/inet.h ../include/ipv4/lwip/ip_addr.h \
+ ../include/lwip/api.h ../include/lwip/netbuf.h ../include/lwip/pbuf.h \
+ ../include/lwip/err.h ../include/lwip/sys.h ../include/arch/sys_arch.h \
+ ../include/lwip/sys.h ../include/ipv4/lwip/igmp.h \
+ ../include/lwip/netif.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/inet.h ../include/lwip/tcp.h ../include/lwip/mem.h \
+ ../include/ipv4/lwip/ip.h ../include/lwip/def.h ../include/lwip/err.h \
+ ../include/ipv4/lwip/icmp.h ../include/lwip/raw.h ../include/lwip/udp.h \
+ ../include/lwip/netif.h ../include/lwip/tcpip.h \
+ ../include/lwip/api_msg.h ../include/ipv4/lwip/igmp.h \
+ ../include/lwip/api.h ../include/lwip/netifapi.h ../include/lwip/arch.h
+netbuf.o: ../api/netbuf.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h ../include/lwip/netbuf.h \
+ ../include/lwip/pbuf.h ../include/lwip/err.h ../include/lwip/memp.h \
+ ../include/lwip/memp_std.h
+netdb.o: ../api/netdb.c ../include/lwip/netdb.h ../include/lwip/opt.h \
+ ../include/lwipopts.h ../include/lwipopts.h ../include/lwip/debug.h \
+ ../include/lwip/arch.h ../include/arch/cc.h \
+ ../../../include/libc/string.h ../include/lwip/debug.h
+loopif.o: ../netif/loopif.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h
+etharp.o: ../netif/etharp.c ../include/lwip/opt.h ../include/lwipopts.h \
+ ../include/lwipopts.h ../include/lwip/debug.h ../include/lwip/arch.h \
+ ../include/arch/cc.h ../../../include/libc/string.h \
+ ../include/lwip/opt.h ../include/lwip/debug.h \
+ ../include/ipv4/lwip/inet.h ../include/lwip/opt.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/def.h ../include/lwip/pbuf.h ../include/lwip/err.h \
+ ../include/lwip/err.h ../include/lwip/stats.h ../include/lwip/mem.h \
+ ../include/lwip/memp.h ../include/lwip/memp_std.h \
+ ../include/lwip/snmp.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/ipv4/lwip/inet.h \
+ ../include/lwip/pbuf.h ../include/lwip/udp.h ../include/ipv4/lwip/ip.h \
+ ../include/lwip/dhcp.h ../include/ipv4/lwip/autoip.h \
+ ../include/netif/etharp.h ../include/lwip/opt.h ../include/lwip/pbuf.h \
+ ../include/ipv4/lwip/ip_addr.h ../include/lwip/netif.h \
+ ../include/ipv4/lwip/ip.h
include .depend
-$(LWIPLIB): $(LWIPOBJS)
- $(CC) -g -nostartfiles -shared -static $^ -o $@
+##$(LWIPLIB): $(LWIPOBJS)
+## $(CC) -g -nostartfiles -shared -static $^ -o $@
.depend: $(LWIPFILES)
$(CC) $(CFLAGS) -MM $^ > .depend || rm -f .depend
--- /dev/null
+/* Copyright (C) 1991,92,93,94,95,96,97,2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/*
+ * ISO C99 Standard: 7.5 Errors <errno.h>
+ */
+
+#ifndef _ERRNO_H
+
+/* The includer defined __need_Emath if he wants only the definitions
+ of EDOM and ERANGE, and not everything else. */
+#ifndef __need_Emath
+# define _ERRNO_H 1
+# include <features.h>
+#endif
+
+__BEGIN_DECLS
+
+/* Get the error number constants from the system-specific file.
+ This file will test __need_Emath and _ERRNO_H. */
+#include <bits/errno.h>
+#undef __need_Emath
+
+#ifdef _ERRNO_H
+
+/* Declare the `errno' variable, unless it's defined as a macro by
+ bits/errno.h. This is the case in GNU, where it is a per-thread
+ variable. This redeclaration using the macro still works, but it
+ will be a function declaration without a prototype and may trigger
+ a -Wstrict-prototypes warning. */
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef __USE_GNU
+
+/* The full and simple forms of the name with which the program was
+ invoked. These variables are set up automatically at startup based on
+ the value of ARGV[0] (this works only if you use GNU ld). */
+extern char *program_invocation_name, *program_invocation_short_name;
+#endif /* __USE_GNU */
+#endif /* _ERRNO_H */
+
+__END_DECLS
+
+#endif /* _ERRNO_H */
+
+/* The Hurd <bits/errno.h> defines `error_t' as an enumerated type so
+ that printing `error_t' values in the debugger shows the names. We
+ might need this definition sometimes even if this file was included
+ before. */
+#if defined __USE_GNU || defined __need_error_t
+# ifndef __error_t_defined
+typedef int error_t;
+# define __error_t_defined 1
+# endif
+# undef __need_error_t
+#endif
#define __ARCH_CC_H__
/* Include some files for defining library routines */
+
#include <string.h>
-//#include <sys/time.h>
+
+extern int fflush(FILE *file);
+extern int printf(char *fmt, ...);
+extern void abort (void);
+
/* Define platform endianness */
#ifndef BYTE_ORDER
//#include <stdio.h>
//#include <stdlib.h>
/* Plaform specific diagnostic output */
-#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
+#define LWIP_PLATFORM_DIAG(x) //do {printf x;} while(0)
-#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
- x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
+#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
+ x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
#endif /* __ARCH_CC_H__ */
/* Include some files for defining library routines */
#include <string.h>
-#include <sys/time.h>
+//#include <sys/time.h>
/* Define platform endianness */
#ifndef BYTE_ORDER
#define PACK_STRUCT_END
/* prototypes for printf() and abort() */
-#include <stdio.h>
-#include <stdlib.h>
+//#include <stdio.h>
+//#include <stdlib.h>
/* Plaform specific diagnostic output */
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#include "arch/cc.h"
+#include "lwip/opt.h"
+
#ifdef __cplusplus
extern "C" {
#endif
#define LWIP_UNUSED_ARG(x) (void)x
#endif /* LWIP_UNUSED_ARG */
+//weird thing, I already defined it in lwipopts.h, does not work? Lei
+#define LWIP_PROVIDE_ERRNO 1
#ifdef LWIP_PROVIDE_ERRNO
--- /dev/null
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __LWIP_ARCH_H__
+#define __LWIP_ARCH_H__
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+#include "arch/cc.h"
+
+#include "lwipopts.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef PACK_STRUCT_BEGIN
+#define PACK_STRUCT_BEGIN
+#endif /* PACK_STRUCT_BEGIN */
+
+#ifndef PACK_STRUCT_END
+#define PACK_STRUCT_END
+#endif /* PACK_STRUCT_END */
+
+#ifndef PACK_STRUCT_FIELD
+#define PACK_STRUCT_FIELD(x) x
+#endif /* PACK_STRUCT_FIELD */
+
+
+#ifndef LWIP_UNUSED_ARG
+#define LWIP_UNUSED_ARG(x) (void)x
+#endif /* LWIP_UNUSED_ARG */
+
+
+#define LWIP_PROVIDE_ERRNO 1
+
+#ifdef LWIP_PROVIDE_ERRNO
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Arg list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+
+
+#define ENSROK 0 /* DNS server returned answer with no data */
+#define ENSRNODATA 160 /* DNS server returned answer with no data */
+#define ENSRFORMERR 161 /* DNS server claims query was misformatted */
+#define ENSRSERVFAIL 162 /* DNS server returned general failure */
+#define ENSRNOTFOUND 163 /* Domain name not found */
+#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */
+#define ENSRREFUSED 165 /* DNS server refused query */
+#define ENSRBADQUERY 166 /* Misformatted DNS query */
+#define ENSRBADNAME 167 /* Misformatted domain name */
+#define ENSRBADFAMILY 168 /* Unsupported address family */
+#define ENSRBADRESP 169 /* Misformatted DNS reply */
+#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */
+#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */
+#define ENSROF 172 /* End of file */
+#define ENSRFILE 173 /* Error reading file */
+#define ENSRNOMEM 174 /* Out of memory */
+#define ENSRDESTRUCTION 175 /* Application terminated lookup */
+#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */
+#define ENSRCNAMELOOP 177 /* Domain name is too long */
+
+#ifndef errno
+extern int errno;
+#endif
+
+#endif /* LWIP_PROVIDE_ERRNO */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LWIP_ARCH_H__ */
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define SOCK_RAW 3
-
+
+#if 0 /* already defined in lwip/arch.h */
+/* added by Lei */
+#define ENOOK 0 /* No error, everything OK. */
+#define ENOMEM -1 /* Out of memory error. */
+#define ENOBUFS -2 /* Buffer error. */
+#define EHOSTUNREACH -3 /* Routing problem. */
+#define ECONNABORTED -4 /* Connection aborted. */
+#define ECONNRESET -5 /* Connection reset. */
+#define ESHUTDOWN -6 /* Connection closed. */
+#define ENOTCONN -7 /* Not connected. */
+#define EINVAL -8 /* Illegal value. */
+#define EIO -9 /* Illegal argument. */
+#define EADDRINUSE -10 /* Address in use. */
+#define ETIMEDOUT -13 /* Timeout */
+#define EINPROGRESS -14 /* Operation in progress */
+#endif
+
/*
* Option flags per-socket. These must match the SOF_ flags in ip.h!
*/
struct sockaddr *to, socklen_t tolen);
int lwip_socket(int domain, int type, int protocol);
int lwip_write(int s, const void *dataptr, int size);
-int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
- struct timeval *timeout);
+int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
int lwip_ioctl(int s, long cmd, void *argp);
#if LWIP_COMPAT_SOCKETS
--- /dev/null
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+
+#ifndef __LWIP_SOCKETS_H__
+#define __LWIP_SOCKETS_H__
+
+#include "lwip/opt.h"
+
+#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/ip_addr.h"
+#include "lwip/inet.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* members are in network byte order */
+struct sockaddr_in {
+ u8_t sin_len;
+ u8_t sin_family;
+ u16_t sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+
+struct sockaddr {
+ u8_t sa_len;
+ u8_t sa_family;
+ char sa_data[14];
+};
+
+#ifndef socklen_t
+# define socklen_t u32_t
+#endif
+
+/* Socket protocol types (TCP/UDP/RAW) */
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+#define SOCK_RAW 3
+
+#if 0 /* already defined in lwip/arch.h */
+/* added by Lei */
+#define ENOOK 0 /* No error, everything OK. */
+#define ENOMEM -1 /* Out of memory error. */
+#define ENOBUFS -2 /* Buffer error. */
+#define EHOSTUNREACH -3 /* Routing problem. */
+#define ECONNABORTED -4 /* Connection aborted. */
+#define ECONNRESET -5 /* Connection reset. */
+#define ESHUTDOWN -6 /* Connection closed. */
+#define ENOTCONN -7 /* Not connected. */
+#define EINVAL -8 /* Illegal value. */
+#define EIO -9 /* Illegal argument. */
+#define EADDRINUSE -10 /* Address in use. */
+#define ETIMEDOUT -13 /* Timeout */
+#define EINPROGRESS -14 /* Operation in progress */
+#endif
+
+/*
+ * Option flags per-socket. These must match the SOF_ flags in ip.h!
+ */
+#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */
+#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
+#define SO_REUSEADDR 0x0004 /* Unimplemented: allow local address reuse */
+#define SO_KEEPALIVE 0x0008 /* keep connections alive */
+#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
+#define SO_BROADCAST 0x0020 /* Unimplemented: permit sending of broadcast msgs */
+#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
+#define SO_LINGER 0x0080 /* linger on close if data present */
+#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */
+#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */
+
+#define SO_DONTLINGER ((int)(~SO_LINGER))
+
+/*
+ * Additional options, not kept in so_options.
+ */
+#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */
+#define SO_RCVBUF 0x1002 /* receive buffer size */
+#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */
+#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */
+#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */
+#define SO_RCVTIMEO 0x1006 /* receive timeout */
+#define SO_ERROR 0x1007 /* get error status and clear */
+#define SO_TYPE 0x1008 /* get socket type */
+#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */
+#define SO_NO_CHECK 0x100a /* don't create UDP checksum */
+
+
+/*
+ * Structure used for manipulating linger option.
+ */
+struct linger {
+ int l_onoff; /* option on/off */
+ int l_linger; /* linger time */
+};
+
+/*
+ * Level number for (get/set)sockopt() to apply to socket itself.
+ */
+#define SOL_SOCKET 0xfff /* options for socket level */
+
+
+#define AF_UNSPEC 0
+#define AF_INET 2
+#define PF_INET AF_INET
+#define PF_UNSPEC AF_UNSPEC
+
+#define IPPROTO_IP 0
+#define IPPROTO_TCP 6
+#define IPPROTO_UDP 17
+#define IPPROTO_UDPLITE 136
+
+#define INADDR_ANY 0
+#define INADDR_BROADCAST 0xffffffff
+
+/* Flags we can use with send and recv. */
+#define MSG_PEEK 0x01 /* Peeks at an incoming message */
+#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */
+#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */
+#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */
+#define MSG_MORE 0x10 /* Sender will send more */
+
+
+/*
+ * Options for level IPPROTO_IP
+ */
+#define IP_TOS 1
+#define IP_TTL 2
+
+#if LWIP_TCP
+/*
+ * Options for level IPPROTO_TCP
+ */
+#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
+#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */
+#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */
+#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */
+#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */
+#endif /* LWIP_TCP */
+
+#if LWIP_UDP && LWIP_UDPLITE
+/*
+ * Options for level IPPROTO_UDPLITE
+ */
+#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */
+#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */
+#endif /* LWIP_UDP && LWIP_UDPLITE*/
+
+
+#if LWIP_IGMP
+/*
+ * Options and types for UDP multicast traffic handling
+ */
+#define IP_ADD_MEMBERSHIP 3
+#define IP_DROP_MEMBERSHIP 4
+#define IP_MULTICAST_TTL 5
+#define IP_MULTICAST_IF 6
+#define IP_MULTICAST_LOOP 7
+
+typedef struct ip_mreq {
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+} ip_mreq;
+#endif /* LWIP_IGMP */
+
+/* Unimplemented for now... */
+#define IPTOS_TOS_MASK 0x1E
+#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_LOWCOST 0x02
+#define IPTOS_MINCOST IPTOS_LOWCOST
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (Unimplemented)
+ */
+#define IPTOS_PREC_MASK 0xe0
+#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
+#define IPTOS_PREC_NETCONTROL 0xe0
+#define IPTOS_PREC_INTERNETCONTROL 0xc0
+#define IPTOS_PREC_CRITIC_ECP 0xa0
+#define IPTOS_PREC_FLASHOVERRIDE 0x80
+#define IPTOS_PREC_FLASH 0x60
+#define IPTOS_PREC_IMMEDIATE 0x40
+#define IPTOS_PREC_PRIORITY 0x20
+#define IPTOS_PREC_ROUTINE 0x00
+
+
+/*
+ * Commands for ioctlsocket(), taken from the BSD file fcntl.h.
+ * lwip_ioctl only supports FIONREAD and FIONBIO, for now
+ *
+ * Ioctl's have the command encoded in the lower word,
+ * and the size of any in or out parameters in the upper
+ * word. The high 2 bits of the upper word are used
+ * to encode the in/out status of the parameter; for now
+ * we restrict parameters to at most 128 bytes.
+ */
+#if !defined(FIONREAD) || !defined(FIONBIO)
+#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */
+#define IOC_VOID 0x20000000UL /* no parameters */
+#define IOC_OUT 0x40000000UL /* copy out parameters */
+#define IOC_IN 0x80000000UL /* copy in parameters */
+#define IOC_INOUT (IOC_IN|IOC_OUT)
+ /* 0x20000000 distinguishes new &
+ old ioctl's */
+#define _IO(x,y) (IOC_VOID|((x)<<8)|(y))
+
+#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
+
+#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
+#endif /* !defined(FIONREAD) || !defined(FIONBIO) */
+
+#ifndef FIONREAD
+#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */
+#endif
+#ifndef FIONBIO
+#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */
+#endif
+
+/* Socket I/O Controls: unimplemented */
+#ifndef SIOCSHIWAT
+#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */
+#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */
+#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */
+#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */
+#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */
+#endif
+
+/* Socket flags: */
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 04000U
+#endif
+
+/* FD_SET used for lwip_select */
+#ifndef FD_SET
+ #undef FD_SETSIZE
+ /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */
+ #define FD_SETSIZE MEMP_NUM_NETCONN
+ #define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7)))
+ #define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7)))
+ #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7)))
+ #define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p)))
+
+ typedef struct fd_set {
+ unsigned char fd_bits [(FD_SETSIZE+7)/8];
+ } fd_set;
+
+#endif /* FD_SET */
+
+/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided
+ * by your system, set this to 0 and include <sys/time.h> in cc.h */
+#ifndef LWIP_TIMEVAL_PRIVATE
+#define LWIP_TIMEVAL_PRIVATE 1
+#endif
+
+#if LWIP_TIMEVAL_PRIVATE
+struct timeval {
+ long tv_sec; /* seconds */
+ long tv_usec; /* and microseconds */
+};
+#endif /* LWIP_TIMEVAL_PRIVATE */
+
+void lwip_socket_init(void);
+
+int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int lwip_bind(int s, struct sockaddr *name, socklen_t namelen);
+int lwip_shutdown(int s, int how);
+int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen);
+int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen);
+int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen);
+int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen);
+int lwip_close(int s);
+int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen);
+int lwip_listen(int s, int backlog);
+int lwip_recv(int s, void *mem, int len, unsigned int flags);
+int lwip_read(int s, void *mem, int len);
+int lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen);
+int lwip_send(int s, const void *dataptr, int size, unsigned int flags);
+int lwip_sendto(int s, const void *dataptr, int size, unsigned int flags,
+ struct sockaddr *to, socklen_t tolen);
+int lwip_socket(int domain, int type, int protocol);
+int lwip_write(int s, const void *dataptr, int size);
+int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+ struct timeval *timeout);
+int lwip_ioctl(int s, long cmd, void *argp);
+
+#if LWIP_COMPAT_SOCKETS
+#define accept(a,b,c) lwip_accept(a,b,c)
+#define bind(a,b,c) lwip_bind(a,b,c)
+#define shutdown(a,b) lwip_shutdown(a,b)
+#define closesocket(s) lwip_close(s)
+#define connect(a,b,c) lwip_connect(a,b,c)
+#define getsockname(a,b,c) lwip_getsockname(a,b,c)
+#define getpeername(a,b,c) lwip_getpeername(a,b,c)
+#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e)
+#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e)
+#define listen(a,b) lwip_listen(a,b)
+#define recv(a,b,c,d) lwip_recv(a,b,c,d)
+#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f)
+#define send(a,b,c,d) lwip_send(a,b,c,d)
+#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f)
+#define socket(a,b,c) lwip_socket(a,b,c)
+#define select(a,b,c,d,e) lwip_select(a,b,c,d,e)
+#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c)
+
+#if LWIP_POSIX_SOCKETS_IO_NAMES
+#define read(a,b,c) lwip_read(a,b,c)
+#define write(a,b,c) lwip_write(a,b,c)
+#define close(s) lwip_close(s)
+#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */
+
+#endif /* LWIP_COMPAT_SOCKETS */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIP_SOCKET */
+
+#endif /* __LWIP_SOCKETS_H__ */
* PPP_SUPPORT==1: Enable PPP.
*/
#define PPP_SUPPORT 0
+
+
+/* use errno provided by lwip, Lei */
+#define LWIP_PROVIDE_ERRNO 1
/* Misc */
-#define LWIP_TIMEVAL_PRIVATE 0
+#define LWIP_TIMEVAL_PRIVATE 1
#endif /* __LWIPOPTS_H__ */
--- /dev/null
+/**
+ * @file
+ *
+ * lwIP Options Configuration
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __LWIPOPTS_H__
+#define __LWIPOPTS_H__
+
+/*
+ * Include user defined options first. Anything not defined in these files
+ * will be set to standard values. Override anything you dont like!
+ */
+#include "lwipopts.h"
+#include "lwip/debug.h"
+
+/*
+ -----------------------------------------------
+ ---------- Platform specific locking ----------
+ -----------------------------------------------
+*/
+
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT 0
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS 0
+
+/*
+ ------------------------------------
+ ---------- Memory options ----------
+ ------------------------------------
+*/
+
+/**
+ * MEM_ALIGNMENT: should be set to the alignment of the CPU
+ * 4 byte alignment -> #define MEM_ALIGNMENT 4
+ * 2 byte alignment -> #define MEM_ALIGNMENT 2
+ */
+#define MEM_ALIGNMENT 1
+
+/**
+ * MEM_SIZE: the size of the heap memory. If the application will send
+ * a lot of data that needs to be copied, this should be set high.
+ */
+#define MEM_SIZE 1600
+
+/*
+ ------------------------------------------------
+ ---------- Internal Memory Pool Sizes ----------
+ ------------------------------------------------
+*/
+/**
+ * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF).
+ * If the application sends a lot of data out of ROM (or other static memory),
+ * this should be set high.
+ */
+#define MEMP_NUM_PBUF 16
+
+/**
+ * MEMP_NUM_RAW_PCB: Number of raw connection PCBs
+ * (requires the LWIP_RAW option)
+ */
+#define MEMP_NUM_RAW_PCB 4
+
+/**
+ * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+ * per active UDP "connection".
+ * (requires the LWIP_UDP option)
+ */
+#define MEMP_NUM_UDP_PCB 4
+
+/**
+ * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections.
+ * (requires the LWIP_TCP option)
+ */
+#define MEMP_NUM_TCP_PCB 4
+
+/**
+ * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections.
+ * (requires the LWIP_TCP option)
+ */
+#define MEMP_NUM_TCP_PCB_LISTEN 4
+
+/**
+ * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments.
+ * (requires the LWIP_TCP option)
+ */
+#define MEMP_NUM_TCP_SEG 16
+
+/**
+ * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for
+ * reassembly (whole packets, not fragments!)
+ */
+#define MEMP_NUM_REASSDATA 1
+
+/**
+ * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing
+ * packets (pbufs) that are waiting for an ARP request (to resolve
+ * their destination address) to finish.
+ * (requires the ARP_QUEUEING option)
+ */
+#define MEMP_NUM_ARP_QUEUE 2
+
+/**
+ * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts.
+ * (requires NO_SYS==0)
+ */
+#define MEMP_NUM_SYS_TIMEOUT 3
+
+/**
+ * MEMP_NUM_NETBUF: the number of struct netbufs.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#define MEMP_NUM_NETBUF 2
+
+/**
+ * MEMP_NUM_NETCONN: the number of struct netconns.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#define MEMP_NUM_NETCONN 4
+
+/**
+ * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
+ * for callback/timeout API communication.
+ * (only needed if you use tcpip.c)
+ */
+#define MEMP_NUM_TCPIP_MSG_API 8
+
+/**
+ * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
+ * for incoming packets.
+ * (only needed if you use tcpip.c)
+ */
+#define MEMP_NUM_TCPIP_MSG_INPKT 8
+
+/**
+ * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
+ */
+#define PBUF_POOL_SIZE 8
+
+/*
+ ---------------------------------
+ ---------- ARP options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_ARP==1: Enable ARP functionality.
+ */
+#define LWIP_ARP 1
+
+/*
+ --------------------------------
+ ---------- IP options ----------
+ --------------------------------
+*/
+/**
+ * IP_FORWARD==1: Enables the ability to forward IP packets across network
+ * interfaces. If you are going to run lwIP on a device with only one network
+ * interface, define this to 0.
+ */
+#define IP_FORWARD 0
+
+/**
+ * IP_OPTIONS: Defines the behavior for IP options.
+ * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
+ * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed).
+ */
+#define IP_OPTIONS_ALLOWED 1
+
+/**
+ * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that
+ * this option does not affect outgoing packet sizes, which can be controlled
+ * via IP_FRAG.
+ */
+#define IP_REASSEMBLY 1
+
+/**
+ * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
+ * that this option does not affect incoming packet sizes, which can be
+ * controlled via IP_REASSEMBLY.
+ */
+#define IP_FRAG 1
+
+/**
+ * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally)
+ * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived
+ * in this time, the whole packet is discarded.
+ */
+#define IP_REASS_MAXAGE 3
+
+/**
+ * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled.
+ * Since the received pbufs are enqueued, be sure to configure
+ * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive
+ * packets even if the maximum amount of fragments is enqueued for reassembly!
+ */
+#define IP_REASS_MAX_PBUFS 4
+
+/**
+ * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP
+ * fragmentation. Otherwise pbufs are allocated and reference the original
+ * packet data to be fragmented.
+*/
+#define IP_FRAG_USES_STATIC_BUF 0
+
+/**
+ * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers.
+ */
+#define IP_DEFAULT_TTL 255
+
+/*
+ ----------------------------------
+ ---------- ICMP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_ICMP==1: Enable ICMP module inside the IP stack.
+ * Be careful, disable that make your product non-compliant to RFC1122
+ */
+#define LWIP_ICMP 1
+
+/*
+ ---------------------------------
+ ---------- RAW options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_RAW==1: Enable application layer to hook into the IP layer itself.
+ */
+#define LWIP_RAW 1
+
+/*
+ ----------------------------------
+ ---------- DHCP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_DHCP==1: Enable DHCP module.
+ */
+#define LWIP_DHCP 0
+
+
+/*
+ ------------------------------------
+ ---------- AUTOIP options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_AUTOIP==1: Enable AUTOIP module.
+ */
+#define LWIP_AUTOIP 0
+
+/*
+ ----------------------------------
+ ---------- SNMP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP
+ * transport.
+ */
+#define LWIP_SNMP 0
+
+/*
+ ----------------------------------
+ ---------- IGMP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_IGMP==1: Turn on IGMP module.
+ */
+#define LWIP_IGMP 0
+
+/*
+ ----------------------------------
+ ---------- DNS options -----------
+ ----------------------------------
+*/
+/**
+ * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS
+ * transport.
+ */
+#define LWIP_DNS 0
+
+/*
+ ---------------------------------
+ ---------- UDP options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_UDP==1: Turn on UDP.
+ */
+#define LWIP_UDP 1
+
+/*
+ ---------------------------------
+ ---------- TCP options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_TCP==1: Turn on TCP.
+ */
+#define LWIP_TCP 1
+
+#define LWIP_LISTEN_BACKLOG 0
+
+/*
+ ----------------------------------
+ ---------- Pbuf options ----------
+ ----------------------------------
+*/
+/**
+ * PBUF_LINK_HLEN: the number of bytes that should be allocated for a
+ * link level header. The default is 14, the standard value for
+ * Ethernet.
+ */
+#define PBUF_LINK_HLEN 16
+
+/**
+ * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is
+ * designed to accomodate single full size TCP frame in one pbuf, including
+ * TCP_MSS, IP header, and link header.
+*
+ */
+#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN)
+
+/*
+ ------------------------------------
+ ---------- LOOPIF options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c
+ */
+#define LWIP_HAVE_LOOPIF 0
+
+/*
+ ----------------------------------------------
+ ---------- Sequential layer options ----------
+ ----------------------------------------------
+*/
+
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN 1
+
+/*
+ ------------------------------------
+ ---------- Socket options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET 1
+
+/*
+ ----------------------------------------
+ ---------- Statistics options ----------
+ ----------------------------------------
+*/
+/**
+ * LWIP_STATS==1: Enable statistics collection in lwip_stats.
+ */
+#define LWIP_STATS 0
+/*
+ ---------------------------------
+ ---------- PPP options ----------
+ ---------------------------------
+*/
+/**
+ * PPP_SUPPORT==1: Enable PPP.
+ */
+#define PPP_SUPPORT 0
+
+
+/* use errno provided by lwip, Lei */
+#define LWIP_PROVIDE_ERRNO 1
+
+
+/* Misc */
+
+#define LWIP_TIMEVAL_PRIVATE 0
+
+#endif /* __LWIPOPTS_H__ */