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@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 <netinet/tcp.h> 46#include <sys/filio.h> 47 48#include "lwip/sockets.h" 49#include "lwip/api.h" 50#include "lwip/sys.h" 51#include "lwip/igmp.h" 52#include "lwip/inet.h" 53#include "lwip/tcp.h" 54#include "lwip/raw.h" 55#include "lwip/udp.h" 56#include "lwip/tcpip.h" 57#include "lwip/sock_serialise.h" 58 59#ifdef BF_LWIP_CHAN_SUPPORT 60# include "lwip/sock_chan_support.h" 61 62# include <barrelfish/barrelfish.h> 63# include <barrelfish/waitset.h> 64# include <barrelfish/waitset_chan.h> 65#endif /* BF_LWIP_CHAN_SUPPORT */ 66 67#include <string.h> 68 69#define NUM_SOCKETS MEMP_NUM_NETCONN 70 71/** Contains all internal pointers and states used for a socket */ 72struct lwip_socket { 73 /** sockets currently are built on netconns, each socket has one netconn */ 74 struct netconn *conn; 75 /** data that was left from the previous read */ 76 struct netbuf *lastdata; 77 /** offset in the data that was left from the previous read */ 78 u16_t lastoffset; 79 /** number of times data was received, set by event_callback(), 80 tested by the receive and select functions */ 81 s16_t rcvevent; 82 /** number of times data was received, set by event_callback(), 83 tested by select */ 84 u16_t sendevent; 85 /** socket flags (currently, only used for O_NONBLOCK) */ 86 u16_t flags; 87 /** last error that occurred on this socket */ 88 int err; 89#ifdef BF_LWIP_CHAN_SUPPORT 90 /** Channel used to signal, when data is ready for reading. */ 91 struct waitset_chanstate recv_chanstate; 92 /** Channel used to signal, when data is ready for writing. */ 93 struct waitset_chanstate send_chanstate; 94#endif /* BF_LWIP_CHAN_SUPPORT */ 95}; 96 97/** Description for a task waiting in select */ 98struct lwip_select_cb { 99 /** Pointer to the next waiting task */ 100 struct lwip_select_cb *next; 101 /** readset passed to select */ 102 fd_set *readset; 103 /** writeset passed to select */ 104 fd_set *writeset; 105 /** unimplemented: exceptset passed to select */ 106 fd_set *exceptset; 107 /** don't signal the same semaphore twice: set to 1 when signalled */ 108 int sem_signalled; 109 /** semaphore to wake up a task waiting for select */ 110 sys_sem_t sem; 111}; 112 113/** This struct is used to pass data to the set/getsockopt_internal 114 * functions running in tcpip_thread context (only a void* is allowed) */ 115struct lwip_setgetsockopt_data { 116 /** socket struct for which to change options */ 117 struct lwip_socket *sock; 118 /** socket index for which to change options */ 119 int s; 120 /** level of the option to process */ 121 int level; 122 /** name of the option to process */ 123 int optname; 124 /** set: value to set the option to 125 * get: value of the option is stored here */ 126 void *optval; 127 /** size of *optval */ 128 socklen_t *optlen; 129 /** if an error occures, it is temporarily stored here */ 130 err_t err; 131}; 132 133/** The global array of available sockets */ 134static struct lwip_socket sockets[NUM_SOCKETS]; 135 136/** The global list of tasks waiting for select */ 137static struct lwip_select_cb *select_cb_list; 138 139/** Semaphore protecting the sockets array */ 140static sys_sem_t socksem; 141 142/** Semaphore protecting select_cb_list */ 143static sys_sem_t selectsem; 144 145/** Table to quickly map an lwIP error (err_t) to a socket error 146 * by using -err as an index */ 147static const int err_to_errno_table[] = { 148 0, /* ERR_OK 0 No error, everything OK. */ 149 ENOMEM, /* ERR_MEM -1 Out of memory error. */ 150 ENOBUFS, /* ERR_BUF -2 Buffer error. */ 151 ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */ 152 EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ 153 ECONNABORTED, /* ERR_ABRT -5 Connection aborted. */ 154 ECONNRESET, /* ERR_RST -6 Connection reset. */ 155 ESHUTDOWN, /* ERR_CLSD -7 Connection closed. */ 156 ENOTCONN, /* ERR_CONN -8 Not connected. */ 157 EINVAL, /* ERR_VAL -9 Illegal value. */ 158 EIO, /* ERR_ARG -10 Illegal argument. */ 159 EADDRINUSE, /* ERR_USE -11 Address in use. */ 160 -1, /* ERR_IF -12 Low-level netif error */ 161 -1, /* ERR_ISCONN -13 Already connected. */ 162 EINPROGRESS /* ERR_INPROGRESS -14 Operation in progress */ 163}; 164 165#define ERR_TO_ERRNO_TABLE_SIZE \ 166 (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0])) 167 168#define err_to_errno(err) \ 169 ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ 170 err_to_errno_table[-(err)] : EIO) 171 172#ifdef ERRNO 173#ifndef set_errno 174#define set_errno(err) errno = (err) 175#endif 176#else 177#define set_errno(err) 178#endif 179 180#define sock_set_errno(sk, e) do { \ 181 sk->err = (e); \ 182 set_errno(sk->err); \ 183} while (0) 184 185/* Forward delcaration of some functions */ 186static void event_callback(struct netconn *conn, enum netconn_evt evt, 187 u16_t len); 188static void lwip_getsockopt_internal(void *arg); 189static void lwip_setsockopt_internal(void *arg); 190 191/** 192 * Initialize this module. This function has to be called before any other 193 * functions in this module! 194 */ 195void lwip_socket_init(void) 196{ 197 socksem = sys_sem_new(1); 198 selectsem = sys_sem_new(1); 199} 200 201/** 202 * Map a externally used socket index to the internal socket representation. 203 * 204 * @param s externally used socket index 205 * @return struct lwip_socket for the socket or NULL if not found 206 */ 207static struct lwip_socket *get_socket(int s) 208{ 209 struct lwip_socket *sock; 210 211 if ((s < 0) || (s >= NUM_SOCKETS)) { 212 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s)); 213 set_errno(EBADF); 214 return NULL; 215 } 216 217 sock = &sockets[s]; 218 219 if (!sock->conn) { 220 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s)); 221 set_errno(EBADF); 222 return NULL; 223 } 224 return sock; 225} 226 227/** 228 * Allocate a new socket for a given netconn. 229 * 230 * @param newconn the netconn for which to allocate a socket 231 * @return the index of the new socket; -1 on error 232 */ 233static int alloc_socket(struct netconn *newconn) 234{ 235 int i; 236 237 /* Protect socket array */ 238 sys_sem_wait(socksem); 239 240 /* allocate a new socket identifier */ 241 for (i = 0; i < NUM_SOCKETS; ++i) { 242 if (!sockets[i].conn) { 243 sockets[i].conn = newconn; 244 sockets[i].lastdata = NULL; 245 sockets[i].lastoffset = 0; 246 sockets[i].rcvevent = 0; 247 sockets[i].sendevent = 1; /* TCP send buf is empty */ 248 sockets[i].flags = 0; 249 sockets[i].err = 0; 250 sys_sem_signal(socksem); 251#ifdef BF_LWIP_CHAN_SUPPORT 252 waitset_chanstate_init(&sockets[i].recv_chanstate, 253 CHANTYPE_LWIP_SOCKET); 254 waitset_chanstate_init(&sockets[i].send_chanstate, 255 CHANTYPE_LWIP_SOCKET); 256#endif /* BF_LWIP_CHAN_SUPPORT */ 257 return i; 258 } 259 } 260 sys_sem_signal(socksem); 261 return -1; 262} 263 264/* Below this, the well-known socket functions are implemented. 265 * Use google.com or opengroup.org to get a good description :-) 266 * 267 * Exceptions are documented! 268 */ 269 270int lwip_accept(int s, struct sockaddr *addr, socklen_t * addrlen) 271{ 272 struct lwip_socket *sock, *nsock; 273 struct netconn *newconn; 274 struct ip_addr naddr; 275 u16_t port; 276 int newsock; 277 struct sockaddr_in sin; 278 err_t err; 279 280 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); 281 sock = get_socket(s); 282 if (!sock) 283 return -1; 284 285 if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) { 286 LWIP_DEBUGF(SOCKETS_DEBUG, 287 ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); 288 sock_set_errno(sock, EWOULDBLOCK); 289 return -1; 290 } 291 292 newconn = netconn_accept(sock->conn); 293 if (!newconn) { 294 LWIP_DEBUGF(SOCKETS_DEBUG, 295 ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err)); 296 sock_set_errno(sock, err_to_errno(sock->conn->err)); 297 return -1; 298 } 299 300 /* get the IP address and port of the remote host */ 301 err = netconn_peer(newconn, &naddr, &port); 302 if (err != ERR_OK) { 303 netconn_delete(newconn); 304 sock_set_errno(sock, err_to_errno(err)); 305 return -1; 306 } 307 308 /* Note that POSIX only requires us to check addr is non-NULL. addrlen must 309 * not be NULL if addr is valid. 310 */ 311 if (NULL != addr) { 312 LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); 313 memset(&sin, 0, sizeof(sin)); 314 sin.sin_len = sizeof(sin); 315 sin.sin_family = AF_INET; 316 sin.sin_port = htons(port); 317 sin.sin_addr.s_addr = naddr.addr; 318 319 if (*addrlen > sizeof(sin)) 320 *addrlen = sizeof(sin); 321 322 MEMCPY(addr, &sin, *addrlen); 323 } 324 325 newsock = alloc_socket(newconn); 326 if (newsock == -1) { 327 netconn_delete(newconn); 328 sock_set_errno(sock, ENFILE); 329 return -1; 330 } 331 LWIP_ASSERT("invalid socket index", (newsock >= 0) 332 && (newsock < NUM_SOCKETS)); 333 newconn->callback = event_callback; 334 nsock = &sockets[newsock]; 335 LWIP_ASSERT("invalid socket pointer", nsock != NULL); 336 337 sys_sem_wait(socksem); 338 /* See event_callback: If data comes in right away after an accept, even 339 * though the server task might not have created a new socket yet. 340 * In that case, newconn->socket is counted down (newconn->socket--), 341 * so nsock->rcvevent is >= 1 here! 342 */ 343 nsock->rcvevent += -1 - newconn->socket; 344 newconn->socket = newsock; 345 sys_sem_signal(socksem); 346 347 LWIP_DEBUGF(SOCKETS_DEBUG, 348 ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); 349 ip_addr_debug_print(SOCKETS_DEBUG, &naddr); 350 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%" U16_F "\n", port)); 351 352 sock_set_errno(sock, 0); 353 return newsock; 354} 355 356int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) 357{ 358 struct lwip_socket *sock; 359 struct ip_addr local_addr; 360 u16_t local_port; 361 err_t err; 362 363 sock = get_socket(s); 364 if (!sock) 365 return -1; 366 367 LWIP_ERROR("lwip_bind: invalid address", 368 ((namelen == sizeof(struct sockaddr_in)) 369 && ((((const struct sockaddr_in *) name)->sin_family) == 370 AF_INET)), sock_set_errno(sock, err_to_errno(ERR_ARG)); 371 return -1; 372 ); 373 374 local_addr.addr = ((const struct sockaddr_in *) name)->sin_addr.s_addr; 375 local_port = ((const struct sockaddr_in *) name)->sin_port; 376 377 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); 378 ip_addr_debug_print(SOCKETS_DEBUG, &local_addr); 379 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%" U16_F ")\n", ntohs(local_port))); 380 381 err = netconn_bind(sock->conn, &local_addr, ntohs(local_port)); 382 383 if (err != ERR_OK) { 384 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); 385 sock_set_errno(sock, err_to_errno(err)); 386 return -1; 387 } 388 389 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); 390 sock_set_errno(sock, 0); 391 return 0; 392} 393 394int lwip_close(int s) 395{ 396 struct lwip_socket *sock; 397 398 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); 399 400 sock = get_socket(s); 401 if (!sock) { 402 return -1; 403 } 404 405 netconn_delete(sock->conn); 406 407 sys_sem_wait(socksem); 408 if (sock->lastdata) { 409 printf("close(%d): last data\n", s); 410 netbuf_delete(sock->lastdata); 411 } 412 sock->lastdata = NULL; 413 sock->lastoffset = 0; 414 sock->conn = NULL; 415 sock_set_errno(sock, 0); 416 sys_sem_signal(socksem); 417 return 0; 418} 419 420int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) 421{ 422 struct lwip_socket *sock; 423 err_t err; 424 425 sock = get_socket(s); 426 if (!sock) 427 return -1; 428 429 LWIP_ERROR("lwip_connect: invalid address", 430 ((namelen == sizeof(struct sockaddr_in)) 431 && ((((const struct sockaddr_in *) name)->sin_family) == 432 AF_INET)), sock_set_errno(sock, err_to_errno(ERR_ARG)); 433 return -1; 434 ); 435 436 if (((const struct sockaddr_in *) name)->sin_family == AF_UNSPEC) { 437 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); 438 err = netconn_disconnect(sock->conn); 439 } else { 440 struct ip_addr remote_addr; 441 u16_t remote_port; 442 443 remote_addr.addr = ((const struct sockaddr_in *) name)->sin_addr.s_addr; 444 remote_port = ((const struct sockaddr_in *) name)->sin_port; 445 446 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); 447 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); 448 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%" U16_F ")\n", ntohs(remote_port))); 449 450 err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); 451 } 452 453 if (err != ERR_OK) { 454 LWIP_DEBUGF(SOCKETS_DEBUG, 455 ("lwip_connect(%d) failed, err=%d\n", s, err)); 456 sock_set_errno(sock, err_to_errno(err)); 457 return -1; 458 } 459 460 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); 461 sock_set_errno(sock, 0); 462 return 0; 463} 464 465/** 466 * Set a socket into listen mode. 467 * The socket may not have been used for another connection previously. 468 * 469 * @param s the socket to set to listening mode 470 * @param backlog (ATTENTION: need TCP_LISTEN_BACKLOG=1) 471 * @return 0 on success, non-zero on failure 472 */ 473int lwip_listen(int s, int backlog) 474{ 475 struct lwip_socket *sock; 476 err_t err; 477 478 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); 479 480 sock = get_socket(s); 481 if (!sock) 482 return -1; 483 484 /* limit the "backlog" parameter to fit in an u8_t */ 485 if (backlog < 0) { 486 backlog = 0; 487 } 488 if (backlog > 0xff) { 489 backlog = 0xff; 490 } 491 492 err = netconn_listen_with_backlog(sock->conn, backlog); 493 494 if (err != ERR_OK) { 495 LWIP_DEBUGF(SOCKETS_DEBUG, 496 ("lwip_listen(%d) failed, err=%d\n", s, err)); 497 sock_set_errno(sock, err_to_errno(err)); 498 return -1; 499 } 500 501 sock_set_errno(sock, 0); 502 return 0; 503} 504 505int 506lwip_recvfrom(int s, void *mem, size_t len, int flags, 507 struct sockaddr *from, socklen_t * fromlen) 508{ 509 struct lwip_socket *sock; 510 struct netbuf *buf; 511 u16_t buflen, copylen, off = 0; 512 struct ip_addr *addr; 513 u16_t port; 514 u8_t done = 0; 515 516 LWIP_DEBUGF(SOCKETS_DEBUG, 517 ("lwip_recvfrom(%d, %p, %" SZT_F ", 0x%x, ..)\n", s, mem, len, 518 flags)); 519 sock = get_socket(s); 520 if (!sock) 521 return -1; 522 523 do { 524 LWIP_DEBUGF(SOCKETS_DEBUG, 525 ("lwip_recvfrom: top while sock->lastdata=%p\n", 526 (void *) sock->lastdata)); 527 /* Check if there is data left from the last recv operation. */ 528 if (sock->lastdata) { 529 buf = sock->lastdata; 530 } else { 531 /* If this is non-blocking call, then check first */ 532 if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && 533 (sock->rcvevent <= 0)) { 534 if (off > 0) { 535 /* already received data, return that */ 536 sock_set_errno(sock, 0); 537 return off; 538 } 539 LWIP_DEBUGF(SOCKETS_DEBUG, 540 ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); 541 sock_set_errno(sock, EWOULDBLOCK); 542 return -1; 543 } 544 545 /* No data was left from the previous operation, so we try to get 546 some from the network. */ 547 sock->lastdata = buf = netconn_recv(sock->conn); 548 LWIP_DEBUGF(SOCKETS_DEBUG, 549 ("lwip_recvfrom: netconn_recv netbuf=%p\n", 550 (void *) buf)); 551 552 if (!buf) { 553 if (off > 0) { 554 /* already received data, return that */ 555 sock_set_errno(sock, 0); 556 return off; 557 } 558 /* We should really do some error checking here. */ 559 LWIP_DEBUGF(SOCKETS_DEBUG, 560 ("lwip_recvfrom(%d): buf == NULL!\n", s)); 561 sock_set_errno(sock, 562 (((sock->conn->pcb.ip != NULL) 563 && (sock->conn->err == ERR_OK)) 564 ? ETIMEDOUT : err_to_errno(sock->conn->err))); 565 return 0; 566 } 567 } 568 569 buflen = netbuf_len(buf); 570 LWIP_DEBUGF(SOCKETS_DEBUG, 571 ("lwip_recvfrom: buflen=%" U16_F " len=%" SZT_F " off=%" 572 U16_F " sock->lastoffset=%" U16_F "\n", buflen, len, off, 573 sock->lastoffset)); 574 575 buflen -= sock->lastoffset; 576 577 if (len > buflen) { 578 copylen = buflen; 579 } else { 580 copylen = (u16_t) len; 581 } 582 583 /* copy the contents of the received buffer into 584 the supplied memory pointer mem */ 585 netbuf_copy_partial(buf, (u8_t *) mem + off, copylen, sock->lastoffset); 586 587 off += copylen; 588 589 if (netconn_type(sock->conn) == NETCONN_TCP) { 590 LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); 591 len -= copylen; 592 if ((len <= 0) || 593 (buf->p->flags & PBUF_FLAG_PUSH) || 594 (sock->rcvevent <= 0) || ((flags & MSG_PEEK) != 0)) { 595 done = 1; 596 } 597 } else { 598 done = 1; 599 } 600 601 /* Check to see from where the data was. */ 602 if (done) { 603 if (from && fromlen) { 604 struct sockaddr_in sin; 605 606 if (netconn_type(sock->conn) == NETCONN_TCP) { 607 addr = (struct ip_addr *) &(sin.sin_addr.s_addr); 608 netconn_getaddr(sock->conn, addr, &port, 0); 609 } else { 610 addr = netbuf_fromaddr(buf); 611 port = netbuf_fromport(buf); 612 } 613 614 memset(&sin, 0, sizeof(sin)); 615 sin.sin_len = sizeof(sin); 616 sin.sin_family = AF_INET; 617 sin.sin_port = htons(port); 618 sin.sin_addr.s_addr = addr->addr; 619 620 if (*fromlen > sizeof(sin)) { 621 *fromlen = sizeof(sin); 622 } 623 624 MEMCPY(from, &sin, *fromlen); 625 626 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); 627 ip_addr_debug_print(SOCKETS_DEBUG, addr); 628 LWIP_DEBUGF(SOCKETS_DEBUG, 629 (" port=%" U16_F " len=%" U16_F "\n", port, off)); 630 } else { 631#if SOCKETS_DEBUG 632 struct sockaddr_in sin; 633 634 if (netconn_type(sock->conn) == NETCONN_TCP) { 635 addr = (struct ip_addr *) &(sin.sin_addr.s_addr); 636 netconn_getaddr(sock->conn, addr, &port, 0); 637 } else { 638 addr = netbuf_fromaddr(buf); 639 port = netbuf_fromport(buf); 640 } 641 642 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); 643 ip_addr_debug_print(SOCKETS_DEBUG, addr); 644 LWIP_DEBUGF(SOCKETS_DEBUG, 645 (" port=%" U16_F " len=%" U16_F "\n", port, off)); 646#endif /* SOCKETS_DEBUG */ 647 } 648 } 649 650 /* If we don't peek the incoming message... */ 651 if ((flags & MSG_PEEK) == 0) { 652 /* If this is a TCP socket, check if there is data left in the 653 buffer. If so, it should be saved in the sock structure for next 654 time around. */ 655 if ((netconn_type(sock->conn) == NETCONN_TCP) 656 && (buflen - copylen > 0)) { 657 sock->lastdata = buf; 658 sock->lastoffset += copylen; 659 LWIP_DEBUGF(SOCKETS_DEBUG, 660 ("lwip_recvfrom: lastdata now netbuf=%p\n", 661 (void *) buf)); 662 } else { 663 sock->lastdata = NULL; 664 sock->lastoffset = 0; 665 LWIP_DEBUGF(SOCKETS_DEBUG, 666 ("lwip_recvfrom: deleting netbuf=%p\n", 667 (void *) buf)); 668 netbuf_delete(buf); 669 } 670 } 671 } while (!done); 672 673 sock_set_errno(sock, 0); 674 return off; 675} 676 677int lwip_read(int s, void *mem, size_t len) 678{ 679 return lwip_recvfrom(s, mem, len, 0, NULL, NULL); 680} 681 682int lwip_recv(int s, void *mem, size_t len, int flags) 683{ 684 return lwip_recvfrom(s, mem, len, flags, NULL, NULL); 685} 686 687int lwip_send(int s, const void *data, size_t size, int flags) 688{ 689 struct lwip_socket *sock; 690 err_t err; 691 692 LWIP_DEBUGF(SOCKETS_DEBUG, 693 ("lwip_send(%d, data=%p, size=%" SZT_F ", flags=0x%x)\n", s, 694 data, size, flags)); 695 696 sock = get_socket(s); 697 if (!sock) 698 return -1; 699 700 if (sock->conn->type != NETCONN_TCP) { 701#if (LWIP_UDP || LWIP_RAW) 702 return lwip_sendto(s, data, size, flags, NULL, 0); 703#else 704 sock_set_errno(sock, err_to_errno(ERR_ARG)); 705 return -1; 706#endif /* (LWIP_UDP || LWIP_RAW) */ 707 } 708 709 err = 710 netconn_write(sock->conn, data, size, 711 NETCONN_COPY | ((flags & MSG_MORE) ? NETCONN_MORE : 0)); 712 713 LWIP_DEBUGF(SOCKETS_DEBUG, 714 ("lwip_send(%d) err=%d size=%" SZT_F "\n", s, err, size)); 715 sock_set_errno(sock, err_to_errno(err)); 716 return (err == ERR_OK ? (int) size : -1); 717} 718 719// XXX: Here for upwards-compatibility with lwIP 1.4.1 720int 721lwip_fcntl(int fd, int cmd, int val) 722{ 723 assert(!"NYI"); 724} 725 726int 727lwip_sendto(int s, const void *data, size_t size, int flags, 728 const struct sockaddr *to, socklen_t tolen) 729{ 730 struct lwip_socket *sock; 731 struct ip_addr remote_addr; 732 err_t err; 733 u16_t short_size; 734 735#if !LWIP_TCPIP_CORE_LOCKING 736 struct netbuf buf; 737 u16_t remote_port; 738#endif 739 740 sock = get_socket(s); 741 if (!sock) 742 return -1; 743 744 if (sock->conn->type == NETCONN_TCP) { 745#if LWIP_TCP 746 return lwip_send(s, data, size, flags); 747#else 748 sock_set_errno(sock, err_to_errno(ERR_ARG)); 749 return -1; 750#endif /* LWIP_TCP */ 751 } 752 753 LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); 754 short_size = (u16_t) size; 755 LWIP_ERROR("lwip_sendto: invalid address", 756 (((to == NULL) && (tolen == 0)) 757 || ((tolen == sizeof(struct sockaddr_in)) 758 && ((((const struct sockaddr_in *) to)->sin_family) == 759 AF_INET))), sock_set_errno(sock, err_to_errno(ERR_ARG)); 760 return -1; 761 ); 762 763#if LWIP_TCPIP_CORE_LOCKING 764 /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */ 765 { 766 struct pbuf *p; 767 768 p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); 769 if (p == NULL) { 770 err = ERR_MEM; 771 } else { 772 p->payload = (void *) data; 773 p->len = p->tot_len = short_size; 774 775 remote_addr.addr = 776 ((const struct sockaddr_in *) to)->sin_addr.s_addr; 777 778 LOCK_TCPIP_CORE(); 779 if (sock->conn->type == NETCONN_RAW) { 780 err = sock->conn->err = 781 raw_sendto(sock->conn->pcb.raw, p, &remote_addr); 782 } else { 783 err = sock->conn->err = 784 udp_sendto(sock->conn->pcb.udp, p, &remote_addr, 785 ntohs(((const struct sockaddr_in *) to)-> 786 sin_port)); 787 } 788 UNLOCK_TCPIP_CORE(); 789 790 pbuf_free(p); 791 } 792 } 793#else 794 /* initialize a buffer */ 795 buf.p = buf.ptr = NULL; 796 if (to) { 797 remote_addr.addr = ((const struct sockaddr_in *) to)->sin_addr.s_addr; 798 remote_port = ntohs(((const struct sockaddr_in *) to)->sin_port); 799 buf.addr = &remote_addr; 800 buf.port = remote_port; 801 } else { 802 remote_addr.addr = 0; 803 remote_port = 0; 804 buf.addr = NULL; 805 buf.port = 0; 806 } 807 808 LWIP_DEBUGF(SOCKETS_DEBUG, 809 ("lwip_sendto(%d, data=%p, short_size=%d" U16_F 810 ", flags=0x%x to=", s, data, short_size, flags)); 811 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); 812 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%" U16_F "\n", remote_port)); 813 814 /* make the buffer point to the data that should be sent */ 815#if LWIP_NETIF_TX_SINGLE_PBUF 816 /* Allocate a new netbuf and copy the data into it. */ 817 if (netbuf_alloc(&buf, short_size) == NULL) { 818 err = ERR_MEM; 819 } else { 820 err = netbuf_take(&buf, data, short_size); 821 } 822#else /* LWIP_NETIF_TX_SINGLE_PBUF */ 823 err = netbuf_ref(&buf, data, short_size); 824#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ 825 if (err == ERR_OK) { 826 /* send the data */ 827 err = netconn_send(sock->conn, &buf); 828 } 829 830 /* deallocated the buffer */ 831 netbuf_free(&buf); 832#endif /* LWIP_TCPIP_CORE_LOCKING */ 833 sock_set_errno(sock, err_to_errno(err)); 834 return (err == ERR_OK ? short_size : -1); 835} 836 837int lwip_sendmsg(int sockfd, const struct msghdr *msg, int flags) 838{ 839 assert(!"NYI"); 840} 841 842int lwip_socket(int domain, int type, int protocol) 843{ 844 struct netconn *conn; 845 int i; 846 847 LWIP_UNUSED_ARG(domain); 848 849 /* create a netconn */ 850 switch (type) { 851 case SOCK_RAW: 852 conn = 853 netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t) protocol, 854 event_callback); 855 LWIP_DEBUGF(SOCKETS_DEBUG, 856 ("lwip_socket(%s, SOCK_RAW, %d) = ", 857 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); 858 break; 859 case SOCK_DGRAM: 860 conn = netconn_new_with_callback((protocol == IPPROTO_UDPLITE) ? 861 NETCONN_UDPLITE : NETCONN_UDP, 862 event_callback); 863 LWIP_DEBUGF(SOCKETS_DEBUG, 864 ("lwip_socket(%s, SOCK_DGRAM, %d) = ", 865 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); 866 break; 867 case SOCK_STREAM: 868 conn = netconn_new_with_callback(NETCONN_TCP, event_callback); 869 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", 870 domain == 871 PF_INET ? "PF_INET" : "UNKNOWN", 872 protocol)); 873 break; 874 default: 875 LWIP_DEBUGF(SOCKETS_DEBUG, 876 ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, 877 protocol)); 878 set_errno(EINVAL); 879 return -1; 880 } 881 882 if (!conn) { 883 LWIP_DEBUGF(SOCKETS_DEBUG, 884 ("-1 / ENOBUFS (could not create netconn)\n")); 885 set_errno(ENOBUFS); 886 return -1; 887 } 888 889 i = alloc_socket(conn); 890 891 if (i == -1) { 892 netconn_delete(conn); 893 set_errno(ENFILE); 894 return -1; 895 } 896 conn->socket = i; 897 LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); 898 set_errno(0); 899 return i; 900} 901 902int lwip_write(int s, const void *data, size_t size) 903{ 904 return lwip_send(s, data, size, 0); 905} 906 907/** 908 * Go through the readset and writeset lists and see which socket of the sockets 909 * set in the sets has events. On return, readset, writeset and exceptset have 910 * the sockets enabled that had events. 911 * 912 * exceptset is not used for now!!! 913 * 914 * @param maxfdp1 the highest socket index in the sets 915 * @param readset in: set of sockets to check for read events; 916 * out: set of sockets that had read events 917 * @param writeset in: set of sockets to check for write events; 918 * out: set of sockets that had write events 919 * @param exceptset not yet implemented 920 * @return number of sockets that had events (read+write) 921 */ 922static int 923lwip_selscan(int maxfdp1, fd_set * readset, fd_set * writeset, 924 fd_set * exceptset) 925{ 926 int i, nready = 0; 927 fd_set lreadset, lwriteset, lexceptset; 928 struct lwip_socket *p_sock; 929 930 FD_ZERO(&lreadset); 931 FD_ZERO(&lwriteset); 932 FD_ZERO(&lexceptset); 933 934 /* Go through each socket in each list to count number of sockets which 935 currently match */ 936 for (i = 0; i < maxfdp1; i++) { 937 if (FD_ISSET(i, readset)) { 938 /* See if netconn of this socket is ready for read */ 939 p_sock = get_socket(i); 940 if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) { 941 FD_SET(i, &lreadset); 942 LWIP_DEBUGF(SOCKETS_DEBUG, 943 ("lwip_selscan: fd=%d ready for reading\n", i)); 944 nready++; 945 } 946 } 947 if (FD_ISSET(i, writeset)) { 948 /* See if netconn of this socket is ready for write */ 949 p_sock = get_socket(i); 950 if (p_sock && p_sock->sendevent) { 951 FD_SET(i, &lwriteset); 952 LWIP_DEBUGF(SOCKETS_DEBUG, 953 ("lwip_selscan: fd=%d ready for writing\n", i)); 954 nready++; 955 } 956 } 957 } 958 *readset = lreadset; 959 *writeset = lwriteset; 960 FD_ZERO(exceptset); 961 962 return nready; 963} 964 965 966/** 967 * Processing exceptset is not yet implemented. 968 */ 969int 970lwip_select(int maxfdp1, fd_set * readset, fd_set * writeset, 971 fd_set * exceptset, struct timeval *timeout) 972{ 973 int i; 974 int nready; 975 fd_set lreadset, lwriteset, lexceptset; 976 u32_t msectimeout; 977 struct lwip_select_cb select_cb; 978 struct lwip_select_cb *p_selcb; 979 980 LWIP_DEBUGF(SOCKETS_DEBUG, 981 ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", maxfdp1, 982 (void *) readset, (void *) writeset, (void *) exceptset, 983 timeout ? (long) timeout->tv_sec : (long) -1, 984 timeout ? (long) timeout->tv_usec : (long) -1)); 985 986 select_cb.next = 0; 987 select_cb.readset = readset; 988 select_cb.writeset = writeset; 989 select_cb.exceptset = exceptset; 990 select_cb.sem_signalled = 0; 991 992 /* Protect ourselves searching through the list */ 993 sys_sem_wait(selectsem); 994 995 if (readset) 996 lreadset = *readset; 997 else 998 FD_ZERO(&lreadset); 999 if (writeset) 1000 lwriteset = *writeset; 1001 else 1002 FD_ZERO(&lwriteset); 1003 if (exceptset) 1004 lexceptset = *exceptset; 1005 else 1006 FD_ZERO(&lexceptset); 1007 1008 /* Go through each socket in each list to count number of sockets which 1009 currently match */ 1010 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); 1011 1012 /* If we don't have any current events, then suspend if we are supposed to */ 1013 if (!nready) { 1014 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { 1015 sys_sem_signal(selectsem); 1016 if (readset) 1017 FD_ZERO(readset); 1018 if (writeset) 1019 FD_ZERO(writeset); 1020 if (exceptset) 1021 FD_ZERO(exceptset); 1022 1023 LWIP_DEBUGF(SOCKETS_DEBUG, 1024 ("lwip_select: no timeout, returning 0\n")); 1025 set_errno(0); 1026 1027 return 0; 1028 } 1029 1030 /* add our semaphore to list */ 1031 /* We don't actually need any dynamic memory. Our entry on the 1032 * list is only valid while we are in this function, so it's ok 1033 * to use local variables */ 1034 1035 select_cb.sem = sys_sem_new(0); 1036 /* Note that we are still protected */ 1037 /* Put this select_cb on top of list */ 1038 select_cb.next = select_cb_list; 1039 select_cb_list = &select_cb; 1040 1041 /* Now we can safely unprotect */ 1042 sys_sem_signal(selectsem); 1043 1044 /* Now just wait to be woken */ 1045 if (timeout == 0) 1046 /* Wait forever */ 1047 msectimeout = 0; 1048 else { 1049 msectimeout = 1050 ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500) / 1000)); 1051 if (msectimeout == 0) 1052 msectimeout = 1; 1053 } 1054 1055 lwip_mutex_unlock(); 1056 i = sys_sem_wait_timeout(select_cb.sem, msectimeout); 1057 lwip_mutex_lock(); 1058 1059 /* Take us off the list */ 1060 sys_sem_wait(selectsem); 1061 if (select_cb_list == &select_cb) 1062 select_cb_list = select_cb.next; 1063 else 1064 for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) { 1065 if (p_selcb->next == &select_cb) { 1066 p_selcb->next = select_cb.next; 1067 break; 1068 } 1069 } 1070 1071 sys_sem_signal(selectsem); 1072 1073 sys_sem_free(select_cb.sem); 1074 if (i == 0) { 1075 /* Timeout */ 1076 if (readset) 1077 FD_ZERO(readset); 1078 if (writeset) 1079 FD_ZERO(writeset); 1080 if (exceptset) 1081 FD_ZERO(exceptset); 1082 1083 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); 1084 set_errno(0); 1085 1086 return 0; 1087 } 1088 1089 if (readset) 1090 lreadset = *readset; 1091 else 1092 FD_ZERO(&lreadset); 1093 if (writeset) 1094 lwriteset = *writeset; 1095 else 1096 FD_ZERO(&lwriteset); 1097 if (exceptset) 1098 lexceptset = *exceptset; 1099 else 1100 FD_ZERO(&lexceptset); 1101 1102 /* See what's set */ 1103 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); 1104 } else 1105 sys_sem_signal(selectsem); 1106 1107 if (readset) 1108 *readset = lreadset; 1109 if (writeset) 1110 *writeset = lwriteset; 1111 if (exceptset) 1112 *exceptset = lexceptset; 1113 1114 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); 1115 set_errno(0); 1116 1117 return nready; 1118} 1119 1120/** 1121 * Callback registered in the netconn layer for each socket-netconn. 1122 * Processes recvevent (data available) and wakes up tasks waiting for select. 1123 */ 1124static void 1125event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) 1126{ 1127 int s; 1128 struct lwip_socket *sock; 1129 struct lwip_select_cb *scb; 1130 1131#ifdef BF_LWIP_CHAN_SUPPORT 1132 errval_t err; 1133#endif /* BF_LWIP_CHAN_SUPPORT */ 1134 1135 LWIP_UNUSED_ARG(len); 1136 1137 /* Get socket */ 1138 if (conn) { 1139 s = conn->socket; 1140 if (s < 0) { 1141 /* Data comes in right away after an accept, even though 1142 * the server task might not have created a new socket yet. 1143 * Just count down (or up) if that's the case and we 1144 * will use the data later. Note that only receive events 1145 * can happen before the new socket is set up. */ 1146 sys_sem_wait(socksem); 1147 if (conn->socket < 0) { 1148 if (evt == NETCONN_EVT_RCVPLUS) { 1149 conn->socket--; 1150 } 1151 sys_sem_signal(socksem); 1152 return; 1153 } 1154 sys_sem_signal(socksem); 1155 } 1156 1157 sock = get_socket(s); 1158 if (!sock) { 1159 return; 1160 } 1161 } else { 1162 return; 1163 } 1164 1165 sys_sem_wait(selectsem); 1166 /* Set event as required */ 1167 switch (evt) { 1168 case NETCONN_EVT_RCVPLUS: 1169 sock->rcvevent++; 1170#ifdef BF_LWIP_CHAN_SUPPORT 1171 /* If the recv channel is associated with a waitset, trigger an 1172 * event. */ 1173 if (waitset_chan_is_registered(&sock->recv_chanstate)) { 1174 err = waitset_chan_trigger(&sock->recv_chanstate); 1175 assert(err_is_ok(err)); 1176 } 1177#endif /* BF_LWIP_CHAN_SUPPORT */ 1178 break; 1179 case NETCONN_EVT_RCVMINUS: 1180 sock->rcvevent--; 1181 break; 1182 case NETCONN_EVT_SENDPLUS: 1183 sock->sendevent = 1; 1184 break; 1185 case NETCONN_EVT_SENDMINUS: 1186 sock->sendevent = 0; 1187#ifdef BF_LWIP_CHAN_SUPPORT 1188 /* If the send channel is associated with a waitset, trigger an 1189 * event. */ 1190 if (waitset_chan_is_registered(&sock->send_chanstate)) { 1191 err = waitset_chan_trigger(&sock->send_chanstate); 1192 assert(err_is_ok(err)); 1193 } 1194#endif /* BF_LWIP_CHAN_SUPPORT */ 1195 break; 1196 default: 1197 LWIP_ASSERT("unknown event", 0); 1198 break; 1199 } 1200 sys_sem_signal(selectsem); 1201 1202 /* Now decide if anyone is waiting for this socket */ 1203 /* NOTE: This code is written this way to protect the select link list 1204 but to avoid a deadlock situation by releasing socksem before 1205 signalling for the select. This means we need to go through the list 1206 multiple times ONLY IF a select was actually waiting. We go through 1207 the list the number of waiting select calls + 1. This list is 1208 expected to be small. */ 1209 while (1) { 1210 sys_sem_wait(selectsem); 1211 for (scb = select_cb_list; scb; scb = scb->next) { 1212 if (scb->sem_signalled == 0) { 1213 /* Test this select call for our socket */ 1214 if (scb->readset && FD_ISSET(s, scb->readset)) 1215 if (sock->rcvevent > 0) 1216 break; 1217 if (scb->writeset && FD_ISSET(s, scb->writeset)) 1218 if (sock->sendevent) 1219 break; 1220 } 1221 } 1222 if (scb) { 1223 scb->sem_signalled = 1; 1224 sys_sem_signal(scb->sem); 1225 sys_sem_signal(selectsem); 1226 } else { 1227 sys_sem_signal(selectsem); 1228 break; 1229 } 1230 } 1231} 1232 1233/** 1234 * Unimplemented: Close one end of a full-duplex connection. 1235 * Currently, the full connection is closed. 1236 */ 1237int lwip_shutdown(int s, int how) 1238{ 1239 LWIP_UNUSED_ARG(how); 1240 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); 1241 return lwip_close(s); /* XXX temporary hack until proper implementation */ 1242} 1243 1244static int 1245lwip_getaddrname(int s, struct sockaddr *name, socklen_t * namelen, u8_t local) 1246{ 1247 struct lwip_socket *sock; 1248 struct sockaddr_in sin; 1249 struct ip_addr naddr; 1250 1251 sock = get_socket(s); 1252 if (!sock) 1253 return -1; 1254 1255 memset(&sin, 0, sizeof(sin)); 1256 sin.sin_len = sizeof(sin); 1257 sin.sin_family = AF_INET; 1258 1259 /* get the IP address and port */ 1260 netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local); 1261 1262 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); 1263 ip_addr_debug_print(SOCKETS_DEBUG, &naddr); 1264 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%" U16_F ")\n", sin.sin_port)); 1265 1266 sin.sin_port = htons(sin.sin_port); 1267 sin.sin_addr.s_addr = naddr.addr; 1268 1269 if (*namelen > sizeof(sin)) 1270 *namelen = sizeof(sin); 1271 1272 MEMCPY(name, &sin, *namelen); 1273 sock_set_errno(sock, 0); 1274 return 0; 1275} 1276 1277int lwip_getpeername(int s, struct sockaddr *name, socklen_t * namelen) 1278{ 1279 return lwip_getaddrname(s, name, namelen, 0); 1280} 1281 1282int lwip_getsockname(int s, struct sockaddr *name, socklen_t * namelen) 1283{ 1284 return lwip_getaddrname(s, name, namelen, 1); 1285} 1286 1287int 1288lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t * optlen) 1289{ 1290 err_t err = ERR_OK; 1291 struct lwip_socket *sock = get_socket(s); 1292 struct lwip_setgetsockopt_data data; 1293 1294 if (!sock) 1295 return -1; 1296 1297 if ((NULL == optval) || (NULL == optlen)) { 1298 sock_set_errno(sock, EFAULT); 1299 return -1; 1300 } 1301 1302 /* Do length and type checks for the various options first, to keep it readable. */ 1303 switch (level) { 1304 1305/* Level: SOL_SOCKET */ 1306 case SOL_SOCKET: 1307 switch (optname) { 1308 1309 case SO_ACCEPTCONN: 1310 case SO_BROADCAST: 1311 /* UNIMPL case SO_DEBUG: */ 1312 /* UNIMPL case SO_DONTROUTE: */ 1313 case SO_ERROR: 1314 case SO_KEEPALIVE: 1315 /* UNIMPL case SO_CONTIMEO: */ 1316 /* UNIMPL case SO_SNDTIMEO: */ 1317#if LWIP_SO_RCVTIMEO 1318 case SO_RCVTIMEO: 1319#endif /* LWIP_SO_RCVTIMEO */ 1320#if LWIP_SO_RCVBUF 1321 case SO_RCVBUF: 1322#endif /* LWIP_SO_RCVBUF */ 1323 /* UNIMPL case SO_OOBINLINE: */ 1324 /* UNIMPL case SO_SNDBUF: */ 1325 /* UNIMPL case SO_RCVLOWAT: */ 1326 /* UNIMPL case SO_SNDLOWAT: */ 1327#if SO_REUSE 1328 case SO_REUSEADDR: 1329 case SO_REUSEPORT: 1330#endif /* SO_REUSE */ 1331 case SO_TYPE: 1332 /* UNIMPL case SO_USELOOPBACK: */ 1333 if (*optlen < sizeof(int)) { 1334 err = EINVAL; 1335 } 1336 break; 1337 1338 case SO_NO_CHECK: 1339 if (*optlen < sizeof(int)) { 1340 err = EINVAL; 1341 } 1342#if LWIP_UDP 1343 if ((sock->conn->type != NETCONN_UDP) || 1344 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 1345 0)) { 1346 /* this flag is only available for UDP, not for UDP lite */ 1347 err = EAFNOSUPPORT; 1348 } 1349#endif /* LWIP_UDP */ 1350 break; 1351 1352 default: 1353 LWIP_DEBUGF(SOCKETS_DEBUG, 1354 ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", 1355 s, optname)); 1356 err = ENOPROTOOPT; 1357 } /* switch (optname) */ 1358 break; 1359 1360/* Level: IPPROTO_IP */ 1361 case IPPROTO_IP: 1362 switch (optname) { 1363 /* UNIMPL case IP_HDRINCL: */ 1364 /* UNIMPL case IP_RCVDSTADDR: */ 1365 /* UNIMPL case IP_RCVIF: */ 1366 case IP_TTL: 1367 case IP_TOS: 1368 if (*optlen < sizeof(int)) { 1369 err = EINVAL; 1370 } 1371 break; 1372#if LWIP_IGMP 1373 case IP_MULTICAST_TTL: 1374 if (*optlen < sizeof(u8_t)) { 1375 err = EINVAL; 1376 } 1377 break; 1378 case IP_MULTICAST_IF: 1379 if (*optlen < sizeof(struct in_addr)) { 1380 err = EINVAL; 1381 } 1382 break; 1383#endif /* LWIP_IGMP */ 1384 1385 default: 1386 LWIP_DEBUGF(SOCKETS_DEBUG, 1387 ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", 1388 s, optname)); 1389 err = ENOPROTOOPT; 1390 } /* switch (optname) */ 1391 break; 1392 1393#if LWIP_TCP 1394/* Level: IPPROTO_TCP */ 1395 case IPPROTO_TCP: 1396 if (*optlen < sizeof(int)) { 1397 err = EINVAL; 1398 break; 1399 } 1400 1401 /* If this is no TCP socket, ignore any options. */ 1402 if (sock->conn->type != NETCONN_TCP) 1403 return 0; 1404 1405 switch (optname) { 1406 case TCP_NODELAY: 1407 case TCP_KEEPALIVE: 1408#if LWIP_TCP_KEEPALIVE 1409 case TCP_KEEPIDLE: 1410 case TCP_KEEPINTVL: 1411 case TCP_KEEPCNT: 1412#endif /* LWIP_TCP_KEEPALIVE */ 1413 break; 1414 1415 default: 1416 LWIP_DEBUGF(SOCKETS_DEBUG, 1417 ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", 1418 s, optname)); 1419 err = ENOPROTOOPT; 1420 } /* switch (optname) */ 1421 break; 1422#endif /* LWIP_TCP */ 1423#if LWIP_UDP && LWIP_UDPLITE 1424/* Level: IPPROTO_UDPLITE */ 1425 case IPPROTO_UDPLITE: 1426 if (*optlen < sizeof(int)) { 1427 err = EINVAL; 1428 break; 1429 } 1430 1431 /* If this is no UDP lite socket, ignore any options. */ 1432 if (sock->conn->type != NETCONN_UDPLITE) 1433 return 0; 1434 1435 switch (optname) { 1436 case UDPLITE_SEND_CSCOV: 1437 case UDPLITE_RECV_CSCOV: 1438 break; 1439 1440 default: 1441 LWIP_DEBUGF(SOCKETS_DEBUG, 1442 ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", 1443 s, optname)); 1444 err = ENOPROTOOPT; 1445 } /* switch (optname) */ 1446 break; 1447#endif /* LWIP_UDP && LWIP_UDPLITE */ 1448/* UNDEFINED LEVEL */ 1449 default: 1450 LWIP_DEBUGF(SOCKETS_DEBUG, 1451 ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", 1452 s, level, optname)); 1453 err = ENOPROTOOPT; 1454 } /* switch */ 1455 1456 1457 if (err != ERR_OK) { 1458 sock_set_errno(sock, err); 1459 return -1; 1460 } 1461 /* Now do the actual option processing */ 1462 data.sock = sock; 1463 data.level = level; 1464 data.optname = optname; 1465 data.optval = optval; 1466 data.optlen = optlen; 1467 data.err = err; 1468 tcpip_callback(lwip_getsockopt_internal, &data); 1469 sys_arch_sem_wait(sock->conn->op_completed, 0); 1470 /* maybe lwip_getsockopt_internal has changed err */ 1471 err = data.err; 1472 1473 sock_set_errno(sock, err); 1474 return err ? -1 : 0; 1475} 1476 1477static void lwip_getsockopt_internal(void *arg) 1478{ 1479 struct lwip_socket *sock; 1480 1481#ifdef LWIP_DEBUG 1482 int s; 1483#endif /* LWIP_DEBUG */ 1484 int level, optname; 1485 void *optval; 1486 struct lwip_setgetsockopt_data *data; 1487 1488 LWIP_ASSERT("arg != NULL", arg != NULL); 1489 1490 data = (struct lwip_setgetsockopt_data *) arg; 1491 sock = data->sock; 1492#ifdef LWIP_DEBUG 1493 s = data->s; 1494#endif /* LWIP_DEBUG */ 1495 level = data->level; 1496 optname = data->optname; 1497 optval = data->optval; 1498 1499 switch (level) { 1500 1501/* Level: SOL_SOCKET */ 1502 case SOL_SOCKET: 1503 switch (optname) { 1504 1505 /* The option flags */ 1506 case SO_ACCEPTCONN: 1507 case SO_BROADCAST: 1508 /* UNIMPL case SO_DEBUG: */ 1509 /* UNIMPL case SO_DONTROUTE: */ 1510 case SO_KEEPALIVE: 1511 /* UNIMPL case SO_OOBINCLUDE: */ 1512#if SO_REUSE 1513 case SO_REUSEADDR: 1514 case SO_REUSEPORT: 1515#endif /* SO_REUSE */ 1516 /*case SO_USELOOPBACK: UNIMPL */ 1517 *(int *) optval = sock->conn->pcb.ip->so_options & optname; 1518 LWIP_DEBUGF(SOCKETS_DEBUG, 1519 ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", 1520 s, optname, (*(int *) optval ? "on" : "off"))); 1521 break; 1522 1523 case SO_TYPE: 1524 switch (NETCONNTYPE_GROUP(sock->conn->type)) { 1525 case NETCONN_RAW: 1526 *(int *) optval = SOCK_RAW; 1527 break; 1528 case NETCONN_TCP: 1529 *(int *) optval = SOCK_STREAM; 1530 break; 1531 case NETCONN_UDP: 1532 *(int *) optval = SOCK_DGRAM; 1533 break; 1534 default: /* unrecognized socket type */ 1535 *(int *) optval = sock->conn->type; 1536 LWIP_DEBUGF(SOCKETS_DEBUG, 1537 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", 1538 s, *(int *) optval)); 1539 } /* switch (sock->conn->type) */ 1540 LWIP_DEBUGF(SOCKETS_DEBUG, 1541 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", 1542 s, *(int *) optval)); 1543 break; 1544 1545 case SO_ERROR: 1546 if (sock->err == 0) { 1547 sock_set_errno(sock, err_to_errno(sock->conn->err)); 1548 } 1549 *(int *) optval = sock->err; 1550 sock->err = 0; 1551 LWIP_DEBUGF(SOCKETS_DEBUG, 1552 ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", 1553 s, *(int *) optval)); 1554 break; 1555 1556#if LWIP_SO_RCVTIMEO 1557 case SO_RCVTIMEO: 1558 *(int *) optval = sock->conn->recv_timeout; 1559 break; 1560#endif /* LWIP_SO_RCVTIMEO */ 1561#if LWIP_SO_RCVBUF 1562 case SO_RCVBUF: 1563 *(int *) optval = sock->conn->recv_bufsize; 1564 break; 1565#endif /* LWIP_SO_RCVBUF */ 1566#if LWIP_UDP 1567 case SO_NO_CHECK: 1568 *(int *) optval = 1569 (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 1570 : 0; 1571 break; 1572#endif /* LWIP_UDP */ 1573 } /* switch (optname) */ 1574 break; 1575 1576/* Level: IPPROTO_IP */ 1577 case IPPROTO_IP: 1578 switch (optname) { 1579 case IP_TTL: 1580 *(int *) optval = sock->conn->pcb.ip->ttl; 1581 LWIP_DEBUGF(SOCKETS_DEBUG, 1582 ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", 1583 s, *(int *) optval)); 1584 break; 1585 case IP_TOS: 1586 *(int *) optval = sock->conn->pcb.ip->tos; 1587 LWIP_DEBUGF(SOCKETS_DEBUG, 1588 ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", 1589 s, *(int *) optval)); 1590 break; 1591#if LWIP_IGMP 1592 case IP_MULTICAST_TTL: 1593 *(u8_t *) optval = sock->conn->pcb.ip->ttl; 1594 LWIP_DEBUGF(SOCKETS_DEBUG, 1595 ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", 1596 s, *(int *) optval)); 1597 break; 1598 case IP_MULTICAST_IF: 1599 ((struct in_addr *) optval)->s_addr = 1600 sock->conn->pcb.udp->multicast_ip.addr; 1601 LWIP_DEBUGF(SOCKETS_DEBUG, 1602 ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%" 1603 X32_F "\n", s, *(u32_t *) optval)); 1604 break; 1605#endif /* LWIP_IGMP */ 1606 } /* switch (optname) */ 1607 break; 1608 1609#if LWIP_TCP 1610/* Level: IPPROTO_TCP */ 1611 case IPPROTO_TCP: 1612 switch (optname) { 1613 case TCP_NODELAY: 1614 *(int *) optval = (sock->conn->pcb.tcp->flags & TF_NODELAY); 1615 LWIP_DEBUGF(SOCKETS_DEBUG, 1616 ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", 1617 s, (*(int *) optval) ? "on" : "off")); 1618 break; 1619 case TCP_KEEPALIVE: 1620 *(int *) optval = (int) sock->conn->pcb.tcp->keep_idle; 1621 LWIP_DEBUGF(SOCKETS_DEBUG, 1622 ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", 1623 s, *(int *) optval)); 1624 break; 1625 1626#if LWIP_TCP_KEEPALIVE 1627 case TCP_KEEPIDLE: 1628 *(int *) optval = 1629 (int) (sock->conn->pcb.tcp->keep_idle / 1000); 1630 LWIP_DEBUGF(SOCKETS_DEBUG, 1631 ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n", 1632 s, *(int *) optval)); 1633 break; 1634 case TCP_KEEPINTVL: 1635 *(int *) optval = 1636 (int) (sock->conn->pcb.tcp->keep_intvl / 1000); 1637 LWIP_DEBUGF(SOCKETS_DEBUG, 1638 ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n", 1639 s, *(int *) optval)); 1640 break; 1641 case TCP_KEEPCNT: 1642 *(int *) optval = (int) sock->conn->pcb.tcp->keep_cnt; 1643 LWIP_DEBUGF(SOCKETS_DEBUG, 1644 ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n", 1645 s, *(int *) optval)); 1646 break; 1647#endif /* LWIP_TCP_KEEPALIVE */ 1648 1649 } /* switch (optname) */ 1650 break; 1651#endif /* LWIP_TCP */ 1652#if LWIP_UDP && LWIP_UDPLITE 1653 /* Level: IPPROTO_UDPLITE */ 1654 case IPPROTO_UDPLITE: 1655 switch (optname) { 1656 case UDPLITE_SEND_CSCOV: 1657 *(int *) optval = sock->conn->pcb.udp->chksum_len_tx; 1658 LWIP_DEBUGF(SOCKETS_DEBUG, 1659 ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", 1660 s, (*(int *) optval))); 1661 break; 1662 case UDPLITE_RECV_CSCOV: 1663 *(int *) optval = sock->conn->pcb.udp->chksum_len_rx; 1664 LWIP_DEBUGF(SOCKETS_DEBUG, 1665 ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", 1666 s, (*(int *) optval))); 1667 break; 1668 } /* switch (optname) */ 1669 break; 1670#endif /* LWIP_UDP */ 1671 } /* switch (level) */ 1672 sys_sem_signal(sock->conn->op_completed); 1673} 1674 1675int 1676lwip_setsockopt(int s, int level, int optname, const void *optval, 1677 socklen_t optlen) 1678{ 1679 struct lwip_socket *sock = get_socket(s); 1680 int err = ERR_OK; 1681 struct lwip_setgetsockopt_data data; 1682 1683 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt: sock is %d\n", sock)); 1684 if (!sock) 1685 return -1; 1686 else 1687 if (NULL == optval) { 1688 sock_set_errno(sock, EFAULT); 1689 return -1; 1690 } 1691 1692 /* Do length and type checks for the various options first, to keep it readable. */ 1693 switch (level) { 1694 1695/* Level: SOL_SOCKET */ 1696 case SOL_SOCKET: 1697 switch (optname) { 1698 1699 case SO_BROADCAST: 1700 /* UNIMPL case SO_DEBUG: */ 1701 /* UNIMPL case SO_DONTROUTE: */ 1702 case SO_KEEPALIVE: 1703 /* UNIMPL case case SO_CONTIMEO: */ 1704 /* UNIMPL case case SO_SNDTIMEO: */ 1705#if LWIP_SO_RCVTIMEO 1706 case SO_RCVTIMEO: 1707#endif /* LWIP_SO_RCVTIMEO */ 1708#if LWIP_SO_RCVBUF 1709 case SO_RCVBUF: 1710#endif /* LWIP_SO_RCVBUF */ 1711 /* UNIMPL case SO_OOBINLINE: */ 1712 /* UNIMPL case SO_SNDBUF: */ 1713 /* UNIMPL case SO_RCVLOWAT: */ 1714 /* UNIMPL case SO_SNDLOWAT: */ 1715#if SO_REUSE 1716 case SO_REUSEADDR: 1717 case SO_REUSEPORT: 1718#endif /* SO_REUSE */ 1719 /* UNIMPL case SO_USELOOPBACK: */ 1720 if (optlen < sizeof(int)) { 1721 err = EINVAL; 1722 } 1723 break; 1724 case SO_NO_CHECK: 1725 if (optlen < sizeof(int)) { 1726 err = EINVAL; 1727 } 1728#if LWIP_UDP 1729 if ((sock->conn->type != NETCONN_UDP) || 1730 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 1731 0)) { 1732 /* this flag is only available for UDP, not for UDP lite */ 1733 err = EAFNOSUPPORT; 1734 } 1735#endif /* LWIP_UDP */ 1736 break; 1737 default: 1738 LWIP_DEBUGF(SOCKETS_DEBUG, 1739 ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", 1740 s, optname)); 1741 err = ENOPROTOOPT; 1742 } /* switch (optname) */ 1743 break; 1744 1745/* Level: IPPROTO_IP */ 1746 case IPPROTO_IP: 1747 switch (optname) { 1748 /* UNIMPL case IP_HDRINCL: */ 1749 /* UNIMPL case IP_RCVDSTADDR: */ 1750 /* UNIMPL case IP_RCVIF: */ 1751 case IP_TTL: 1752 case IP_TOS: 1753 if (optlen < sizeof(int)) { 1754 err = EINVAL; 1755 } 1756 break; 1757#if LWIP_IGMP 1758 case IP_MULTICAST_TTL: 1759 if (optlen < sizeof(u8_t)) { 1760 err = EINVAL; 1761 } 1762 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1763 err = EAFNOSUPPORT; 1764 } 1765 break; 1766 case IP_MULTICAST_IF: 1767 if (optlen < sizeof(struct in_addr)) { 1768 err = EINVAL; 1769 } 1770 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1771 err = EAFNOSUPPORT; 1772 } 1773 break; 1774 case IP_ADD_MEMBERSHIP: 1775 case IP_DROP_MEMBERSHIP: 1776 if (optlen < sizeof(struct ip_mreq)) { 1777 err = EINVAL; 1778 } 1779 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { 1780 err = EAFNOSUPPORT; 1781 } 1782 break; 1783#endif /* LWIP_IGMP */ 1784 default: 1785 LWIP_DEBUGF(SOCKETS_DEBUG, 1786 ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", 1787 s, optname)); 1788 err = ENOPROTOOPT; 1789 } /* switch (optname) */ 1790 break; 1791 1792#if LWIP_TCP 1793/* Level: IPPROTO_TCP */ 1794 case IPPROTO_TCP: 1795 if (optlen < sizeof(int)) { 1796 err = EINVAL; 1797 break; 1798 } 1799 1800 /* If this is no TCP socket, ignore any options. */ 1801 if (sock->conn->type != NETCONN_TCP) 1802 return 0; 1803 1804 switch (optname) { 1805 case TCP_NODELAY: 1806 case TCP_KEEPALIVE: 1807#if LWIP_TCP_KEEPALIVE 1808 case TCP_KEEPIDLE: 1809 case TCP_KEEPINTVL: 1810 case TCP_KEEPCNT: 1811#endif /* LWIP_TCP_KEEPALIVE */ 1812 break; 1813 1814 default: 1815 LWIP_DEBUGF(SOCKETS_DEBUG, 1816 ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", 1817 s, optname)); 1818 err = ENOPROTOOPT; 1819 } /* switch (optname) */ 1820 break; 1821#endif /* LWIP_TCP */ 1822#if LWIP_UDP && LWIP_UDPLITE 1823/* Level: IPPROTO_UDPLITE */ 1824 case IPPROTO_UDPLITE: 1825 if (optlen < sizeof(int)) { 1826 err = EINVAL; 1827 break; 1828 } 1829 1830 /* If this is no UDP lite socket, ignore any options. */ 1831 if (sock->conn->type != NETCONN_UDPLITE) 1832 return 0; 1833 1834 switch (optname) { 1835 case UDPLITE_SEND_CSCOV: 1836 case UDPLITE_RECV_CSCOV: 1837 break; 1838 1839 default: 1840 LWIP_DEBUGF(SOCKETS_DEBUG, 1841 ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", 1842 s, optname)); 1843 err = ENOPROTOOPT; 1844 } /* switch (optname) */ 1845 break; 1846#endif /* LWIP_UDP && LWIP_UDPLITE */ 1847/* UNDEFINED LEVEL */ 1848 default: 1849 LWIP_DEBUGF(SOCKETS_DEBUG, 1850 ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", 1851 s, level, optname)); 1852 err = ENOPROTOOPT; 1853 } /* switch (level) */ 1854 1855 1856 if (err != ERR_OK) { 1857 sock_set_errno(sock, err); 1858 return -1; 1859 } 1860 1861 1862 /* Now do the actual option processing */ 1863 data.sock = sock; 1864 data.level = level; 1865 data.optname = optname; 1866 data.optval = (void *) optval; 1867 data.optlen = &optlen; 1868 data.err = err; 1869 tcpip_callback(lwip_setsockopt_internal, &data); 1870 sys_arch_sem_wait(sock->conn->op_completed, 0); 1871 /* maybe lwip_setsockopt_internal has changed err */ 1872 err = data.err; 1873 1874 sock_set_errno(sock, err); 1875 return err ? -1 : 0; 1876} 1877 1878static void lwip_setsockopt_internal(void *arg) 1879{ 1880 struct lwip_socket *sock; 1881 1882#ifdef LWIP_DEBUG 1883 int s; 1884#endif /* LWIP_DEBUG */ 1885 int level, optname; 1886 const void *optval; 1887 struct lwip_setgetsockopt_data *data; 1888 1889 LWIP_ASSERT("arg != NULL", arg != NULL); 1890 1891 data = (struct lwip_setgetsockopt_data *) arg; 1892 sock = data->sock; 1893#ifdef LWIP_DEBUG 1894 s = data->s; 1895#endif /* LWIP_DEBUG */ 1896 level = data->level; 1897 optname = data->optname; 1898 optval = data->optval; 1899 1900 switch (level) { 1901 1902/* Level: SOL_SOCKET */ 1903 case SOL_SOCKET: 1904 switch (optname) { 1905 1906 /* The option flags */ 1907 case SO_BROADCAST: 1908 /* UNIMPL case SO_DEBUG: */ 1909 /* UNIMPL case SO_DONTROUTE: */ 1910 case SO_KEEPALIVE: 1911 /* UNIMPL case SO_OOBINCLUDE: */ 1912#if SO_REUSE 1913 case SO_REUSEADDR: 1914 case SO_REUSEPORT: 1915#endif /* SO_REUSE */ 1916 /* UNIMPL case SO_USELOOPBACK: */ 1917 if (*(int *) optval) { 1918 sock->conn->pcb.ip->so_options |= optname; 1919 } else { 1920 sock->conn->pcb.ip->so_options &= ~optname; 1921 } 1922 LWIP_DEBUGF(SOCKETS_DEBUG, 1923 ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", 1924 s, optname, (*(int *) optval ? "on" : "off"))); 1925 break; 1926#if LWIP_SO_RCVTIMEO 1927 case SO_RCVTIMEO: 1928 sock->conn->recv_timeout = (*(int *) optval); 1929 break; 1930#endif /* LWIP_SO_RCVTIMEO */ 1931#if LWIP_SO_RCVBUF 1932 case SO_RCVBUF: 1933 sock->conn->recv_bufsize = (*(int *) optval); 1934 break; 1935#endif /* LWIP_SO_RCVBUF */ 1936#if LWIP_UDP 1937 case SO_NO_CHECK: 1938 if (*(int *) optval) { 1939 udp_setflags(sock->conn->pcb.udp, 1940 udp_flags(sock->conn->pcb. 1941 udp) | UDP_FLAGS_NOCHKSUM); 1942 } else { 1943 udp_setflags(sock->conn->pcb.udp, 1944 udp_flags(sock->conn->pcb. 1945 udp) & ~UDP_FLAGS_NOCHKSUM); 1946 } 1947 break; 1948#endif /* LWIP_UDP */ 1949 } /* switch (optname) */ 1950 break; 1951 1952/* Level: IPPROTO_IP */ 1953 case IPPROTO_IP: 1954 switch (optname) { 1955 case IP_TTL: 1956 sock->conn->pcb.ip->ttl = (u8_t) (*(int *) optval); 1957 LWIP_DEBUGF(SOCKETS_DEBUG, 1958 ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", 1959 s, sock->conn->pcb.ip->ttl)); 1960 break; 1961 case IP_TOS: 1962 sock->conn->pcb.ip->tos = (u8_t) (*(int *) optval); 1963 LWIP_DEBUGF(SOCKETS_DEBUG, 1964 ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", 1965 s, sock->conn->pcb.ip->tos)); 1966 break; 1967#if LWIP_IGMP 1968 case IP_MULTICAST_TTL: 1969 sock->conn->pcb.udp->ttl = (u8_t) (*(u8_t *) optval); 1970 break; 1971 case IP_MULTICAST_IF: 1972 sock->conn->pcb.udp->multicast_ip.addr = 1973 ((struct in_addr *) optval)->s_addr; 1974 break; 1975 case IP_ADD_MEMBERSHIP: 1976 case IP_DROP_MEMBERSHIP: 1977 { 1978 /* If this is a TCP or a RAW socket, ignore these options. */ 1979 struct ip_mreq *imr = (struct ip_mreq *) optval; 1980 1981 if (optname == IP_ADD_MEMBERSHIP) { 1982 data->err = 1983 igmp_joingroup((struct ip_addr *) 1984 &(imr->imr_interface.s_addr), 1985 (struct ip_addr *) &(imr-> 1986 imr_multiaddr. 1987 s_addr)); 1988 } else { 1989 data->err = 1990 igmp_leavegroup((struct ip_addr *) 1991 &(imr->imr_interface.s_addr), 1992 (struct ip_addr *) &(imr-> 1993 imr_multiaddr. 1994 s_addr)); 1995 } 1996 if (data->err != ERR_OK) { 1997 data->err = EADDRNOTAVAIL; 1998 } 1999 } 2000 break; 2001#endif /* LWIP_IGMP */ 2002 } /* switch (optname) */ 2003 break; 2004 2005#if LWIP_TCP 2006/* Level: IPPROTO_TCP */ 2007 case IPPROTO_TCP: 2008 switch (optname) { 2009 case TCP_NODELAY: 2010 if (*(int *) optval) { 2011 sock->conn->pcb.tcp->flags |= TF_NODELAY; 2012 } else { 2013 sock->conn->pcb.tcp->flags &= ~TF_NODELAY; 2014 } 2015 LWIP_DEBUGF(SOCKETS_DEBUG, 2016 ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", 2017 s, (*(int *) optval) ? "on" : "off")); 2018 break; 2019 case TCP_KEEPALIVE: 2020 sock->conn->pcb.tcp->keep_idle = (u32_t) (*(int *) optval); 2021 LWIP_DEBUGF(SOCKETS_DEBUG, 2022 ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %" 2023 U32_F "\n", s, 2024 sock->conn->pcb.tcp->keep_idle)); 2025 break; 2026 2027#if LWIP_TCP_KEEPALIVE 2028 case TCP_KEEPIDLE: 2029 sock->conn->pcb.tcp->keep_idle = 2030 1000 * (u32_t) (*(int *) optval); 2031 LWIP_DEBUGF(SOCKETS_DEBUG, 2032 ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %" 2033 U32_F "\n", s, 2034 sock->conn->pcb.tcp->keep_idle)); 2035 break; 2036 case TCP_KEEPINTVL: 2037 sock->conn->pcb.tcp->keep_intvl = 2038 1000 * (u32_t) (*(int *) optval); 2039 LWIP_DEBUGF(SOCKETS_DEBUG, 2040 ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %" 2041 U32_F "\n", s, 2042 sock->conn->pcb.tcp->keep_intvl)); 2043 break; 2044 case TCP_KEEPCNT: 2045 sock->conn->pcb.tcp->keep_cnt = (u32_t) (*(int *) optval); 2046 LWIP_DEBUGF(SOCKETS_DEBUG, 2047 ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %" 2048 U32_F "\n", s, sock->conn->pcb.tcp->keep_cnt)); 2049 break; 2050#endif /* LWIP_TCP_KEEPALIVE */ 2051 2052 } /* switch (optname) */ 2053 break; 2054#endif /* LWIP_TCP */ 2055#if LWIP_UDP && LWIP_UDPLITE 2056 /* Level: IPPROTO_UDPLITE */ 2057 case IPPROTO_UDPLITE: 2058 switch (optname) { 2059 case UDPLITE_SEND_CSCOV: 2060 if ((*(int *) optval != 0) && (*(int *) optval < 8)) { 2061 /* don't allow illegal values! */ 2062 sock->conn->pcb.udp->chksum_len_tx = 8; 2063 } else { 2064 sock->conn->pcb.udp->chksum_len_tx = *(int *) optval; 2065 } 2066 LWIP_DEBUGF(SOCKETS_DEBUG, 2067 ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", 2068 s, (*(int *) optval))); 2069 break; 2070 case UDPLITE_RECV_CSCOV: 2071 if ((*(int *) optval != 0) && (*(int *) optval < 8)) { 2072 /* don't allow illegal values! */ 2073 sock->conn->pcb.udp->chksum_len_rx = 8; 2074 } else { 2075 sock->conn->pcb.udp->chksum_len_rx = *(int *) optval; 2076 } 2077 LWIP_DEBUGF(SOCKETS_DEBUG, 2078 ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", 2079 s, (*(int *) optval))); 2080 break; 2081 } /* switch (optname) */ 2082 break; 2083#endif /* LWIP_UDP */ 2084 } /* switch (level) */ 2085 sys_sem_signal(sock->conn->op_completed); 2086} 2087 2088int lwip_ioctl(int s, long cmd, void *argp) 2089{ 2090 struct lwip_socket *sock = get_socket(s); 2091 u16_t buflen = 0; 2092 s16_t recv_avail; 2093 2094 if (!sock) 2095 return -1; 2096 2097 switch (cmd) { 2098 case FIONREAD: 2099 if (!argp) { 2100 sock_set_errno(sock, EINVAL); 2101 return -1; 2102 } 2103 2104 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); 2105 if (recv_avail < 0) 2106 recv_avail = 0; 2107 *((u16_t *) argp) = (u16_t) recv_avail; 2108 2109 /* Check if there is data left from the last recv operation. /maq 041215 */ 2110 if (sock->lastdata) { 2111 buflen = netbuf_len(sock->lastdata); 2112 buflen -= sock->lastoffset; 2113 2114 *((u16_t *) argp) += buflen; 2115 } 2116 2117 LWIP_DEBUGF(SOCKETS_DEBUG, 2118 ("lwip_ioctl(%d, FIONREAD, %p) = %" U16_F "\n", s, argp, 2119 *((u16_t *) argp))); 2120 sock_set_errno(sock, 0); 2121 return 0; 2122 2123 case FIONBIO: 2124 if (argp && *(u32_t *) argp) 2125 sock->flags |= O_NONBLOCK; 2126 else 2127 sock->flags &= ~O_NONBLOCK; 2128 LWIP_DEBUGF(SOCKETS_DEBUG, 2129 ("lwip_ioctl(%d, FIONBIO, %d)\n", s, 2130 ! !(sock->flags & O_NONBLOCK))); 2131 sock_set_errno(sock, 0); 2132 return 0; 2133 2134 default: 2135 LWIP_DEBUGF(SOCKETS_DEBUG, 2136 ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); 2137 sock_set_errno(sock, ENOSYS); /* not yet implemented */ 2138 return -1; 2139 } /* switch (cmd) */ 2140} 2141 2142int lwip_serialise_sock(int s, struct lwip_sockinfo *si) 2143{ 2144 struct lwip_socket *sock; 2145 2146 // err_t err; 2147 2148 sock = get_socket(s); 2149 if (!sock) 2150 return -1; 2151 2152 assert(sock->conn->type == NETCONN_TCP); 2153 2154 si->local_ip = sock->conn->pcb.ip->local_ip; 2155 si->remote_ip = sock->conn->pcb.ip->remote_ip; 2156 si->local_port = sock->conn->pcb.tcp->local_port; 2157 si->remote_port = sock->conn->pcb.tcp->remote_port; 2158 memcpy(&(si->netconn_state), sock->conn, sizeof(struct netconn)); 2159 memcpy(&(si->tcp_state), sock->conn->pcb.tcp, sizeof(struct tcp_pcb)); 2160 2161 if (sock->conn->pcb.tcp->state == ESTABLISHED) { 2162 // Pause the socket, we're inheriting 2163 err_t err = netconn_pause(sock->conn, &si->local_ip, si->local_port, 2164 &si->remote_ip, si->remote_port); 2165 2166 if (err != ERR_OK) { 2167 LWIP_DEBUGF(SOCKETS_DEBUG, 2168 ("lwip_redirect(%d) failed, err=%d\n", s, err)); 2169 sock_set_errno(sock, err_to_errno(err)); 2170 return -1; 2171 } 2172 } 2173 2174 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_redirect(%d) succeeded\n", s)); 2175 sock_set_errno(sock, 0); 2176 2177 return 0; 2178} 2179 2180static int lwip_redirect(int s, struct lwip_sockinfo *si) 2181{ 2182 struct lwip_socket *sock; 2183 err_t err; 2184 2185 sock = get_socket(s); 2186 if (!sock) 2187 return -1; 2188 2189 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_redirect(%d, ", s)); 2190 LWIP_DEBUGF(SOCKETS_DEBUG, (" local port=%" U16_F ")\n", si->local_port)); 2191 LWIP_DEBUGF(SOCKETS_DEBUG, (" remote port=%" U16_F ")\n", si->remote_port)); 2192 2193 err = netconn_redirect(sock->conn, &si->local_ip, si->local_port, 2194 &si->remote_ip, si->remote_port); 2195 2196 if (err != ERR_OK) { 2197 LWIP_DEBUGF(SOCKETS_DEBUG, 2198 ("lwip_redirect(%d) failed, err=%d\n", s, err)); 2199 sock_set_errno(sock, err_to_errno(err)); 2200 return -1; 2201 } 2202 2203 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_redirect(%d) succeeded\n", s)); 2204 sock_set_errno(sock, 0); 2205 return 0; 2206} 2207 2208 2209int lwip_deserialise_sock(int s, struct lwip_sockinfo *si) 2210{ 2211 struct lwip_socket *sock; 2212 2213 //err_t err; 2214 2215 sock = get_socket(s); 2216 if (!sock) { 2217 return -1; 2218 } 2219 struct tcp_pcb *next = sock->conn->pcb.tcp->next; 2220 2221 assert(sock->conn->type == NETCONN_TCP); 2222 2223 memcpy(sock->conn->pcb.tcp, &(si->tcp_state), sizeof(struct tcp_pcb)); 2224#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3) 2225 sock->conn->pcb.tcp->snd_queuelen = 0; 2226 sock->conn->pcb.tcp->unsent = NULL; /* Unsent (queued) segments. */ 2227 sock->conn->pcb.tcp->unacked = NULL; /* Sent but unacknowledged segments. */ 2228#if TCP_QUEUE_OOSEQ 2229 sock->conn->pcb.tcp->ooseq = NULL; /* Received out of sequence segments. */ 2230#endif /* TCP_QUEUE_OOSEQ */ 2231 sock->conn->pcb.ip->local_ip = si->local_ip; 2232 sock->conn->pcb.ip->remote_ip = si->remote_ip; 2233 sock->conn->pcb.tcp->local_port = si->local_port; 2234 sock->conn->pcb.tcp->remote_port = si->remote_port; 2235 sock->conn->pcb.tcp->callback_arg = sock->conn; 2236 sock->conn->pcb.tcp->next = next; 2237 2238 if (sock->conn->pcb.tcp->state == ESTABLISHED) { 2239 printf("lwip_deserialise_sock: in ESTABLISHED state!!!\n"); 2240 TCP_REG(&tcp_active_pcbs, sock->conn->pcb.tcp); 2241 /* start lwip redirect now */ 2242 int ret = lwip_redirect(s, si); 2243 2244 assert(ret == 0); 2245 } else if (sock->conn->pcb.tcp->state == LISTEN) { 2246 printf("lwip_deserialise_sock: in LISTEN state!!!\n"); 2247// TCP_REG(&tcp_bound_pcbs, sock->conn->pcb.tcp); 2248 } else { 2249 printf("lwip_deserialise_sock: in %d state!!!\n", 2250 sock->conn->pcb.tcp->state); 2251 } 2252 2253 return 0; 2254} 2255 2256#ifdef BF_LWIP_CHAN_SUPPORT 2257/** 2258 * \brief Check if a read on the socket would not block. 2259 * 2260 * \param socket Socket to check. 2261 * \return Whether or not the socket is ready. 2262 */ 2263bool lwip_sock_ready_read(int socket) 2264{ 2265 bool is_ready = false; 2266 struct lwip_socket *p_sock; 2267 2268 p_sock = get_socket(socket); 2269 assert(p_sock != NULL); 2270 2271 if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) { 2272 is_ready = true; 2273 } 2274 2275 return is_ready; 2276} 2277 2278/** 2279 * \brief Check if a write on the socket would not block. 2280 * 2281 * \param socket Socket to check. 2282 * \return Whether or not the socket is ready. 2283 */ 2284bool lwip_sock_ready_write(int socket) 2285{ 2286 bool is_ready = false; 2287 struct lwip_socket *p_sock; 2288 2289 p_sock = get_socket(socket); 2290 assert(p_sock != NULL); 2291 2292 if (p_sock && p_sock->sendevent) { 2293 is_ready = true; 2294 } 2295 2296 return is_ready; 2297} 2298 2299bool lwip_sock_is_open(int s) 2300{ 2301 assert(!"NYI"); 2302} 2303 2304static void do_nothing(void *arg) 2305{ 2306 return; 2307} 2308 2309/** 2310 * \brief Deregister previously registered waitset on which an event is delivered 2311 * when the socket is ready for reading. 2312 */ 2313errval_t lwip_sock_waitset_deregister_read(int socket) 2314{ 2315 errval_t err; 2316 struct lwip_socket *p_sock; 2317 2318 p_sock = get_socket(socket); 2319 assert(p_sock != NULL); 2320 2321 err = waitset_chan_deregister(&p_sock->recv_chanstate); 2322 if (err_is_fail(err)) { 2323 return err; 2324 } 2325 2326 return SYS_ERR_OK; 2327} 2328 2329/** 2330 * \brief Register a waitset on which an event is delivered when the socket is 2331 * ready for reading. 2332 * 2333 * The event is triggered ONCE, when the socket becomes ready for reading. If 2334 * the socket is already ready, the event is triggered right away. 2335 * 2336 * \param socket Socket 2337 * \param ws Waitset 2338 */ 2339errval_t lwip_sock_waitset_register_read(int socket, struct waitset *ws) 2340{ 2341 errval_t err; 2342 struct lwip_socket *p_sock; 2343 2344 assert(ws != NULL); 2345 2346 p_sock = get_socket(socket); 2347 assert(p_sock != NULL); 2348 2349 waitset_chanstate_init(&p_sock->recv_chanstate, CHANTYPE_LWIP_SOCKET); 2350 2351 err = waitset_chan_register(ws, &p_sock->recv_chanstate, 2352 MKCLOSURE(do_nothing, NULL)); 2353 if (err_is_fail(err)) { 2354 DEBUG_ERR(err, "Error register recv channel on waitset."); 2355 return err; 2356 } 2357 2358 /* if socket is ready, trigger event right away */ 2359 if (lwip_sock_ready_read(socket)) { 2360 err = waitset_chan_trigger(&p_sock->recv_chanstate); 2361 if (err_is_fail(err)) { 2362 DEBUG_ERR(err, "Error trigger event on recv channel."); 2363 return err; 2364 } 2365 } 2366 2367 return SYS_ERR_OK; 2368} 2369 2370/** 2371 * \brief Deregister previously registered waitset on which an event is delivered 2372 * when the socket is ready for writing. 2373 */ 2374errval_t lwip_sock_waitset_deregister_write(int socket) 2375{ 2376 errval_t err; 2377 struct lwip_socket *p_sock; 2378 2379 p_sock = get_socket(socket); 2380 assert(p_sock != NULL); 2381 2382 err = waitset_chan_deregister(&p_sock->send_chanstate); 2383 if (err_is_fail(err)) { 2384 return err; 2385 } 2386 2387 return SYS_ERR_OK; 2388} 2389 2390/** 2391 * \brief Register a waitset on which an event is delivered when the socket is 2392 * ready for writing. 2393 * 2394 * The event is triggered ONCE, when the socket becomes ready for writing. If 2395 * the socket is already ready, the event is triggered right away. 2396 * 2397 * \param socket Socket 2398 * \param ws Waitset 2399 */ 2400errval_t lwip_sock_waitset_register_write(int socket, struct waitset *ws) 2401{ 2402 errval_t err; 2403 struct lwip_socket *p_sock; 2404 2405 assert(ws != NULL); 2406 2407 p_sock = get_socket(socket); 2408 assert(p_sock != NULL); 2409 2410 waitset_chanstate_init(&p_sock->send_chanstate, CHANTYPE_LWIP_SOCKET); 2411 2412 err = waitset_chan_register(ws, &p_sock->send_chanstate, 2413 MKCLOSURE(do_nothing, NULL)); 2414 if (err_is_fail(err)) { 2415 DEBUG_ERR(err, "Error register send channel on waitset."); 2416 return err; 2417 } 2418 2419 /* if socket is ready, trigger event right away */ 2420 if (lwip_sock_ready_write(socket)) { 2421 err = waitset_chan_trigger(&p_sock->send_chanstate); 2422 if (err_is_fail(err)) { 2423 DEBUG_ERR(err, "Error trigger event on send channel."); 2424 return err; 2425 } 2426 } 2427 2428 return SYS_ERR_OK; 2429} 2430#endif /* BF_LWIP_CHAN_SUPPORT */ 2431 2432#endif /* LWIP_SOCKET */ 2433