uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sockets.c
Go to the documentation of this file.
1 
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  * derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
38  *
39  */
40 
41 #include "lwip/opt.h"
42 
43 #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
44 
45 #include "lwip/sockets.h"
46 #include "lwip/api.h"
47 #include "lwip/sys.h"
48 #include "lwip/igmp.h"
49 #include "lwip/inet.h"
50 #include "lwip/tcp.h"
51 #include "lwip/raw.h"
52 #include "lwip/udp.h"
53 #include "lwip/tcpip.h"
54 #include "lwip/pbuf.h"
55 #if LWIP_CHECKSUM_ON_COPY
56 #include "lwip/inet_chksum.h"
57 #endif
58 
59 #include <string.h>
60 
61 #define NUM_SOCKETS MEMP_NUM_NETCONN
62 
64 struct lwip_sock {
66  struct netconn *conn;
68  void *lastdata;
70  u16_t lastoffset;
73  s16_t rcvevent;
76  u16_t sendevent;
78  u16_t errevent;
80  int err;
82  int select_waiting;
83 };
84 
86 struct lwip_select_cb {
88  struct lwip_select_cb *next;
90  struct lwip_select_cb *prev;
92  fd_set *readset;
94  fd_set *writeset;
96  fd_set *exceptset;
98  int sem_signalled;
100  sys_sem_t sem;
101 };
102 
105 struct lwip_setgetsockopt_data {
107  struct lwip_sock *sock;
108 #ifdef LWIP_DEBUG
109 
110  int s;
111 #endif /* LWIP_DEBUG */
112 
113  int level;
115  int optname;
118  void *optval;
120  socklen_t *optlen;
122  err_t err;
123 };
124 
126 static struct lwip_sock sockets[NUM_SOCKETS];
128 static struct lwip_select_cb *select_cb_list;
131 static volatile int select_cb_ctr;
132 
135 static const int err_to_errno_table[] = {
136  0, /* ERR_OK 0 No error, everything OK. */
137  ENOMEM, /* ERR_MEM -1 Out of memory error. */
138  ENOBUFS, /* ERR_BUF -2 Buffer error. */
139  EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
140  EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
141  EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
142  EINVAL, /* ERR_VAL -6 Illegal value. */
143  EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
144  ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
145  ECONNRESET, /* ERR_RST -9 Connection reset. */
146  ESHUTDOWN, /* ERR_CLSD -10 Connection closed. */
147  ENOTCONN, /* ERR_CONN -11 Not connected. */
148  EIO, /* ERR_ARG -12 Illegal argument. */
149  EADDRINUSE, /* ERR_USE -13 Address in use. */
150  -1, /* ERR_IF -14 Low-level netif error */
151  -1, /* ERR_ISCONN -15 Already connected. */
152 };
153 
154 #define ERR_TO_ERRNO_TABLE_SIZE \
155  (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
156 
157 #define err_to_errno(err) \
158  ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
159  err_to_errno_table[-(err)] : EIO)
160 
161 #ifdef ERRNO
162 #ifndef set_errno
163 #define set_errno(err) errno = (err)
164 #endif
165 #else /* ERRNO */
166 #define set_errno(err)
167 #endif /* ERRNO */
168 
169 #define sock_set_errno(sk, e) do { \
170  sk->err = (e); \
171  set_errno(sk->err); \
172 } while (0)
173 
174 /* Forward delcaration of some functions */
175 static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
176 static void lwip_getsockopt_internal(void *arg);
177 static void lwip_setsockopt_internal(void *arg);
178 
183 void
184 lwip_socket_init(void)
185 {
186 }
187 
194 static struct lwip_sock *
195 get_socket(int s)
196 {
197  struct lwip_sock *sock;
198 
199  if ((s < 0) || (s >= NUM_SOCKETS)) {
200  LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
201  set_errno(EBADF);
202  return NULL;
203  }
204 
205  sock = &sockets[s];
206 
207  if (!sock->conn) {
208  LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
209  set_errno(EBADF);
210  return NULL;
211  }
212 
213  return sock;
214 }
215 
222 static struct lwip_sock *
223 tryget_socket(int s)
224 {
225  if ((s < 0) || (s >= NUM_SOCKETS)) {
226  return NULL;
227  }
228  if (!sockets[s].conn) {
229  return NULL;
230  }
231  return &sockets[s];
232 }
233 
242 static int
243 alloc_socket(struct netconn *newconn, int accepted)
244 {
245  int i;
247 
248  /* allocate a new socket identifier */
249  for (i = 0; i < NUM_SOCKETS; ++i) {
250  /* Protect socket array */
251  SYS_ARCH_PROTECT(lev);
252  if (!sockets[i].conn) {
253  sockets[i].conn = newconn;
254  /* The socket is not yet known to anyone, so no need to protect
255  after having marked it as used. */
256  SYS_ARCH_UNPROTECT(lev);
257  sockets[i].lastdata = NULL;
258  sockets[i].lastoffset = 0;
259  sockets[i].rcvevent = 0;
260  /* TCP sendbuf is empty, but the socket is not yet writable until connected
261  * (unless it has been created by accept()). */
262  sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
263  sockets[i].errevent = 0;
264  sockets[i].err = 0;
265  sockets[i].select_waiting = 0;
266  return i;
267  }
268  SYS_ARCH_UNPROTECT(lev);
269  }
270  return -1;
271 }
272 
279 static void
280 free_socket(struct lwip_sock *sock, int is_tcp)
281 {
282  void *lastdata;
284 
285  lastdata = sock->lastdata;
286  sock->lastdata = NULL;
287  sock->lastoffset = 0;
288  sock->err = 0;
289 
290  /* Protect socket array */
291  SYS_ARCH_PROTECT(lev);
292  sock->conn = NULL;
293  SYS_ARCH_UNPROTECT(lev);
294  /* don't use 'sock' after this line, as another task might have allocated it */
295 
296  if (lastdata != NULL) {
297  if (is_tcp) {
298  pbuf_free((struct pbuf *)lastdata);
299  } else {
300  netbuf_delete((struct netbuf *)lastdata);
301  }
302  }
303 }
304 
305 /* Below this, the well-known socket functions are implemented.
306  * Use google.com or opengroup.org to get a good description :-)
307  *
308  * Exceptions are documented!
309  */
310 
311 int
312 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
313 {
314  struct lwip_sock *sock, *nsock;
315  struct netconn *newconn;
316  ip_addr_t naddr;
317  u16_t port;
318  int newsock;
319  struct sockaddr_in sin;
320  err_t err;
322 
323  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
324  sock = get_socket(s);
325  if (!sock) {
326  return -1;
327  }
328 
329  if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
330  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
331  sock_set_errno(sock, EWOULDBLOCK);
332  return -1;
333  }
334 
335  /* wait for a new connection */
336  err = netconn_accept(sock->conn, &newconn);
337  if (err != ERR_OK) {
338  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
339  sock_set_errno(sock, err_to_errno(err));
340  return -1;
341  }
342  LWIP_ASSERT("newconn != NULL", newconn != NULL);
343  /* Prevent automatic window updates, we do this on our own! */
344  netconn_set_noautorecved(newconn, 1);
345 
346  /* get the IP address and port of the remote host */
347  err = netconn_peer(newconn, &naddr, &port);
348  if (err != ERR_OK) {
349  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
350  netconn_delete(newconn);
351  sock_set_errno(sock, err_to_errno(err));
352  return -1;
353  }
354 
355  /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
356  * not be NULL if addr is valid.
357  */
358  if (NULL != addr) {
359  LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
360  memset(&sin, 0, sizeof(sin));
361  sin.sin_len = sizeof(sin);
362  sin.sin_family = AF_INET;
363  sin.sin_port = htons(port);
364  inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
365 
366  if (*addrlen > sizeof(sin))
367  *addrlen = sizeof(sin);
368 
369  MEMCPY(addr, &sin, *addrlen);
370  }
371 
372  newsock = alloc_socket(newconn, 1);
373  if (newsock == -1) {
374  netconn_delete(newconn);
375  sock_set_errno(sock, ENFILE);
376  return -1;
377  }
378  LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
379  LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
380  nsock = &sockets[newsock];
381 
382  /* See event_callback: If data comes in right away after an accept, even
383  * though the server task might not have created a new socket yet.
384  * In that case, newconn->socket is counted down (newconn->socket--),
385  * so nsock->rcvevent is >= 1 here!
386  */
387  SYS_ARCH_PROTECT(lev);
388  nsock->rcvevent += (s16_t)(-1 - newconn->socket);
389  newconn->socket = newsock;
390  SYS_ARCH_UNPROTECT(lev);
391 
392  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
394  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
395 
396  sock_set_errno(sock, 0);
397  return newsock;
398 }
399 
400 int
401 lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
402 {
403  struct lwip_sock *sock;
404  ip_addr_t local_addr;
405  u16_t local_port;
406  err_t err;
407  const struct sockaddr_in *name_in;
408 
409  sock = get_socket(s);
410  if (!sock) {
411  return -1;
412  }
413 
414  /* check size, familiy and alignment of 'name' */
415  LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
416  ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
417  sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
418  name_in = (const struct sockaddr_in *)(void*)name;
419 
420  inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr);
421  local_port = name_in->sin_port;
422 
423  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
424  ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
425  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
426 
427  err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
428 
429  if (err != ERR_OK) {
430  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
431  sock_set_errno(sock, err_to_errno(err));
432  return -1;
433  }
434 
435  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
436  sock_set_errno(sock, 0);
437  return 0;
438 }
439 
440 int
441 lwip_close(int s)
442 {
443  struct lwip_sock *sock;
444  int is_tcp = 0;
445 
446  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
447 
448  sock = get_socket(s);
449  if (!sock) {
450  return -1;
451  }
452 
453  if(sock->conn != NULL) {
454  is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
455  } else {
456  LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
457  }
458 
459  netconn_delete(sock->conn);
460 
461  free_socket(sock, is_tcp);
462  set_errno(0);
463  return 0;
464 }
465 
466 int
467 lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
468 {
469  struct lwip_sock *sock;
470  err_t err;
471  const struct sockaddr_in *name_in;
472 
473  sock = get_socket(s);
474  if (!sock) {
475  return -1;
476  }
477 
478  /* check size, familiy and alignment of 'name' */
479  LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
480  ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
481  sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
482  name_in = (const struct sockaddr_in *)(void*)name;
483 
484  if (name_in->sin_family == AF_UNSPEC) {
485  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
486  err = netconn_disconnect(sock->conn);
487  } else {
488  ip_addr_t remote_addr;
489  u16_t remote_port;
490 
491  inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr);
492  remote_port = name_in->sin_port;
493 
494  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
495  ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
496  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
497 
498  err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
499  }
500 
501  if (err != ERR_OK) {
502  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
503  sock_set_errno(sock, err_to_errno(err));
504  return -1;
505  }
506 
507  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
508  sock_set_errno(sock, 0);
509  return 0;
510 }
511 
520 int
521 lwip_listen(int s, int backlog)
522 {
523  struct lwip_sock *sock;
524  err_t err;
525 
526  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
527 
528  sock = get_socket(s);
529  if (!sock) {
530  return -1;
531  }
532 
533  /* limit the "backlog" parameter to fit in an u8_t */
534  backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
535 
536  err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
537 
538  if (err != ERR_OK) {
539  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
540  sock_set_errno(sock, err_to_errno(err));
541  return -1;
542  }
543 
544  sock_set_errno(sock, 0);
545  return 0;
546 }
547 
548 int
549 lwip_recvfrom(int s, void *mem, size_t len, int flags,
550  struct sockaddr *from, socklen_t *fromlen)
551 {
552  struct lwip_sock *sock;
553  void *buf = NULL;
554  struct pbuf *p;
555  u16_t buflen, copylen;
556  int off = 0;
557  ip_addr_t *addr;
558  u16_t port;
559  u8_t done = 0;
560  err_t err;
561 
562  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
563  sock = get_socket(s);
564  if (!sock) {
565  return -1;
566  }
567 
568  do {
569  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
570  /* Check if there is data left from the last recv operation. */
571  if (sock->lastdata) {
572  buf = sock->lastdata;
573  } else {
574  /* If this is non-blocking call, then check first */
575  if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
576  (sock->rcvevent <= 0)) {
577  if (off > 0) {
578  /* update receive window */
579  netconn_recved(sock->conn, (u32_t)off);
580  /* already received data, return that */
581  sock_set_errno(sock, 0);
582  return off;
583  }
584  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
585  sock_set_errno(sock, EWOULDBLOCK);
586  return -1;
587  }
588 
589  /* No data was left from the previous operation, so we try to get
590  some from the network. */
591  if (netconn_type(sock->conn) == NETCONN_TCP) {
592  err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
593  } else {
594  err = netconn_recv(sock->conn, (struct netbuf **)&buf);
595  }
596  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
597  err, buf));
598 
599  if (err != ERR_OK) {
600  if (off > 0) {
601  /* update receive window */
602  netconn_recved(sock->conn, (u32_t)off);
603  /* already received data, return that */
604  sock_set_errno(sock, 0);
605  return off;
606  }
607  /* We should really do some error checking here. */
608  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
609  s, lwip_strerr(err)));
610  sock_set_errno(sock, err_to_errno(err));
611  if (err == ERR_CLSD) {
612  return 0;
613  } else {
614  return -1;
615  }
616  }
617  LWIP_ASSERT("buf != NULL", buf != NULL);
618  sock->lastdata = buf;
619  }
620 
621  if (netconn_type(sock->conn) == NETCONN_TCP) {
622  p = (struct pbuf *)buf;
623  } else {
624  p = ((struct netbuf *)buf)->p;
625  }
626  buflen = p->tot_len;
627  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
628  buflen, len, off, sock->lastoffset));
629 
630  buflen -= sock->lastoffset;
631 
632  if (len > buflen) {
633  copylen = buflen;
634  } else {
635  copylen = (u16_t)len;
636  }
637 
638  /* copy the contents of the received buffer into
639  the supplied memory pointer mem */
640  pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
641 
642  off += copylen;
643 
644  if (netconn_type(sock->conn) == NETCONN_TCP) {
645  LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
646  len -= copylen;
647  if ( (len <= 0) ||
648  (p->flags & PBUF_FLAG_PUSH) ||
649  (sock->rcvevent <= 0) ||
650  ((flags & MSG_PEEK)!=0)) {
651  done = 1;
652  }
653  } else {
654  done = 1;
655  }
656 
657  /* Check to see from where the data was.*/
658  if (done) {
659  ip_addr_t fromaddr;
660  if (from && fromlen) {
661  struct sockaddr_in sin;
662 
663  if (netconn_type(sock->conn) == NETCONN_TCP) {
664  addr = &fromaddr;
665  netconn_getaddr(sock->conn, addr, &port, 0);
666  } else {
667  addr = netbuf_fromaddr((struct netbuf *)buf);
668  port = netbuf_fromport((struct netbuf *)buf);
669  }
670 
671  memset(&sin, 0, sizeof(sin));
672  sin.sin_len = sizeof(sin);
673  sin.sin_family = AF_INET;
674  sin.sin_port = htons(port);
675  inet_addr_from_ipaddr(&sin.sin_addr, addr);
676 
677  if (*fromlen > sizeof(sin)) {
678  *fromlen = sizeof(sin);
679  }
680 
681  MEMCPY(from, &sin, *fromlen);
682 
683  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
685  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
686  } else {
687 #if SOCKETS_DEBUG
688  if (netconn_type(sock->conn) == NETCONN_TCP) {
689  addr = &fromaddr;
690  netconn_getaddr(sock->conn, addr, &port, 0);
691  } else {
692  addr = netbuf_fromaddr((struct netbuf *)buf);
693  port = netbuf_fromport((struct netbuf *)buf);
694  }
695 
696  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
698  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
699 #endif /* SOCKETS_DEBUG */
700  }
701  }
702 
703  /* If we don't peek the incoming message... */
704  if ((flags & MSG_PEEK) == 0) {
705  /* If this is a TCP socket, check if there is data left in the
706  buffer. If so, it should be saved in the sock structure for next
707  time around. */
708  if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
709  sock->lastdata = buf;
710  sock->lastoffset += copylen;
711  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
712  } else {
713  sock->lastdata = NULL;
714  sock->lastoffset = 0;
715  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
716  if (netconn_type(sock->conn) == NETCONN_TCP) {
717  pbuf_free((struct pbuf *)buf);
718  } else {
719  netbuf_delete((struct netbuf *)buf);
720  }
721  }
722  }
723  } while (!done);
724 
725  if (off > 0) {
726  /* update receive window */
727  netconn_recved(sock->conn, (u32_t)off);
728  }
729  sock_set_errno(sock, 0);
730  return off;
731 }
732 
733 int
734 lwip_read(int s, void *mem, size_t len)
735 {
736  return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
737 }
738 
739 int
740 lwip_recv(int s, void *mem, size_t len, int flags)
741 {
742  return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
743 }
744 
745 int
746 lwip_send(int s, const void *data, size_t size, int flags)
747 {
748  struct lwip_sock *sock;
749  err_t err;
750  u8_t write_flags;
751 
752  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
753  s, data, size, flags));
754 
755  sock = get_socket(s);
756  if (!sock) {
757  return -1;
758  }
759 
760  if (sock->conn->type != NETCONN_TCP) {
761 #if (LWIP_UDP || LWIP_RAW)
762  return lwip_sendto(s, data, size, flags, NULL, 0);
763 #else /* (LWIP_UDP || LWIP_RAW) */
764  sock_set_errno(sock, err_to_errno(ERR_ARG));
765  return -1;
766 #endif /* (LWIP_UDP || LWIP_RAW) */
767  }
768 
769  if ((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) {
770  if ((size > TCP_SND_BUF) || ((size / TCP_MSS) > TCP_SND_QUEUELEN)) {
771  /* too much data to ever send nonblocking! */
772  sock_set_errno(sock, EMSGSIZE);
773  return -1;
774  }
775  }
776 
777  write_flags = NETCONN_COPY |
778  ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
779  ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
780  err = netconn_write(sock->conn, data, size, write_flags);
781 
782  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
783  sock_set_errno(sock, err_to_errno(err));
784  return (err == ERR_OK ? (int)size : -1);
785 }
786 
787 int
788 lwip_sendto(int s, const void *data, size_t size, int flags,
789  const struct sockaddr *to, socklen_t tolen)
790 {
791  struct lwip_sock *sock;
792  err_t err;
793  u16_t short_size;
794  const struct sockaddr_in *to_in;
795  u16_t remote_port;
796 #if !LWIP_TCPIP_CORE_LOCKING
797  struct netbuf buf;
798 #endif
799 
800  sock = get_socket(s);
801  if (!sock) {
802  return -1;
803  }
804 
805  if (sock->conn->type == NETCONN_TCP) {
806 #if LWIP_TCP
807  return lwip_send(s, data, size, flags);
808 #else /* LWIP_TCP */
809  LWIP_UNUSED_ARG(flags);
810  sock_set_errno(sock, err_to_errno(ERR_ARG));
811  return -1;
812 #endif /* LWIP_TCP */
813  }
814 
815  /* @todo: split into multiple sendto's? */
816  LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
817  short_size = (u16_t)size;
818  LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
819  ((tolen == sizeof(struct sockaddr_in)) &&
820  ((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))),
821  sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
822  to_in = (const struct sockaddr_in *)(void*)to;
823 
824 #if LWIP_TCPIP_CORE_LOCKING
825  /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
826  {
827  struct pbuf* p;
828  ip_addr_t *remote_addr;
829 
830 #if LWIP_NETIF_TX_SINGLE_PBUF
831  p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
832  if (p != NULL) {
833 #if LWIP_CHECKSUM_ON_COPY
834  u16_t chksum = 0;
835  if (sock->conn->type != NETCONN_RAW) {
836  chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
837  } else
838 #endif /* LWIP_CHECKSUM_ON_COPY */
839  MEMCPY(p->payload, data, size);
840 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
841  p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF);
842  if (p != NULL) {
843  p->payload = (void*)data;
844 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
845 
846  if (to_in != NULL) {
847  inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr);
848  remote_port = ntohs(to_in->sin_port);
849  } else {
850  remote_addr = IP_ADDR_ANY;
851  remote_port = 0;
852  }
853 
854  LOCK_TCPIP_CORE();
855  if (sock->conn->type == NETCONN_RAW) {
856  err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
857  } else {
858 #if LWIP_UDP
859 #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
860  err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
861  remote_addr, remote_port, 1, chksum);
862 #else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
863  err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
864  remote_addr, remote_port);
865 #endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
866 #else /* LWIP_UDP */
867  err = ERR_ARG;
868 #endif /* LWIP_UDP */
869  }
871 
872  pbuf_free(p);
873  } else {
874  err = ERR_MEM;
875  }
876  }
877 #else /* LWIP_TCPIP_CORE_LOCKING */
878  /* initialize a buffer */
879  buf.p = buf.ptr = NULL;
880 #if LWIP_CHECKSUM_ON_COPY
881  buf.flags = 0;
882 #endif /* LWIP_CHECKSUM_ON_COPY */
883  if (to) {
884  inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr);
885  remote_port = ntohs(to_in->sin_port);
886  netbuf_fromport(&buf) = remote_port;
887  } else {
888  remote_port = 0;
889  ip_addr_set_any(&buf.addr);
890  netbuf_fromport(&buf) = 0;
891  }
892 
893  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
894  s, data, short_size, flags));
896  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
897 
898  /* make the buffer point to the data that should be sent */
899 #if LWIP_NETIF_TX_SINGLE_PBUF
900  /* Allocate a new netbuf and copy the data into it. */
901  if (netbuf_alloc(&buf, short_size) == NULL) {
902  err = ERR_MEM;
903  } else {
904 #if LWIP_CHECKSUM_ON_COPY
905  if (sock->conn->type != NETCONN_RAW) {
906  u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
907  netbuf_set_chksum(&buf, chksum);
908  err = ERR_OK;
909  } else
910 #endif /* LWIP_CHECKSUM_ON_COPY */
911  {
912  err = netbuf_take(&buf, data, short_size);
913  }
914  }
915 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
916  err = netbuf_ref(&buf, data, short_size);
917 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
918  if (err == ERR_OK) {
919  /* send the data */
920  err = netconn_send(sock->conn, &buf);
921  }
922 
923  /* deallocated the buffer */
924  netbuf_free(&buf);
925 #endif /* LWIP_TCPIP_CORE_LOCKING */
926  sock_set_errno(sock, err_to_errno(err));
927  return (err == ERR_OK ? short_size : -1);
928 }
929 
930 int
931 lwip_socket(int domain, int type, int protocol)
932 {
933  struct netconn *conn;
934  int i;
935 
936  LWIP_UNUSED_ARG(domain);
937 
938  /* create a netconn */
939  switch (type) {
940  case SOCK_RAW:
941  conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
942  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
943  domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
944  break;
945  case SOCK_DGRAM:
946  conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
947  NETCONN_UDPLITE : NETCONN_UDP, event_callback);
948  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
949  domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
950  break;
951  case SOCK_STREAM:
952  conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
953  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
954  domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
955  if (conn != NULL) {
956  /* Prevent automatic window updates, we do this on our own! */
957  netconn_set_noautorecved(conn, 1);
958  }
959  break;
960  default:
961  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
962  domain, type, protocol));
963  set_errno(EINVAL);
964  return -1;
965  }
966 
967  if (!conn) {
968  LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
969  set_errno(ENOBUFS);
970  return -1;
971  }
972 
973  i = alloc_socket(conn, 0);
974 
975  if (i == -1) {
976  netconn_delete(conn);
977  set_errno(ENFILE);
978  return -1;
979  }
980  conn->socket = i;
981  LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
982  set_errno(0);
983  return i;
984 }
985 
986 int
987 lwip_write(int s, const void *data, size_t size)
988 {
989  return lwip_send(s, data, size, 0);
990 }
991 
1008 static int
1009 lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
1010  fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
1011 {
1012  int i, nready = 0;
1013  fd_set lreadset, lwriteset, lexceptset;
1014  struct lwip_sock *sock;
1015  SYS_ARCH_DECL_PROTECT(lev);
1016 
1017  FD_ZERO(&lreadset);
1018  FD_ZERO(&lwriteset);
1019  FD_ZERO(&lexceptset);
1020 
1021  /* Go through each socket in each list to count number of sockets which
1022  currently match */
1023  for(i = 0; i < maxfdp1; i++) {
1024  void* lastdata = NULL;
1025  s16_t rcvevent = 0;
1026  u16_t sendevent = 0;
1027  u16_t errevent = 0;
1028  /* First get the socket's status (protected)... */
1029  SYS_ARCH_PROTECT(lev);
1030  sock = tryget_socket(i);
1031  if (sock != NULL) {
1032  lastdata = sock->lastdata;
1033  rcvevent = sock->rcvevent;
1034  sendevent = sock->sendevent;
1035  errevent = sock->errevent;
1036  }
1037  SYS_ARCH_UNPROTECT(lev);
1038  /* ... then examine it: */
1039  /* See if netconn of this socket is ready for read */
1040  if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
1041  FD_SET(i, &lreadset);
1042  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
1043  nready++;
1044  }
1045  /* See if netconn of this socket is ready for write */
1046  if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
1047  FD_SET(i, &lwriteset);
1048  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
1049  nready++;
1050  }
1051  /* See if netconn of this socket had an error */
1052  if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
1053  FD_SET(i, &lexceptset);
1054  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
1055  nready++;
1056  }
1057  }
1058  /* copy local sets to the ones provided as arguments */
1059  *readset_out = lreadset;
1060  *writeset_out = lwriteset;
1061  *exceptset_out = lexceptset;
1062 
1063  LWIP_ASSERT("nready >= 0", nready >= 0);
1064  return nready;
1065 }
1066 
1070 int
1071 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
1072  struct timeval *timeout)
1073 {
1074  u32_t waitres = 0;
1075  int nready;
1076  fd_set lreadset, lwriteset, lexceptset;
1077  u32_t msectimeout;
1078  struct lwip_select_cb select_cb;
1079  err_t err;
1080  int i;
1081  SYS_ARCH_DECL_PROTECT(lev);
1082 
1083  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
1084  maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
1085  timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
1086  timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
1087 
1088  /* Go through each socket in each list to count number of sockets which
1089  currently match */
1090  nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1091 
1092  /* If we don't have any current events, then suspend if we are supposed to */
1093  if (!nready) {
1094  if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
1095  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
1096  /* This is OK as the local fdsets are empty and nready is zero,
1097  or we would have returned earlier. */
1098  goto return_copy_fdsets;
1099  }
1100 
1101  /* None ready: add our semaphore to list:
1102  We don't actually need any dynamic memory. Our entry on the
1103  list is only valid while we are in this function, so it's ok
1104  to use local variables. */
1105 
1106  select_cb.next = NULL;
1107  select_cb.prev = NULL;
1108  select_cb.readset = readset;
1109  select_cb.writeset = writeset;
1110  select_cb.exceptset = exceptset;
1111  select_cb.sem_signalled = 0;
1112  err = sys_sem_new(&select_cb.sem, 0);
1113  if (err != ERR_OK) {
1114  /* failed to create semaphore */
1115  set_errno(ENOMEM);
1116  return -1;
1117  }
1118 
1119  /* Protect the select_cb_list */
1120  SYS_ARCH_PROTECT(lev);
1121 
1122  /* Put this select_cb on top of list */
1123  select_cb.next = select_cb_list;
1124  if (select_cb_list != NULL) {
1125  select_cb_list->prev = &select_cb;
1126  }
1127  select_cb_list = &select_cb;
1128  /* Increasing this counter tells even_callback that the list has changed. */
1129  select_cb_ctr++;
1130 
1131  /* Now we can safely unprotect */
1132  SYS_ARCH_UNPROTECT(lev);
1133 
1134  /* Increase select_waiting for each socket we are interested in */
1135  for(i = 0; i < maxfdp1; i++) {
1136  if ((readset && FD_ISSET(i, readset)) ||
1137  (writeset && FD_ISSET(i, writeset)) ||
1138  (exceptset && FD_ISSET(i, exceptset))) {
1139  struct lwip_sock *sock = tryget_socket(i);
1140  LWIP_ASSERT("sock != NULL", sock != NULL);
1141  SYS_ARCH_PROTECT(lev);
1142  sock->select_waiting++;
1143  LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
1144  SYS_ARCH_UNPROTECT(lev);
1145  }
1146  }
1147 
1148  /* Call lwip_selscan again: there could have been events between
1149  the last scan (whithout us on the list) and putting us on the list! */
1150  nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1151  if (!nready) {
1152  /* Still none ready, just wait to be woken */
1153  if (timeout == 0) {
1154  /* Wait forever */
1155  msectimeout = 0;
1156  } else {
1157  msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
1158  if (msectimeout == 0) {
1159  /* Wait 1ms at least (0 means wait forever) */
1160  msectimeout = 1;
1161  }
1162  }
1163 
1164  waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout);
1165  }
1166  /* Increase select_waiting for each socket we are interested in */
1167  for(i = 0; i < maxfdp1; i++) {
1168  if ((readset && FD_ISSET(i, readset)) ||
1169  (writeset && FD_ISSET(i, writeset)) ||
1170  (exceptset && FD_ISSET(i, exceptset))) {
1171  struct lwip_sock *sock = tryget_socket(i);
1172  LWIP_ASSERT("sock != NULL", sock != NULL);
1173  SYS_ARCH_PROTECT(lev);
1174  sock->select_waiting--;
1175  LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0);
1176  SYS_ARCH_UNPROTECT(lev);
1177  }
1178  }
1179  /* Take us off the list */
1180  SYS_ARCH_PROTECT(lev);
1181  if (select_cb.next != NULL) {
1182  select_cb.next->prev = select_cb.prev;
1183  }
1184  if (select_cb_list == &select_cb) {
1185  LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
1186  select_cb_list = select_cb.next;
1187  } else {
1188  LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
1189  select_cb.prev->next = select_cb.next;
1190  }
1191  /* Increasing this counter tells even_callback that the list has changed. */
1192  select_cb_ctr++;
1193  SYS_ARCH_UNPROTECT(lev);
1194 
1195  sys_sem_free(&select_cb.sem);
1196  if (waitres == SYS_ARCH_TIMEOUT) {
1197  /* Timeout */
1198  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
1199  /* This is OK as the local fdsets are empty and nready is zero,
1200  or we would have returned earlier. */
1201  goto return_copy_fdsets;
1202  }
1203 
1204  /* See what's set */
1205  nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1206  }
1207 
1208  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
1209 return_copy_fdsets:
1210  set_errno(0);
1211  if (readset) {
1212  *readset = lreadset;
1213  }
1214  if (writeset) {
1215  *writeset = lwriteset;
1216  }
1217  if (exceptset) {
1218  *exceptset = lexceptset;
1219  }
1220 
1221 
1222  return nready;
1223 }
1224 
1229 static void
1230 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
1231 {
1232  int s;
1233  struct lwip_sock *sock;
1234  struct lwip_select_cb *scb;
1235  int last_select_cb_ctr;
1236  SYS_ARCH_DECL_PROTECT(lev);
1237 
1238  LWIP_UNUSED_ARG(len);
1239 
1240  /* Get socket */
1241  if (conn) {
1242  s = conn->socket;
1243  if (s < 0) {
1244  /* Data comes in right away after an accept, even though
1245  * the server task might not have created a new socket yet.
1246  * Just count down (or up) if that's the case and we
1247  * will use the data later. Note that only receive events
1248  * can happen before the new socket is set up. */
1249  SYS_ARCH_PROTECT(lev);
1250  if (conn->socket < 0) {
1251  if (evt == NETCONN_EVT_RCVPLUS) {
1252  conn->socket--;
1253  }
1254  SYS_ARCH_UNPROTECT(lev);
1255  return;
1256  }
1257  s = conn->socket;
1258  SYS_ARCH_UNPROTECT(lev);
1259  }
1260 
1261  sock = get_socket(s);
1262  if (!sock) {
1263  return;
1264  }
1265  } else {
1266  return;
1267  }
1268 
1269  SYS_ARCH_PROTECT(lev);
1270  /* Set event as required */
1271  switch (evt) {
1272  case NETCONN_EVT_RCVPLUS:
1273  sock->rcvevent++;
1274  break;
1275  case NETCONN_EVT_RCVMINUS:
1276  sock->rcvevent--;
1277  break;
1278  case NETCONN_EVT_SENDPLUS:
1279  sock->sendevent = 1;
1280  break;
1281  case NETCONN_EVT_SENDMINUS:
1282  sock->sendevent = 0;
1283  break;
1284  case NETCONN_EVT_ERROR:
1285  sock->errevent = 1;
1286  break;
1287  default:
1288  LWIP_ASSERT("unknown event", 0);
1289  break;
1290  }
1291 
1292  if (sock->select_waiting == 0) {
1293  /* noone is waiting for this socket, no need to check select_cb_list */
1294  SYS_ARCH_UNPROTECT(lev);
1295  return;
1296  }
1297 
1298  /* Now decide if anyone is waiting for this socket */
1299  /* NOTE: This code goes through the select_cb_list list multiple times
1300  ONLY IF a select was actually waiting. We go through the list the number
1301  of waiting select calls + 1. This list is expected to be small. */
1302 
1303  /* At this point, SYS_ARCH is still protected! */
1304 again:
1305  for (scb = select_cb_list; scb != NULL; scb = scb->next) {
1306  if (scb->sem_signalled == 0) {
1307  /* semaphore not signalled yet */
1308  int do_signal = 0;
1309  /* Test this select call for our socket */
1310  if (sock->rcvevent > 0) {
1311  if (scb->readset && FD_ISSET(s, scb->readset)) {
1312  do_signal = 1;
1313  }
1314  }
1315  if (sock->sendevent != 0) {
1316  if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
1317  do_signal = 1;
1318  }
1319  }
1320  if (sock->errevent != 0) {
1321  if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
1322  do_signal = 1;
1323  }
1324  }
1325  if (do_signal) {
1326  scb->sem_signalled = 1;
1327  /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
1328  lead to the select thread taking itself off the list, invalidagin the semaphore. */
1329  sys_sem_signal(&scb->sem);
1330  }
1331  }
1332  /* unlock interrupts with each step */
1333  last_select_cb_ctr = select_cb_ctr;
1334  SYS_ARCH_UNPROTECT(lev);
1335  /* this makes sure interrupt protection time is short */
1336  SYS_ARCH_PROTECT(lev);
1337  if (last_select_cb_ctr != select_cb_ctr) {
1338  /* someone has changed select_cb_list, restart at the beginning */
1339  goto again;
1340  }
1341  }
1342  SYS_ARCH_UNPROTECT(lev);
1343 }
1344 
1349 int
1350 lwip_shutdown(int s, int how)
1351 {
1352  struct lwip_sock *sock;
1353  err_t err;
1354  u8_t shut_rx = 0, shut_tx = 0;
1355 
1356  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
1357 
1358  sock = get_socket(s);
1359  if (!sock) {
1360  return -1;
1361  }
1362 
1363  if (sock->conn != NULL) {
1364  if (netconn_type(sock->conn) != NETCONN_TCP) {
1365  sock_set_errno(sock, EOPNOTSUPP);
1366  return EOPNOTSUPP;
1367  }
1368  } else {
1369  sock_set_errno(sock, ENOTCONN);
1370  return ENOTCONN;
1371  }
1372 
1373  if (how == SHUT_RD) {
1374  shut_rx = 1;
1375  } else if (how == SHUT_WR) {
1376  shut_tx = 1;
1377  } else if(how == SHUT_RDWR) {
1378  shut_rx = 1;
1379  shut_tx = 1;
1380  } else {
1381  sock_set_errno(sock, EINVAL);
1382  return EINVAL;
1383  }
1384  err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
1385 
1386  sock_set_errno(sock, err_to_errno(err));
1387  return (err == ERR_OK ? 0 : -1);
1388 }
1389 
1390 static int
1391 lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
1392 {
1393  struct lwip_sock *sock;
1394  struct sockaddr_in sin;
1395  ip_addr_t naddr;
1396 
1397  sock = get_socket(s);
1398  if (!sock) {
1399  return -1;
1400  }
1401 
1402  memset(&sin, 0, sizeof(sin));
1403  sin.sin_len = sizeof(sin);
1404  sin.sin_family = AF_INET;
1405 
1406  /* get the IP address and port */
1407  netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
1408 
1409  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
1411  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
1412 
1413  sin.sin_port = htons(sin.sin_port);
1414  inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
1415 
1416  if (*namelen > sizeof(sin)) {
1417  *namelen = sizeof(sin);
1418  }
1419 
1420  MEMCPY(name, &sin, *namelen);
1421  sock_set_errno(sock, 0);
1422  return 0;
1423 }
1424 
1425 int
1426 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
1427 {
1428  return lwip_getaddrname(s, name, namelen, 0);
1429 }
1430 
1431 int
1432 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
1433 {
1434  return lwip_getaddrname(s, name, namelen, 1);
1435 }
1436 
1437 int
1438 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1439 {
1440  err_t err = ERR_OK;
1441  struct lwip_sock *sock = get_socket(s);
1442  struct lwip_setgetsockopt_data data;
1443 
1444  if (!sock) {
1445  return -1;
1446  }
1447 
1448  if ((NULL == optval) || (NULL == optlen)) {
1449  sock_set_errno(sock, EFAULT);
1450  return -1;
1451  }
1452 
1453  /* Do length and type checks for the various options first, to keep it readable. */
1454  switch (level) {
1455 
1456 /* Level: SOL_SOCKET */
1457  case SOL_SOCKET:
1458  switch (optname) {
1459 
1460  case SO_ACCEPTCONN:
1461  case SO_BROADCAST:
1462  /* UNIMPL case SO_DEBUG: */
1463  /* UNIMPL case SO_DONTROUTE: */
1464  case SO_ERROR:
1465  case SO_KEEPALIVE:
1466  /* UNIMPL case SO_CONTIMEO: */
1467  /* UNIMPL case SO_SNDTIMEO: */
1468 #if LWIP_SO_RCVTIMEO
1469  case SO_RCVTIMEO:
1470 #endif /* LWIP_SO_RCVTIMEO */
1471 #if LWIP_SO_RCVBUF
1472  case SO_RCVBUF:
1473 #endif /* LWIP_SO_RCVBUF */
1474  /* UNIMPL case SO_OOBINLINE: */
1475  /* UNIMPL case SO_SNDBUF: */
1476  /* UNIMPL case SO_RCVLOWAT: */
1477  /* UNIMPL case SO_SNDLOWAT: */
1478 #if SO_REUSE
1479  case SO_REUSEADDR:
1480  case SO_REUSEPORT:
1481 #endif /* SO_REUSE */
1482  case SO_TYPE:
1483  /* UNIMPL case SO_USELOOPBACK: */
1484  if (*optlen < sizeof(int)) {
1485  err = EINVAL;
1486  }
1487  break;
1488 
1489  case SO_NO_CHECK:
1490  if (*optlen < sizeof(int)) {
1491  err = EINVAL;
1492  }
1493 #if LWIP_UDP
1494  if ((sock->conn->type != NETCONN_UDP) ||
1495  ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1496  /* this flag is only available for UDP, not for UDP lite */
1497  err = EAFNOSUPPORT;
1498  }
1499 #endif /* LWIP_UDP */
1500  break;
1501 
1502  default:
1503  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1504  s, optname));
1505  err = ENOPROTOOPT;
1506  } /* switch (optname) */
1507  break;
1508 
1509 /* Level: IPPROTO_IP */
1510  case IPPROTO_IP:
1511  switch (optname) {
1512  /* UNIMPL case IP_HDRINCL: */
1513  /* UNIMPL case IP_RCVDSTADDR: */
1514  /* UNIMPL case IP_RCVIF: */
1515  case IP_TTL:
1516  case IP_TOS:
1517  if (*optlen < sizeof(int)) {
1518  err = EINVAL;
1519  }
1520  break;
1521 #if LWIP_IGMP
1522  case IP_MULTICAST_TTL:
1523  if (*optlen < sizeof(u8_t)) {
1524  err = EINVAL;
1525  }
1526  break;
1527  case IP_MULTICAST_IF:
1528  if (*optlen < sizeof(struct in_addr)) {
1529  err = EINVAL;
1530  }
1531  break;
1532  case IP_MULTICAST_LOOP:
1533  if (*optlen < sizeof(u8_t)) {
1534  err = EINVAL;
1535  }
1536  if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1537  err = EAFNOSUPPORT;
1538  }
1539  break;
1540 #endif /* LWIP_IGMP */
1541 
1542  default:
1543  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1544  s, optname));
1545  err = ENOPROTOOPT;
1546  } /* switch (optname) */
1547  break;
1548 
1549 #if LWIP_TCP
1550 /* Level: IPPROTO_TCP */
1551  case IPPROTO_TCP:
1552  if (*optlen < sizeof(int)) {
1553  err = EINVAL;
1554  break;
1555  }
1556 
1557  /* If this is no TCP socket, ignore any options. */
1558  if (sock->conn->type != NETCONN_TCP)
1559  return 0;
1560 
1561  switch (optname) {
1562  case TCP_NODELAY:
1563  case TCP_KEEPALIVE:
1564 #if LWIP_TCP_KEEPALIVE
1565  case TCP_KEEPIDLE:
1566  case TCP_KEEPINTVL:
1567  case TCP_KEEPCNT:
1568 #endif /* LWIP_TCP_KEEPALIVE */
1569  break;
1570 
1571  default:
1572  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1573  s, optname));
1574  err = ENOPROTOOPT;
1575  } /* switch (optname) */
1576  break;
1577 #endif /* LWIP_TCP */
1578 #if LWIP_UDP && LWIP_UDPLITE
1579 /* Level: IPPROTO_UDPLITE */
1580  case IPPROTO_UDPLITE:
1581  if (*optlen < sizeof(int)) {
1582  err = EINVAL;
1583  break;
1584  }
1585 
1586  /* If this is no UDP lite socket, ignore any options. */
1587  if (sock->conn->type != NETCONN_UDPLITE) {
1588  return 0;
1589  }
1590 
1591  switch (optname) {
1592  case UDPLITE_SEND_CSCOV:
1593  case UDPLITE_RECV_CSCOV:
1594  break;
1595 
1596  default:
1597  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
1598  s, optname));
1599  err = ENOPROTOOPT;
1600  } /* switch (optname) */
1601  break;
1602 #endif /* LWIP_UDP && LWIP_UDPLITE*/
1603 /* UNDEFINED LEVEL */
1604  default:
1605  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
1606  s, level, optname));
1607  err = ENOPROTOOPT;
1608  } /* switch */
1609 
1610 
1611  if (err != ERR_OK) {
1612  sock_set_errno(sock, err);
1613  return -1;
1614  }
1615 
1616  /* Now do the actual option processing */
1617  data.sock = sock;
1618 #ifdef LWIP_DEBUG
1619  data.s = s;
1620 #endif /* LWIP_DEBUG */
1621  data.level = level;
1622  data.optname = optname;
1623  data.optval = optval;
1624  data.optlen = optlen;
1625  data.err = err;
1626  tcpip_callback(lwip_getsockopt_internal, &data);
1627  sys_arch_sem_wait(&sock->conn->op_completed, 0);
1628  /* maybe lwip_getsockopt_internal has changed err */
1629  err = data.err;
1630 
1631  sock_set_errno(sock, err);
1632  return err ? -1 : 0;
1633 }
1634 
1635 static void
1636 lwip_getsockopt_internal(void *arg)
1637 {
1638  struct lwip_sock *sock;
1639 #ifdef LWIP_DEBUG
1640  int s;
1641 #endif /* LWIP_DEBUG */
1642  int level, optname;
1643  void *optval;
1644  struct lwip_setgetsockopt_data *data;
1645 
1646  LWIP_ASSERT("arg != NULL", arg != NULL);
1647 
1648  data = (struct lwip_setgetsockopt_data*)arg;
1649  sock = data->sock;
1650 #ifdef LWIP_DEBUG
1651  s = data->s;
1652 #endif /* LWIP_DEBUG */
1653  level = data->level;
1654  optname = data->optname;
1655  optval = data->optval;
1656 
1657  switch (level) {
1658 
1659 /* Level: SOL_SOCKET */
1660  case SOL_SOCKET:
1661  switch (optname) {
1662 
1663  /* The option flags */
1664  case SO_ACCEPTCONN:
1665  case SO_BROADCAST:
1666  /* UNIMPL case SO_DEBUG: */
1667  /* UNIMPL case SO_DONTROUTE: */
1668  case SO_KEEPALIVE:
1669  /* UNIMPL case SO_OOBINCLUDE: */
1670 #if SO_REUSE
1671  case SO_REUSEADDR:
1672  case SO_REUSEPORT:
1673 #endif /* SO_REUSE */
1674  /*case SO_USELOOPBACK: UNIMPL */
1675  *(int*)optval = sock->conn->pcb.ip->so_options & optname;
1676  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
1677  s, optname, (*(int*)optval?"on":"off")));
1678  break;
1679 
1680  case SO_TYPE:
1681  switch (NETCONNTYPE_GROUP(sock->conn->type)) {
1682  case NETCONN_RAW:
1683  *(int*)optval = SOCK_RAW;
1684  break;
1685  case NETCONN_TCP:
1686  *(int*)optval = SOCK_STREAM;
1687  break;
1688  case NETCONN_UDP:
1689  *(int*)optval = SOCK_DGRAM;
1690  break;
1691  default: /* unrecognized socket type */
1692  *(int*)optval = sock->conn->type;
1694  ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
1695  s, *(int *)optval));
1696  } /* switch (sock->conn->type) */
1697  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
1698  s, *(int *)optval));
1699  break;
1700 
1701  case SO_ERROR:
1702  /* only overwrite ERR_OK or tempoary errors */
1703  if ((sock->err == 0) || (sock->err == EINPROGRESS)) {
1704  sock_set_errno(sock, err_to_errno(sock->conn->last_err));
1705  }
1706  *(int *)optval = sock->err;
1707  sock->err = 0;
1708  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
1709  s, *(int *)optval));
1710  break;
1711 
1712 #if LWIP_SO_RCVTIMEO
1713  case SO_RCVTIMEO:
1714  *(int *)optval = netconn_get_recvtimeout(sock->conn);
1715  break;
1716 #endif /* LWIP_SO_RCVTIMEO */
1717 #if LWIP_SO_RCVBUF
1718  case SO_RCVBUF:
1719  *(int *)optval = netconn_get_recvbufsize(sock->conn);
1720  break;
1721 #endif /* LWIP_SO_RCVBUF */
1722 #if LWIP_UDP
1723  case SO_NO_CHECK:
1724  *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
1725  break;
1726 #endif /* LWIP_UDP*/
1727  default:
1728  LWIP_ASSERT("unhandled optname", 0);
1729  break;
1730  } /* switch (optname) */
1731  break;
1732 
1733 /* Level: IPPROTO_IP */
1734  case IPPROTO_IP:
1735  switch (optname) {
1736  case IP_TTL:
1737  *(int*)optval = sock->conn->pcb.ip->ttl;
1738  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
1739  s, *(int *)optval));
1740  break;
1741  case IP_TOS:
1742  *(int*)optval = sock->conn->pcb.ip->tos;
1743  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
1744  s, *(int *)optval));
1745  break;
1746 #if LWIP_IGMP
1747  case IP_MULTICAST_TTL:
1748  *(u8_t*)optval = sock->conn->pcb.ip->ttl;
1749  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
1750  s, *(int *)optval));
1751  break;
1752  case IP_MULTICAST_IF:
1753  inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip);
1754  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
1755  s, *(u32_t *)optval));
1756  break;
1757  case IP_MULTICAST_LOOP:
1758  if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
1759  *(u8_t*)optval = 1;
1760  } else {
1761  *(u8_t*)optval = 0;
1762  }
1763  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
1764  s, *(int *)optval));
1765  break;
1766 #endif /* LWIP_IGMP */
1767  default:
1768  LWIP_ASSERT("unhandled optname", 0);
1769  break;
1770  } /* switch (optname) */
1771  break;
1772 
1773 #if LWIP_TCP
1774 /* Level: IPPROTO_TCP */
1775  case IPPROTO_TCP:
1776  switch (optname) {
1777  case TCP_NODELAY:
1778  *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
1779  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
1780  s, (*(int*)optval)?"on":"off") );
1781  break;
1782  case TCP_KEEPALIVE:
1783  *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
1784  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
1785  s, *(int *)optval));
1786  break;
1787 
1788 #if LWIP_TCP_KEEPALIVE
1789  case TCP_KEEPIDLE:
1790  *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
1791  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
1792  s, *(int *)optval));
1793  break;
1794  case TCP_KEEPINTVL:
1795  *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
1796  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
1797  s, *(int *)optval));
1798  break;
1799  case TCP_KEEPCNT:
1800  *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
1801  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
1802  s, *(int *)optval));
1803  break;
1804 #endif /* LWIP_TCP_KEEPALIVE */
1805  default:
1806  LWIP_ASSERT("unhandled optname", 0);
1807  break;
1808  } /* switch (optname) */
1809  break;
1810 #endif /* LWIP_TCP */
1811 #if LWIP_UDP && LWIP_UDPLITE
1812  /* Level: IPPROTO_UDPLITE */
1813  case IPPROTO_UDPLITE:
1814  switch (optname) {
1815  case UDPLITE_SEND_CSCOV:
1816  *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
1817  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
1818  s, (*(int*)optval)) );
1819  break;
1820  case UDPLITE_RECV_CSCOV:
1821  *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
1822  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
1823  s, (*(int*)optval)) );
1824  break;
1825  default:
1826  LWIP_ASSERT("unhandled optname", 0);
1827  break;
1828  } /* switch (optname) */
1829  break;
1830 #endif /* LWIP_UDP */
1831  default:
1832  LWIP_ASSERT("unhandled level", 0);
1833  break;
1834  } /* switch (level) */
1835  sys_sem_signal(&sock->conn->op_completed);
1836 }
1837 
1838 int
1839 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1840 {
1841  struct lwip_sock *sock = get_socket(s);
1842  err_t err = ERR_OK;
1843  struct lwip_setgetsockopt_data data;
1844 
1845  if (!sock) {
1846  return -1;
1847  }
1848 
1849  if (NULL == optval) {
1850  sock_set_errno(sock, EFAULT);
1851  return -1;
1852  }
1853 
1854  /* Do length and type checks for the various options first, to keep it readable. */
1855  switch (level) {
1856 
1857 /* Level: SOL_SOCKET */
1858  case SOL_SOCKET:
1859  switch (optname) {
1860 
1861  case SO_BROADCAST:
1862  /* UNIMPL case SO_DEBUG: */
1863  /* UNIMPL case SO_DONTROUTE: */
1864  case SO_KEEPALIVE:
1865  /* UNIMPL case case SO_CONTIMEO: */
1866  /* UNIMPL case case SO_SNDTIMEO: */
1867 #if LWIP_SO_RCVTIMEO
1868  case SO_RCVTIMEO:
1869 #endif /* LWIP_SO_RCVTIMEO */
1870 #if LWIP_SO_RCVBUF
1871  case SO_RCVBUF:
1872 #endif /* LWIP_SO_RCVBUF */
1873  /* UNIMPL case SO_OOBINLINE: */
1874  /* UNIMPL case SO_SNDBUF: */
1875  /* UNIMPL case SO_RCVLOWAT: */
1876  /* UNIMPL case SO_SNDLOWAT: */
1877 #if SO_REUSE
1878  case SO_REUSEADDR:
1879  case SO_REUSEPORT:
1880 #endif /* SO_REUSE */
1881  /* UNIMPL case SO_USELOOPBACK: */
1882  if (optlen < sizeof(int)) {
1883  err = EINVAL;
1884  }
1885  break;
1886  case SO_NO_CHECK:
1887  if (optlen < sizeof(int)) {
1888  err = EINVAL;
1889  }
1890 #if LWIP_UDP
1891  if ((sock->conn->type != NETCONN_UDP) ||
1892  ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1893  /* this flag is only available for UDP, not for UDP lite */
1894  err = EAFNOSUPPORT;
1895  }
1896 #endif /* LWIP_UDP */
1897  break;
1898  default:
1899  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1900  s, optname));
1901  err = ENOPROTOOPT;
1902  } /* switch (optname) */
1903  break;
1904 
1905 /* Level: IPPROTO_IP */
1906  case IPPROTO_IP:
1907  switch (optname) {
1908  /* UNIMPL case IP_HDRINCL: */
1909  /* UNIMPL case IP_RCVDSTADDR: */
1910  /* UNIMPL case IP_RCVIF: */
1911  case IP_TTL:
1912  case IP_TOS:
1913  if (optlen < sizeof(int)) {
1914  err = EINVAL;
1915  }
1916  break;
1917 #if LWIP_IGMP
1918  case IP_MULTICAST_TTL:
1919  if (optlen < sizeof(u8_t)) {
1920  err = EINVAL;
1921  }
1922  if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1923  err = EAFNOSUPPORT;
1924  }
1925  break;
1926  case IP_MULTICAST_IF:
1927  if (optlen < sizeof(struct in_addr)) {
1928  err = EINVAL;
1929  }
1930  if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1931  err = EAFNOSUPPORT;
1932  }
1933  break;
1934  case IP_MULTICAST_LOOP:
1935  if (optlen < sizeof(u8_t)) {
1936  err = EINVAL;
1937  }
1938  if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1939  err = EAFNOSUPPORT;
1940  }
1941  break;
1942  case IP_ADD_MEMBERSHIP:
1943  case IP_DROP_MEMBERSHIP:
1944  if (optlen < sizeof(struct ip_mreq)) {
1945  err = EINVAL;
1946  }
1947  if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1948  err = EAFNOSUPPORT;
1949  }
1950  break;
1951 #endif /* LWIP_IGMP */
1952  default:
1953  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1954  s, optname));
1955  err = ENOPROTOOPT;
1956  } /* switch (optname) */
1957  break;
1958 
1959 #if LWIP_TCP
1960 /* Level: IPPROTO_TCP */
1961  case IPPROTO_TCP:
1962  if (optlen < sizeof(int)) {
1963  err = EINVAL;
1964  break;
1965  }
1966 
1967  /* If this is no TCP socket, ignore any options. */
1968  if (sock->conn->type != NETCONN_TCP)
1969  return 0;
1970 
1971  switch (optname) {
1972  case TCP_NODELAY:
1973  case TCP_KEEPALIVE:
1974 #if LWIP_TCP_KEEPALIVE
1975  case TCP_KEEPIDLE:
1976  case TCP_KEEPINTVL:
1977  case TCP_KEEPCNT:
1978 #endif /* LWIP_TCP_KEEPALIVE */
1979  break;
1980 
1981  default:
1982  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1983  s, optname));
1984  err = ENOPROTOOPT;
1985  } /* switch (optname) */
1986  break;
1987 #endif /* LWIP_TCP */
1988 #if LWIP_UDP && LWIP_UDPLITE
1989 /* Level: IPPROTO_UDPLITE */
1990  case IPPROTO_UDPLITE:
1991  if (optlen < sizeof(int)) {
1992  err = EINVAL;
1993  break;
1994  }
1995 
1996  /* If this is no UDP lite socket, ignore any options. */
1997  if (sock->conn->type != NETCONN_UDPLITE)
1998  return 0;
1999 
2000  switch (optname) {
2001  case UDPLITE_SEND_CSCOV:
2002  case UDPLITE_RECV_CSCOV:
2003  break;
2004 
2005  default:
2006  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
2007  s, optname));
2008  err = ENOPROTOOPT;
2009  } /* switch (optname) */
2010  break;
2011 #endif /* LWIP_UDP && LWIP_UDPLITE */
2012 /* UNDEFINED LEVEL */
2013  default:
2014  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
2015  s, level, optname));
2016  err = ENOPROTOOPT;
2017  } /* switch (level) */
2018 
2019 
2020  if (err != ERR_OK) {
2021  sock_set_errno(sock, err);
2022  return -1;
2023  }
2024 
2025 
2026  /* Now do the actual option processing */
2027  data.sock = sock;
2028 #ifdef LWIP_DEBUG
2029  data.s = s;
2030 #endif /* LWIP_DEBUG */
2031  data.level = level;
2032  data.optname = optname;
2033  data.optval = (void*)optval;
2034  data.optlen = &optlen;
2035  data.err = err;
2036  tcpip_callback(lwip_setsockopt_internal, &data);
2037  sys_arch_sem_wait(&sock->conn->op_completed, 0);
2038  /* maybe lwip_setsockopt_internal has changed err */
2039  err = data.err;
2040 
2041  sock_set_errno(sock, err);
2042  return err ? -1 : 0;
2043 }
2044 
2045 static void
2046 lwip_setsockopt_internal(void *arg)
2047 {
2048  struct lwip_sock *sock;
2049 #ifdef LWIP_DEBUG
2050  int s;
2051 #endif /* LWIP_DEBUG */
2052  int level, optname;
2053  const void *optval;
2054  struct lwip_setgetsockopt_data *data;
2055 
2056  LWIP_ASSERT("arg != NULL", arg != NULL);
2057 
2058  data = (struct lwip_setgetsockopt_data*)arg;
2059  sock = data->sock;
2060 #ifdef LWIP_DEBUG
2061  s = data->s;
2062 #endif /* LWIP_DEBUG */
2063  level = data->level;
2064  optname = data->optname;
2065  optval = data->optval;
2066 
2067  switch (level) {
2068 
2069 /* Level: SOL_SOCKET */
2070  case SOL_SOCKET:
2071  switch (optname) {
2072 
2073  /* The option flags */
2074  case SO_BROADCAST:
2075  /* UNIMPL case SO_DEBUG: */
2076  /* UNIMPL case SO_DONTROUTE: */
2077  case SO_KEEPALIVE:
2078  /* UNIMPL case SO_OOBINCLUDE: */
2079 #if SO_REUSE
2080  case SO_REUSEADDR:
2081  case SO_REUSEPORT:
2082 #endif /* SO_REUSE */
2083  /* UNIMPL case SO_USELOOPBACK: */
2084  if (*(int*)optval) {
2085  sock->conn->pcb.ip->so_options |= optname;
2086  } else {
2087  sock->conn->pcb.ip->so_options &= ~optname;
2088  }
2089  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
2090  s, optname, (*(int*)optval?"on":"off")));
2091  break;
2092 #if LWIP_SO_RCVTIMEO
2093  case SO_RCVTIMEO:
2094  netconn_set_recvtimeout(sock->conn, *(int*)optval);
2095  break;
2096 #endif /* LWIP_SO_RCVTIMEO */
2097 #if LWIP_SO_RCVBUF
2098  case SO_RCVBUF:
2099  netconn_set_recvbufsize(sock->conn, *(int*)optval);
2100  break;
2101 #endif /* LWIP_SO_RCVBUF */
2102 #if LWIP_UDP
2103  case SO_NO_CHECK:
2104  if (*(int*)optval) {
2105  udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
2106  } else {
2107  udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
2108  }
2109  break;
2110 #endif /* LWIP_UDP */
2111  default:
2112  LWIP_ASSERT("unhandled optname", 0);
2113  break;
2114  } /* switch (optname) */
2115  break;
2116 
2117 /* Level: IPPROTO_IP */
2118  case IPPROTO_IP:
2119  switch (optname) {
2120  case IP_TTL:
2121  sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
2122  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
2123  s, sock->conn->pcb.ip->ttl));
2124  break;
2125  case IP_TOS:
2126  sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
2127  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
2128  s, sock->conn->pcb.ip->tos));
2129  break;
2130 #if LWIP_IGMP
2131  case IP_MULTICAST_TTL:
2132  sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
2133  break;
2134  case IP_MULTICAST_IF:
2135  inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval);
2136  break;
2137  case IP_MULTICAST_LOOP:
2138  if (*(u8_t*)optval) {
2139  udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
2140  } else {
2141  udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
2142  }
2143  break;
2144  case IP_ADD_MEMBERSHIP:
2145  case IP_DROP_MEMBERSHIP:
2146  {
2147  /* If this is a TCP or a RAW socket, ignore these options. */
2148  struct ip_mreq *imr = (struct ip_mreq *)optval;
2149  ip_addr_t if_addr;
2150  ip_addr_t multi_addr;
2151  inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
2152  inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
2153  if(optname == IP_ADD_MEMBERSHIP){
2154  data->err = igmp_joingroup(&if_addr, &multi_addr);
2155  } else {
2156  data->err = igmp_leavegroup(&if_addr, &multi_addr);
2157  }
2158  if(data->err != ERR_OK) {
2159  data->err = EADDRNOTAVAIL;
2160  }
2161  }
2162  break;
2163 #endif /* LWIP_IGMP */
2164  default:
2165  LWIP_ASSERT("unhandled optname", 0);
2166  break;
2167  } /* switch (optname) */
2168  break;
2169 
2170 #if LWIP_TCP
2171 /* Level: IPPROTO_TCP */
2172  case IPPROTO_TCP:
2173  switch (optname) {
2174  case TCP_NODELAY:
2175  if (*(int*)optval) {
2176  tcp_nagle_disable(sock->conn->pcb.tcp);
2177  } else {
2178  tcp_nagle_enable(sock->conn->pcb.tcp);
2179  }
2180  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
2181  s, (*(int *)optval)?"on":"off") );
2182  break;
2183  case TCP_KEEPALIVE:
2184  sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
2185  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
2186  s, sock->conn->pcb.tcp->keep_idle));
2187  break;
2188 
2189 #if LWIP_TCP_KEEPALIVE
2190  case TCP_KEEPIDLE:
2191  sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
2192  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
2193  s, sock->conn->pcb.tcp->keep_idle));
2194  break;
2195  case TCP_KEEPINTVL:
2196  sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
2197  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
2198  s, sock->conn->pcb.tcp->keep_intvl));
2199  break;
2200  case TCP_KEEPCNT:
2201  sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
2202  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
2203  s, sock->conn->pcb.tcp->keep_cnt));
2204  break;
2205 #endif /* LWIP_TCP_KEEPALIVE */
2206  default:
2207  LWIP_ASSERT("unhandled optname", 0);
2208  break;
2209  } /* switch (optname) */
2210  break;
2211 #endif /* LWIP_TCP*/
2212 #if LWIP_UDP && LWIP_UDPLITE
2213  /* Level: IPPROTO_UDPLITE */
2214  case IPPROTO_UDPLITE:
2215  switch (optname) {
2216  case UDPLITE_SEND_CSCOV:
2217  if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
2218  /* don't allow illegal values! */
2219  sock->conn->pcb.udp->chksum_len_tx = 8;
2220  } else {
2221  sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval;
2222  }
2223  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
2224  s, (*(int*)optval)) );
2225  break;
2226  case UDPLITE_RECV_CSCOV:
2227  if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
2228  /* don't allow illegal values! */
2229  sock->conn->pcb.udp->chksum_len_rx = 8;
2230  } else {
2231  sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval;
2232  }
2233  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
2234  s, (*(int*)optval)) );
2235  break;
2236  default:
2237  LWIP_ASSERT("unhandled optname", 0);
2238  break;
2239  } /* switch (optname) */
2240  break;
2241 #endif /* LWIP_UDP */
2242  default:
2243  LWIP_ASSERT("unhandled level", 0);
2244  break;
2245  } /* switch (level) */
2246  sys_sem_signal(&sock->conn->op_completed);
2247 }
2248 
2249 int
2250 lwip_ioctl(int s, long cmd, void *argp)
2251 {
2252  struct lwip_sock *sock = get_socket(s);
2253  u8_t val;
2254 #if LWIP_SO_RCVBUF
2255  u16_t buflen = 0;
2256  s16_t recv_avail;
2257 #endif /* LWIP_SO_RCVBUF */
2258 
2259  if (!sock) {
2260  return -1;
2261  }
2262 
2263  switch (cmd) {
2264 #if LWIP_SO_RCVBUF
2265  case FIONREAD:
2266  if (!argp) {
2267  sock_set_errno(sock, EINVAL);
2268  return -1;
2269  }
2270 
2271  SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
2272  if (recv_avail < 0) {
2273  recv_avail = 0;
2274  }
2275  *((u16_t*)argp) = (u16_t)recv_avail;
2276 
2277  /* Check if there is data left from the last recv operation. /maq 041215 */
2278  if (sock->lastdata) {
2279  struct pbuf *p = (struct pbuf *)sock->lastdata;
2280  if (netconn_type(sock->conn) != NETCONN_TCP) {
2281  p = ((struct netbuf *)p)->p;
2282  }
2283  buflen = p->tot_len;
2284  buflen -= sock->lastoffset;
2285 
2286  *((u16_t*)argp) += buflen;
2287  }
2288 
2289  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
2290  sock_set_errno(sock, 0);
2291  return 0;
2292 #endif /* LWIP_SO_RCVBUF */
2293 
2294  case FIONBIO:
2295  val = 0;
2296  if (argp && *(u32_t*)argp) {
2297  val = 1;
2298  }
2299  netconn_set_nonblocking(sock->conn, val);
2300  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
2301  sock_set_errno(sock, 0);
2302  return 0;
2303 
2304  default:
2305  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
2306  sock_set_errno(sock, ENOSYS); /* not yet implemented */
2307  return -1;
2308  } /* switch (cmd) */
2309 }
2310 
2315 int
2316 lwip_fcntl(int s, int cmd, int val)
2317 {
2318  struct lwip_sock *sock = get_socket(s);
2319  int ret = -1;
2320 
2321  if (!sock || !sock->conn) {
2322  return -1;
2323  }
2324 
2325  switch (cmd) {
2326  case F_GETFL:
2327  ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
2328  break;
2329  case F_SETFL:
2330  if ((val & ~O_NONBLOCK) == 0) {
2331  /* only O_NONBLOCK, all other bits are zero */
2332  netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
2333  ret = 0;
2334  }
2335  break;
2336  default:
2337  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
2338  break;
2339  }
2340  return ret;
2341 }
2342 
2343 #endif /* LWIP_SOCKET */