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
00055 #include <string.h>
00056
00057 #define NUM_SOCKETS MEMP_NUM_NETCONN
00058
00059
00060 struct lwip_socket {
00061
00062 struct netconn *conn;
00063
00064 struct netbuf *lastdata;
00065
00066 u16_t lastoffset;
00067
00068
00069 s16_t rcvevent;
00070
00071
00072 u16_t sendevent;
00073
00074 u16_t flags;
00075
00076 int err;
00077 };
00078
00079
00080 struct lwip_select_cb {
00081
00082 struct lwip_select_cb *next;
00083
00084 fd_set *readset;
00085
00086 fd_set *writeset;
00087
00088 fd_set *exceptset;
00089
00090 int sem_signalled;
00091
00092 sys_sem_t sem;
00093 };
00094
00095
00096
00097 struct lwip_setgetsockopt_data {
00098
00099 struct lwip_socket *sock;
00100
00101 int s;
00102
00103 int level;
00104
00105 int optname;
00106
00107
00108 void *optval;
00109
00110 socklen_t *optlen;
00111
00112 err_t err;
00113 };
00114
00115
00116 static struct lwip_socket sockets[NUM_SOCKETS];
00117
00118 static struct lwip_select_cb *select_cb_list;
00119
00120
00121 static sys_sem_t socksem;
00122
00123 static sys_sem_t selectsem;
00124
00125
00126
00127 static const int err_to_errno_table[] = {
00128 0,
00129 ENOMEM,
00130 ENOBUFS,
00131 ETIMEDOUT,
00132 EHOSTUNREACH,
00133 ECONNABORTED,
00134 ECONNRESET,
00135 ESHUTDOWN,
00136 ENOTCONN,
00137 EINVAL,
00138 EIO,
00139 EADDRINUSE,
00140 -1,
00141 -1,
00142 EINPROGRESS
00143 };
00144
00145 #define ERR_TO_ERRNO_TABLE_SIZE \
00146 (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
00147
00148 #define err_to_errno(err) \
00149 ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
00150 err_to_errno_table[-(err)] : EIO)
00151
00152 #ifdef ERRNO
00153 #ifndef set_errno
00154 #define set_errno(err) errno = (err)
00155 #endif
00156 #else
00157 #define set_errno(err)
00158 #endif
00159
00160 #define sock_set_errno(sk, e) do { \
00161 sk->err = (e); \
00162 set_errno(sk->err); \
00163 } while (0)
00164
00165
00166 static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
00167 static void lwip_getsockopt_internal(void *arg);
00168 static void lwip_setsockopt_internal(void *arg);
00169
00170
00171
00172
00173
00174 void
00175 lwip_socket_init(void)
00176 {
00177 socksem = sys_sem_new(1);
00178 selectsem = sys_sem_new(1);
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 static struct lwip_socket *
00188 get_socket(int s)
00189 {
00190 struct lwip_socket *sock;
00191
00192 if ((s < 0) || (s >= NUM_SOCKETS)) {
00193 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
00194 set_errno(EBADF);
00195 return NULL;
00196 }
00197
00198 sock = &sockets[s];
00199
00200 if (!sock->conn) {
00201 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
00202 set_errno(EBADF);
00203 return NULL;
00204 }
00205
00206 return sock;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 static int
00216 alloc_socket(struct netconn *newconn)
00217 {
00218 int i;
00219
00220
00221 sys_sem_wait(socksem);
00222
00223
00224 for (i = 0; i < NUM_SOCKETS; ++i) {
00225 if (!sockets[i].conn) {
00226 sockets[i].conn = newconn;
00227 sockets[i].lastdata = NULL;
00228 sockets[i].lastoffset = 0;
00229 sockets[i].rcvevent = 0;
00230 sockets[i].sendevent = 1;
00231 sockets[i].flags = 0;
00232 sockets[i].err = 0;
00233 sys_sem_signal(socksem);
00234 return i;
00235 }
00236 }
00237 sys_sem_signal(socksem);
00238 return -1;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 int
00248 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
00249 {
00250 struct lwip_socket *sock, *nsock;
00251 struct netconn *newconn;
00252 struct ip_addr naddr;
00253 u16_t port;
00254 int newsock;
00255 struct sockaddr_in sin;
00256 err_t err;
00257
00258 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
00259 sock = get_socket(s);
00260 if (!sock)
00261 return -1;
00262
00263 if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) {
00264 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
00265 sock_set_errno(sock, EWOULDBLOCK);
00266 return -1;
00267 }
00268
00269 newconn = netconn_accept(sock->conn);
00270 if (!newconn) {
00271 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err));
00272 sock_set_errno(sock, err_to_errno(sock->conn->err));
00273 return -1;
00274 }
00275
00276
00277 err = netconn_peer(newconn, &naddr, &port);
00278 if (err != ERR_OK) {
00279 netconn_delete(newconn);
00280 sock_set_errno(sock, err_to_errno(err));
00281 return -1;
00282 }
00283
00284
00285
00286
00287 if (NULL != addr) {
00288 LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
00289 memset(&sin, 0, sizeof(sin));
00290 sin.sin_len = sizeof(sin);
00291 sin.sin_family = AF_INET;
00292 sin.sin_port = htons(port);
00293 sin.sin_addr.s_addr = naddr.addr;
00294
00295 if (*addrlen > sizeof(sin))
00296 *addrlen = sizeof(sin);
00297
00298 MEMCPY(addr, &sin, *addrlen);
00299 }
00300
00301 newsock = alloc_socket(newconn);
00302 if (newsock == -1) {
00303 netconn_delete(newconn);
00304 sock_set_errno(sock, ENFILE);
00305 return -1;
00306 }
00307 LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
00308 newconn->callback = event_callback;
00309 nsock = &sockets[newsock];
00310 LWIP_ASSERT("invalid socket pointer", nsock != NULL);
00311
00312 sys_sem_wait(socksem);
00313
00314
00315
00316
00317
00318 nsock->rcvevent += -1 - newconn->socket;
00319 newconn->socket = newsock;
00320 sys_sem_signal(socksem);
00321
00322 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
00323 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
00324 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
00325
00326 sock_set_errno(sock, 0);
00327 return newsock;
00328 }
00329
00330 int
00331 lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
00332 {
00333 struct lwip_socket *sock;
00334 struct ip_addr local_addr;
00335 u16_t local_port;
00336 err_t err;
00337
00338 sock = get_socket(s);
00339 if (!sock)
00340 return -1;
00341
00342 LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
00343 ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
00344 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
00345
00346 local_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
00347 local_port = ((const struct sockaddr_in *)name)->sin_port;
00348
00349 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
00350 ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
00351 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
00352
00353 err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
00354
00355 if (err != ERR_OK) {
00356 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
00357 sock_set_errno(sock, err_to_errno(err));
00358 return -1;
00359 }
00360
00361 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
00362 sock_set_errno(sock, 0);
00363 return 0;
00364 }
00365
00366 int
00367 lwip_close(int s)
00368 {
00369 struct lwip_socket *sock;
00370
00371 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
00372
00373 sock = get_socket(s);
00374 if (!sock) {
00375 return -1;
00376 }
00377
00378 netconn_delete(sock->conn);
00379
00380 sys_sem_wait(socksem);
00381 if (sock->lastdata) {
00382 netbuf_delete(sock->lastdata);
00383 }
00384 sock->lastdata = NULL;
00385 sock->lastoffset = 0;
00386 sock->conn = NULL;
00387 sock_set_errno(sock, 0);
00388 sys_sem_signal(socksem);
00389 return 0;
00390 }
00391
00392 int
00393 lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
00394 {
00395 struct lwip_socket *sock;
00396 err_t err;
00397
00398 sock = get_socket(s);
00399 if (!sock)
00400 return -1;
00401
00402 LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
00403 ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
00404 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
00405
00406 if (((const struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
00407 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
00408 err = netconn_disconnect(sock->conn);
00409 } else {
00410 struct ip_addr remote_addr;
00411 u16_t remote_port;
00412
00413 remote_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
00414 remote_port = ((const struct sockaddr_in *)name)->sin_port;
00415
00416 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
00417 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
00418 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
00419
00420 err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
00421 }
00422
00423 if (err != ERR_OK) {
00424 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
00425 sock_set_errno(sock, err_to_errno(err));
00426 return -1;
00427 }
00428
00429 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
00430 sock_set_errno(sock, 0);
00431 return 0;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 int
00443 lwip_listen(int s, int backlog)
00444 {
00445 struct lwip_socket *sock;
00446 err_t err;
00447
00448 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
00449
00450 sock = get_socket(s);
00451 if (!sock)
00452 return -1;
00453
00454
00455 if (backlog < 0) {
00456 backlog = 0;
00457 }
00458 if (backlog > 0xff) {
00459 backlog = 0xff;
00460 }
00461
00462 err = netconn_listen_with_backlog(sock->conn, backlog);
00463
00464 if (err != ERR_OK) {
00465 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
00466 sock_set_errno(sock, err_to_errno(err));
00467 return -1;
00468 }
00469
00470 sock_set_errno(sock, 0);
00471 return 0;
00472 }
00473
00474 int
00475 lwip_recvfrom(int s, void *mem, size_t len, int flags,
00476 struct sockaddr *from, socklen_t *fromlen)
00477 {
00478 struct lwip_socket *sock;
00479 struct netbuf *buf;
00480 u16_t buflen, copylen, off = 0;
00481 struct ip_addr *addr;
00482 u16_t port;
00483 u8_t done = 0;
00484
00485 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
00486 sock = get_socket(s);
00487 if (!sock)
00488 return -1;
00489
00490 do {
00491 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", (void*)sock->lastdata));
00492
00493 if (sock->lastdata) {
00494 buf = sock->lastdata;
00495 } else {
00496
00497 if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
00498 (sock->rcvevent <= 0)) {
00499 if (off > 0) {
00500
00501 sock_set_errno(sock, 0);
00502 return off;
00503 }
00504 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
00505 sock_set_errno(sock, EWOULDBLOCK);
00506 return -1;
00507 }
00508
00509
00510
00511 sock->lastdata = buf = netconn_recv(sock->conn);
00512 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", (void*)buf));
00513
00514 if (!buf) {
00515 if (off > 0) {
00516
00517 sock_set_errno(sock, 0);
00518 return off;
00519 }
00520
00521 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
00522 sock_set_errno(sock, (((sock->conn->pcb.ip != NULL) && (sock->conn->err == ERR_OK))
00523 ? ETIMEDOUT : err_to_errno(sock->conn->err)));
00524 return 0;
00525 }
00526 }
00527
00528 buflen = netbuf_len(buf);
00529 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%"U16_F" sock->lastoffset=%"U16_F"\n",
00530 buflen, len, off, sock->lastoffset));
00531
00532 buflen -= sock->lastoffset;
00533
00534 if (len > buflen) {
00535 copylen = buflen;
00536 } else {
00537 copylen = (u16_t)len;
00538 }
00539
00540
00541
00542 netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset);
00543
00544 off += copylen;
00545
00546 if (netconn_type(sock->conn) == NETCONN_TCP) {
00547 LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
00548 len -= copylen;
00549 if ( (len <= 0) ||
00550 (buf->p->flags & PBUF_FLAG_PUSH) ||
00551 (sock->rcvevent <= 0) ||
00552 ((flags & MSG_PEEK)!=0)) {
00553 done = 1;
00554 }
00555 } else {
00556 done = 1;
00557 }
00558
00559
00560 if (done) {
00561 if (from && fromlen) {
00562 struct sockaddr_in sin;
00563
00564 if (netconn_type(sock->conn) == NETCONN_TCP) {
00565 addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
00566 netconn_getaddr(sock->conn, addr, &port, 0);
00567 } else {
00568 addr = netbuf_fromaddr(buf);
00569 port = netbuf_fromport(buf);
00570 }
00571
00572 memset(&sin, 0, sizeof(sin));
00573 sin.sin_len = sizeof(sin);
00574 sin.sin_family = AF_INET;
00575 sin.sin_port = htons(port);
00576 sin.sin_addr.s_addr = addr->addr;
00577
00578 if (*fromlen > sizeof(sin)) {
00579 *fromlen = sizeof(sin);
00580 }
00581
00582 MEMCPY(from, &sin, *fromlen);
00583
00584 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
00585 ip_addr_debug_print(SOCKETS_DEBUG, addr);
00586 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
00587 } else {
00588 #if SOCKETS_DEBUG
00589 struct sockaddr_in sin;
00590
00591 if (netconn_type(sock->conn) == NETCONN_TCP) {
00592 addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
00593 netconn_getaddr(sock->conn, addr, &port, 0);
00594 } else {
00595 addr = netbuf_fromaddr(buf);
00596 port = netbuf_fromport(buf);
00597 }
00598
00599 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
00600 ip_addr_debug_print(SOCKETS_DEBUG, addr);
00601 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
00602 #endif
00603 }
00604 }
00605
00606
00607 if ((flags & MSG_PEEK)==0) {
00608
00609
00610
00611 if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
00612 sock->lastdata = buf;
00613 sock->lastoffset += copylen;
00614 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
00615 } else {
00616 sock->lastdata = NULL;
00617 sock->lastoffset = 0;
00618 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
00619 netbuf_delete(buf);
00620 }
00621 }
00622 } while (!done);
00623
00624 sock_set_errno(sock, 0);
00625 return off;
00626 }
00627
00628 int
00629 lwip_read(int s, void *mem, size_t len)
00630 {
00631 return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
00632 }
00633
00634 int
00635 lwip_recv(int s, void *mem, size_t len, int flags)
00636 {
00637 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
00638 }
00639
00640 int
00641 lwip_send(int s, const void *data, size_t size, int flags)
00642 {
00643 struct lwip_socket *sock;
00644 err_t err;
00645
00646 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
00647 s, data, size, flags));
00648
00649 sock = get_socket(s);
00650 if (!sock)
00651 return -1;
00652
00653 if (sock->conn->type != NETCONN_TCP) {
00654 #if (LWIP_UDP || LWIP_RAW)
00655 return lwip_sendto(s, data, size, flags, NULL, 0);
00656 #else
00657 sock_set_errno(sock, err_to_errno(ERR_ARG));
00658 return -1;
00659 #endif
00660 }
00661
00662 err = netconn_write(sock->conn, data, size, NETCONN_COPY | ((flags & MSG_MORE)?NETCONN_MORE:0));
00663
00664 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
00665 sock_set_errno(sock, err_to_errno(err));
00666 return (err == ERR_OK ? (int)size : -1);
00667 }
00668
00669 int
00670 lwip_sendto(int s, const void *data, size_t size, int flags,
00671 const struct sockaddr *to, socklen_t tolen)
00672 {
00673 struct lwip_socket *sock;
00674 struct ip_addr remote_addr;
00675 err_t err;
00676 u16_t short_size;
00677 #if !LWIP_TCPIP_CORE_LOCKING
00678 struct netbuf buf;
00679 u16_t remote_port;
00680 #endif
00681
00682 sock = get_socket(s);
00683 if (!sock)
00684 return -1;
00685
00686 if (sock->conn->type == NETCONN_TCP) {
00687 #if LWIP_TCP
00688 return lwip_send(s, data, size, flags);
00689 #else
00690 sock_set_errno(sock, err_to_errno(ERR_ARG));
00691 return -1;
00692 #endif
00693 }
00694
00695 LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
00696 short_size = (u16_t)size;
00697 LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
00698 ((tolen == sizeof(struct sockaddr_in)) &&
00699 ((((const struct sockaddr_in *)to)->sin_family) == AF_INET))),
00700 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
00701
00702 #if LWIP_TCPIP_CORE_LOCKING
00703
00704 { struct pbuf* p;
00705
00706 p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
00707 if (p == NULL) {
00708 err = ERR_MEM;
00709 } else {
00710 p->payload = (void*)data;
00711 p->len = p->tot_len = short_size;
00712
00713 remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
00714
00715 LOCK_TCPIP_CORE();
00716 if (sock->conn->type==NETCONN_RAW) {
00717 err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
00718 } else {
00719 err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port));
00720 }
00721 UNLOCK_TCPIP_CORE();
00722
00723 pbuf_free(p);
00724 }
00725 }
00726 #else
00727
00728 buf.p = buf.ptr = NULL;
00729 if (to) {
00730 remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
00731 remote_port = ntohs(((const struct sockaddr_in *)to)->sin_port);
00732 buf.addr = &remote_addr;
00733 buf.port = remote_port;
00734 } else {
00735 remote_addr.addr = 0;
00736 remote_port = 0;
00737 buf.addr = NULL;
00738 buf.port = 0;
00739 }
00740
00741 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
00742 s, data, short_size, flags));
00743 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
00744 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
00745
00746
00747 #if LWIP_NETIF_TX_SINGLE_PBUF
00748
00749 if (netbuf_alloc(&buf, short_size) == NULL) {
00750 err = ERR_MEM;
00751 } else {
00752 err = netbuf_take(&buf, data, short_size);
00753 }
00754 #else
00755 err = netbuf_ref(&buf, data, short_size);
00756 #endif
00757 if (err == ERR_OK) {
00758
00759 err = netconn_send(sock->conn, &buf);
00760 }
00761
00762
00763 netbuf_free(&buf);
00764 #endif
00765 sock_set_errno(sock, err_to_errno(err));
00766 return (err == ERR_OK ? short_size : -1);
00767 }
00768
00769 int
00770 lwip_socket(int domain, int type, int protocol)
00771 {
00772 struct netconn *conn;
00773 int i;
00774
00775 LWIP_UNUSED_ARG(domain);
00776
00777
00778 switch (type) {
00779 case SOCK_RAW:
00780 conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
00781 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
00782 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00783 break;
00784 case SOCK_DGRAM:
00785 conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
00786 NETCONN_UDPLITE : NETCONN_UDP, event_callback);
00787 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
00788 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00789 break;
00790 case SOCK_STREAM:
00791 conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
00792 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
00793 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00794 break;
00795 default:
00796 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
00797 domain, type, protocol));
00798 set_errno(EINVAL);
00799 return -1;
00800 }
00801
00802 if (!conn) {
00803 LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
00804 set_errno(ENOBUFS);
00805 return -1;
00806 }
00807
00808 i = alloc_socket(conn);
00809
00810 if (i == -1) {
00811 netconn_delete(conn);
00812 set_errno(ENFILE);
00813 return -1;
00814 }
00815 conn->socket = i;
00816 LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
00817 set_errno(0);
00818 return i;
00819 }
00820
00821 int
00822 lwip_write(int s, const void *data, size_t size)
00823 {
00824 return lwip_send(s, data, size, 0);
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 static int
00843 lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
00844 {
00845 int i, nready = 0;
00846 fd_set lreadset, lwriteset, lexceptset;
00847 struct lwip_socket *p_sock;
00848
00849 FD_ZERO(&lreadset);
00850 FD_ZERO(&lwriteset);
00851 FD_ZERO(&lexceptset);
00852
00853
00854
00855 for(i = 0; i < maxfdp1; i++) {
00856 if (FD_ISSET(i, readset)) {
00857
00858 p_sock = get_socket(i);
00859 if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) {
00860 FD_SET(i, &lreadset);
00861 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
00862 nready++;
00863 }
00864 }
00865 if (FD_ISSET(i, writeset)) {
00866
00867 p_sock = get_socket(i);
00868 if (p_sock && p_sock->sendevent) {
00869 FD_SET(i, &lwriteset);
00870 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
00871 nready++;
00872 }
00873 }
00874 }
00875 *readset = lreadset;
00876 *writeset = lwriteset;
00877 FD_ZERO(exceptset);
00878
00879 return nready;
00880 }
00881
00882
00883
00884
00885
00886 int
00887 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
00888 struct timeval *timeout)
00889 {
00890 int i;
00891 int nready;
00892 fd_set lreadset, lwriteset, lexceptset;
00893 u32_t msectimeout;
00894 struct lwip_select_cb select_cb;
00895 struct lwip_select_cb *p_selcb;
00896
00897 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
00898 maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
00899 timeout ? (long)timeout->tv_sec : (long)-1,
00900 timeout ? (long)timeout->tv_usec : (long)-1));
00901
00902 select_cb.next = 0;
00903 select_cb.readset = readset;
00904 select_cb.writeset = writeset;
00905 select_cb.exceptset = exceptset;
00906 select_cb.sem_signalled = 0;
00907
00908
00909 sys_sem_wait(selectsem);
00910
00911 if (readset)
00912 lreadset = *readset;
00913 else
00914 FD_ZERO(&lreadset);
00915 if (writeset)
00916 lwriteset = *writeset;
00917 else
00918 FD_ZERO(&lwriteset);
00919 if (exceptset)
00920 lexceptset = *exceptset;
00921 else
00922 FD_ZERO(&lexceptset);
00923
00924
00925
00926 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
00927
00928
00929 if (!nready) {
00930 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
00931 sys_sem_signal(selectsem);
00932 if (readset)
00933 FD_ZERO(readset);
00934 if (writeset)
00935 FD_ZERO(writeset);
00936 if (exceptset)
00937 FD_ZERO(exceptset);
00938
00939 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
00940 set_errno(0);
00941
00942 return 0;
00943 }
00944
00945
00946
00947
00948
00949
00950 select_cb.sem = sys_sem_new(0);
00951
00952
00953 select_cb.next = select_cb_list;
00954 select_cb_list = &select_cb;
00955
00956
00957 sys_sem_signal(selectsem);
00958
00959
00960 if (timeout == 0)
00961
00962 msectimeout = 0;
00963 else {
00964 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
00965 if(msectimeout == 0)
00966 msectimeout = 1;
00967 }
00968
00969 i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
00970
00971
00972 sys_sem_wait(selectsem);
00973 if (select_cb_list == &select_cb)
00974 select_cb_list = select_cb.next;
00975 else
00976 for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) {
00977 if (p_selcb->next == &select_cb) {
00978 p_selcb->next = select_cb.next;
00979 break;
00980 }
00981 }
00982
00983 sys_sem_signal(selectsem);
00984
00985 sys_sem_free(select_cb.sem);
00986 if (i == 0) {
00987
00988 if (readset)
00989 FD_ZERO(readset);
00990 if (writeset)
00991 FD_ZERO(writeset);
00992 if (exceptset)
00993 FD_ZERO(exceptset);
00994
00995 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
00996 set_errno(0);
00997
00998 return 0;
00999 }
01000
01001 if (readset)
01002 lreadset = *readset;
01003 else
01004 FD_ZERO(&lreadset);
01005 if (writeset)
01006 lwriteset = *writeset;
01007 else
01008 FD_ZERO(&lwriteset);
01009 if (exceptset)
01010 lexceptset = *exceptset;
01011 else
01012 FD_ZERO(&lexceptset);
01013
01014
01015 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
01016 } else
01017 sys_sem_signal(selectsem);
01018
01019 if (readset)
01020 *readset = lreadset;
01021 if (writeset)
01022 *writeset = lwriteset;
01023 if (exceptset)
01024 *exceptset = lexceptset;
01025
01026 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
01027 set_errno(0);
01028
01029 return nready;
01030 }
01031
01032
01033
01034
01035
01036 static void
01037 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
01038 {
01039 int s;
01040 struct lwip_socket *sock;
01041 struct lwip_select_cb *scb;
01042
01043 LWIP_UNUSED_ARG(len);
01044
01045
01046 if (conn) {
01047 s = conn->socket;
01048 if (s < 0) {
01049
01050
01051
01052
01053
01054 sys_sem_wait(socksem);
01055 if (conn->socket < 0) {
01056 if (evt == NETCONN_EVT_RCVPLUS) {
01057 conn->socket--;
01058 }
01059 sys_sem_signal(socksem);
01060 return;
01061 }
01062 s = conn->socket;
01063 sys_sem_signal(socksem);
01064 }
01065
01066 sock = get_socket(s);
01067 if (!sock) {
01068 return;
01069 }
01070 } else {
01071 return;
01072 }
01073
01074 sys_sem_wait(selectsem);
01075
01076 switch (evt) {
01077 case NETCONN_EVT_RCVPLUS:
01078 sock->rcvevent++;
01079 break;
01080 case NETCONN_EVT_RCVMINUS:
01081 sock->rcvevent--;
01082 break;
01083 case NETCONN_EVT_SENDPLUS:
01084 sock->sendevent = 1;
01085 break;
01086 case NETCONN_EVT_SENDMINUS:
01087 sock->sendevent = 0;
01088 break;
01089 default:
01090 LWIP_ASSERT("unknown event", 0);
01091 break;
01092 }
01093 sys_sem_signal(selectsem);
01094
01095
01096
01097
01098
01099
01100
01101
01102 while (1) {
01103 sys_sem_wait(selectsem);
01104 for (scb = select_cb_list; scb; scb = scb->next) {
01105 if (scb->sem_signalled == 0) {
01106
01107 if (scb->readset && FD_ISSET(s, scb->readset))
01108 if (sock->rcvevent > 0)
01109 break;
01110 if (scb->writeset && FD_ISSET(s, scb->writeset))
01111 if (sock->sendevent)
01112 break;
01113 }
01114 }
01115 if (scb) {
01116 scb->sem_signalled = 1;
01117 sys_sem_signal(scb->sem);
01118 sys_sem_signal(selectsem);
01119 } else {
01120 sys_sem_signal(selectsem);
01121 break;
01122 }
01123 }
01124 }
01125
01126
01127
01128
01129
01130 int
01131 lwip_shutdown(int s, int how)
01132 {
01133 LWIP_UNUSED_ARG(how);
01134 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
01135 return lwip_close(s);
01136 }
01137
01138 static int
01139 lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
01140 {
01141 struct lwip_socket *sock;
01142 struct sockaddr_in sin;
01143 struct ip_addr naddr;
01144
01145 sock = get_socket(s);
01146 if (!sock)
01147 return -1;
01148
01149 memset(&sin, 0, sizeof(sin));
01150 sin.sin_len = sizeof(sin);
01151 sin.sin_family = AF_INET;
01152
01153
01154 netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
01155
01156 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
01157 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
01158 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
01159
01160 sin.sin_port = htons(sin.sin_port);
01161 sin.sin_addr.s_addr = naddr.addr;
01162
01163 if (*namelen > sizeof(sin))
01164 *namelen = sizeof(sin);
01165
01166 MEMCPY(name, &sin, *namelen);
01167 sock_set_errno(sock, 0);
01168 return 0;
01169 }
01170
01171 int
01172 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
01173 {
01174 return lwip_getaddrname(s, name, namelen, 0);
01175 }
01176
01177 int
01178 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
01179 {
01180 return lwip_getaddrname(s, name, namelen, 1);
01181 }
01182
01183 int
01184 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
01185 {
01186 err_t err = ERR_OK;
01187 struct lwip_socket *sock = get_socket(s);
01188 struct lwip_setgetsockopt_data data;
01189
01190 if (!sock)
01191 return -1;
01192
01193 if ((NULL == optval) || (NULL == optlen)) {
01194 sock_set_errno(sock, EFAULT);
01195 return -1;
01196 }
01197
01198
01199 switch (level) {
01200
01201
01202 case SOL_SOCKET:
01203 switch (optname) {
01204
01205 case SO_ACCEPTCONN:
01206 case SO_BROADCAST:
01207
01208
01209 case SO_ERROR:
01210 case SO_KEEPALIVE:
01211
01212
01213 #if LWIP_SO_RCVTIMEO
01214 case SO_RCVTIMEO:
01215 #endif
01216 #if LWIP_SO_RCVBUF
01217 case SO_RCVBUF:
01218 #endif
01219
01220
01221
01222
01223 #if SO_REUSE
01224 case SO_REUSEADDR:
01225 case SO_REUSEPORT:
01226 #endif
01227 case SO_TYPE:
01228
01229 if (*optlen < sizeof(int)) {
01230 err = EINVAL;
01231 }
01232 break;
01233
01234 case SO_NO_CHECK:
01235 if (*optlen < sizeof(int)) {
01236 err = EINVAL;
01237 }
01238 #if LWIP_UDP
01239 if ((sock->conn->type != NETCONN_UDP) ||
01240 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
01241
01242 err = EAFNOSUPPORT;
01243 }
01244 #endif
01245 break;
01246
01247 default:
01248 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
01249 s, optname));
01250 err = ENOPROTOOPT;
01251 }
01252 break;
01253
01254
01255 case IPPROTO_IP:
01256 switch (optname) {
01257
01258
01259
01260 case IP_TTL:
01261 case IP_TOS:
01262 if (*optlen < sizeof(int)) {
01263 err = EINVAL;
01264 }
01265 break;
01266 #if LWIP_IGMP
01267 case IP_MULTICAST_TTL:
01268 if (*optlen < sizeof(u8_t)) {
01269 err = EINVAL;
01270 }
01271 break;
01272 case IP_MULTICAST_IF:
01273 if (*optlen < sizeof(struct in_addr)) {
01274 err = EINVAL;
01275 }
01276 break;
01277 #endif
01278
01279 default:
01280 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
01281 s, optname));
01282 err = ENOPROTOOPT;
01283 }
01284 break;
01285
01286 #if LWIP_TCP
01287
01288 case IPPROTO_TCP:
01289 if (*optlen < sizeof(int)) {
01290 err = EINVAL;
01291 break;
01292 }
01293
01294
01295 if (sock->conn->type != NETCONN_TCP)
01296 return 0;
01297
01298 switch (optname) {
01299 case TCP_NODELAY:
01300 case TCP_KEEPALIVE:
01301 #if LWIP_TCP_KEEPALIVE
01302 case TCP_KEEPIDLE:
01303 case TCP_KEEPINTVL:
01304 case TCP_KEEPCNT:
01305 #endif
01306 break;
01307
01308 default:
01309 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
01310 s, optname));
01311 err = ENOPROTOOPT;
01312 }
01313 break;
01314 #endif
01315 #if LWIP_UDP && LWIP_UDPLITE
01316
01317 case IPPROTO_UDPLITE:
01318 if (*optlen < sizeof(int)) {
01319 err = EINVAL;
01320 break;
01321 }
01322
01323
01324 if (sock->conn->type != NETCONN_UDPLITE)
01325 return 0;
01326
01327 switch (optname) {
01328 case UDPLITE_SEND_CSCOV:
01329 case UDPLITE_RECV_CSCOV:
01330 break;
01331
01332 default:
01333 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
01334 s, optname));
01335 err = ENOPROTOOPT;
01336 }
01337 break;
01338 #endif
01339
01340 default:
01341 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
01342 s, level, optname));
01343 err = ENOPROTOOPT;
01344 }
01345
01346
01347 if (err != ERR_OK) {
01348 sock_set_errno(sock, err);
01349 return -1;
01350 }
01351
01352
01353 data.sock = sock;
01354 data.level = level;
01355 data.optname = optname;
01356 data.optval = optval;
01357 data.optlen = optlen;
01358 data.err = err;
01359 tcpip_callback(lwip_getsockopt_internal, &data);
01360 sys_arch_sem_wait(sock->conn->op_completed, 0);
01361
01362 err = data.err;
01363
01364 sock_set_errno(sock, err);
01365 return err ? -1 : 0;
01366 }
01367
01368 static void
01369 lwip_getsockopt_internal(void *arg)
01370 {
01371 struct lwip_socket *sock;
01372 #ifdef LWIP_DEBUG
01373 int s;
01374 #endif
01375 int level, optname;
01376 void *optval;
01377 struct lwip_setgetsockopt_data *data;
01378
01379 LWIP_ASSERT("arg != NULL", arg != NULL);
01380
01381 data = (struct lwip_setgetsockopt_data*)arg;
01382 sock = data->sock;
01383 #ifdef LWIP_DEBUG
01384 s = data->s;
01385 #endif
01386 level = data->level;
01387 optname = data->optname;
01388 optval = data->optval;
01389
01390 switch (level) {
01391
01392
01393 case SOL_SOCKET:
01394 switch (optname) {
01395
01396
01397 case SO_ACCEPTCONN:
01398 case SO_BROADCAST:
01399
01400
01401 case SO_KEEPALIVE:
01402
01403 #if SO_REUSE
01404 case SO_REUSEADDR:
01405 case SO_REUSEPORT:
01406 #endif
01407
01408 *(int*)optval = sock->conn->pcb.ip->so_options & optname;
01409 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
01410 s, optname, (*(int*)optval?"on":"off")));
01411 break;
01412
01413 case SO_TYPE:
01414 switch (NETCONNTYPE_GROUP(sock->conn->type)) {
01415 case NETCONN_RAW:
01416 *(int*)optval = SOCK_RAW;
01417 break;
01418 case NETCONN_TCP:
01419 *(int*)optval = SOCK_STREAM;
01420 break;
01421 case NETCONN_UDP:
01422 *(int*)optval = SOCK_DGRAM;
01423 break;
01424 default:
01425 *(int*)optval = sock->conn->type;
01426 LWIP_DEBUGF(SOCKETS_DEBUG,
01427 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
01428 s, *(int *)optval));
01429 }
01430 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
01431 s, *(int *)optval));
01432 break;
01433
01434 case SO_ERROR:
01435 if (sock->err == 0) {
01436 sock_set_errno(sock, err_to_errno(sock->conn->err));
01437 }
01438 *(int *)optval = sock->err;
01439 sock->err = 0;
01440 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
01441 s, *(int *)optval));
01442 break;
01443
01444 #if LWIP_SO_RCVTIMEO
01445 case SO_RCVTIMEO:
01446 *(int *)optval = sock->conn->recv_timeout;
01447 break;
01448 #endif
01449 #if LWIP_SO_RCVBUF
01450 case SO_RCVBUF:
01451 *(int *)optval = sock->conn->recv_bufsize;
01452 break;
01453 #endif
01454 #if LWIP_UDP
01455 case SO_NO_CHECK:
01456 *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
01457 break;
01458 #endif
01459 }
01460 break;
01461
01462
01463 case IPPROTO_IP:
01464 switch (optname) {
01465 case IP_TTL:
01466 *(int*)optval = sock->conn->pcb.ip->ttl;
01467 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
01468 s, *(int *)optval));
01469 break;
01470 case IP_TOS:
01471 *(int*)optval = sock->conn->pcb.ip->tos;
01472 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
01473 s, *(int *)optval));
01474 break;
01475 #if LWIP_IGMP
01476 case IP_MULTICAST_TTL:
01477 *(u8_t*)optval = sock->conn->pcb.ip->ttl;
01478 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
01479 s, *(int *)optval));
01480 break;
01481 case IP_MULTICAST_IF:
01482 ((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr;
01483 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
01484 s, *(u32_t *)optval));
01485 break;
01486 #endif
01487 }
01488 break;
01489
01490 #if LWIP_TCP
01491
01492 case IPPROTO_TCP:
01493 switch (optname) {
01494 case TCP_NODELAY:
01495 *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
01496 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
01497 s, (*(int*)optval)?"on":"off") );
01498 break;
01499 case TCP_KEEPALIVE:
01500 *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
01501 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
01502 s, *(int *)optval));
01503 break;
01504
01505 #if LWIP_TCP_KEEPALIVE
01506 case TCP_KEEPIDLE:
01507 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
01508 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
01509 s, *(int *)optval));
01510 break;
01511 case TCP_KEEPINTVL:
01512 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
01513 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
01514 s, *(int *)optval));
01515 break;
01516 case TCP_KEEPCNT:
01517 *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
01518 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
01519 s, *(int *)optval));
01520 break;
01521 #endif
01522
01523 }
01524 break;
01525 #endif
01526 #if LWIP_UDP && LWIP_UDPLITE
01527
01528 case IPPROTO_UDPLITE:
01529 switch (optname) {
01530 case UDPLITE_SEND_CSCOV:
01531 *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
01532 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
01533 s, (*(int*)optval)) );
01534 break;
01535 case UDPLITE_RECV_CSCOV:
01536 *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
01537 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
01538 s, (*(int*)optval)) );
01539 break;
01540 }
01541 break;
01542 #endif
01543 }
01544 sys_sem_signal(sock->conn->op_completed);
01545 }
01546
01547 int
01548 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
01549 {
01550 struct lwip_socket *sock = get_socket(s);
01551 int err = ERR_OK;
01552 struct lwip_setgetsockopt_data data;
01553
01554 if (!sock)
01555 return -1;
01556
01557 if (NULL == optval) {
01558 sock_set_errno(sock, EFAULT);
01559 return -1;
01560 }
01561
01562
01563 switch (level) {
01564
01565
01566 case SOL_SOCKET:
01567 switch (optname) {
01568
01569 case SO_BROADCAST:
01570
01571
01572 case SO_KEEPALIVE:
01573
01574
01575 #if LWIP_SO_RCVTIMEO
01576 case SO_RCVTIMEO:
01577 #endif
01578 #if LWIP_SO_RCVBUF
01579 case SO_RCVBUF:
01580 #endif
01581
01582
01583
01584
01585 #if SO_REUSE
01586 case SO_REUSEADDR:
01587 case SO_REUSEPORT:
01588 #endif
01589
01590 if (optlen < sizeof(int)) {
01591 err = EINVAL;
01592 }
01593 break;
01594 case SO_NO_CHECK:
01595 if (optlen < sizeof(int)) {
01596 err = EINVAL;
01597 }
01598 #if LWIP_UDP
01599 if ((sock->conn->type != NETCONN_UDP) ||
01600 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
01601
01602 err = EAFNOSUPPORT;
01603 }
01604 #endif
01605 break;
01606 default:
01607 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
01608 s, optname));
01609 err = ENOPROTOOPT;
01610 }
01611 break;
01612
01613
01614 case IPPROTO_IP:
01615 switch (optname) {
01616
01617
01618
01619 case IP_TTL:
01620 case IP_TOS:
01621 if (optlen < sizeof(int)) {
01622 err = EINVAL;
01623 }
01624 break;
01625 #if LWIP_IGMP
01626 case IP_MULTICAST_TTL:
01627 if (optlen < sizeof(u8_t)) {
01628 err = EINVAL;
01629 }
01630 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01631 err = EAFNOSUPPORT;
01632 }
01633 break;
01634 case IP_MULTICAST_IF:
01635 if (optlen < sizeof(struct in_addr)) {
01636 err = EINVAL;
01637 }
01638 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01639 err = EAFNOSUPPORT;
01640 }
01641 break;
01642 case IP_ADD_MEMBERSHIP:
01643 case IP_DROP_MEMBERSHIP:
01644 if (optlen < sizeof(struct ip_mreq)) {
01645 err = EINVAL;
01646 }
01647 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
01648 err = EAFNOSUPPORT;
01649 }
01650 break;
01651 #endif
01652 default:
01653 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
01654 s, optname));
01655 err = ENOPROTOOPT;
01656 }
01657 break;
01658
01659 #if LWIP_TCP
01660
01661 case IPPROTO_TCP:
01662 if (optlen < sizeof(int)) {
01663 err = EINVAL;
01664 break;
01665 }
01666
01667
01668 if (sock->conn->type != NETCONN_TCP)
01669 return 0;
01670
01671 switch (optname) {
01672 case TCP_NODELAY:
01673 case TCP_KEEPALIVE:
01674 #if LWIP_TCP_KEEPALIVE
01675 case TCP_KEEPIDLE:
01676 case TCP_KEEPINTVL:
01677 case TCP_KEEPCNT:
01678 #endif
01679 break;
01680
01681 default:
01682 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
01683 s, optname));
01684 err = ENOPROTOOPT;
01685 }
01686 break;
01687 #endif
01688 #if LWIP_UDP && LWIP_UDPLITE
01689
01690 case IPPROTO_UDPLITE:
01691 if (optlen < sizeof(int)) {
01692 err = EINVAL;
01693 break;
01694 }
01695
01696
01697 if (sock->conn->type != NETCONN_UDPLITE)
01698 return 0;
01699
01700 switch (optname) {
01701 case UDPLITE_SEND_CSCOV:
01702 case UDPLITE_RECV_CSCOV:
01703 break;
01704
01705 default:
01706 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
01707 s, optname));
01708 err = ENOPROTOOPT;
01709 }
01710 break;
01711 #endif
01712
01713 default:
01714 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
01715 s, level, optname));
01716 err = ENOPROTOOPT;
01717 }
01718
01719
01720 if (err != ERR_OK) {
01721 sock_set_errno(sock, err);
01722 return -1;
01723 }
01724
01725
01726
01727 data.sock = sock;
01728 data.level = level;
01729 data.optname = optname;
01730 data.optval = (void*)optval;
01731 data.optlen = &optlen;
01732 data.err = err;
01733 tcpip_callback(lwip_setsockopt_internal, &data);
01734 sys_arch_sem_wait(sock->conn->op_completed, 0);
01735
01736 err = data.err;
01737
01738 sock_set_errno(sock, err);
01739 return err ? -1 : 0;
01740 }
01741
01742 static void
01743 lwip_setsockopt_internal(void *arg)
01744 {
01745 struct lwip_socket *sock;
01746 #ifdef LWIP_DEBUG
01747 int s;
01748 #endif
01749 int level, optname;
01750 const void *optval;
01751 struct lwip_setgetsockopt_data *data;
01752
01753 LWIP_ASSERT("arg != NULL", arg != NULL);
01754
01755 data = (struct lwip_setgetsockopt_data*)arg;
01756 sock = data->sock;
01757 #ifdef LWIP_DEBUG
01758 s = data->s;
01759 #endif
01760 level = data->level;
01761 optname = data->optname;
01762 optval = data->optval;
01763
01764 switch (level) {
01765
01766
01767 case SOL_SOCKET:
01768 switch (optname) {
01769
01770
01771 case SO_BROADCAST:
01772
01773
01774 case SO_KEEPALIVE:
01775
01776 #if SO_REUSE
01777 case SO_REUSEADDR:
01778 case SO_REUSEPORT:
01779 #endif
01780
01781 if (*(int*)optval) {
01782 sock->conn->pcb.ip->so_options |= optname;
01783 } else {
01784 sock->conn->pcb.ip->so_options &= ~optname;
01785 }
01786 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
01787 s, optname, (*(int*)optval?"on":"off")));
01788 break;
01789 #if LWIP_SO_RCVTIMEO
01790 case SO_RCVTIMEO:
01791 sock->conn->recv_timeout = ( *(int*)optval );
01792 break;
01793 #endif
01794 #if LWIP_SO_RCVBUF
01795 case SO_RCVBUF:
01796 sock->conn->recv_bufsize = ( *(int*)optval );
01797 break;
01798 #endif
01799 #if LWIP_UDP
01800 case SO_NO_CHECK:
01801 if (*(int*)optval) {
01802 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
01803 } else {
01804 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
01805 }
01806 break;
01807 #endif
01808 }
01809 break;
01810
01811
01812 case IPPROTO_IP:
01813 switch (optname) {
01814 case IP_TTL:
01815 sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
01816 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
01817 s, sock->conn->pcb.ip->ttl));
01818 break;
01819 case IP_TOS:
01820 sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
01821 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
01822 s, sock->conn->pcb.ip->tos));
01823 break;
01824 #if LWIP_IGMP
01825 case IP_MULTICAST_TTL:
01826 sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
01827 break;
01828 case IP_MULTICAST_IF:
01829 sock->conn->pcb.udp->multicast_ip.addr = ((struct in_addr*) optval)->s_addr;
01830 break;
01831 case IP_ADD_MEMBERSHIP:
01832 case IP_DROP_MEMBERSHIP:
01833 {
01834
01835 struct ip_mreq *imr = (struct ip_mreq *)optval;
01836 if(optname == IP_ADD_MEMBERSHIP){
01837 data->err = igmp_joingroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
01838 } else {
01839 data->err = igmp_leavegroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
01840 }
01841 if(data->err != ERR_OK) {
01842 data->err = EADDRNOTAVAIL;
01843 }
01844 }
01845 break;
01846 #endif
01847 }
01848 break;
01849
01850 #if LWIP_TCP
01851
01852 case IPPROTO_TCP:
01853 switch (optname) {
01854 case TCP_NODELAY:
01855 if (*(int*)optval) {
01856 tcp_nagle_disable(sock->conn->pcb.tcp);
01857 } else {
01858 tcp_nagle_enable(sock->conn->pcb.tcp);
01859 }
01860 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
01861 s, (*(int *)optval)?"on":"off") );
01862 break;
01863 case TCP_KEEPALIVE:
01864 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
01865 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
01866 s, sock->conn->pcb.tcp->keep_idle));
01867 break;
01868
01869 #if LWIP_TCP_KEEPALIVE
01870 case TCP_KEEPIDLE:
01871 sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
01872 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
01873 s, sock->conn->pcb.tcp->keep_idle));
01874 break;
01875 case TCP_KEEPINTVL:
01876 sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
01877 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
01878 s, sock->conn->pcb.tcp->keep_intvl));
01879 break;
01880 case TCP_KEEPCNT:
01881 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
01882 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
01883 s, sock->conn->pcb.tcp->keep_cnt));
01884 break;
01885 #endif
01886
01887 }
01888 break;
01889 #endif
01890 #if LWIP_UDP && LWIP_UDPLITE
01891
01892 case IPPROTO_UDPLITE:
01893 switch (optname) {
01894 case UDPLITE_SEND_CSCOV:
01895 if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
01896
01897 sock->conn->pcb.udp->chksum_len_tx = 8;
01898 } else {
01899 sock->conn->pcb.udp->chksum_len_tx = *(int*)optval;
01900 }
01901 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
01902 s, (*(int*)optval)) );
01903 break;
01904 case UDPLITE_RECV_CSCOV:
01905 if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
01906
01907 sock->conn->pcb.udp->chksum_len_rx = 8;
01908 } else {
01909 sock->conn->pcb.udp->chksum_len_rx = *(int*)optval;
01910 }
01911 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
01912 s, (*(int*)optval)) );
01913 break;
01914 }
01915 break;
01916 #endif
01917 }
01918 sys_sem_signal(sock->conn->op_completed);
01919 }
01920
01921 int
01922 lwip_ioctl(int s, long cmd, void *argp)
01923 {
01924 struct lwip_socket *sock = get_socket(s);
01925 u16_t buflen = 0;
01926 s16_t recv_avail;
01927
01928 if (!sock)
01929 return -1;
01930
01931 switch (cmd) {
01932 case FIONREAD:
01933 if (!argp) {
01934 sock_set_errno(sock, EINVAL);
01935 return -1;
01936 }
01937
01938 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
01939 if (recv_avail < 0)
01940 recv_avail = 0;
01941 *((u16_t*)argp) = (u16_t)recv_avail;
01942
01943
01944 if (sock->lastdata) {
01945 buflen = netbuf_len(sock->lastdata);
01946 buflen -= sock->lastoffset;
01947
01948 *((u16_t*)argp) += buflen;
01949 }
01950
01951 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
01952 sock_set_errno(sock, 0);
01953 return 0;
01954
01955 case FIONBIO:
01956 if (argp && *(u32_t*)argp)
01957 sock->flags |= O_NONBLOCK;
01958 else
01959 sock->flags &= ~O_NONBLOCK;
01960 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
01961 sock_set_errno(sock, 0);
01962 return 0;
01963
01964 default:
01965 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
01966 sock_set_errno(sock, ENOSYS);
01967 return -1;
01968 }
01969 }
01970
01971 #endif