00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "lwip/opt.h"
00042
00043 #if LWIP_SOCKET
00044
00045 #include "lwip/sockets.h"
00046 #include "lwip/api.h"
00047 #include "lwip/sys.h"
00048 #include "lwip/igmp.h"
00049 #include "lwip/inet.h"
00050 #include "lwip/tcp.h"
00051 #include "lwip/raw.h"
00052 #include "lwip/udp.h"
00053 #include "lwip/tcpip.h"
00054 #include "lwip/pbuf.h"
00055 #if LWIP_CHECKSUM_ON_COPY
00056 #include "lwip/inet_chksum.h"
00057 #endif
00058
00059 #include <string.h>
00060
00061 #define NUM_SOCKETS MEMP_NUM_NETCONN
00062
00063
00064 struct lwip_sock {
00065
00066 struct netconn *conn;
00067
00068 void *lastdata;
00069
00070 u16_t lastoffset;
00071
00072
00073 s16_t rcvevent;
00074
00075
00076 u16_t sendevent;
00077
00078 u16_t errevent;
00079
00080 int err;
00081
00082 int select_waiting;
00083 };
00084
00085
00086 struct lwip_select_cb {
00087
00088 struct lwip_select_cb *next;
00089
00090 struct lwip_select_cb *prev;
00091
00092 fd_set *readset;
00093
00094 fd_set *writeset;
00095
00096 fd_set *exceptset;
00097
00098 int sem_signalled;
00099
00100 sys_sem_t sem;
00101 };
00102
00103
00104
00105 struct lwip_setgetsockopt_data {
00106
00107 struct lwip_sock *sock;
00108 #ifdef LWIP_DEBUG
00109
00110 int s;
00111 #endif
00112
00113 int level;
00114
00115 int optname;
00116
00117
00118 void *optval;
00119
00120 socklen_t *optlen;
00121
00122 err_t err;
00123 };
00124
00125
00126 static struct lwip_sock sockets[NUM_SOCKETS];
00127
00128 static struct lwip_select_cb *select_cb_list;
00129
00130
00131 static volatile int select_cb_ctr;
00132
00133
00134
00135 static const int err_to_errno_table[] = {
00136 0,
00137 ENOMEM,
00138 ENOBUFS,
00139 EWOULDBLOCK,
00140 EHOSTUNREACH,
00141 EINPROGRESS,
00142 EINVAL,
00143 EWOULDBLOCK,
00144 EADDRINUSE,
00145 EALREADY,
00146 ECONNABORTED,
00147 ECONNRESET,
00148 ENOTCONN,
00149 ENOTCONN,
00150 EIO,
00151 -1,
00152 };
00153
00154 #define ERR_TO_ERRNO_TABLE_SIZE \
00155 (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
00156
00157 #define err_to_errno(err) \
00158 ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
00159 err_to_errno_table[-(err)] : EIO)
00160
00161 #ifdef ERRNO
00162 #ifndef set_errno
00163 #define set_errno(err) errno = (err)
00164 #endif
00165 #else
00166 #define set_errno(err)
00167 #endif
00168
00169 #define sock_set_errno(sk, e) do { \
00170 sk->err = (e); \
00171 set_errno(sk->err); \
00172 } while (0)
00173
00174
00175 static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
00176 static void lwip_getsockopt_internal(void *arg);
00177 static void lwip_setsockopt_internal(void *arg);
00178
00179
00180
00181
00182
00183 void
00184 lwip_socket_init(void)
00185 {
00186 }
00187
00188
00189
00190
00191
00192
00193
00194 static struct lwip_sock *
00195 get_socket(int s)
00196 {
00197 struct lwip_sock *sock;
00198
00199 if ((s < 0) || (s >= NUM_SOCKETS)) {
00200 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
00201 set_errno(EBADF);
00202 return NULL;
00203 }
00204
00205 sock = &sockets[s];
00206
00207 if (!sock->conn) {
00208 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
00209 set_errno(EBADF);
00210 return NULL;
00211 }
00212
00213 return sock;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 static struct lwip_sock *
00223 tryget_socket(int s)
00224 {
00225 if ((s < 0) || (s >= NUM_SOCKETS)) {
00226 return NULL;
00227 }
00228 if (!sockets[s].conn) {
00229 return NULL;
00230 }
00231 return &sockets[s];
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 static int
00243 alloc_socket(struct netconn *newconn, int accepted)
00244 {
00245 int i;
00246 SYS_ARCH_DECL_PROTECT(lev);
00247
00248
00249 for (i = 0; i < NUM_SOCKETS; ++i) {
00250
00251 SYS_ARCH_PROTECT(lev);
00252 if (!sockets[i].conn) {
00253 sockets[i].conn = newconn;
00254
00255
00256 SYS_ARCH_UNPROTECT(lev);
00257 sockets[i].lastdata = NULL;
00258 sockets[i].lastoffset = 0;
00259 sockets[i].rcvevent = 0;
00260
00261
00262 sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
00263 sockets[i].errevent = 0;
00264 sockets[i].err = 0;
00265 sockets[i].select_waiting = 0;
00266 return i;
00267 }
00268 SYS_ARCH_UNPROTECT(lev);
00269 }
00270 return -1;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 static void
00280 free_socket(struct lwip_sock *sock, int is_tcp)
00281 {
00282 void *lastdata;
00283 SYS_ARCH_DECL_PROTECT(lev);
00284
00285 lastdata = sock->lastdata;
00286 sock->lastdata = NULL;
00287 sock->lastoffset = 0;
00288 sock->err = 0;
00289
00290
00291 SYS_ARCH_PROTECT(lev);
00292 sock->conn = NULL;
00293 SYS_ARCH_UNPROTECT(lev);
00294
00295
00296 if (lastdata != NULL) {
00297 if (is_tcp) {
00298 pbuf_free((struct pbuf *)lastdata);
00299 } else {
00300 netbuf_delete((struct netbuf *)lastdata);
00301 }
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 int
00312 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
00313 {
00314 struct lwip_sock *sock, *nsock;
00315 struct netconn *newconn;
00316 ip_addr_t naddr;
00317 u16_t port;
00318 int newsock;
00319 struct sockaddr_in sin;
00320 err_t err;
00321 SYS_ARCH_DECL_PROTECT(lev);
00322
00323 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
00324 sock = get_socket(s);
00325 if (!sock) {
00326 return -1;
00327 }
00328
00329 if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
00330 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
00331 sock_set_errno(sock, EWOULDBLOCK);
00332 return -1;
00333 }
00334
00335
00336 err = netconn_accept(sock->conn, &newconn);
00337 if (err != ERR_OK) {
00338 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
00339 if (netconn_type(sock->conn) != NETCONN_TCP) {
00340 sock_set_errno(sock, EOPNOTSUPP);
00341 return EOPNOTSUPP;
00342 }
00343 sock_set_errno(sock, err_to_errno(err));
00344 return -1;
00345 }
00346 LWIP_ASSERT("newconn != NULL", newconn != NULL);
00347
00348 netconn_set_noautorecved(newconn, 1);
00349
00350
00351 err = netconn_peer(newconn, &naddr, &port);
00352 if (err != ERR_OK) {
00353 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
00354 netconn_delete(newconn);
00355 sock_set_errno(sock, err_to_errno(err));
00356 return -1;
00357 }
00358
00359
00360
00361
00362 if (NULL != addr) {
00363 LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
00364 memset(&sin, 0, sizeof(sin));
00365 sin.sin_len = sizeof(sin);
00366 sin.sin_family = AF_INET;
00367 sin.sin_port = htons(port);
00368 inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
00369
00370 if (*addrlen > sizeof(sin))
00371 *addrlen = sizeof(sin);
00372
00373 MEMCPY(addr, &sin, *addrlen);
00374 }
00375
00376 newsock = alloc_socket(newconn, 1);
00377 if (newsock == -1) {
00378 netconn_delete(newconn);
00379 sock_set_errno(sock, ENFILE);
00380 return -1;
00381 }
00382 LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
00383 LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
00384 nsock = &sockets[newsock];
00385
00386
00387
00388
00389
00390
00391 SYS_ARCH_PROTECT(lev);
00392 nsock->rcvevent += (s16_t)(-1 - newconn->socket);
00393 newconn->socket = newsock;
00394 SYS_ARCH_UNPROTECT(lev);
00395
00396 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
00397 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
00398 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
00399
00400 sock_set_errno(sock, 0);
00401 return newsock;
00402 }
00403
00404 int
00405 lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
00406 {
00407 struct lwip_sock *sock;
00408 ip_addr_t local_addr;
00409 u16_t local_port;
00410 err_t err;
00411 const struct sockaddr_in *name_in;
00412
00413 sock = get_socket(s);
00414 if (!sock) {
00415 return -1;
00416 }
00417
00418
00419 LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
00420 ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
00421 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
00422 name_in = (const struct sockaddr_in *)(void*)name;
00423
00424 inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr);
00425 local_port = name_in->sin_port;
00426
00427 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
00428 ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
00429 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
00430
00431 err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
00432
00433 if (err != ERR_OK) {
00434 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
00435 sock_set_errno(sock, err_to_errno(err));
00436 return -1;
00437 }
00438
00439 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
00440 sock_set_errno(sock, 0);
00441 return 0;
00442 }
00443
00444 int
00445 lwip_close(int s)
00446 {
00447 struct lwip_sock *sock;
00448 int is_tcp = 0;
00449
00450 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
00451
00452 sock = get_socket(s);
00453 if (!sock) {
00454 return -1;
00455 }
00456
00457 if(sock->conn != NULL) {
00458 is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
00459 } else {
00460 LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
00461 }
00462
00463 netconn_delete(sock->conn);
00464
00465 free_socket(sock, is_tcp);
00466 set_errno(0);
00467 return 0;
00468 }
00469
00470 int
00471 lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
00472 {
00473 struct lwip_sock *sock;
00474 err_t err;
00475 const struct sockaddr_in *name_in;
00476
00477 sock = get_socket(s);
00478 if (!sock) {
00479 return -1;
00480 }
00481
00482
00483 LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
00484 ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
00485 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
00486 name_in = (const struct sockaddr_in *)(void*)name;
00487
00488 if (name_in->sin_family == AF_UNSPEC) {
00489 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
00490 err = netconn_disconnect(sock->conn);
00491 } else {
00492 ip_addr_t remote_addr;
00493 u16_t remote_port;
00494
00495 inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr);
00496 remote_port = name_in->sin_port;
00497
00498 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
00499 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
00500 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
00501
00502 err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
00503 }
00504
00505 if (err != ERR_OK) {
00506 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
00507 sock_set_errno(sock, err_to_errno(err));
00508 return -1;
00509 }
00510
00511 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
00512 sock_set_errno(sock, 0);
00513 return 0;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 int
00525 lwip_listen(int s, int backlog)
00526 {
00527 struct lwip_sock *sock;
00528 err_t err;
00529
00530 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
00531
00532 sock = get_socket(s);
00533 if (!sock) {
00534 return -1;
00535 }
00536
00537
00538 backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
00539
00540 err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
00541
00542 if (err != ERR_OK) {
00543 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
00544 if (netconn_type(sock->conn) != NETCONN_TCP) {
00545 sock_set_errno(sock, EOPNOTSUPP);
00546 return EOPNOTSUPP;
00547 }
00548 sock_set_errno(sock, err_to_errno(err));
00549 return -1;
00550 }
00551
00552 sock_set_errno(sock, 0);
00553 return 0;
00554 }
00555
00556 int
00557 lwip_recvfrom(int s, void *mem, size_t len, int flags,
00558 struct sockaddr *from, socklen_t *fromlen)
00559 {
00560 struct lwip_sock *sock;
00561 void *buf = NULL;
00562 struct pbuf *p;
00563 u16_t buflen, copylen;
00564 int off = 0;
00565 ip_addr_t *addr;
00566 u16_t port;
00567 u8_t done = 0;
00568 err_t err;
00569
00570 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
00571 sock = get_socket(s);
00572 if (!sock) {
00573 return -1;
00574 }
00575
00576 do {
00577 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
00578
00579 if (sock->lastdata) {
00580 buf = sock->lastdata;
00581 } else {
00582
00583 if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
00584 (sock->rcvevent <= 0)) {
00585 if (off > 0) {
00586
00587 netconn_recved(sock->conn, (u32_t)off);
00588
00589 sock_set_errno(sock, 0);
00590 return off;
00591 }
00592 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
00593 sock_set_errno(sock, EWOULDBLOCK);
00594 return -1;
00595 }
00596
00597
00598
00599 if (netconn_type(sock->conn) == NETCONN_TCP) {
00600 err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
00601 } else {
00602 err = netconn_recv(sock->conn, (struct netbuf **)&buf);
00603 }
00604 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
00605 err, buf));
00606
00607 if (err != ERR_OK) {
00608 if (off > 0) {
00609
00610 netconn_recved(sock->conn, (u32_t)off);
00611
00612 sock_set_errno(sock, 0);
00613 return off;
00614 }
00615
00616 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
00617 s, lwip_strerr(err)));
00618 sock_set_errno(sock, err_to_errno(err));
00619 if (err == ERR_CLSD) {
00620 return 0;
00621 } else {
00622 return -1;
00623 }
00624 }
00625 LWIP_ASSERT("buf != NULL", buf != NULL);
00626 sock->lastdata = buf;
00627 }
00628
00629 if (netconn_type(sock->conn) == NETCONN_TCP) {
00630 p = (struct pbuf *)buf;
00631 } else {
00632 p = ((struct netbuf *)buf)->p;
00633 }
00634 buflen = p->tot_len;
00635 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
00636 buflen, len, off, sock->lastoffset));
00637
00638 buflen -= sock->lastoffset;
00639
00640 if (len > buflen) {
00641 copylen = buflen;
00642 } else {
00643 copylen = (u16_t)len;
00644 }
00645
00646
00647
00648 pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
00649
00650 off += copylen;
00651
00652 if (netconn_type(sock->conn) == NETCONN_TCP) {
00653 LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
00654 len -= copylen;
00655 if ( (len <= 0) ||
00656 (p->flags & PBUF_FLAG_PUSH) ||
00657 (sock->rcvevent <= 0) ||
00658 ((flags & MSG_PEEK)!=0)) {
00659 done = 1;
00660 }
00661 } else {
00662 done = 1;
00663 }
00664
00665
00666 if (done) {
00667 ip_addr_t fromaddr;
00668 if (from && fromlen) {
00669 struct sockaddr_in sin;
00670
00671 if (netconn_type(sock->conn) == NETCONN_TCP) {
00672 addr = &fromaddr;
00673 netconn_getaddr(sock->conn, addr, &port, 0);
00674 } else {
00675 addr = netbuf_fromaddr((struct netbuf *)buf);
00676 port = netbuf_fromport((struct netbuf *)buf);
00677 }
00678
00679 memset(&sin, 0, sizeof(sin));
00680 sin.sin_len = sizeof(sin);
00681 sin.sin_family = AF_INET;
00682 sin.sin_port = htons(port);
00683 inet_addr_from_ipaddr(&sin.sin_addr, addr);
00684
00685 if (*fromlen > sizeof(sin)) {
00686 *fromlen = sizeof(sin);
00687 }
00688
00689 MEMCPY(from, &sin, *fromlen);
00690
00691 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
00692 ip_addr_debug_print(SOCKETS_DEBUG, addr);
00693 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
00694 } else {
00695 #if SOCKETS_DEBUG
00696 if (netconn_type(sock->conn) == NETCONN_TCP) {
00697 addr = &fromaddr;
00698 netconn_getaddr(sock->conn, addr, &port, 0);
00699 } else {
00700 addr = netbuf_fromaddr((struct netbuf *)buf);
00701 port = netbuf_fromport((struct netbuf *)buf);
00702 }
00703
00704 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
00705 ip_addr_debug_print(SOCKETS_DEBUG, addr);
00706 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
00707 #endif
00708 }
00709 }
00710
00711
00712 if ((flags & MSG_PEEK) == 0) {
00713
00714
00715
00716 if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
00717 sock->lastdata = buf;
00718 sock->lastoffset += copylen;
00719 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
00720 } else {
00721 sock->lastdata = NULL;
00722 sock->lastoffset = 0;
00723 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
00724 if (netconn_type(sock->conn) == NETCONN_TCP) {
00725 pbuf_free((struct pbuf *)buf);
00726 } else {
00727 netbuf_delete((struct netbuf *)buf);
00728 }
00729 }
00730 }
00731 } while (!done);
00732
00733 if (off > 0) {
00734
00735 netconn_recved(sock->conn, (u32_t)off);
00736 }
00737 sock_set_errno(sock, 0);
00738 return off;
00739 }
00740
00741 int
00742 lwip_read(int s, void *mem, size_t len)
00743 {
00744 return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
00745 }
00746
00747 int
00748 lwip_recv(int s, void *mem, size_t len, int flags)
00749 {
00750 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
00751 }
00752
00753 int
00754 lwip_send(int s, const void *data, size_t size, int flags)
00755 {
00756 struct lwip_sock *sock;
00757 err_t err;
00758 u8_t write_flags;
00759 size_t written;
00760
00761 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
00762 s, data, size, flags));
00763
00764 sock = get_socket(s);
00765 if (!sock) {
00766 return -1;
00767 }
00768
00769 if (sock->conn->type != NETCONN_TCP) {
00770 #if (LWIP_UDP || LWIP_RAW)
00771 return lwip_sendto(s, data, size, flags, NULL, 0);
00772 #else
00773 sock_set_errno(sock, err_to_errno(ERR_ARG));
00774 return -1;
00775 #endif
00776 }
00777
00778 write_flags = NETCONN_COPY |
00779 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
00780 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
00781 written = 0;
00782 err = netconn_write_partly(sock->conn, data, size, write_flags, &written);
00783
00784 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written));
00785 sock_set_errno(sock, err_to_errno(err));
00786 return (err == ERR_OK ? (int)written : -1);
00787 }
00788
00789 int
00790 lwip_sendto(int s, const void *data, size_t size, int flags,
00791 const struct sockaddr *to, socklen_t tolen)
00792 {
00793 struct lwip_sock *sock;
00794 err_t err;
00795 u16_t short_size;
00796 const struct sockaddr_in *to_in;
00797 u16_t remote_port;
00798 #if !LWIP_TCPIP_CORE_LOCKING
00799 struct netbuf buf;
00800 #endif
00801
00802 sock = get_socket(s);
00803 if (!sock) {
00804 return -1;
00805 }
00806
00807 if (sock->conn->type == NETCONN_TCP) {
00808 #if LWIP_TCP
00809 return lwip_send(s, data, size, flags);
00810 #else
00811 LWIP_UNUSED_ARG(flags);
00812 sock_set_errno(sock, err_to_errno(ERR_ARG));
00813 return -1;
00814 #endif
00815 }
00816
00817
00818 LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
00819 short_size = (u16_t)size;
00820 LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
00821 ((tolen == sizeof(struct sockaddr_in)) &&
00822 ((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))),
00823 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
00824 to_in = (const struct sockaddr_in *)(void*)to;
00825
00826 #if LWIP_TCPIP_CORE_LOCKING
00827
00828 {
00829 struct pbuf* p;
00830 ip_addr_t *remote_addr;
00831
00832 #if LWIP_NETIF_TX_SINGLE_PBUF
00833 p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
00834 if (p != NULL) {
00835 #if LWIP_CHECKSUM_ON_COPY
00836 u16_t chksum = 0;
00837 if (sock->conn->type != NETCONN_RAW) {
00838 chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
00839 } else
00840 #endif
00841 MEMCPY(p->payload, data, size);
00842 #else
00843 p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF);
00844 if (p != NULL) {
00845 p->payload = (void*)data;
00846 #endif
00847
00848 if (to_in != NULL) {
00849 inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr);
00850 remote_port = ntohs(to_in->sin_port);
00851 } else {
00852 remote_addr = &sock->conn->pcb.ip->remote_ip;
00853 #if LWIP_UDP
00854 if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_UDP) {
00855 remote_port = sock->conn->pcb.udp->remote_port;
00856 } else
00857 #endif
00858 {
00859 remote_port = 0;
00860 }
00861 }
00862
00863 LOCK_TCPIP_CORE();
00864 if (netconn_type(sock->conn) == NETCONN_RAW) {
00865 #if LWIP_RAW
00866 err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
00867 #else
00868 err = ERR_ARG;
00869 #endif
00870 }
00871 #if LWIP_UDP && LWIP_RAW
00872 else
00873 #endif
00874 {
00875 #if LWIP_UDP
00876 #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
00877 err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
00878 remote_addr, remote_port, 1, chksum);
00879 #else
00880 err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
00881 remote_addr, remote_port);
00882 #endif
00883 #else
00884 err = ERR_ARG;
00885 #endif
00886 }
00887 UNLOCK_TCPIP_CORE();
00888
00889 pbuf_free(p);
00890 } else {
00891 err = ERR_MEM;
00892 }
00893 }
00894 #else
00895
00896 buf.p = buf.ptr = NULL;
00897 #if LWIP_CHECKSUM_ON_COPY
00898 buf.flags = 0;
00899 #endif
00900 if (to) {
00901 inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr);
00902 remote_port = ntohs(to_in->sin_port);
00903 netbuf_fromport(&buf) = remote_port;
00904 } else {
00905 remote_port = 0;
00906 ip_addr_set_any(&buf.addr);
00907 netbuf_fromport(&buf) = 0;
00908 }
00909
00910 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
00911 s, data, short_size, flags));
00912 ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
00913 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
00914
00915
00916 #if LWIP_NETIF_TX_SINGLE_PBUF
00917
00918 if (netbuf_alloc(&buf, short_size) == NULL) {
00919 err = ERR_MEM;
00920 } else {
00921 #if LWIP_CHECKSUM_ON_COPY
00922 if (sock->conn->type != NETCONN_RAW) {
00923 u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
00924 netbuf_set_chksum(&buf, chksum);
00925 err = ERR_OK;
00926 } else
00927 #endif
00928 {
00929 err = netbuf_take(&buf, data, short_size);
00930 }
00931 }
00932 #else
00933 err = netbuf_ref(&buf, data, short_size);
00934 #endif
00935 if (err == ERR_OK) {
00936
00937 err = netconn_send(sock->conn, &buf);
00938 }
00939
00940
00941 netbuf_free(&buf);
00942 #endif
00943 sock_set_errno(sock, err_to_errno(err));
00944 return (err == ERR_OK ? short_size : -1);
00945 }
00946
00947 int
00948 lwip_socket(int domain, int type, int protocol)
00949 {
00950 struct netconn *conn;
00951 int i;
00952
00953 LWIP_UNUSED_ARG(domain);
00954
00955
00956 switch (type) {
00957 case SOCK_RAW:
00958 conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
00959 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
00960 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00961 break;
00962 case SOCK_DGRAM:
00963 conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
00964 NETCONN_UDPLITE : NETCONN_UDP, event_callback);
00965 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
00966 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00967 break;
00968 case SOCK_STREAM:
00969 conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
00970 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
00971 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00972 if (conn != NULL) {
00973
00974 netconn_set_noautorecved(conn, 1);
00975 }
00976 break;
00977 default:
00978 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
00979 domain, type, protocol));
00980 set_errno(EINVAL);
00981 return -1;
00982 }
00983
00984 if (!conn) {
00985 LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
00986 set_errno(ENOBUFS);
00987 return -1;
00988 }
00989
00990 i = alloc_socket(conn, 0);
00991
00992 if (i == -1) {
00993 netconn_delete(conn);
00994 set_errno(ENFILE);
00995 return -1;
00996 }
00997 conn->socket = i;
00998 LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
00999 set_errno(0);
01000 return i;
01001 }
01002
01003 int
01004 lwip_write(int s, const void *data, size_t size)
01005 {
01006 return lwip_send(s, data, size, 0);
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025 static int
01026 lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
01027 fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
01028 {
01029 int i, nready = 0;
01030 fd_set lreadset, lwriteset, lexceptset;
01031 struct lwip_sock *sock;
01032 SYS_ARCH_DECL_PROTECT(lev);
01033
01034 FD_ZERO(&lreadset);
01035 FD_ZERO(&lwriteset);
01036 FD_ZERO(&lexceptset);
01037
01038
01039
01040 for(i = 0; i < maxfdp1; i++) {
01041 void* lastdata = NULL;
01042 s16_t rcvevent = 0;
01043 u16_t sendevent = 0;
01044 u16_t errevent = 0;
01045
01046 SYS_ARCH_PROTECT(lev);
01047 sock = tryget_socket(i);
01048 if (sock != NULL) {
01049 lastdata = sock->lastdata;
01050 rcvevent = sock->rcvevent;
01051 sendevent = sock->sendevent;
01052 errevent = sock->errevent;
01053 }
01054 SYS_ARCH_UNPROTECT(lev);
01055
01056
01057 if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
01058 FD_SET(i, &lreadset);
01059 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
01060 nready++;
01061 }
01062
01063 if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
01064 FD_SET(i, &lwriteset);
01065 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
01066 nready++;
01067 }
01068
01069 if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
01070 FD_SET(i, &lexceptset);
01071 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
01072 nready++;
01073 }
01074 }
01075
01076 *readset_out = lreadset;
01077 *writeset_out = lwriteset;
01078 *exceptset_out = lexceptset;
01079
01080 LWIP_ASSERT("nready >= 0", nready >= 0);
01081 return nready;
01082 }
01083
01084
01085
01086
01087 int
01088 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
01089 struct timeval *timeout)
01090 {
01091 u32_t waitres = 0;
01092 int nready;
01093 fd_set lreadset, lwriteset, lexceptset;
01094 u32_t msectimeout;
01095 struct lwip_select_cb select_cb;
01096 err_t err;
01097 int i;
01098 SYS_ARCH_DECL_PROTECT(lev);
01099
01100 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
01101 maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
01102 timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
01103 timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
01104
01105
01106
01107 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
01108
01109
01110 if (!nready) {
01111 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
01112 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
01113
01114
01115 goto return_copy_fdsets;
01116 }
01117
01118
01119
01120
01121
01122
01123 select_cb.next = NULL;
01124 select_cb.prev = NULL;
01125 select_cb.readset = readset;
01126 select_cb.writeset = writeset;
01127 select_cb.exceptset = exceptset;
01128 select_cb.sem_signalled = 0;
01129 err = sys_sem_new(&select_cb.sem, 0);
01130 if (err != ERR_OK) {
01131
01132 set_errno(ENOMEM);
01133 return -1;
01134 }
01135
01136
01137 SYS_ARCH_PROTECT(lev);
01138
01139
01140 select_cb.next = select_cb_list;
01141 if (select_cb_list != NULL) {
01142 select_cb_list->prev = &select_cb;
01143 }
01144 select_cb_list = &select_cb;
01145
01146 select_cb_ctr++;
01147
01148
01149 SYS_ARCH_UNPROTECT(lev);
01150
01151
01152 for(i = 0; i < maxfdp1; i++) {
01153 if ((readset && FD_ISSET(i, readset)) ||
01154 (writeset && FD_ISSET(i, writeset)) ||
01155 (exceptset && FD_ISSET(i, exceptset))) {
01156 struct lwip_sock *sock = tryget_socket(i);
01157 LWIP_ASSERT("sock != NULL", sock != NULL);
01158 SYS_ARCH_PROTECT(lev);
01159 sock->select_waiting++;
01160 LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
01161 SYS_ARCH_UNPROTECT(lev);
01162 }
01163 }
01164
01165
01166
01167 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
01168 if (!nready) {
01169
01170 if (timeout == 0) {
01171
01172 msectimeout = 0;
01173 } else {
01174 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
01175 if (msectimeout == 0) {
01176
01177 msectimeout = 1;
01178 }
01179 }
01180
01181 waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout);
01182 }
01183
01184 for(i = 0; i < maxfdp1; i++) {
01185 if ((readset && FD_ISSET(i, readset)) ||
01186 (writeset && FD_ISSET(i, writeset)) ||
01187 (exceptset && FD_ISSET(i, exceptset))) {
01188 struct lwip_sock *sock = tryget_socket(i);
01189 LWIP_ASSERT("sock != NULL", sock != NULL);
01190 SYS_ARCH_PROTECT(lev);
01191 sock->select_waiting--;
01192 LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0);
01193 SYS_ARCH_UNPROTECT(lev);
01194 }
01195 }
01196
01197 SYS_ARCH_PROTECT(lev);
01198 if (select_cb.next != NULL) {
01199 select_cb.next->prev = select_cb.prev;
01200 }
01201 if (select_cb_list == &select_cb) {
01202 LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
01203 select_cb_list = select_cb.next;
01204 } else {
01205 LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
01206 select_cb.prev->next = select_cb.next;
01207 }
01208
01209 select_cb_ctr++;
01210 SYS_ARCH_UNPROTECT(lev);
01211
01212 sys_sem_free(&select_cb.sem);
01213 if (waitres == SYS_ARCH_TIMEOUT) {
01214
01215 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
01216
01217
01218 goto return_copy_fdsets;
01219 }
01220
01221
01222 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
01223 }
01224
01225 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
01226 return_copy_fdsets:
01227 set_errno(0);
01228 if (readset) {
01229 *readset = lreadset;
01230 }
01231 if (writeset) {
01232 *writeset = lwriteset;
01233 }
01234 if (exceptset) {
01235 *exceptset = lexceptset;
01236 }
01237
01238
01239 return nready;
01240 }
01241
01242
01243
01244
01245
01246 static void
01247 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
01248 {
01249 int s;
01250 struct lwip_sock *sock;
01251 struct lwip_select_cb *scb;
01252 int last_select_cb_ctr;
01253 SYS_ARCH_DECL_PROTECT(lev);
01254
01255 LWIP_UNUSED_ARG(len);
01256
01257
01258 if (conn) {
01259 s = conn->socket;
01260 if (s < 0) {
01261
01262
01263
01264
01265
01266 SYS_ARCH_PROTECT(lev);
01267 if (conn->socket < 0) {
01268 if (evt == NETCONN_EVT_RCVPLUS) {
01269 conn->socket--;
01270 }
01271 SYS_ARCH_UNPROTECT(lev);
01272 return;
01273 }
01274 s = conn->socket;
01275 SYS_ARCH_UNPROTECT(lev);
01276 }
01277
01278 sock = get_socket(s);
01279 if (!sock) {
01280 return;
01281 }
01282 } else {
01283 return;
01284 }
01285
01286 SYS_ARCH_PROTECT(lev);
01287
01288 switch (evt) {
01289 case NETCONN_EVT_RCVPLUS:
01290 sock->rcvevent++;
01291 break;
01292 case NETCONN_EVT_RCVMINUS:
01293 sock->rcvevent--;
01294 break;
01295 case NETCONN_EVT_SENDPLUS:
01296 sock->sendevent = 1;
01297 break;
01298 case NETCONN_EVT_SENDMINUS:
01299 sock->sendevent = 0;
01300 break;
01301 case NETCONN_EVT_ERROR:
01302 sock->errevent = 1;
01303 break;
01304 default:
01305 LWIP_ASSERT("unknown event", 0);
01306 break;
01307 }
01308
01309 if (sock->select_waiting == 0) {
01310
01311 SYS_ARCH_UNPROTECT(lev);
01312 return;
01313 }
01314
01315
01316
01317
01318
01319
01320
01321 again:
01322 for (scb = select_cb_list; scb != NULL; scb = scb->next) {
01323 if (scb->sem_signalled == 0) {
01324
01325 int do_signal = 0;
01326
01327 if (sock->rcvevent > 0) {
01328 if (scb->readset && FD_ISSET(s, scb->readset)) {
01329 do_signal = 1;
01330 }
01331 }
01332 if (sock->sendevent != 0) {
01333 if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
01334 do_signal = 1;
01335 }
01336 }
01337 if (sock->errevent != 0) {
01338 if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
01339 do_signal = 1;
01340 }
01341 }
01342 if (do_signal) {
01343 scb->sem_signalled = 1;
01344
01345
01346 sys_sem_signal(&scb->sem);
01347 }
01348 }
01349
01350 last_select_cb_ctr = select_cb_ctr;
01351 SYS_ARCH_UNPROTECT(lev);
01352
01353 SYS_ARCH_PROTECT(lev);
01354 if (last_select_cb_ctr != select_cb_ctr) {
01355
01356 goto again;
01357 }
01358 }
01359 SYS_ARCH_UNPROTECT(lev);
01360 }
01361
01362
01363
01364
01365
01366 int
01367 lwip_shutdown(int s, int how)
01368 {
01369 struct lwip_sock *sock;
01370 err_t err;
01371 u8_t shut_rx = 0, shut_tx = 0;
01372
01373 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
01374
01375 sock = get_socket(s);
01376 if (!sock) {
01377 return -1;
01378 }
01379
01380 if (sock->conn != NULL) {
01381 if (netconn_type(sock->conn) != NETCONN_TCP) {
01382 sock_set_errno(sock, EOPNOTSUPP);
01383 return EOPNOTSUPP;
01384 }
01385 } else {
01386 sock_set_errno(sock, ENOTCONN);
01387 return ENOTCONN;
01388 }
01389
01390 if (how == SHUT_RD) {
01391 shut_rx = 1;
01392 } else if (how == SHUT_WR) {
01393 shut_tx = 1;
01394 } else if(how == SHUT_RDWR) {
01395 shut_rx = 1;
01396 shut_tx = 1;
01397 } else {
01398 sock_set_errno(sock, EINVAL);
01399 return EINVAL;
01400 }
01401 err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
01402
01403 sock_set_errno(sock, err_to_errno(err));
01404 return (err == ERR_OK ? 0 : -1);
01405 }
01406
01407 static int
01408 lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
01409 {
01410 struct lwip_sock *sock;
01411 struct sockaddr_in sin;
01412 ip_addr_t naddr;
01413
01414 sock = get_socket(s);
01415 if (!sock) {
01416 return -1;
01417 }
01418
01419 memset(&sin, 0, sizeof(sin));
01420 sin.sin_len = sizeof(sin);
01421 sin.sin_family = AF_INET;
01422
01423
01424 netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
01425
01426 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
01427 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
01428 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
01429
01430 sin.sin_port = htons(sin.sin_port);
01431 inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
01432
01433 if (*namelen > sizeof(sin)) {
01434 *namelen = sizeof(sin);
01435 }
01436
01437 MEMCPY(name, &sin, *namelen);
01438 sock_set_errno(sock, 0);
01439 return 0;
01440 }
01441
01442 int
01443 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
01444 {
01445 return lwip_getaddrname(s, name, namelen, 0);
01446 }
01447
01448 int
01449 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
01450 {
01451 return lwip_getaddrname(s, name, namelen, 1);
01452 }
01453
01454 int
01455 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
01456 {
01457 err_t err = ERR_OK;
01458 struct lwip_sock *sock = get_socket(s);
01459 struct lwip_setgetsockopt_data data;
01460
01461 if (!sock) {
01462 return -1;
01463 }
01464
01465 if ((NULL == optval) || (NULL == optlen)) {
01466 sock_set_errno(sock, EFAULT);
01467 return -1;
01468 }
01469
01470
01471 switch (level) {
01472
01473
01474 case SOL_SOCKET:
01475 switch (optname) {
01476
01477 case SO_ACCEPTCONN:
01478 case SO_BROADCAST:
01479
01480
01481 case SO_ERROR:
01482 case SO_KEEPALIVE:
01483
01484 #if LWIP_SO_SNDTIMEO
01485 case SO_SNDTIMEO:
01486 #endif
01487 #if LWIP_SO_RCVTIMEO
01488 case SO_RCVTIMEO:
01489 #endif
01490 #if LWIP_SO_RCVBUF
01491 case SO_RCVBUF:
01492 #endif
01493
01494
01495
01496
01497 #if SO_REUSE
01498 case SO_REUSEADDR:
01499 case SO_REUSEPORT:
01500 #endif
01501 case SO_TYPE:
01502
01503 if (*optlen < sizeof(int)) {
01504 err = EINVAL;
01505 }
01506 break;
01507
01508 case SO_NO_CHECK:
01509 if (*optlen < sizeof(int)) {
01510 err = EINVAL;
01511 }
01512 #if LWIP_UDP
01513 if ((sock->conn->type != NETCONN_UDP) ||
01514 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
01515
01516 err = EAFNOSUPPORT;
01517 }
01518 #endif
01519 break;
01520
01521 default:
01522 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
01523 s, optname));
01524 err = ENOPROTOOPT;
01525 }
01526 break;
01527
01528
01529 case IPPROTO_IP:
01530 switch (optname) {
01531
01532
01533
01534 case IP_TTL:
01535 case IP_TOS:
01536 if (*optlen < sizeof(int)) {
01537 err = EINVAL;
01538 }
01539 break;
01540 #if LWIP_IGMP
01541 case IP_MULTICAST_TTL:
01542 if (*optlen < sizeof(u8_t)) {
01543 err = EINVAL;
01544 }
01545 break;
01546 case IP_MULTICAST_IF:
01547 if (*optlen < sizeof(struct in_addr)) {
01548 err = EINVAL;
01549 }
01550 break;
01551 case IP_MULTICAST_LOOP:
01552 if (*optlen < sizeof(u8_t)) {
01553 err = EINVAL;
01554 }
01555 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01556 err = EAFNOSUPPORT;
01557 }
01558 break;
01559 #endif
01560
01561 default:
01562 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
01563 s, optname));
01564 err = ENOPROTOOPT;
01565 }
01566 break;
01567
01568 #if LWIP_TCP
01569
01570 case IPPROTO_TCP:
01571 if (*optlen < sizeof(int)) {
01572 err = EINVAL;
01573 break;
01574 }
01575
01576
01577 if (sock->conn->type != NETCONN_TCP)
01578 return 0;
01579
01580 switch (optname) {
01581 case TCP_NODELAY:
01582 case TCP_KEEPALIVE:
01583 #if LWIP_TCP_KEEPALIVE
01584 case TCP_KEEPIDLE:
01585 case TCP_KEEPINTVL:
01586 case TCP_KEEPCNT:
01587 #endif
01588 break;
01589
01590 default:
01591 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
01592 s, optname));
01593 err = ENOPROTOOPT;
01594 }
01595 break;
01596 #endif
01597 #if LWIP_UDP && LWIP_UDPLITE
01598
01599 case IPPROTO_UDPLITE:
01600 if (*optlen < sizeof(int)) {
01601 err = EINVAL;
01602 break;
01603 }
01604
01605
01606 if (sock->conn->type != NETCONN_UDPLITE) {
01607 return 0;
01608 }
01609
01610 switch (optname) {
01611 case UDPLITE_SEND_CSCOV:
01612 case UDPLITE_RECV_CSCOV:
01613 break;
01614
01615 default:
01616 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
01617 s, optname));
01618 err = ENOPROTOOPT;
01619 }
01620 break;
01621 #endif
01622
01623 default:
01624 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
01625 s, level, optname));
01626 err = ENOPROTOOPT;
01627 }
01628
01629
01630 if (err != ERR_OK) {
01631 sock_set_errno(sock, err);
01632 return -1;
01633 }
01634
01635
01636 data.sock = sock;
01637 #ifdef LWIP_DEBUG
01638 data.s = s;
01639 #endif
01640 data.level = level;
01641 data.optname = optname;
01642 data.optval = optval;
01643 data.optlen = optlen;
01644 data.err = err;
01645 tcpip_callback(lwip_getsockopt_internal, &data);
01646 sys_arch_sem_wait(&sock->conn->op_completed, 0);
01647
01648 err = data.err;
01649
01650 sock_set_errno(sock, err);
01651 return err ? -1 : 0;
01652 }
01653
01654 static void
01655 lwip_getsockopt_internal(void *arg)
01656 {
01657 struct lwip_sock *sock;
01658 #ifdef LWIP_DEBUG
01659 int s;
01660 #endif
01661 int level, optname;
01662 void *optval;
01663 struct lwip_setgetsockopt_data *data;
01664
01665 LWIP_ASSERT("arg != NULL", arg != NULL);
01666
01667 data = (struct lwip_setgetsockopt_data*)arg;
01668 sock = data->sock;
01669 #ifdef LWIP_DEBUG
01670 s = data->s;
01671 #endif
01672 level = data->level;
01673 optname = data->optname;
01674 optval = data->optval;
01675
01676 switch (level) {
01677
01678
01679 case SOL_SOCKET:
01680 switch (optname) {
01681
01682
01683 case SO_ACCEPTCONN:
01684 case SO_BROADCAST:
01685
01686
01687 case SO_KEEPALIVE:
01688
01689 #if SO_REUSE
01690 case SO_REUSEADDR:
01691 case SO_REUSEPORT:
01692 #endif
01693
01694 *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname);
01695 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
01696 s, optname, (*(int*)optval?"on":"off")));
01697 break;
01698
01699 case SO_TYPE:
01700 switch (NETCONNTYPE_GROUP(sock->conn->type)) {
01701 case NETCONN_RAW:
01702 *(int*)optval = SOCK_RAW;
01703 break;
01704 case NETCONN_TCP:
01705 *(int*)optval = SOCK_STREAM;
01706 break;
01707 case NETCONN_UDP:
01708 *(int*)optval = SOCK_DGRAM;
01709 break;
01710 default:
01711 *(int*)optval = sock->conn->type;
01712 LWIP_DEBUGF(SOCKETS_DEBUG,
01713 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
01714 s, *(int *)optval));
01715 }
01716 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
01717 s, *(int *)optval));
01718 break;
01719
01720 case SO_ERROR:
01721
01722 if ((sock->err == 0) || (sock->err == EINPROGRESS)) {
01723 sock_set_errno(sock, err_to_errno(sock->conn->last_err));
01724 }
01725 *(int *)optval = sock->err;
01726 sock->err = 0;
01727 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
01728 s, *(int *)optval));
01729 break;
01730
01731 #if LWIP_SO_SNDTIMEO
01732 case SO_SNDTIMEO:
01733 *(int *)optval = netconn_get_sendtimeout(sock->conn);
01734 break;
01735 #endif
01736 #if LWIP_SO_RCVTIMEO
01737 case SO_RCVTIMEO:
01738 *(int *)optval = netconn_get_recvtimeout(sock->conn);
01739 break;
01740 #endif
01741 #if LWIP_SO_RCVBUF
01742 case SO_RCVBUF:
01743 *(int *)optval = netconn_get_recvbufsize(sock->conn);
01744 break;
01745 #endif
01746 #if LWIP_UDP
01747 case SO_NO_CHECK:
01748 *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
01749 break;
01750 #endif
01751 default:
01752 LWIP_ASSERT("unhandled optname", 0);
01753 break;
01754 }
01755 break;
01756
01757
01758 case IPPROTO_IP:
01759 switch (optname) {
01760 case IP_TTL:
01761 *(int*)optval = sock->conn->pcb.ip->ttl;
01762 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
01763 s, *(int *)optval));
01764 break;
01765 case IP_TOS:
01766 *(int*)optval = sock->conn->pcb.ip->tos;
01767 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
01768 s, *(int *)optval));
01769 break;
01770 #if LWIP_IGMP
01771 case IP_MULTICAST_TTL:
01772 *(u8_t*)optval = sock->conn->pcb.ip->ttl;
01773 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
01774 s, *(int *)optval));
01775 break;
01776 case IP_MULTICAST_IF:
01777 inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip);
01778 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
01779 s, *(u32_t *)optval));
01780 break;
01781 case IP_MULTICAST_LOOP:
01782 if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
01783 *(u8_t*)optval = 1;
01784 } else {
01785 *(u8_t*)optval = 0;
01786 }
01787 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
01788 s, *(int *)optval));
01789 break;
01790 #endif
01791 default:
01792 LWIP_ASSERT("unhandled optname", 0);
01793 break;
01794 }
01795 break;
01796
01797 #if LWIP_TCP
01798
01799 case IPPROTO_TCP:
01800 switch (optname) {
01801 case TCP_NODELAY:
01802 *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
01803 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
01804 s, (*(int*)optval)?"on":"off") );
01805 break;
01806 case TCP_KEEPALIVE:
01807 *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
01808 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
01809 s, *(int *)optval));
01810 break;
01811
01812 #if LWIP_TCP_KEEPALIVE
01813 case TCP_KEEPIDLE:
01814 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
01815 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
01816 s, *(int *)optval));
01817 break;
01818 case TCP_KEEPINTVL:
01819 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
01820 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
01821 s, *(int *)optval));
01822 break;
01823 case TCP_KEEPCNT:
01824 *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
01825 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
01826 s, *(int *)optval));
01827 break;
01828 #endif
01829 default:
01830 LWIP_ASSERT("unhandled optname", 0);
01831 break;
01832 }
01833 break;
01834 #endif
01835 #if LWIP_UDP && LWIP_UDPLITE
01836
01837 case IPPROTO_UDPLITE:
01838 switch (optname) {
01839 case UDPLITE_SEND_CSCOV:
01840 *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
01841 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
01842 s, (*(int*)optval)) );
01843 break;
01844 case UDPLITE_RECV_CSCOV:
01845 *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
01846 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
01847 s, (*(int*)optval)) );
01848 break;
01849 default:
01850 LWIP_ASSERT("unhandled optname", 0);
01851 break;
01852 }
01853 break;
01854 #endif
01855 default:
01856 LWIP_ASSERT("unhandled level", 0);
01857 break;
01858 }
01859 sys_sem_signal(&sock->conn->op_completed);
01860 }
01861
01862 int
01863 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
01864 {
01865 struct lwip_sock *sock = get_socket(s);
01866 err_t err = ERR_OK;
01867 struct lwip_setgetsockopt_data data;
01868
01869 if (!sock) {
01870 return -1;
01871 }
01872
01873 if (NULL == optval) {
01874 sock_set_errno(sock, EFAULT);
01875 return -1;
01876 }
01877
01878
01879 switch (level) {
01880
01881
01882 case SOL_SOCKET:
01883 switch (optname) {
01884
01885 case SO_BROADCAST:
01886
01887
01888 case SO_KEEPALIVE:
01889
01890 #if LWIP_SO_SNDTIMEO
01891 case SO_SNDTIMEO:
01892 #endif
01893 #if LWIP_SO_RCVTIMEO
01894 case SO_RCVTIMEO:
01895 #endif
01896 #if LWIP_SO_RCVBUF
01897 case SO_RCVBUF:
01898 #endif
01899
01900
01901
01902
01903 #if SO_REUSE
01904 case SO_REUSEADDR:
01905 case SO_REUSEPORT:
01906 #endif
01907
01908 if (optlen < sizeof(int)) {
01909 err = EINVAL;
01910 }
01911 break;
01912 case SO_NO_CHECK:
01913 if (optlen < sizeof(int)) {
01914 err = EINVAL;
01915 }
01916 #if LWIP_UDP
01917 if ((sock->conn->type != NETCONN_UDP) ||
01918 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
01919
01920 err = EAFNOSUPPORT;
01921 }
01922 #endif
01923 break;
01924 default:
01925 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
01926 s, optname));
01927 err = ENOPROTOOPT;
01928 }
01929 break;
01930
01931
01932 case IPPROTO_IP:
01933 switch (optname) {
01934
01935
01936
01937 case IP_TTL:
01938 case IP_TOS:
01939 if (optlen < sizeof(int)) {
01940 err = EINVAL;
01941 }
01942 break;
01943 #if LWIP_IGMP
01944 case IP_MULTICAST_TTL:
01945 if (optlen < sizeof(u8_t)) {
01946 err = EINVAL;
01947 }
01948 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01949 err = EAFNOSUPPORT;
01950 }
01951 break;
01952 case IP_MULTICAST_IF:
01953 if (optlen < sizeof(struct in_addr)) {
01954 err = EINVAL;
01955 }
01956 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01957 err = EAFNOSUPPORT;
01958 }
01959 break;
01960 case IP_MULTICAST_LOOP:
01961 if (optlen < sizeof(u8_t)) {
01962 err = EINVAL;
01963 }
01964 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01965 err = EAFNOSUPPORT;
01966 }
01967 break;
01968 case IP_ADD_MEMBERSHIP:
01969 case IP_DROP_MEMBERSHIP:
01970 if (optlen < sizeof(struct ip_mreq)) {
01971 err = EINVAL;
01972 }
01973 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01974 err = EAFNOSUPPORT;
01975 }
01976 break;
01977 #endif
01978 default:
01979 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
01980 s, optname));
01981 err = ENOPROTOOPT;
01982 }
01983 break;
01984
01985 #if LWIP_TCP
01986
01987 case IPPROTO_TCP:
01988 if (optlen < sizeof(int)) {
01989 err = EINVAL;
01990 break;
01991 }
01992
01993
01994 if (sock->conn->type != NETCONN_TCP)
01995 return 0;
01996
01997 switch (optname) {
01998 case TCP_NODELAY:
01999 case TCP_KEEPALIVE:
02000 #if LWIP_TCP_KEEPALIVE
02001 case TCP_KEEPIDLE:
02002 case TCP_KEEPINTVL:
02003 case TCP_KEEPCNT:
02004 #endif
02005 break;
02006
02007 default:
02008 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
02009 s, optname));
02010 err = ENOPROTOOPT;
02011 }
02012 break;
02013 #endif
02014 #if LWIP_UDP && LWIP_UDPLITE
02015
02016 case IPPROTO_UDPLITE:
02017 if (optlen < sizeof(int)) {
02018 err = EINVAL;
02019 break;
02020 }
02021
02022
02023 if (sock->conn->type != NETCONN_UDPLITE)
02024 return 0;
02025
02026 switch (optname) {
02027 case UDPLITE_SEND_CSCOV:
02028 case UDPLITE_RECV_CSCOV:
02029 break;
02030
02031 default:
02032 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
02033 s, optname));
02034 err = ENOPROTOOPT;
02035 }
02036 break;
02037 #endif
02038
02039 default:
02040 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
02041 s, level, optname));
02042 err = ENOPROTOOPT;
02043 }
02044
02045
02046 if (err != ERR_OK) {
02047 sock_set_errno(sock, err);
02048 return -1;
02049 }
02050
02051
02052
02053 data.sock = sock;
02054 #ifdef LWIP_DEBUG
02055 data.s = s;
02056 #endif
02057 data.level = level;
02058 data.optname = optname;
02059 data.optval = (void*)optval;
02060 data.optlen = &optlen;
02061 data.err = err;
02062 tcpip_callback(lwip_setsockopt_internal, &data);
02063 sys_arch_sem_wait(&sock->conn->op_completed, 0);
02064
02065 err = data.err;
02066
02067 sock_set_errno(sock, err);
02068 return err ? -1 : 0;
02069 }
02070
02071 static void
02072 lwip_setsockopt_internal(void *arg)
02073 {
02074 struct lwip_sock *sock;
02075 #ifdef LWIP_DEBUG
02076 int s;
02077 #endif
02078 int level, optname;
02079 const void *optval;
02080 struct lwip_setgetsockopt_data *data;
02081
02082 LWIP_ASSERT("arg != NULL", arg != NULL);
02083
02084 data = (struct lwip_setgetsockopt_data*)arg;
02085 sock = data->sock;
02086 #ifdef LWIP_DEBUG
02087 s = data->s;
02088 #endif
02089 level = data->level;
02090 optname = data->optname;
02091 optval = data->optval;
02092
02093 switch (level) {
02094
02095
02096 case SOL_SOCKET:
02097 switch (optname) {
02098
02099
02100 case SO_BROADCAST:
02101
02102
02103 case SO_KEEPALIVE:
02104
02105 #if SO_REUSE
02106 case SO_REUSEADDR:
02107 case SO_REUSEPORT:
02108 #endif
02109
02110 if (*(int*)optval) {
02111 ip_set_option(sock->conn->pcb.ip, optname);
02112 } else {
02113 ip_reset_option(sock->conn->pcb.ip, optname);
02114 }
02115 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
02116 s, optname, (*(int*)optval?"on":"off")));
02117 break;
02118 #if LWIP_SO_SNDTIMEO
02119 case SO_SNDTIMEO:
02120 netconn_set_sendtimeout(sock->conn, (s32_t)*(int*)optval);
02121 break;
02122 #endif
02123 #if LWIP_SO_RCVTIMEO
02124 case SO_RCVTIMEO:
02125 netconn_set_recvtimeout(sock->conn, *(int*)optval);
02126 break;
02127 #endif
02128 #if LWIP_SO_RCVBUF
02129 case SO_RCVBUF:
02130 netconn_set_recvbufsize(sock->conn, *(int*)optval);
02131 break;
02132 #endif
02133 #if LWIP_UDP
02134 case SO_NO_CHECK:
02135 if (*(int*)optval) {
02136 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
02137 } else {
02138 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
02139 }
02140 break;
02141 #endif
02142 default:
02143 LWIP_ASSERT("unhandled optname", 0);
02144 break;
02145 }
02146 break;
02147
02148
02149 case IPPROTO_IP:
02150 switch (optname) {
02151 case IP_TTL:
02152 sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
02153 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
02154 s, sock->conn->pcb.ip->ttl));
02155 break;
02156 case IP_TOS:
02157 sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
02158 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
02159 s, sock->conn->pcb.ip->tos));
02160 break;
02161 #if LWIP_IGMP
02162 case IP_MULTICAST_TTL:
02163 sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
02164 break;
02165 case IP_MULTICAST_IF:
02166 inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval);
02167 break;
02168 case IP_MULTICAST_LOOP:
02169 if (*(u8_t*)optval) {
02170 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
02171 } else {
02172 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
02173 }
02174 break;
02175 case IP_ADD_MEMBERSHIP:
02176 case IP_DROP_MEMBERSHIP:
02177 {
02178
02179 struct ip_mreq *imr = (struct ip_mreq *)optval;
02180 ip_addr_t if_addr;
02181 ip_addr_t multi_addr;
02182 inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
02183 inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
02184 if(optname == IP_ADD_MEMBERSHIP){
02185 data->err = igmp_joingroup(&if_addr, &multi_addr);
02186 } else {
02187 data->err = igmp_leavegroup(&if_addr, &multi_addr);
02188 }
02189 if(data->err != ERR_OK) {
02190 data->err = EADDRNOTAVAIL;
02191 }
02192 }
02193 break;
02194 #endif
02195 default:
02196 LWIP_ASSERT("unhandled optname", 0);
02197 break;
02198 }
02199 break;
02200
02201 #if LWIP_TCP
02202
02203 case IPPROTO_TCP:
02204 switch (optname) {
02205 case TCP_NODELAY:
02206 if (*(int*)optval) {
02207 tcp_nagle_disable(sock->conn->pcb.tcp);
02208 } else {
02209 tcp_nagle_enable(sock->conn->pcb.tcp);
02210 }
02211 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
02212 s, (*(int *)optval)?"on":"off") );
02213 break;
02214 case TCP_KEEPALIVE:
02215 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
02216 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
02217 s, sock->conn->pcb.tcp->keep_idle));
02218 break;
02219
02220 #if LWIP_TCP_KEEPALIVE
02221 case TCP_KEEPIDLE:
02222 sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
02223 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
02224 s, sock->conn->pcb.tcp->keep_idle));
02225 break;
02226 case TCP_KEEPINTVL:
02227 sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
02228 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
02229 s, sock->conn->pcb.tcp->keep_intvl));
02230 break;
02231 case TCP_KEEPCNT:
02232 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
02233 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
02234 s, sock->conn->pcb.tcp->keep_cnt));
02235 break;
02236 #endif
02237 default:
02238 LWIP_ASSERT("unhandled optname", 0);
02239 break;
02240 }
02241 break;
02242 #endif
02243 #if LWIP_UDP && LWIP_UDPLITE
02244
02245 case IPPROTO_UDPLITE:
02246 switch (optname) {
02247 case UDPLITE_SEND_CSCOV:
02248 if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) {
02249
02250 sock->conn->pcb.udp->chksum_len_tx = 8;
02251 } else {
02252 sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval;
02253 }
02254 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
02255 s, (*(int*)optval)) );
02256 break;
02257 case UDPLITE_RECV_CSCOV:
02258 if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) {
02259
02260 sock->conn->pcb.udp->chksum_len_rx = 8;
02261 } else {
02262 sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval;
02263 }
02264 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
02265 s, (*(int*)optval)) );
02266 break;
02267 default:
02268 LWIP_ASSERT("unhandled optname", 0);
02269 break;
02270 }
02271 break;
02272 #endif
02273 default:
02274 LWIP_ASSERT("unhandled level", 0);
02275 break;
02276 }
02277 sys_sem_signal(&sock->conn->op_completed);
02278 }
02279
02280 int
02281 lwip_ioctl(int s, long cmd, void *argp)
02282 {
02283 struct lwip_sock *sock = get_socket(s);
02284 u8_t val;
02285 #if LWIP_SO_RCVBUF
02286 u16_t buflen = 0;
02287 s16_t recv_avail;
02288 #endif
02289
02290 if (!sock) {
02291 return -1;
02292 }
02293
02294 switch (cmd) {
02295 #if LWIP_SO_RCVBUF
02296 case FIONREAD:
02297 if (!argp) {
02298 sock_set_errno(sock, EINVAL);
02299 return -1;
02300 }
02301
02302 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
02303 if (recv_avail < 0) {
02304 recv_avail = 0;
02305 }
02306 *((u16_t*)argp) = (u16_t)recv_avail;
02307
02308
02309 if (sock->lastdata) {
02310 struct pbuf *p = (struct pbuf *)sock->lastdata;
02311 if (netconn_type(sock->conn) != NETCONN_TCP) {
02312 p = ((struct netbuf *)p)->p;
02313 }
02314 buflen = p->tot_len;
02315 buflen -= sock->lastoffset;
02316
02317 *((u16_t*)argp) += buflen;
02318 }
02319
02320 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
02321 sock_set_errno(sock, 0);
02322 return 0;
02323 #endif
02324
02325 case FIONBIO:
02326 val = 0;
02327 if (argp && *(u32_t*)argp) {
02328 val = 1;
02329 }
02330 netconn_set_nonblocking(sock->conn, val);
02331 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
02332 sock_set_errno(sock, 0);
02333 return 0;
02334
02335 default:
02336 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
02337 sock_set_errno(sock, ENOSYS);
02338 return -1;
02339 }
02340 }
02341
02342
02343
02344
02345
02346 int
02347 lwip_fcntl(int s, int cmd, int val)
02348 {
02349 struct lwip_sock *sock = get_socket(s);
02350 int ret = -1;
02351
02352 if (!sock || !sock->conn) {
02353 return -1;
02354 }
02355
02356 switch (cmd) {
02357 case F_GETFL:
02358 ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
02359 break;
02360 case F_SETFL:
02361 if ((val & ~O_NONBLOCK) == 0) {
02362
02363 netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
02364 ret = 0;
02365 }
02366 break;
02367 default:
02368 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
02369 break;
02370 }
02371 return ret;
02372 }
02373
02374 #endif