1 /** 2 * @file 3 * Sockets BSD-Like API module 4 * 5 */ 6 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 (at) sics.se> 36 * 37 * Improved by Marc Boucher <marc (at) mbsi.ca> and David Haas <dhaas (at) 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 63 /** Contains all internal pointers and states used for a socket */ 64 struct lwip_sock { 65 /** sockets currently are built on netconns, each socket has one netconn */ 66 struct netconn *conn; 67 /** data that was left from the previous read */ 68 void *lastdata; 69 /** offset in the data that was left from the previous read */ 70 u16_t lastoffset; 71 /** number of times data was received, set by event_callback(), 72 tested by the receive and select functions */ 73 s16_t rcvevent; 74 /** number of times data was ACKed (free send buffer), set by event_callback(), 75 tested by select */ 76 u16_t sendevent; 77 /** error happened for this socket, set by event_callback(), tested by select */ 78 u16_t errevent; 79 /** last error that occurred on this socket */ 80 int err; 81 /** counter of how many threads are waiting for this socket using select */ 82 int select_waiting; 83 }; 84 85 /** Description for a task waiting in select */ 86 struct lwip_select_cb { 87 /** Pointer to the next waiting task */ 88 struct lwip_select_cb *next; 89 /** Pointer to the previous waiting task */ 90 struct lwip_select_cb *prev; 91 /** readset passed to select */ 92 fd_set *readset; 93 /** writeset passed to select */ 94 fd_set *writeset; 95 /** unimplemented: exceptset passed to select */ 96 fd_set *exceptset; 97 /** don't signal the same semaphore twice: set to 1 when signalled */ 98 int sem_signalled; 99 /** semaphore to wake up a task waiting for select */ 100 sys_sem_t sem; 101 }; 102 103 /** This struct is used to pass data to the set/getsockopt_internal 104 * functions running in tcpip_thread context (only a void* is allowed) */ 105 struct lwip_setgetsockopt_data { 106 /** socket struct for which to change options */ 107 struct lwip_sock *sock; 108 #ifdef LWIP_DEBUG 109 /** socket index for which to change options */ 110 int s; 111 #endif /* LWIP_DEBUG */ 112 /** level of the option to process */ 113 int level; 114 /** name of the option to process */ 115 int optname; 116 /** set: value to set the option to 117 * get: value of the option is stored here */ 118 void *optval; 119 /** size of *optval */ 120 socklen_t *optlen; 121 /** if an error occures, it is temporarily stored here */ 122 err_t err; 123 }; 124 125 /** The global array of available sockets */ 126 static struct lwip_sock sockets[NUM_SOCKETS]; 127 /** The global list of tasks waiting for select */ 128 static struct lwip_select_cb *select_cb_list; 129 /** This counter is increased from lwip_select when the list is chagned 130 and checked in event_callback to see if it has changed. */ 131 static volatile int select_cb_ctr; 132 133 /** Table to quickly map an lwIP error (err_t) to a socket error 134 * by using -err as an index */ 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 EADDRINUSE, /* ERR_USE -8 Address in use. */ 145 EALREADY, /* ERR_ISCONN -9 Already connected. */ 146 ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ 147 ECONNRESET, /* ERR_RST -11 Connection reset. */ 148 ENOTCONN, /* ERR_CLSD -12 Connection closed. */ 149 ENOTCONN, /* ERR_CONN -13 Not connected. */ 150 EIO, /* ERR_ARG -14 Illegal argument. */ 151 -1, /* ERR_IF -15 Low-level netif error */ 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 179 /** 180 * Initialize this module. This function has to be called before any other 181 * functions in this module! 182 */ 183 void 184 lwip_socket_init(void) 185 { 186 } 187 188 /** 189 * Map a externally used socket index to the internal socket representation. 190 * 191 * @param s externally used socket index 192 * @return struct lwip_sock for the socket or NULL if not found 193 */ 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 216 /** 217 * Same as get_socket but doesn't set errno 218 * 219 * @param s externally used socket index 220 * @return struct lwip_sock for the socket or NULL if not found 221 */ 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 234 /** 235 * Allocate a new socket for a given netconn. 236 * 237 * @param newconn the netconn for which to allocate a socket 238 * @param accepted 1 if socket has been created by accept(), 239 * 0 if socket has been created by socket() 240 * @return the index of the new socket; -1 on error 241 */ 242 static int 243 alloc_socket(struct netconn *newconn, int accepted) 244 { 245 int i; 246 SYS_ARCH_DECL_PROTECT(lev); 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 273 /** Free a socket. The socket's netconn must have been 274 * delete before! 275 * 276 * @param sock the socket to free 277 * @param is_tcp != 0 for TCP sockets, used to free lastdata 278 */ 279 static void 280 free_socket(struct lwip_sock *sock, int is_tcp) 281 { 282 void *lastdata; 283 SYS_ARCH_DECL_PROTECT(lev); 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; 321 SYS_ARCH_DECL_PROTECT(lev); 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)); 393 ip_addr_debug_print(SOCKETS_DEBUG, &naddr); 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 512 /** 513 * Set a socket into listen mode. 514 * The socket may not have been used for another connection previously. 515 * 516 * @param s the socket to set to listening mode 517 * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) 518 * @return 0 on success, non-zero on failure 519 */ 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)); 684 ip_addr_debug_print(SOCKETS_DEBUG, addr); 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)); 697 ip_addr_debug_print(SOCKETS_DEBUG, addr); 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 = &sock->conn->pcb.raw->remote_ip; 851 if (sock->conn->type == NETCONN_RAW) { 852 remote_port = 0; 853 } else { 854 remote_port = sock->conn->pcb.udp->remote_port; 855 } 856 } 857 858 LOCK_TCPIP_CORE(); 859 if (sock->conn->type == NETCONN_RAW) { 860 err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr); 861 } else { 862 #if LWIP_UDP 863 #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF 864 err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p, 865 remote_addr, remote_port, 1, chksum); 866 #else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ 867 err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p, 868 remote_addr, remote_port); 869 #endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ 870 #else /* LWIP_UDP */ 871 err = ERR_ARG; 872 #endif /* LWIP_UDP */ 873 } 874 UNLOCK_TCPIP_CORE(); 875 876 pbuf_free(p); 877 } else { 878 err = ERR_MEM; 879 } 880 } 881 #else /* LWIP_TCPIP_CORE_LOCKING */ 882 /* initialize a buffer */ 883 buf.p = buf.ptr = NULL; 884 #if LWIP_CHECKSUM_ON_COPY 885 buf.flags = 0; 886 #endif /* LWIP_CHECKSUM_ON_COPY */ 887 if (to) { 888 inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr); 889 remote_port = ntohs(to_in->sin_port); 890 netbuf_fromport(&buf) = remote_port; 891 } else { 892 remote_port = 0; 893 ip_addr_set_any(&buf.addr); 894 netbuf_fromport(&buf) = 0; 895 } 896 897 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", 898 s, data, short_size, flags)); 899 ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); 900 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); 901 902 /* make the buffer point to the data that should be sent */ 903 #if LWIP_NETIF_TX_SINGLE_PBUF 904 /* Allocate a new netbuf and copy the data into it. */ 905 if (netbuf_alloc(&buf, short_size) == NULL) { 906 err = ERR_MEM; 907 } else { 908 #if LWIP_CHECKSUM_ON_COPY 909 if (sock->conn->type != NETCONN_RAW) { 910 u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); 911 netbuf_set_chksum(&buf, chksum); 912 err = ERR_OK; 913 } else 914 #endif /* LWIP_CHECKSUM_ON_COPY */ 915 { 916 err = netbuf_take(&buf, data, short_size); 917 } 918 } 919 #else /* LWIP_NETIF_TX_SINGLE_PBUF */ 920 err = netbuf_ref(&buf, data, short_size); 921 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */ 922 if (err == ERR_OK) { 923 /* send the data */ 924 err = netconn_send(sock->conn, &buf); 925 } 926 927 /* deallocated the buffer */ 928 netbuf_free(&buf); 929 #endif /* LWIP_TCPIP_CORE_LOCKING */ 930 sock_set_errno(sock, err_to_errno(err)); 931 return (err == ERR_OK ? short_size : -1); 932 } 933 934 int 935 lwip_socket(int domain, int type, int protocol) 936 { 937 struct netconn *conn; 938 int i; 939 940 LWIP_UNUSED_ARG(domain); 941 942 /* create a netconn */ 943 switch (type) { 944 case SOCK_RAW: 945 conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback); 946 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", 947 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); 948 break; 949 case SOCK_DGRAM: 950 conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ? 951 NETCONN_UDPLITE : NETCONN_UDP, event_callback); 952 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", 953 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); 954 break; 955 case SOCK_STREAM: 956 conn = netconn_new_with_callback(NETCONN_TCP, event_callback); 957 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", 958 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); 959 if (conn != NULL) { 960 /* Prevent automatic window updates, we do this on our own! */ 961 netconn_set_noautorecved(conn, 1); 962 } 963 break; 964 default: 965 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", 966 domain, type, protocol)); 967 set_errno(EINVAL); 968 return -1; 969 } 970 971 if (!conn) { 972 LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); 973 set_errno(ENOBUFS); 974 return -1; 975 } 976 977 i = alloc_socket(conn, 0); 978 979 if (i == -1) { 980 netconn_delete(conn); 981 set_errno(ENFILE); 982 return -1; 983 } 984 conn->socket = i; 985 LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); 986 set_errno(0); 987 return i; 988 } 989 990 int 991 lwip_write(int s, const void *data, size_t size) 992 { 993 return lwip_send(s, data, size, 0); 994 } 995 996 /** 997 * Go through the readset and writeset lists and see which socket of the sockets 998 * set in the sets has events. On return, readset, writeset and exceptset have 999 * the sockets enabled that had events. 1000 * 1001 * exceptset is not used for now!!! 1002 * 1003 * @param maxfdp1 the highest socket index in the sets 1004 * @param readset_in: set of sockets to check for read events 1005 * @param writeset_in: set of sockets to check for write events 1006 * @param exceptset_in: set of sockets to check for error events 1007 * @param readset_out: set of sockets that had read events 1008 * @param writeset_out: set of sockets that had write events 1009 * @param exceptset_out: set os sockets that had error events 1010 * @return number of sockets that had events (read/write/exception) (>= 0) 1011 */ 1012 static int 1013 lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, 1014 fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) 1015 { 1016 int i, nready = 0; 1017 fd_set lreadset, lwriteset, lexceptset; 1018 struct lwip_sock *sock; 1019 SYS_ARCH_DECL_PROTECT(lev); 1020 1021 FD_ZERO(&lreadset); 1022 FD_ZERO(&lwriteset); 1023 FD_ZERO(&lexceptset); 1024 1025 /* Go through each socket in each list to count number of sockets which 1026 currently match */ 1027 for(i = 0; i < maxfdp1; i++) { 1028 void* lastdata = NULL; 1029 s16_t rcvevent = 0; 1030 u16_t sendevent = 0; 1031 u16_t errevent = 0; 1032 /* First get the socket's status (protected)... */ 1033 SYS_ARCH_PROTECT(lev); 1034 sock = tryget_socket(i); 1035 if (sock != NULL) { 1036 lastdata = sock->lastdata; 1037 rcvevent = sock->rcvevent; 1038 sendevent = sock->sendevent; 1039 errevent = sock->errevent; 1040 } 1041 SYS_ARCH_UNPROTECT(lev); 1042 /* ... then examine it: */ 1043 /* See if netconn of this socket is ready for read */ 1044 if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { 1045 FD_SET(i, &lreadset); 1046 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); 1047 nready++; 1048 } 1049 /* See if netconn of this socket is ready for write */ 1050 if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { 1051 FD_SET(i, &lwriteset); 1052 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); 1053 nready++; 1054 } 1055 /* See if netconn of this socket had an error */ 1056 if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { 1057 FD_SET(i, &lexceptset); 1058 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); 1059 nready++; 1060 } 1061 } 1062 /* copy local sets to the ones provided as arguments */ 1063 *readset_out = lreadset; 1064 *writeset_out = lwriteset; 1065 *exceptset_out = lexceptset; 1066 1067 LWIP_ASSERT("nready >= 0", nready >= 0); 1068 return nready; 1069 } 1070 1071 /** 1072 * Processing exceptset is not yet implemented. 1073 */ 1074 int 1075 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, 1076 struct timeval *timeout) 1077 { 1078 u32_t waitres = 0; 1079 int nready; 1080 fd_set lreadset, lwriteset, lexceptset; 1081 u32_t msectimeout; 1082 struct lwip_select_cb select_cb; 1083 err_t err; 1084 int i; 1085 SYS_ARCH_DECL_PROTECT(lev); 1086 1087 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", 1088 maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, 1089 timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, 1090 timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); 1091 1092 /* Go through each socket in each list to count number of sockets which 1093 currently match */ 1094 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); 1095 1096 /* If we don't have any current events, then suspend if we are supposed to */ 1097 if (!nready) { 1098 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { 1099 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); 1100 /* This is OK as the local fdsets are empty and nready is zero, 1101 or we would have returned earlier. */ 1102 goto return_copy_fdsets; 1103 } 1104 1105 /* None ready: add our semaphore to list: 1106 We don't actually need any dynamic memory. Our entry on the 1107 list is only valid while we are in this function, so it's ok 1108 to use local variables. */ 1109 1110 select_cb.next = NULL; 1111 select_cb.prev = NULL; 1112 select_cb.readset = readset; 1113 select_cb.writeset = writeset; 1114 select_cb.exceptset = exceptset; 1115 select_cb.sem_signalled = 0; 1116 err = sys_sem_new(&select_cb.sem, 0); 1117 if (err != ERR_OK) { 1118 /* failed to create semaphore */ 1119 set_errno(ENOMEM); 1120 return -1; 1121 } 1122 1123 /* Protect the select_cb_list */ 1124 SYS_ARCH_PROTECT(lev); 1125 1126 /* Put this select_cb on top of list */ 1127 select_cb.next = select_cb_list; 1128 if (select_cb_list != NULL) { 1129 select_cb_list->prev = &select_cb; 1130 } 1131 select_cb_list = &select_cb; 1132 /* Increasing this counter tells even_callback that the list has changed. */ 1133 select_cb_ctr++; 1134 1135 /* Now we can safely unprotect */ 1136 SYS_ARCH_UNPROTECT(lev); 1137 1138 /* Increase select_waiting for each socket we are interested in */ 1139 for(i = 0; i < maxfdp1; i++) { 1140 if ((readset && FD_ISSET(i, readset)) || 1141 (writeset && FD_ISSET(i, writeset)) || 1142 (exceptset && FD_ISSET(i, exceptset))) { 1143 struct lwip_sock *sock = tryget_socket(i); 1144 LWIP_ASSERT("sock != NULL", sock != NULL); 1145 SYS_ARCH_PROTECT(lev); 1146 sock->select_waiting++; 1147 LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); 1148 SYS_ARCH_UNPROTECT(lev); 1149 } 1150 } 1151 1152 /* Call lwip_selscan again: there could have been events between 1153 the last scan (whithout us on the list) and putting us on the list! */ 1154 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); 1155 if (!nready) { 1156 /* Still none ready, just wait to be woken */ 1157 if (timeout == 0) { 1158 /* Wait forever */ 1159 msectimeout = 0; 1160 } else { 1161 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); 1162 if (msectimeout == 0) { 1163 /* Wait 1ms at least (0 means wait forever) */ 1164 msectimeout = 1; 1165 } 1166 } 1167 1168 waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout); 1169 } 1170 /* Increase select_waiting for each socket we are interested in */ 1171 for(i = 0; i < maxfdp1; i++) { 1172 if ((readset && FD_ISSET(i, readset)) || 1173 (writeset && FD_ISSET(i, writeset)) || 1174 (exceptset && FD_ISSET(i, exceptset))) { 1175 struct lwip_sock *sock = tryget_socket(i); 1176 LWIP_ASSERT("sock != NULL", sock != NULL); 1177 SYS_ARCH_PROTECT(lev); 1178 sock->select_waiting--; 1179 LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0); 1180 SYS_ARCH_UNPROTECT(lev); 1181 } 1182 } 1183 /* Take us off the list */ 1184 SYS_ARCH_PROTECT(lev); 1185 if (select_cb.next != NULL) { 1186 select_cb.next->prev = select_cb.prev; 1187 } 1188 if (select_cb_list == &select_cb) { 1189 LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); 1190 select_cb_list = select_cb.next; 1191 } else { 1192 LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); 1193 select_cb.prev->next = select_cb.next; 1194 } 1195 /* Increasing this counter tells even_callback that the list has changed. */ 1196 select_cb_ctr++; 1197 SYS_ARCH_UNPROTECT(lev); 1198 1199 sys_sem_free(&select_cb.sem); 1200 if (waitres == SYS_ARCH_TIMEOUT) { 1201 /* Timeout */ 1202 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); 1203 /* This is OK as the local fdsets are empty and nready is zero, 1204 or we would have returned earlier. */ 1205 goto return_copy_fdsets; 1206 } 1207 1208 /* See what's set */ 1209 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); 1210 } 1211 1212 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); 1213 return_copy_fdsets: 1214 set_errno(0); 1215 if (readset) { 1216 *readset = lreadset; 1217 } 1218 if (writeset) { 1219 *writeset = lwriteset; 1220 } 1221 if (exceptset) { 1222 *exceptset = lexceptset; 1223 } 1224 1225 1226 return nready; 1227 } 1228 1229 /** 1230 * Callback registered in the netconn layer for each socket-netconn. 1231 * Processes recvevent (data available) and wakes up tasks waiting for select. 1232 */ 1233 static void 1234 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) 1235 { 1236 int s; 1237 struct lwip_sock *sock; 1238 struct lwip_select_cb *scb; 1239 int last_select_cb_ctr; 1240 SYS_ARCH_DECL_PROTECT(lev); 1241 1242 LWIP_UNUSED_ARG(len); 1243 1244 /* Get socket */ 1245 if (conn) { 1246 s = conn->socket; 1247 if (s < 0) { 1248 /* Data comes in right away after an accept, even though 1249 * the server task might not have created a new socket yet. 1250 * Just count down (or up) if that's the case and we 1251 * will use the data later. Note that only receive events 1252 * can happen before the new socket is set up. */ 1253 SYS_ARCH_PROTECT(lev); 1254 if (conn->socket < 0) { 1255 if (evt == NETCONN_EVT_RCVPLUS) { 1256 conn->socket--; 1257 } 1258 SYS_ARCH_UNPROTECT(lev); 1259 return; 1260 } 1261 s = conn->socket; 1262 SYS_ARCH_UNPROTECT(lev); 1263 } 1264 1265 sock = get_socket(s); 1266 if (!sock) { 1267 return; 1268 } 1269 } else { 1270 return; 1271 } 1272 1273 SYS_ARCH_PROTECT(lev); 1274 /* Set event as required */ 1275 switch (evt) { 1276 case NETCONN_EVT_RCVPLUS: 1277 sock->rcvevent++; 1278 break; 1279 case NETCONN_EVT_RCVMINUS: 1280 sock->rcvevent--; 1281 break; 1282 case NETCONN_EVT_SENDPLUS: 1283 sock->sendevent = 1; 1284 break; 1285 case NETCONN_EVT_SENDMINUS: 1286 sock->sendevent = 0; 1287 break; 1288 case NETCONN_EVT_ERROR: 1289 sock->errevent = 1; 1290 break; 1291 default: 1292 LWIP_ASSERT("unknown event", 0); 1293 break; 1294 } 1295 1296 if (sock->select_waiting == 0) { 1297 /* noone is waiting for this socket, no need to check select_cb_list */ 1298 SYS_ARCH_UNPROTECT(lev); 1299 return; 1300 } 1301 1302 /* Now decide if anyone is waiting for this socket */ 1303 /* NOTE: This code goes through the select_cb_list list multiple times 1304 ONLY IF a select was actually waiting. We go through the list the number 1305 of waiting select calls + 1. This list is expected to be small. */ 1306 1307 /* At this point, SYS_ARCH is still protected! */ 1308 again: 1309 for (scb = select_cb_list; scb != NULL; scb = scb->next) { 1310 if (scb->sem_signalled == 0) { 1311 /* semaphore not signalled yet */ 1312 int do_signal = 0; 1313 /* Test this select call for our socket */ 1314 if (sock->rcvevent > 0) { 1315 if (scb->readset && FD_ISSET(s, scb->readset)) { 1316 do_signal = 1; 1317 } 1318 } 1319 if (sock->sendevent != 0) { 1320 if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { 1321 do_signal = 1; 1322 } 1323 } 1324 if (sock->errevent != 0) { 1325 if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { 1326 do_signal = 1; 1327 } 1328 } 1329 if (do_signal) { 1330 scb->sem_signalled = 1; 1331 /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might 1332 lead to the select thread taking itself off the list, invalidagin the semaphore. */ 1333 sys_sem_signal(&scb->sem); 1334 } 1335 } 1336 /* unlock interrupts with each step */ 1337 last_select_cb_ctr = select_cb_ctr; 1338 SYS_ARCH_UNPROTECT(lev); 1339 /* this makes sure interrupt protection time is short */ 1340 SYS_ARCH_PROTECT(lev); 1341 if (last_select_cb_ctr != select_cb_ctr) { 1342 /* someone has changed select_cb_list, restart at the beginning */ 1343 goto again; 1344 } 1345 } 1346 SYS_ARCH_UNPROTECT(lev); 1347 } 1348 1349 /** 1350 * Unimplemented: Close one end of a full-duplex connection. 1351 * Currently, the full connection is closed. 1352 */ 1353 int 1354 lwip_shutdown(int s, int how) 1355 { 1356 struct lwip_sock *sock; 1357 err_t err; 1358 u8_t shut_rx = 0, shut_tx = 0; 1359 1360 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); 1361 1362 sock = get_socket(s); 1363 if (!sock) { 1364 return -1; 1365 } 1366 1367 if (sock->conn != NULL) { 1368 if (netconn_type(sock->conn) != NETCONN_TCP) { 1369 sock_set_errno(sock, EOPNOTSUPP); 1370 return EOPNOTSUPP; 1371 } 1372 } else { 1373 sock_set_errno(sock, ENOTCONN); 1374 return ENOTCONN; 1375 } 1376 1377 if (how == SHUT_RD) { 1378 shut_rx = 1; 1379 } else if (how == SHUT_WR) { 1380 shut_tx = 1; 1381 } else if(how == SHUT_RDWR) { 1382 shut_rx = 1; 1383 shut_tx = 1; 1384 } else { 1385 sock_set_errno(sock, EINVAL); 1386 return EINVAL; 1387 } 1388 err = netconn_shutdown(sock->conn, shut_rx, shut_tx); 1389 1390 sock_set_errno(sock, err_to_errno(err)); 1391 return (err == ERR_OK ? 0 : -1); 1392 } 1393 1394 static int 1395 lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) 1396 { 1397 struct lwip_sock *sock; 1398 struct sockaddr_in sin; 1399 ip_addr_t naddr; 1400 1401 sock = get_socket(s); 1402 if (!sock) { 1403 return -1; 1404 } 1405 1406 memset(&sin, 0, sizeof(sin)); 1407 sin.sin_len = sizeof(sin); 1408 sin.sin_family = AF_INET; 1409 1410 /* get the IP address and port */ 1411 netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local); 1412 1413 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); 1414 ip_addr_debug_print(SOCKETS_DEBUG, &naddr); 1415 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port)); 1416 1417 sin.sin_port = htons(sin.sin_port); 1418 inet_addr_from_ipaddr(&sin.sin_addr, &naddr); 1419 1420 if (*namelen > sizeof(sin)) { 1421 *namelen = sizeof(sin); 1422 } 1423 1424 MEMCPY(name, &sin, *namelen); 1425 sock_set_errno(sock, 0); 1426 return 0; 1427 } 1428 1429 int 1430 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) 1431 { 1432 return lwip_getaddrname(s, name, namelen, 0); 1433 } 1434 1435 int 1436 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) 1437 { 1438 return lwip_getaddrname(s, name, namelen, 1); 1439 } 1440 1441 int 1442 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) 1443 { 1444 err_t err = ERR_OK; 1445 struct lwip_sock *sock = get_socket(s); 1446 struct lwip_setgetsockopt_data data; 1447 1448 if (!sock) { 1449 return -1; 1450 } 1451 1452 if ((NULL == optval) || (NULL == optlen)) { 1453 sock_set_errno(sock, EFAULT); 1454 return -1; 1455 } 1456 1457 /* Do length and type checks for the various options first, to keep it readable. */ 1458 switch (level) { 1459 1460 /* Level: SOL_SOCKET */ 1461 case SOL_SOCKET: 1462 switch (optname) { 1463 1464 case SO_ACCEPTCONN: 1465 case SO_BROADCAST: 1466 /* UNIMPL case SO_DEBUG: */ 1467 /* UNIMPL case SO_DONTROUTE: */ 1468 case SO_ERROR: 1469 case SO_KEEPALIVE: 1470 /* UNIMPL case SO_CONTIMEO: */ 1471 /* UNIMPL case SO_SNDTIMEO: */ 1472 #if LWIP_SO_RCVTIMEO 1473 case SO_RCVTIMEO: 1474 #endif /* LWIP_SO_RCVTIMEO */ 1475 #if LWIP_SO_RCVBUF 1476 case SO_RCVBUF: 1477 #endif /* LWIP_SO_RCVBUF */ 1478 /* UNIMPL case SO_OOBINLINE: */ 1479 /* UNIMPL case SO_SNDBUF: */ 1480 /* UNIMPL case SO_RCVLOWAT: */ 1481 /* UNIMPL case SO_SNDLOWAT: */ 1482 #if SO_REUSE 1483 case SO_REUSEADDR: 1484 case SO_REUSEPORT: 1485 #endif /* SO_REUSE */ 1486 case SO_TYPE: 1487 /* UNIMPL case SO_USELOOPBACK: */ 1488 if (*optlen < sizeof(int)) { 1489 err = EINVAL; 1490 } 1491 break; 1492 1493 case SO_NO_CHECK: 1494 if (*optlen < sizeof(int)) { 1495 err = EINVAL; 1496 } 1497 #if LWIP_UDP 1498 if ((sock->conn->type != NETCONN_UDP) || 1499 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { 1500 /* this flag is only available for UDP, not for UDP lite */ 1501 err = EAFNOSUPPORT; 1502 } 1503 #endif /* LWIP_UDP */ 1504 break; 1505 1506 default: 1507 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", 1508 s, optname)); 1509 err = ENOPROTOOPT; 1510 } /* switch (optname) */ 1511 break; 1512 1513 /* Level: IPPROTO_IP */ 1514 case IPPROTO_IP: 1515 switch (optname) { 1516 /* UNIMPL case IP_HDRINCL: */ 1517 /* UNIMPL case IP_RCVDSTADDR: */ 1518 /* UNIMPL case IP_RCVIF: */ 1519 case IP_TTL: 1520 case IP_TOS: 1521 if (*optlen < sizeof(int)) { 1522 err = EINVAL; 1523 } 1524 break; 1525 #if LWIP_IGMP 1526 case IP_MULTICAST_TTL: 1527 if (*optlen < sizeof(u8_t)) { 1528 err = EINVAL; 1529 } 1530 break; 1531 case IP_MULTICAST_IF: 1532 if (*optlen < sizeof(struct in_addr)) { 1533 err = EINVAL; 1534 } 1535 break; 1536 case IP_MULTICAST_LOOP: 1537 if (*optlen < sizeof(u8_t)) { 1538 err = EINVAL; 1539 } 1540 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1541 err = EAFNOSUPPORT; 1542 } 1543 break; 1544 #endif /* LWIP_IGMP */ 1545 1546 default: 1547 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", 1548 s, optname)); 1549 err = ENOPROTOOPT; 1550 } /* switch (optname) */ 1551 break; 1552 1553 #if LWIP_TCP 1554 /* Level: IPPROTO_TCP */ 1555 case IPPROTO_TCP: 1556 if (*optlen < sizeof(int)) { 1557 err = EINVAL; 1558 break; 1559 } 1560 1561 /* If this is no TCP socket, ignore any options. */ 1562 if (sock->conn->type != NETCONN_TCP) 1563 return 0; 1564 1565 switch (optname) { 1566 case TCP_NODELAY: 1567 case TCP_KEEPALIVE: 1568 #if LWIP_TCP_KEEPALIVE 1569 case TCP_KEEPIDLE: 1570 case TCP_KEEPINTVL: 1571 case TCP_KEEPCNT: 1572 #endif /* LWIP_TCP_KEEPALIVE */ 1573 break; 1574 1575 default: 1576 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", 1577 s, optname)); 1578 err = ENOPROTOOPT; 1579 } /* switch (optname) */ 1580 break; 1581 #endif /* LWIP_TCP */ 1582 #if LWIP_UDP && LWIP_UDPLITE 1583 /* Level: IPPROTO_UDPLITE */ 1584 case IPPROTO_UDPLITE: 1585 if (*optlen < sizeof(int)) { 1586 err = EINVAL; 1587 break; 1588 } 1589 1590 /* If this is no UDP lite socket, ignore any options. */ 1591 if (sock->conn->type != NETCONN_UDPLITE) { 1592 return 0; 1593 } 1594 1595 switch (optname) { 1596 case UDPLITE_SEND_CSCOV: 1597 case UDPLITE_RECV_CSCOV: 1598 break; 1599 1600 default: 1601 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", 1602 s, optname)); 1603 err = ENOPROTOOPT; 1604 } /* switch (optname) */ 1605 break; 1606 #endif /* LWIP_UDP && LWIP_UDPLITE*/ 1607 /* UNDEFINED LEVEL */ 1608 default: 1609 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", 1610 s, level, optname)); 1611 err = ENOPROTOOPT; 1612 } /* switch */ 1613 1614 1615 if (err != ERR_OK) { 1616 sock_set_errno(sock, err); 1617 return -1; 1618 } 1619 1620 /* Now do the actual option processing */ 1621 data.sock = sock; 1622 #ifdef LWIP_DEBUG 1623 data.s = s; 1624 #endif /* LWIP_DEBUG */ 1625 data.level = level; 1626 data.optname = optname; 1627 data.optval = optval; 1628 data.optlen = optlen; 1629 data.err = err; 1630 tcpip_callback(lwip_getsockopt_internal, &data); 1631 sys_arch_sem_wait(&sock->conn->op_completed, 0); 1632 /* maybe lwip_getsockopt_internal has changed err */ 1633 err = data.err; 1634 1635 sock_set_errno(sock, err); 1636 return err ? -1 : 0; 1637 } 1638 1639 static void 1640 lwip_getsockopt_internal(void *arg) 1641 { 1642 struct lwip_sock *sock; 1643 #ifdef LWIP_DEBUG 1644 int s; 1645 #endif /* LWIP_DEBUG */ 1646 int level, optname; 1647 void *optval; 1648 struct lwip_setgetsockopt_data *data; 1649 1650 LWIP_ASSERT("arg != NULL", arg != NULL); 1651 1652 data = (struct lwip_setgetsockopt_data*)arg; 1653 sock = data->sock; 1654 #ifdef LWIP_DEBUG 1655 s = data->s; 1656 #endif /* LWIP_DEBUG */ 1657 level = data->level; 1658 optname = data->optname; 1659 optval = data->optval; 1660 1661 switch (level) { 1662 1663 /* Level: SOL_SOCKET */ 1664 case SOL_SOCKET: 1665 switch (optname) { 1666 1667 /* The option flags */ 1668 case SO_ACCEPTCONN: 1669 case SO_BROADCAST: 1670 /* UNIMPL case SO_DEBUG: */ 1671 /* UNIMPL case SO_DONTROUTE: */ 1672 case SO_KEEPALIVE: 1673 /* UNIMPL case SO_OOBINCLUDE: */ 1674 #if SO_REUSE 1675 case SO_REUSEADDR: 1676 case SO_REUSEPORT: 1677 #endif /* SO_REUSE */ 1678 /*case SO_USELOOPBACK: UNIMPL */ 1679 *(int*)optval = sock->conn->pcb.ip->so_options & optname; 1680 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", 1681 s, optname, (*(int*)optval?"on":"off"))); 1682 break; 1683 1684 case SO_TYPE: 1685 switch (NETCONNTYPE_GROUP(sock->conn->type)) { 1686 case NETCONN_RAW: 1687 *(int*)optval = SOCK_RAW; 1688 break; 1689 case NETCONN_TCP: 1690 *(int*)optval = SOCK_STREAM; 1691 break; 1692 case NETCONN_UDP: 1693 *(int*)optval = SOCK_DGRAM; 1694 break; 1695 default: /* unrecognized socket type */ 1696 *(int*)optval = sock->conn->type; 1697 LWIP_DEBUGF(SOCKETS_DEBUG, 1698 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", 1699 s, *(int *)optval)); 1700 } /* switch (sock->conn->type) */ 1701 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", 1702 s, *(int *)optval)); 1703 break; 1704 1705 case SO_ERROR: 1706 /* only overwrite ERR_OK or tempoary errors */ 1707 if ((sock->err == 0) || (sock->err == EINPROGRESS)) { 1708 sock_set_errno(sock, err_to_errno(sock->conn->last_err)); 1709 } 1710 *(int *)optval = sock->err; 1711 sock->err = 0; 1712 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", 1713 s, *(int *)optval)); 1714 break; 1715 1716 #if LWIP_SO_RCVTIMEO 1717 case SO_RCVTIMEO: 1718 *(int *)optval = netconn_get_recvtimeout(sock->conn); 1719 break; 1720 #endif /* LWIP_SO_RCVTIMEO */ 1721 #if LWIP_SO_RCVBUF 1722 case SO_RCVBUF: 1723 *(int *)optval = netconn_get_recvbufsize(sock->conn); 1724 break; 1725 #endif /* LWIP_SO_RCVBUF */ 1726 #if LWIP_UDP 1727 case SO_NO_CHECK: 1728 *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; 1729 break; 1730 #endif /* LWIP_UDP*/ 1731 default: 1732 LWIP_ASSERT("unhandled optname", 0); 1733 break; 1734 } /* switch (optname) */ 1735 break; 1736 1737 /* Level: IPPROTO_IP */ 1738 case IPPROTO_IP: 1739 switch (optname) { 1740 case IP_TTL: 1741 *(int*)optval = sock->conn->pcb.ip->ttl; 1742 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", 1743 s, *(int *)optval)); 1744 break; 1745 case IP_TOS: 1746 *(int*)optval = sock->conn->pcb.ip->tos; 1747 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", 1748 s, *(int *)optval)); 1749 break; 1750 #if LWIP_IGMP 1751 case IP_MULTICAST_TTL: 1752 *(u8_t*)optval = sock->conn->pcb.ip->ttl; 1753 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", 1754 s, *(int *)optval)); 1755 break; 1756 case IP_MULTICAST_IF: 1757 inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip); 1758 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", 1759 s, *(u32_t *)optval)); 1760 break; 1761 case IP_MULTICAST_LOOP: 1762 if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { 1763 *(u8_t*)optval = 1; 1764 } else { 1765 *(u8_t*)optval = 0; 1766 } 1767 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", 1768 s, *(int *)optval)); 1769 break; 1770 #endif /* LWIP_IGMP */ 1771 default: 1772 LWIP_ASSERT("unhandled optname", 0); 1773 break; 1774 } /* switch (optname) */ 1775 break; 1776 1777 #if LWIP_TCP 1778 /* Level: IPPROTO_TCP */ 1779 case IPPROTO_TCP: 1780 switch (optname) { 1781 case TCP_NODELAY: 1782 *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); 1783 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", 1784 s, (*(int*)optval)?"on":"off") ); 1785 break; 1786 case TCP_KEEPALIVE: 1787 *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; 1788 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", 1789 s, *(int *)optval)); 1790 break; 1791 1792 #if LWIP_TCP_KEEPALIVE 1793 case TCP_KEEPIDLE: 1794 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); 1795 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n", 1796 s, *(int *)optval)); 1797 break; 1798 case TCP_KEEPINTVL: 1799 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); 1800 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n", 1801 s, *(int *)optval)); 1802 break; 1803 case TCP_KEEPCNT: 1804 *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; 1805 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n", 1806 s, *(int *)optval)); 1807 break; 1808 #endif /* LWIP_TCP_KEEPALIVE */ 1809 default: 1810 LWIP_ASSERT("unhandled optname", 0); 1811 break; 1812 } /* switch (optname) */ 1813 break; 1814 #endif /* LWIP_TCP */ 1815 #if LWIP_UDP && LWIP_UDPLITE 1816 /* Level: IPPROTO_UDPLITE */ 1817 case IPPROTO_UDPLITE: 1818 switch (optname) { 1819 case UDPLITE_SEND_CSCOV: 1820 *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; 1821 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", 1822 s, (*(int*)optval)) ); 1823 break; 1824 case UDPLITE_RECV_CSCOV: 1825 *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; 1826 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", 1827 s, (*(int*)optval)) ); 1828 break; 1829 default: 1830 LWIP_ASSERT("unhandled optname", 0); 1831 break; 1832 } /* switch (optname) */ 1833 break; 1834 #endif /* LWIP_UDP */ 1835 default: 1836 LWIP_ASSERT("unhandled level", 0); 1837 break; 1838 } /* switch (level) */ 1839 sys_sem_signal(&sock->conn->op_completed); 1840 } 1841 1842 int 1843 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) 1844 { 1845 struct lwip_sock *sock = get_socket(s); 1846 err_t err = ERR_OK; 1847 struct lwip_setgetsockopt_data data; 1848 1849 if (!sock) { 1850 return -1; 1851 } 1852 1853 if (NULL == optval) { 1854 sock_set_errno(sock, EFAULT); 1855 return -1; 1856 } 1857 1858 /* Do length and type checks for the various options first, to keep it readable. */ 1859 switch (level) { 1860 1861 /* Level: SOL_SOCKET */ 1862 case SOL_SOCKET: 1863 switch (optname) { 1864 1865 case SO_BROADCAST: 1866 /* UNIMPL case SO_DEBUG: */ 1867 /* UNIMPL case SO_DONTROUTE: */ 1868 case SO_KEEPALIVE: 1869 /* UNIMPL case case SO_CONTIMEO: */ 1870 /* UNIMPL case case SO_SNDTIMEO: */ 1871 #if LWIP_SO_RCVTIMEO 1872 case SO_RCVTIMEO: 1873 #endif /* LWIP_SO_RCVTIMEO */ 1874 #if LWIP_SO_RCVBUF 1875 case SO_RCVBUF: 1876 #endif /* LWIP_SO_RCVBUF */ 1877 /* UNIMPL case SO_OOBINLINE: */ 1878 /* UNIMPL case SO_SNDBUF: */ 1879 /* UNIMPL case SO_RCVLOWAT: */ 1880 /* UNIMPL case SO_SNDLOWAT: */ 1881 #if SO_REUSE 1882 case SO_REUSEADDR: 1883 case SO_REUSEPORT: 1884 #endif /* SO_REUSE */ 1885 /* UNIMPL case SO_USELOOPBACK: */ 1886 if (optlen < sizeof(int)) { 1887 err = EINVAL; 1888 } 1889 break; 1890 case SO_NO_CHECK: 1891 if (optlen < sizeof(int)) { 1892 err = EINVAL; 1893 } 1894 #if LWIP_UDP 1895 if ((sock->conn->type != NETCONN_UDP) || 1896 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { 1897 /* this flag is only available for UDP, not for UDP lite */ 1898 err = EAFNOSUPPORT; 1899 } 1900 #endif /* LWIP_UDP */ 1901 break; 1902 default: 1903 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", 1904 s, optname)); 1905 err = ENOPROTOOPT; 1906 } /* switch (optname) */ 1907 break; 1908 1909 /* Level: IPPROTO_IP */ 1910 case IPPROTO_IP: 1911 switch (optname) { 1912 /* UNIMPL case IP_HDRINCL: */ 1913 /* UNIMPL case IP_RCVDSTADDR: */ 1914 /* UNIMPL case IP_RCVIF: */ 1915 case IP_TTL: 1916 case IP_TOS: 1917 if (optlen < sizeof(int)) { 1918 err = EINVAL; 1919 } 1920 break; 1921 #if LWIP_IGMP 1922 case IP_MULTICAST_TTL: 1923 if (optlen < sizeof(u8_t)) { 1924 err = EINVAL; 1925 } 1926 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1927 err = EAFNOSUPPORT; 1928 } 1929 break; 1930 case IP_MULTICAST_IF: 1931 if (optlen < sizeof(struct in_addr)) { 1932 err = EINVAL; 1933 } 1934 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1935 err = EAFNOSUPPORT; 1936 } 1937 break; 1938 case IP_MULTICAST_LOOP: 1939 if (optlen < sizeof(u8_t)) { 1940 err = EINVAL; 1941 } 1942 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1943 err = EAFNOSUPPORT; 1944 } 1945 break; 1946 case IP_ADD_MEMBERSHIP: 1947 case IP_DROP_MEMBERSHIP: 1948 if (optlen < sizeof(struct ip_mreq)) { 1949 err = EINVAL; 1950 } 1951 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1952 err = EAFNOSUPPORT; 1953 } 1954 break; 1955 #endif /* LWIP_IGMP */ 1956 default: 1957 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", 1958 s, optname)); 1959 err = ENOPROTOOPT; 1960 } /* switch (optname) */ 1961 break; 1962 1963 #if LWIP_TCP 1964 /* Level: IPPROTO_TCP */ 1965 case IPPROTO_TCP: 1966 if (optlen < sizeof(int)) { 1967 err = EINVAL; 1968 break; 1969 } 1970 1971 /* If this is no TCP socket, ignore any options. */ 1972 if (sock->conn->type != NETCONN_TCP) 1973 return 0; 1974 1975 switch (optname) { 1976 case TCP_NODELAY: 1977 case TCP_KEEPALIVE: 1978 #if LWIP_TCP_KEEPALIVE 1979 case TCP_KEEPIDLE: 1980 case TCP_KEEPINTVL: 1981 case TCP_KEEPCNT: 1982 #endif /* LWIP_TCP_KEEPALIVE */ 1983 break; 1984 1985 default: 1986 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", 1987 s, optname)); 1988 err = ENOPROTOOPT; 1989 } /* switch (optname) */ 1990 break; 1991 #endif /* LWIP_TCP */ 1992 #if LWIP_UDP && LWIP_UDPLITE 1993 /* Level: IPPROTO_UDPLITE */ 1994 case IPPROTO_UDPLITE: 1995 if (optlen < sizeof(int)) { 1996 err = EINVAL; 1997 break; 1998 } 1999 2000 /* If this is no UDP lite socket, ignore any options. */ 2001 if (sock->conn->type != NETCONN_UDPLITE) 2002 return 0; 2003 2004 switch (optname) { 2005 case UDPLITE_SEND_CSCOV: 2006 case UDPLITE_RECV_CSCOV: 2007 break; 2008 2009 default: 2010 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", 2011 s, optname)); 2012 err = ENOPROTOOPT; 2013 } /* switch (optname) */ 2014 break; 2015 #endif /* LWIP_UDP && LWIP_UDPLITE */ 2016 /* UNDEFINED LEVEL */ 2017 default: 2018 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", 2019 s, level, optname)); 2020 err = ENOPROTOOPT; 2021 } /* switch (level) */ 2022 2023 2024 if (err != ERR_OK) { 2025 sock_set_errno(sock, err); 2026 return -1; 2027 } 2028 2029 2030 /* Now do the actual option processing */ 2031 data.sock = sock; 2032 #ifdef LWIP_DEBUG 2033 data.s = s; 2034 #endif /* LWIP_DEBUG */ 2035 data.level = level; 2036 data.optname = optname; 2037 data.optval = (void*)optval; 2038 data.optlen = &optlen; 2039 data.err = err; 2040 tcpip_callback(lwip_setsockopt_internal, &data); 2041 sys_arch_sem_wait(&sock->conn->op_completed, 0); 2042 /* maybe lwip_setsockopt_internal has changed err */ 2043 err = data.err; 2044 2045 sock_set_errno(sock, err); 2046 return err ? -1 : 0; 2047 } 2048 2049 static void 2050 lwip_setsockopt_internal(void *arg) 2051 { 2052 struct lwip_sock *sock; 2053 #ifdef LWIP_DEBUG 2054 int s; 2055 #endif /* LWIP_DEBUG */ 2056 int level, optname; 2057 const void *optval; 2058 struct lwip_setgetsockopt_data *data; 2059 2060 LWIP_ASSERT("arg != NULL", arg != NULL); 2061 2062 data = (struct lwip_setgetsockopt_data*)arg; 2063 sock = data->sock; 2064 #ifdef LWIP_DEBUG 2065 s = data->s; 2066 #endif /* LWIP_DEBUG */ 2067 level = data->level; 2068 optname = data->optname; 2069 optval = data->optval; 2070 2071 switch (level) { 2072 2073 /* Level: SOL_SOCKET */ 2074 case SOL_SOCKET: 2075 switch (optname) { 2076 2077 /* The option flags */ 2078 case SO_BROADCAST: 2079 /* UNIMPL case SO_DEBUG: */ 2080 /* UNIMPL case SO_DONTROUTE: */ 2081 case SO_KEEPALIVE: 2082 /* UNIMPL case SO_OOBINCLUDE: */ 2083 #if SO_REUSE 2084 case SO_REUSEADDR: 2085 case SO_REUSEPORT: 2086 #endif /* SO_REUSE */ 2087 /* UNIMPL case SO_USELOOPBACK: */ 2088 if (*(int*)optval) { 2089 sock->conn->pcb.ip->so_options |= optname; 2090 } else { 2091 sock->conn->pcb.ip->so_options &= ~optname; 2092 } 2093 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", 2094 s, optname, (*(int*)optval?"on":"off"))); 2095 break; 2096 #if LWIP_SO_RCVTIMEO 2097 case SO_RCVTIMEO: 2098 netconn_set_recvtimeout(sock->conn, *(int*)optval); 2099 break; 2100 #endif /* LWIP_SO_RCVTIMEO */ 2101 #if LWIP_SO_RCVBUF 2102 case SO_RCVBUF: 2103 netconn_set_recvbufsize(sock->conn, *(int*)optval); 2104 break; 2105 #endif /* LWIP_SO_RCVBUF */ 2106 #if LWIP_UDP 2107 case SO_NO_CHECK: 2108 if (*(int*)optval) { 2109 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); 2110 } else { 2111 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); 2112 } 2113 break; 2114 #endif /* LWIP_UDP */ 2115 default: 2116 LWIP_ASSERT("unhandled optname", 0); 2117 break; 2118 } /* switch (optname) */ 2119 break; 2120 2121 /* Level: IPPROTO_IP */ 2122 case IPPROTO_IP: 2123 switch (optname) { 2124 case IP_TTL: 2125 sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval); 2126 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", 2127 s, sock->conn->pcb.ip->ttl)); 2128 break; 2129 case IP_TOS: 2130 sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval); 2131 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", 2132 s, sock->conn->pcb.ip->tos)); 2133 break; 2134 #if LWIP_IGMP 2135 case IP_MULTICAST_TTL: 2136 sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval); 2137 break; 2138 case IP_MULTICAST_IF: 2139 inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval); 2140 break; 2141 case IP_MULTICAST_LOOP: 2142 if (*(u8_t*)optval) { 2143 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); 2144 } else { 2145 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); 2146 } 2147 break; 2148 case IP_ADD_MEMBERSHIP: 2149 case IP_DROP_MEMBERSHIP: 2150 { 2151 /* If this is a TCP or a RAW socket, ignore these options. */ 2152 struct ip_mreq *imr = (struct ip_mreq *)optval; 2153 ip_addr_t if_addr; 2154 ip_addr_t multi_addr; 2155 inet_addr_to_ipaddr(&if_addr, &imr->imr_interface); 2156 inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr); 2157 if(optname == IP_ADD_MEMBERSHIP){ 2158 data->err = igmp_joingroup(&if_addr, &multi_addr); 2159 } else { 2160 data->err = igmp_leavegroup(&if_addr, &multi_addr); 2161 } 2162 if(data->err != ERR_OK) { 2163 data->err = EADDRNOTAVAIL; 2164 } 2165 } 2166 break; 2167 #endif /* LWIP_IGMP */ 2168 default: 2169 LWIP_ASSERT("unhandled optname", 0); 2170 break; 2171 } /* switch (optname) */ 2172 break; 2173 2174 #if LWIP_TCP 2175 /* Level: IPPROTO_TCP */ 2176 case IPPROTO_TCP: 2177 switch (optname) { 2178 case TCP_NODELAY: 2179 if (*(int*)optval) { 2180 tcp_nagle_disable(sock->conn->pcb.tcp); 2181 } else { 2182 tcp_nagle_enable(sock->conn->pcb.tcp); 2183 } 2184 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", 2185 s, (*(int *)optval)?"on":"off") ); 2186 break; 2187 case TCP_KEEPALIVE: 2188 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval); 2189 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", 2190 s, sock->conn->pcb.tcp->keep_idle)); 2191 break; 2192 2193 #if LWIP_TCP_KEEPALIVE 2194 case TCP_KEEPIDLE: 2195 sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval); 2196 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", 2197 s, sock->conn->pcb.tcp->keep_idle)); 2198 break; 2199 case TCP_KEEPINTVL: 2200 sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval); 2201 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", 2202 s, sock->conn->pcb.tcp->keep_intvl)); 2203 break; 2204 case TCP_KEEPCNT: 2205 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval); 2206 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", 2207 s, sock->conn->pcb.tcp->keep_cnt)); 2208 break; 2209 #endif /* LWIP_TCP_KEEPALIVE */ 2210 default: 2211 LWIP_ASSERT("unhandled optname", 0); 2212 break; 2213 } /* switch (optname) */ 2214 break; 2215 #endif /* LWIP_TCP*/ 2216 #if LWIP_UDP && LWIP_UDPLITE 2217 /* Level: IPPROTO_UDPLITE */ 2218 case IPPROTO_UDPLITE: 2219 switch (optname) { 2220 case UDPLITE_SEND_CSCOV: 2221 if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) { 2222 /* don't allow illegal values! */ 2223 sock->conn->pcb.udp->chksum_len_tx = 8; 2224 } else { 2225 sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval; 2226 } 2227 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", 2228 s, (*(int*)optval)) ); 2229 break; 2230 case UDPLITE_RECV_CSCOV: 2231 if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) { 2232 /* don't allow illegal values! */ 2233 sock->conn->pcb.udp->chksum_len_rx = 8; 2234 } else { 2235 sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval; 2236 } 2237 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", 2238 s, (*(int*)optval)) ); 2239 break; 2240 default: 2241 LWIP_ASSERT("unhandled optname", 0); 2242 break; 2243 } /* switch (optname) */ 2244 break; 2245 #endif /* LWIP_UDP */ 2246 default: 2247 LWIP_ASSERT("unhandled level", 0); 2248 break; 2249 } /* switch (level) */ 2250 sys_sem_signal(&sock->conn->op_completed); 2251 } 2252 2253 int 2254 lwip_ioctl(int s, long cmd, void *argp) 2255 { 2256 struct lwip_sock *sock = get_socket(s); 2257 u8_t val; 2258 #if LWIP_SO_RCVBUF 2259 u16_t buflen = 0; 2260 s16_t recv_avail; 2261 #endif /* LWIP_SO_RCVBUF */ 2262 2263 if (!sock) { 2264 return -1; 2265 } 2266 2267 switch (cmd) { 2268 #if LWIP_SO_RCVBUF 2269 case FIONREAD: 2270 if (!argp) { 2271 sock_set_errno(sock, EINVAL); 2272 return -1; 2273 } 2274 2275 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); 2276 if (recv_avail < 0) { 2277 recv_avail = 0; 2278 } 2279 *((u16_t*)argp) = (u16_t)recv_avail; 2280 2281 /* Check if there is data left from the last recv operation. /maq 041215 */ 2282 if (sock->lastdata) { 2283 struct pbuf *p = (struct pbuf *)sock->lastdata; 2284 if (netconn_type(sock->conn) != NETCONN_TCP) { 2285 p = ((struct netbuf *)p)->p; 2286 } 2287 buflen = p->tot_len; 2288 buflen -= sock->lastoffset; 2289 2290 *((u16_t*)argp) += buflen; 2291 } 2292 2293 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); 2294 sock_set_errno(sock, 0); 2295 return 0; 2296 #endif /* LWIP_SO_RCVBUF */ 2297 2298 case FIONBIO: 2299 val = 0; 2300 if (argp && *(u32_t*)argp) { 2301 val = 1; 2302 } 2303 netconn_set_nonblocking(sock->conn, val); 2304 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); 2305 sock_set_errno(sock, 0); 2306 return 0; 2307 2308 default: 2309 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); 2310 sock_set_errno(sock, ENOSYS); /* not yet implemented */ 2311 return -1; 2312 } /* switch (cmd) */ 2313 } 2314 2315 /** A minimal implementation of fcntl. 2316 * Currently only the commands F_GETFL and F_SETFL are implemented. 2317 * Only the flag O_NONBLOCK is implemented. 2318 */ 2319 int 2320 lwip_fcntl(int s, int cmd, int val) 2321 { 2322 struct lwip_sock *sock = get_socket(s); 2323 int ret = -1; 2324 2325 if (!sock || !sock->conn) { 2326 return -1; 2327 } 2328 2329 switch (cmd) { 2330 case F_GETFL: 2331 ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; 2332 break; 2333 case F_SETFL: 2334 if ((val & ~O_NONBLOCK) == 0) { 2335 /* only O_NONBLOCK, all other bits are zero */ 2336 netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); 2337 ret = 0; 2338 } 2339 break; 2340 default: 2341 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); 2342 break; 2343 } 2344 return ret; 2345 } 2346 2347 #endif /* LWIP_SOCKET */ 2348