Warning, cross-references for /kernel/lwip/api/sockets.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #include "lwip/opt.h"
0042
0043 #if LWIP_SOCKET
0044
0045 #include "lwip/sockets.h"
0046 #include "lwip/api.h"
0047 #include "lwip/sys.h"
0048 #include "lwip/igmp.h"
0049 #include "lwip/inet.h"
0050 #include "lwip/tcp.h"
0051 #include "lwip/raw.h"
0052 #include "lwip/udp.h"
0053 #include "lwip/tcpip.h"
0054
0055 #include <string.h>
0056
0057 #define NUM_SOCKETS MEMP_NUM_NETCONN
0058
0059
0060 struct lwip_socket {
0061
0062 struct netconn *conn;
0063
0064 struct netbuf *lastdata;
0065
0066 u16_t lastoffset;
0067
0068
0069 s16_t rcvevent;
0070
0071
0072 u16_t sendevent;
0073
0074 u16_t flags;
0075
0076 int err;
0077 };
0078
0079
0080 struct lwip_select_cb {
0081
0082 struct lwip_select_cb *next;
0083
0084 fd_set *readset;
0085
0086 fd_set *writeset;
0087
0088 fd_set *exceptset;
0089
0090 int sem_signalled;
0091
0092 sys_sem_t sem;
0093 };
0094
0095
0096
0097 struct lwip_setgetsockopt_data {
0098
0099 struct lwip_socket *sock;
0100
0101 int s;
0102
0103 int level;
0104
0105 int optname;
0106
0107
0108 void *optval;
0109
0110 socklen_t *optlen;
0111
0112 err_t err;
0113 };
0114
0115
0116 static struct lwip_socket sockets[NUM_SOCKETS];
0117
0118 static struct lwip_select_cb *select_cb_list;
0119
0120
0121 static sys_sem_t socksem;
0122
0123 static sys_sem_t selectsem;
0124
0125
0126
0127 static const int err_to_errno_table[] = {
0128 0,
0129 ENOMEM,
0130 ENOBUFS,
0131 ETIMEDOUT,
0132 EHOSTUNREACH,
0133 ECONNABORTED,
0134 ECONNRESET,
0135 ESHUTDOWN,
0136 ENOTCONN,
0137 EINVAL,
0138 EIO,
0139 EADDRINUSE,
0140 -1,
0141 -1,
0142 EINPROGRESS
0143 };
0144
0145 #define ERR_TO_ERRNO_TABLE_SIZE \
0146 (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
0147
0148 #define err_to_errno(err) \
0149 ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
0150 err_to_errno_table[-(err)] : EIO)
0151
0152 #ifdef ERRNO
0153 #ifndef set_errno
0154 #define set_errno(err) errno = (err)
0155 #endif
0156 #else
0157 #define set_errno(err)
0158 #endif
0159
0160 #define sock_set_errno(sk, e) do { \
0161 sk->err = (e); \
0162 set_errno(sk->err); \
0163 } while (0)
0164
0165
0166 static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
0167 static void lwip_getsockopt_internal(void *arg);
0168 static void lwip_setsockopt_internal(void *arg);
0169
0170
0171
0172
0173
0174 void
0175 lwip_socket_init(void)
0176 {
0177 socksem = sys_sem_new(1);
0178 selectsem = sys_sem_new(1);
0179 }
0180
0181
0182
0183
0184
0185
0186
0187 static struct lwip_socket *
0188 get_socket(int s)
0189 {
0190 struct lwip_socket *sock;
0191
0192 if ((s < 0) || (s >= NUM_SOCKETS)) {
0193 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
0194 set_errno(EBADF);
0195 return NULL;
0196 }
0197
0198 sock = &sockets[s];
0199
0200 if (!sock->conn) {
0201 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
0202 set_errno(EBADF);
0203 return NULL;
0204 }
0205
0206 return sock;
0207 }
0208
0209
0210
0211
0212
0213
0214
0215 static int
0216 alloc_socket(struct netconn *newconn)
0217 {
0218 int i;
0219
0220
0221 sys_sem_wait(socksem);
0222
0223
0224 for (i = 0; i < NUM_SOCKETS; ++i) {
0225 if (!sockets[i].conn) {
0226 sockets[i].conn = newconn;
0227 sockets[i].lastdata = NULL;
0228 sockets[i].lastoffset = 0;
0229 sockets[i].rcvevent = 0;
0230 sockets[i].sendevent = 1;
0231 sockets[i].flags = 0;
0232 sockets[i].err = 0;
0233 sys_sem_signal(socksem);
0234 return i;
0235 }
0236 }
0237 sys_sem_signal(socksem);
0238 return -1;
0239 }
0240
0241
0242
0243
0244
0245
0246
0247 int
0248 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
0249 {
0250 struct lwip_socket *sock, *nsock;
0251 struct netconn *newconn;
0252 struct ip_addr naddr;
0253 u16_t port;
0254 int newsock;
0255 struct sockaddr_in sin;
0256 err_t err;
0257
0258 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
0259 sock = get_socket(s);
0260 if (!sock)
0261 return -1;
0262
0263 if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) {
0264 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
0265 sock_set_errno(sock, EWOULDBLOCK);
0266 return -1;
0267 }
0268
0269 newconn = netconn_accept(sock->conn);
0270 if (!newconn) {
0271 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err));
0272 sock_set_errno(sock, err_to_errno(sock->conn->err));
0273 return -1;
0274 }
0275
0276
0277 err = netconn_peer(newconn, &naddr, &port);
0278 if (err != ERR_OK) {
0279 netconn_delete(newconn);
0280 sock_set_errno(sock, err_to_errno(err));
0281 return -1;
0282 }
0283
0284
0285
0286
0287 if (NULL != addr) {
0288 LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
0289 memset(&sin, 0, sizeof(sin));
0290 sin.sin_len = sizeof(sin);
0291 sin.sin_family = AF_INET;
0292 sin.sin_port = htons(port);
0293 sin.sin_addr.s_addr = naddr.addr;
0294
0295 if (*addrlen > sizeof(sin))
0296 *addrlen = sizeof(sin);
0297
0298 MEMCPY(addr, &sin, *addrlen);
0299 }
0300
0301 newsock = alloc_socket(newconn);
0302 if (newsock == -1) {
0303 netconn_delete(newconn);
0304 sock_set_errno(sock, ENFILE);
0305 return -1;
0306 }
0307 LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
0308 newconn->callback = event_callback;
0309 nsock = &sockets[newsock];
0310 LWIP_ASSERT("invalid socket pointer", nsock != NULL);
0311
0312 sys_sem_wait(socksem);
0313
0314
0315
0316
0317
0318 nsock->rcvevent += -1 - newconn->socket;
0319 newconn->socket = newsock;
0320 sys_sem_signal(socksem);
0321
0322 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
0323 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
0324 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
0325
0326 sock_set_errno(sock, 0);
0327 return newsock;
0328 }
0329
0330 int
0331 lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
0332 {
0333 struct lwip_socket *sock;
0334 struct ip_addr local_addr;
0335 u16_t local_port;
0336 err_t err;
0337
0338 sock = get_socket(s);
0339 if (!sock)
0340 return -1;
0341
0342 LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
0343 ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
0344 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
0345
0346 local_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
0347 local_port = ((const struct sockaddr_in *)name)->sin_port;
0348
0349 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
0350 ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
0351 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
0352
0353 err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
0354
0355 if (err != ERR_OK) {
0356 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
0357 sock_set_errno(sock, err_to_errno(err));
0358 return -1;
0359 }
0360
0361 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
0362 sock_set_errno(sock, 0);
0363 return 0;
0364 }
0365
0366 int
0367 lwip_close(int s)
0368 {
0369 struct lwip_socket *sock;
0370
0371 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
0372
0373 sock = get_socket(s);
0374 if (!sock) {
0375 return -1;
0376 }
0377
0378 netconn_delete(sock->conn);
0379
0380 sys_sem_wait(socksem);
0381 if (sock->lastdata) {
0382 netbuf_delete(sock->lastdata);
0383 }
0384 sock->lastdata = NULL;
0385 sock->lastoffset = 0;
0386 sock->conn = NULL;
0387 sock_set_errno(sock, 0);
0388 sys_sem_signal(socksem);
0389 return 0;
0390 }
0391
0392 int
0393 lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
0394 {
0395 struct lwip_socket *sock;
0396 err_t err;
0397
0398 sock = get_socket(s);
0399 if (!sock)
0400 return -1;
0401
0402 LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
0403 ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
0404 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
0405
0406 if (((const struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
0407 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
0408 err = netconn_disconnect(sock->conn);
0409 } else {
0410 struct ip_addr remote_addr;
0411 u16_t remote_port;
0412
0413 remote_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
0414 remote_port = ((const struct sockaddr_in *)name)->sin_port;
0415
0416 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
0417 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
0418 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
0419
0420 err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
0421 }
0422
0423 if (err != ERR_OK) {
0424 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
0425 sock_set_errno(sock, err_to_errno(err));
0426 return -1;
0427 }
0428
0429 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
0430 sock_set_errno(sock, 0);
0431 return 0;
0432 }
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442 int
0443 lwip_listen(int s, int backlog)
0444 {
0445 struct lwip_socket *sock;
0446 err_t err;
0447
0448 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
0449
0450 sock = get_socket(s);
0451 if (!sock)
0452 return -1;
0453
0454
0455 if (backlog < 0) {
0456 backlog = 0;
0457 }
0458 if (backlog > 0xff) {
0459 backlog = 0xff;
0460 }
0461
0462 err = netconn_listen_with_backlog(sock->conn, backlog);
0463
0464 if (err != ERR_OK) {
0465 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
0466 sock_set_errno(sock, err_to_errno(err));
0467 return -1;
0468 }
0469
0470 sock_set_errno(sock, 0);
0471 return 0;
0472 }
0473
0474 int
0475 lwip_recvfrom(int s, void *mem, size_t len, int flags,
0476 struct sockaddr *from, socklen_t *fromlen)
0477 {
0478 struct lwip_socket *sock;
0479 struct netbuf *buf;
0480 u16_t buflen, copylen, off = 0;
0481 struct ip_addr *addr;
0482 u16_t port;
0483 u8_t done = 0;
0484
0485 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
0486 sock = get_socket(s);
0487 if (!sock)
0488 return -1;
0489
0490 do {
0491 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", (void*)sock->lastdata));
0492
0493 if (sock->lastdata) {
0494 buf = sock->lastdata;
0495 } else {
0496
0497 if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
0498 (sock->rcvevent <= 0)) {
0499 if (off > 0) {
0500
0501 sock_set_errno(sock, 0);
0502 return off;
0503 }
0504 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
0505 sock_set_errno(sock, EWOULDBLOCK);
0506 return -1;
0507 }
0508
0509
0510
0511 sock->lastdata = buf = netconn_recv(sock->conn);
0512 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", (void*)buf));
0513
0514 if (!buf) {
0515 if (off > 0) {
0516
0517 sock_set_errno(sock, 0);
0518 return off;
0519 }
0520
0521 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
0522 sock_set_errno(sock, (((sock->conn->pcb.ip != NULL) && (sock->conn->err == ERR_OK))
0523 ? ETIMEDOUT : err_to_errno(sock->conn->err)));
0524 return 0;
0525 }
0526 }
0527
0528 buflen = netbuf_len(buf);
0529 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%"U16_F" sock->lastoffset=%"U16_F"\n",
0530 buflen, len, off, sock->lastoffset));
0531
0532 buflen -= sock->lastoffset;
0533
0534 if (len > buflen) {
0535 copylen = buflen;
0536 } else {
0537 copylen = (u16_t)len;
0538 }
0539
0540
0541
0542 netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset);
0543
0544 off += copylen;
0545
0546 if (netconn_type(sock->conn) == NETCONN_TCP) {
0547 LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
0548 len -= copylen;
0549 if ( (len <= 0) ||
0550 (buf->p->flags & PBUF_FLAG_PUSH) ||
0551 (sock->rcvevent <= 0) ||
0552 ((flags & MSG_PEEK)!=0)) {
0553 done = 1;
0554 }
0555 } else {
0556 done = 1;
0557 }
0558
0559
0560 if (done) {
0561 if (from && fromlen) {
0562 struct sockaddr_in sin;
0563
0564 if (netconn_type(sock->conn) == NETCONN_TCP) {
0565 addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
0566 netconn_getaddr(sock->conn, addr, &port, 0);
0567 } else {
0568 addr = netbuf_fromaddr(buf);
0569 port = netbuf_fromport(buf);
0570 }
0571
0572 memset(&sin, 0, sizeof(sin));
0573 sin.sin_len = sizeof(sin);
0574 sin.sin_family = AF_INET;
0575 sin.sin_port = htons(port);
0576 sin.sin_addr.s_addr = addr->addr;
0577
0578 if (*fromlen > sizeof(sin)) {
0579 *fromlen = sizeof(sin);
0580 }
0581
0582 MEMCPY(from, &sin, *fromlen);
0583
0584 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
0585 ip_addr_debug_print(SOCKETS_DEBUG, addr);
0586 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
0587 } else {
0588 #if SOCKETS_DEBUG
0589 struct sockaddr_in sin;
0590
0591 if (netconn_type(sock->conn) == NETCONN_TCP) {
0592 addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
0593 netconn_getaddr(sock->conn, addr, &port, 0);
0594 } else {
0595 addr = netbuf_fromaddr(buf);
0596 port = netbuf_fromport(buf);
0597 }
0598
0599 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
0600 ip_addr_debug_print(SOCKETS_DEBUG, addr);
0601 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
0602 #endif
0603 }
0604 }
0605
0606
0607 if ((flags & MSG_PEEK)==0) {
0608
0609
0610
0611 if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
0612 sock->lastdata = buf;
0613 sock->lastoffset += copylen;
0614 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
0615 } else {
0616 sock->lastdata = NULL;
0617 sock->lastoffset = 0;
0618 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
0619 netbuf_delete(buf);
0620 }
0621 }
0622 } while (!done);
0623
0624 sock_set_errno(sock, 0);
0625 return off;
0626 }
0627
0628 int
0629 lwip_read(int s, void *mem, size_t len)
0630 {
0631 return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
0632 }
0633
0634 int
0635 lwip_recv(int s, void *mem, size_t len, int flags)
0636 {
0637 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
0638 }
0639
0640 int
0641 lwip_send(int s, const void *data, size_t size, int flags)
0642 {
0643 struct lwip_socket *sock;
0644 err_t err;
0645
0646 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
0647 s, data, size, flags));
0648
0649 sock = get_socket(s);
0650 if (!sock)
0651 return -1;
0652
0653 if (sock->conn->type != NETCONN_TCP) {
0654 #if (LWIP_UDP || LWIP_RAW)
0655 return lwip_sendto(s, data, size, flags, NULL, 0);
0656 #else
0657 sock_set_errno(sock, err_to_errno(ERR_ARG));
0658 return -1;
0659 #endif
0660 }
0661
0662 err = netconn_write(sock->conn, data, size, NETCONN_COPY | ((flags & MSG_MORE)?NETCONN_MORE:0));
0663
0664 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
0665 sock_set_errno(sock, err_to_errno(err));
0666 return (err == ERR_OK ? (int)size : -1);
0667 }
0668
0669 int
0670 lwip_sendto(int s, const void *data, size_t size, int flags,
0671 const struct sockaddr *to, socklen_t tolen)
0672 {
0673 struct lwip_socket *sock;
0674 struct ip_addr remote_addr;
0675 err_t err;
0676 u16_t short_size;
0677 #if !LWIP_TCPIP_CORE_LOCKING
0678 struct netbuf buf;
0679 u16_t remote_port;
0680 #endif
0681
0682 sock = get_socket(s);
0683 if (!sock)
0684 return -1;
0685
0686 if (sock->conn->type == NETCONN_TCP) {
0687 #if LWIP_TCP
0688 return lwip_send(s, data, size, flags);
0689 #else
0690 sock_set_errno(sock, err_to_errno(ERR_ARG));
0691 return -1;
0692 #endif
0693 }
0694
0695 LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
0696 short_size = (u16_t)size;
0697 LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
0698 ((tolen == sizeof(struct sockaddr_in)) &&
0699 ((((const struct sockaddr_in *)to)->sin_family) == AF_INET))),
0700 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
0701
0702 #if LWIP_TCPIP_CORE_LOCKING
0703
0704 { struct pbuf* p;
0705
0706 p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
0707 if (p == NULL) {
0708 err = ERR_MEM;
0709 } else {
0710 p->payload = (void*)data;
0711 p->len = p->tot_len = short_size;
0712
0713 remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
0714
0715 LOCK_TCPIP_CORE();
0716 if (sock->conn->type==NETCONN_RAW) {
0717 err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
0718 } else {
0719 err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port));
0720 }
0721 UNLOCK_TCPIP_CORE();
0722
0723 pbuf_free(p);
0724 }
0725 }
0726 #else
0727
0728 buf.p = buf.ptr = NULL;
0729 if (to) {
0730 remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
0731 remote_port = ntohs(((const struct sockaddr_in *)to)->sin_port);
0732 buf.addr = &remote_addr;
0733 buf.port = remote_port;
0734 } else {
0735 remote_addr.addr = 0;
0736 remote_port = 0;
0737 buf.addr = NULL;
0738 buf.port = 0;
0739 }
0740
0741 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
0742 s, data, short_size, flags));
0743 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
0744 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
0745
0746
0747 #if LWIP_NETIF_TX_SINGLE_PBUF
0748
0749 if (netbuf_alloc(&buf, short_size) == NULL) {
0750 err = ERR_MEM;
0751 } else {
0752 err = netbuf_take(&buf, data, short_size);
0753 }
0754 #else
0755 err = netbuf_ref(&buf, data, short_size);
0756 #endif
0757 if (err == ERR_OK) {
0758
0759 err = netconn_send(sock->conn, &buf);
0760 }
0761
0762
0763 netbuf_free(&buf);
0764 #endif
0765 sock_set_errno(sock, err_to_errno(err));
0766 return (err == ERR_OK ? short_size : -1);
0767 }
0768
0769 int
0770 lwip_socket(int domain, int type, int protocol)
0771 {
0772 struct netconn *conn;
0773 int i;
0774
0775 LWIP_UNUSED_ARG(domain);
0776
0777
0778 switch (type) {
0779 case SOCK_RAW:
0780 conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
0781 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
0782 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
0783 break;
0784 case SOCK_DGRAM:
0785 conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
0786 NETCONN_UDPLITE : NETCONN_UDP, event_callback);
0787 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
0788 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
0789 break;
0790 case SOCK_STREAM:
0791 conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
0792 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
0793 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
0794 break;
0795 default:
0796 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
0797 domain, type, protocol));
0798 set_errno(EINVAL);
0799 return -1;
0800 }
0801
0802 if (!conn) {
0803 LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
0804 set_errno(ENOBUFS);
0805 return -1;
0806 }
0807
0808 i = alloc_socket(conn);
0809
0810 if (i == -1) {
0811 netconn_delete(conn);
0812 set_errno(ENFILE);
0813 return -1;
0814 }
0815 conn->socket = i;
0816 LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
0817 set_errno(0);
0818 return i;
0819 }
0820
0821 int
0822 lwip_write(int s, const void *data, size_t size)
0823 {
0824 return lwip_send(s, data, size, 0);
0825 }
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842 static int
0843 lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
0844 {
0845 int i, nready = 0;
0846 fd_set lreadset, lwriteset, lexceptset;
0847 struct lwip_socket *p_sock;
0848
0849 FD_ZERO(&lreadset);
0850 FD_ZERO(&lwriteset);
0851 FD_ZERO(&lexceptset);
0852
0853
0854
0855 for(i = 0; i < maxfdp1; i++) {
0856 if (FD_ISSET(i, readset)) {
0857
0858 p_sock = get_socket(i);
0859 if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) {
0860 FD_SET(i, &lreadset);
0861 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
0862 nready++;
0863 }
0864 }
0865 if (FD_ISSET(i, writeset)) {
0866
0867 p_sock = get_socket(i);
0868 if (p_sock && p_sock->sendevent) {
0869 FD_SET(i, &lwriteset);
0870 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
0871 nready++;
0872 }
0873 }
0874 }
0875 *readset = lreadset;
0876 *writeset = lwriteset;
0877 FD_ZERO(exceptset);
0878
0879 return nready;
0880 }
0881
0882
0883
0884
0885
0886 int
0887 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
0888 struct timeval *timeout)
0889 {
0890 int i;
0891 int nready;
0892 fd_set lreadset, lwriteset, lexceptset;
0893 u32_t msectimeout;
0894 struct lwip_select_cb select_cb;
0895 struct lwip_select_cb *p_selcb;
0896
0897 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
0898 maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
0899 timeout ? (long)timeout->tv_sec : (long)-1,
0900 timeout ? (long)timeout->tv_usec : (long)-1));
0901
0902 select_cb.next = 0;
0903 select_cb.readset = readset;
0904 select_cb.writeset = writeset;
0905 select_cb.exceptset = exceptset;
0906 select_cb.sem_signalled = 0;
0907
0908
0909 sys_sem_wait(selectsem);
0910
0911 if (readset)
0912 lreadset = *readset;
0913 else
0914 FD_ZERO(&lreadset);
0915 if (writeset)
0916 lwriteset = *writeset;
0917 else
0918 FD_ZERO(&lwriteset);
0919 if (exceptset)
0920 lexceptset = *exceptset;
0921 else
0922 FD_ZERO(&lexceptset);
0923
0924
0925
0926 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
0927
0928
0929 if (!nready) {
0930 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
0931 sys_sem_signal(selectsem);
0932 if (readset)
0933 FD_ZERO(readset);
0934 if (writeset)
0935 FD_ZERO(writeset);
0936 if (exceptset)
0937 FD_ZERO(exceptset);
0938
0939 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
0940 set_errno(0);
0941
0942 return 0;
0943 }
0944
0945
0946
0947
0948
0949
0950 select_cb.sem = sys_sem_new(0);
0951
0952
0953 select_cb.next = select_cb_list;
0954 select_cb_list = &select_cb;
0955
0956
0957 sys_sem_signal(selectsem);
0958
0959
0960 if (timeout == 0)
0961
0962 msectimeout = 0;
0963 else {
0964 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
0965 if(msectimeout == 0)
0966 msectimeout = 1;
0967 }
0968
0969 i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
0970
0971
0972 sys_sem_wait(selectsem);
0973 if (select_cb_list == &select_cb)
0974 select_cb_list = select_cb.next;
0975 else
0976 for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) {
0977 if (p_selcb->next == &select_cb) {
0978 p_selcb->next = select_cb.next;
0979 break;
0980 }
0981 }
0982
0983 sys_sem_signal(selectsem);
0984
0985 sys_sem_free(select_cb.sem);
0986 if (i == 0) {
0987
0988 if (readset)
0989 FD_ZERO(readset);
0990 if (writeset)
0991 FD_ZERO(writeset);
0992 if (exceptset)
0993 FD_ZERO(exceptset);
0994
0995 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
0996 set_errno(0);
0997
0998 return 0;
0999 }
1000
1001 if (readset)
1002 lreadset = *readset;
1003 else
1004 FD_ZERO(&lreadset);
1005 if (writeset)
1006 lwriteset = *writeset;
1007 else
1008 FD_ZERO(&lwriteset);
1009 if (exceptset)
1010 lexceptset = *exceptset;
1011 else
1012 FD_ZERO(&lexceptset);
1013
1014
1015 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
1016 } else
1017 sys_sem_signal(selectsem);
1018
1019 if (readset)
1020 *readset = lreadset;
1021 if (writeset)
1022 *writeset = lwriteset;
1023 if (exceptset)
1024 *exceptset = lexceptset;
1025
1026 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
1027 set_errno(0);
1028
1029 return nready;
1030 }
1031
1032
1033
1034
1035
1036 static void
1037 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
1038 {
1039 int s;
1040 struct lwip_socket *sock;
1041 struct lwip_select_cb *scb;
1042
1043 LWIP_UNUSED_ARG(len);
1044
1045
1046 if (conn) {
1047 s = conn->socket;
1048 if (s < 0) {
1049
1050
1051
1052
1053
1054 sys_sem_wait(socksem);
1055 if (conn->socket < 0) {
1056 if (evt == NETCONN_EVT_RCVPLUS) {
1057 conn->socket--;
1058 }
1059 sys_sem_signal(socksem);
1060 return;
1061 }
1062 s = conn->socket;
1063 sys_sem_signal(socksem);
1064 }
1065
1066 sock = get_socket(s);
1067 if (!sock) {
1068 return;
1069 }
1070 } else {
1071 return;
1072 }
1073
1074 sys_sem_wait(selectsem);
1075
1076 switch (evt) {
1077 case NETCONN_EVT_RCVPLUS:
1078 sock->rcvevent++;
1079 break;
1080 case NETCONN_EVT_RCVMINUS:
1081 sock->rcvevent--;
1082 break;
1083 case NETCONN_EVT_SENDPLUS:
1084 sock->sendevent = 1;
1085 break;
1086 case NETCONN_EVT_SENDMINUS:
1087 sock->sendevent = 0;
1088 break;
1089 default:
1090 LWIP_ASSERT("unknown event", 0);
1091 break;
1092 }
1093 sys_sem_signal(selectsem);
1094
1095
1096
1097
1098
1099
1100
1101
1102 while (1) {
1103 sys_sem_wait(selectsem);
1104 for (scb = select_cb_list; scb; scb = scb->next) {
1105 if (scb->sem_signalled == 0) {
1106
1107 if (scb->readset && FD_ISSET(s, scb->readset))
1108 if (sock->rcvevent > 0)
1109 break;
1110 if (scb->writeset && FD_ISSET(s, scb->writeset))
1111 if (sock->sendevent)
1112 break;
1113 }
1114 }
1115 if (scb) {
1116 scb->sem_signalled = 1;
1117 sys_sem_signal(scb->sem);
1118 sys_sem_signal(selectsem);
1119 } else {
1120 sys_sem_signal(selectsem);
1121 break;
1122 }
1123 }
1124 }
1125
1126
1127
1128
1129
1130 int
1131 lwip_shutdown(int s, int how)
1132 {
1133 LWIP_UNUSED_ARG(how);
1134 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
1135 return lwip_close(s);
1136 }
1137
1138 static int
1139 lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
1140 {
1141 struct lwip_socket *sock;
1142 struct sockaddr_in sin;
1143 struct ip_addr naddr;
1144
1145 sock = get_socket(s);
1146 if (!sock)
1147 return -1;
1148
1149 memset(&sin, 0, sizeof(sin));
1150 sin.sin_len = sizeof(sin);
1151 sin.sin_family = AF_INET;
1152
1153
1154 netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
1155
1156 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
1157 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
1158 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
1159
1160 sin.sin_port = htons(sin.sin_port);
1161 sin.sin_addr.s_addr = naddr.addr;
1162
1163 if (*namelen > sizeof(sin))
1164 *namelen = sizeof(sin);
1165
1166 MEMCPY(name, &sin, *namelen);
1167 sock_set_errno(sock, 0);
1168 return 0;
1169 }
1170
1171 int
1172 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
1173 {
1174 return lwip_getaddrname(s, name, namelen, 0);
1175 }
1176
1177 int
1178 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
1179 {
1180 return lwip_getaddrname(s, name, namelen, 1);
1181 }
1182
1183 int
1184 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1185 {
1186 err_t err = ERR_OK;
1187 struct lwip_socket *sock = get_socket(s);
1188 struct lwip_setgetsockopt_data data;
1189
1190 if (!sock)
1191 return -1;
1192
1193 if ((NULL == optval) || (NULL == optlen)) {
1194 sock_set_errno(sock, EFAULT);
1195 return -1;
1196 }
1197
1198
1199 switch (level) {
1200
1201
1202 case SOL_SOCKET:
1203 switch (optname) {
1204
1205 case SO_ACCEPTCONN:
1206 case SO_BROADCAST:
1207
1208
1209 case SO_ERROR:
1210 case SO_KEEPALIVE:
1211
1212
1213 #if LWIP_SO_RCVTIMEO
1214 case SO_RCVTIMEO:
1215 #endif
1216 #if LWIP_SO_RCVBUF
1217 case SO_RCVBUF:
1218 #endif
1219
1220
1221
1222
1223 #if SO_REUSE
1224 case SO_REUSEADDR:
1225 case SO_REUSEPORT:
1226 #endif
1227 case SO_TYPE:
1228
1229 if (*optlen < sizeof(int)) {
1230 err = EINVAL;
1231 }
1232 break;
1233
1234 case SO_NO_CHECK:
1235 if (*optlen < sizeof(int)) {
1236 err = EINVAL;
1237 }
1238 #if LWIP_UDP
1239 if ((sock->conn->type != NETCONN_UDP) ||
1240 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1241
1242 err = EAFNOSUPPORT;
1243 }
1244 #endif
1245 break;
1246
1247 default:
1248 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1249 s, optname));
1250 err = ENOPROTOOPT;
1251 }
1252 break;
1253
1254
1255 case IPPROTO_IP:
1256 switch (optname) {
1257
1258
1259
1260 case IP_TTL:
1261 case IP_TOS:
1262 if (*optlen < sizeof(int)) {
1263 err = EINVAL;
1264 }
1265 break;
1266 #if LWIP_IGMP
1267 case IP_MULTICAST_TTL:
1268 if (*optlen < sizeof(u8_t)) {
1269 err = EINVAL;
1270 }
1271 break;
1272 case IP_MULTICAST_IF:
1273 if (*optlen < sizeof(struct in_addr)) {
1274 err = EINVAL;
1275 }
1276 break;
1277 #endif
1278
1279 default:
1280 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1281 s, optname));
1282 err = ENOPROTOOPT;
1283 }
1284 break;
1285
1286 #if LWIP_TCP
1287
1288 case IPPROTO_TCP:
1289 if (*optlen < sizeof(int)) {
1290 err = EINVAL;
1291 break;
1292 }
1293
1294
1295 if (sock->conn->type != NETCONN_TCP)
1296 return 0;
1297
1298 switch (optname) {
1299 case TCP_NODELAY:
1300 case TCP_KEEPALIVE:
1301 #if LWIP_TCP_KEEPALIVE
1302 case TCP_KEEPIDLE:
1303 case TCP_KEEPINTVL:
1304 case TCP_KEEPCNT:
1305 #endif
1306 break;
1307
1308 default:
1309 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1310 s, optname));
1311 err = ENOPROTOOPT;
1312 }
1313 break;
1314 #endif
1315 #if LWIP_UDP && LWIP_UDPLITE
1316
1317 case IPPROTO_UDPLITE:
1318 if (*optlen < sizeof(int)) {
1319 err = EINVAL;
1320 break;
1321 }
1322
1323
1324 if (sock->conn->type != NETCONN_UDPLITE)
1325 return 0;
1326
1327 switch (optname) {
1328 case UDPLITE_SEND_CSCOV:
1329 case UDPLITE_RECV_CSCOV:
1330 break;
1331
1332 default:
1333 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
1334 s, optname));
1335 err = ENOPROTOOPT;
1336 }
1337 break;
1338 #endif
1339
1340 default:
1341 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
1342 s, level, optname));
1343 err = ENOPROTOOPT;
1344 }
1345
1346
1347 if (err != ERR_OK) {
1348 sock_set_errno(sock, err);
1349 return -1;
1350 }
1351
1352
1353 data.sock = sock;
1354 data.level = level;
1355 data.optname = optname;
1356 data.optval = optval;
1357 data.optlen = optlen;
1358 data.err = err;
1359 tcpip_callback(lwip_getsockopt_internal, &data);
1360 sys_arch_sem_wait(sock->conn->op_completed, 0);
1361
1362 err = data.err;
1363
1364 sock_set_errno(sock, err);
1365 return err ? -1 : 0;
1366 }
1367
1368 static void
1369 lwip_getsockopt_internal(void *arg)
1370 {
1371 struct lwip_socket *sock;
1372 #ifdef LWIP_DEBUG
1373 int s;
1374 #endif
1375 int level, optname;
1376 void *optval;
1377 struct lwip_setgetsockopt_data *data;
1378
1379 LWIP_ASSERT("arg != NULL", arg != NULL);
1380
1381 data = (struct lwip_setgetsockopt_data*)arg;
1382 sock = data->sock;
1383 #ifdef LWIP_DEBUG
1384 s = data->s;
1385 #endif
1386 level = data->level;
1387 optname = data->optname;
1388 optval = data->optval;
1389
1390 switch (level) {
1391
1392
1393 case SOL_SOCKET:
1394 switch (optname) {
1395
1396
1397 case SO_ACCEPTCONN:
1398 case SO_BROADCAST:
1399
1400
1401 case SO_KEEPALIVE:
1402
1403 #if SO_REUSE
1404 case SO_REUSEADDR:
1405 case SO_REUSEPORT:
1406 #endif
1407
1408 *(int*)optval = sock->conn->pcb.ip->so_options & optname;
1409 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
1410 s, optname, (*(int*)optval?"on":"off")));
1411 break;
1412
1413 case SO_TYPE:
1414 switch (NETCONNTYPE_GROUP(sock->conn->type)) {
1415 case NETCONN_RAW:
1416 *(int*)optval = SOCK_RAW;
1417 break;
1418 case NETCONN_TCP:
1419 *(int*)optval = SOCK_STREAM;
1420 break;
1421 case NETCONN_UDP:
1422 *(int*)optval = SOCK_DGRAM;
1423 break;
1424 default:
1425 *(int*)optval = sock->conn->type;
1426 LWIP_DEBUGF(SOCKETS_DEBUG,
1427 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
1428 s, *(int *)optval));
1429 }
1430 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
1431 s, *(int *)optval));
1432 break;
1433
1434 case SO_ERROR:
1435 if (sock->err == 0) {
1436 sock_set_errno(sock, err_to_errno(sock->conn->err));
1437 }
1438 *(int *)optval = sock->err;
1439 sock->err = 0;
1440 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
1441 s, *(int *)optval));
1442 break;
1443
1444 #if LWIP_SO_RCVTIMEO
1445 case SO_RCVTIMEO:
1446 *(int *)optval = sock->conn->recv_timeout;
1447 break;
1448 #endif
1449 #if LWIP_SO_RCVBUF
1450 case SO_RCVBUF:
1451 *(int *)optval = sock->conn->recv_bufsize;
1452 break;
1453 #endif
1454 #if LWIP_UDP
1455 case SO_NO_CHECK:
1456 *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
1457 break;
1458 #endif
1459 }
1460 break;
1461
1462
1463 case IPPROTO_IP:
1464 switch (optname) {
1465 case IP_TTL:
1466 *(int*)optval = sock->conn->pcb.ip->ttl;
1467 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
1468 s, *(int *)optval));
1469 break;
1470 case IP_TOS:
1471 *(int*)optval = sock->conn->pcb.ip->tos;
1472 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
1473 s, *(int *)optval));
1474 break;
1475 #if LWIP_IGMP
1476 case IP_MULTICAST_TTL:
1477 *(u8_t*)optval = sock->conn->pcb.ip->ttl;
1478 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
1479 s, *(int *)optval));
1480 break;
1481 case IP_MULTICAST_IF:
1482 ((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr;
1483 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
1484 s, *(u32_t *)optval));
1485 break;
1486 #endif
1487 }
1488 break;
1489
1490 #if LWIP_TCP
1491
1492 case IPPROTO_TCP:
1493 switch (optname) {
1494 case TCP_NODELAY:
1495 *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
1496 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
1497 s, (*(int*)optval)?"on":"off") );
1498 break;
1499 case TCP_KEEPALIVE:
1500 *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
1501 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
1502 s, *(int *)optval));
1503 break;
1504
1505 #if LWIP_TCP_KEEPALIVE
1506 case TCP_KEEPIDLE:
1507 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
1508 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
1509 s, *(int *)optval));
1510 break;
1511 case TCP_KEEPINTVL:
1512 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
1513 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
1514 s, *(int *)optval));
1515 break;
1516 case TCP_KEEPCNT:
1517 *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
1518 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
1519 s, *(int *)optval));
1520 break;
1521 #endif
1522
1523 }
1524 break;
1525 #endif
1526 #if LWIP_UDP && LWIP_UDPLITE
1527
1528 case IPPROTO_UDPLITE:
1529 switch (optname) {
1530 case UDPLITE_SEND_CSCOV:
1531 *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
1532 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
1533 s, (*(int*)optval)) );
1534 break;
1535 case UDPLITE_RECV_CSCOV:
1536 *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
1537 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
1538 s, (*(int*)optval)) );
1539 break;
1540 }
1541 break;
1542 #endif
1543 }
1544 sys_sem_signal(sock->conn->op_completed);
1545 }
1546
1547 int
1548 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1549 {
1550 struct lwip_socket *sock = get_socket(s);
1551 int err = ERR_OK;
1552 struct lwip_setgetsockopt_data data;
1553
1554 if (!sock)
1555 return -1;
1556
1557 if (NULL == optval) {
1558 sock_set_errno(sock, EFAULT);
1559 return -1;
1560 }
1561
1562
1563 switch (level) {
1564
1565
1566 case SOL_SOCKET:
1567 switch (optname) {
1568
1569 case SO_BROADCAST:
1570
1571
1572 case SO_KEEPALIVE:
1573
1574
1575 #if LWIP_SO_RCVTIMEO
1576 case SO_RCVTIMEO:
1577 #endif
1578 #if LWIP_SO_RCVBUF
1579 case SO_RCVBUF:
1580 #endif
1581
1582
1583
1584
1585 #if SO_REUSE
1586 case SO_REUSEADDR:
1587 case SO_REUSEPORT:
1588 #endif
1589
1590 if (optlen < sizeof(int)) {
1591 err = EINVAL;
1592 }
1593 break;
1594 case SO_NO_CHECK:
1595 if (optlen < sizeof(int)) {
1596 err = EINVAL;
1597 }
1598 #if LWIP_UDP
1599 if ((sock->conn->type != NETCONN_UDP) ||
1600 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1601
1602 err = EAFNOSUPPORT;
1603 }
1604 #endif
1605 break;
1606 default:
1607 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1608 s, optname));
1609 err = ENOPROTOOPT;
1610 }
1611 break;
1612
1613
1614 case IPPROTO_IP:
1615 switch (optname) {
1616
1617
1618
1619 case IP_TTL:
1620 case IP_TOS:
1621 if (optlen < sizeof(int)) {
1622 err = EINVAL;
1623 }
1624 break;
1625 #if LWIP_IGMP
1626 case IP_MULTICAST_TTL:
1627 if (optlen < sizeof(u8_t)) {
1628 err = EINVAL;
1629 }
1630 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1631 err = EAFNOSUPPORT;
1632 }
1633 break;
1634 case IP_MULTICAST_IF:
1635 if (optlen < sizeof(struct in_addr)) {
1636 err = EINVAL;
1637 }
1638 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1639 err = EAFNOSUPPORT;
1640 }
1641 break;
1642 case IP_ADD_MEMBERSHIP:
1643 case IP_DROP_MEMBERSHIP:
1644 if (optlen < sizeof(struct ip_mreq)) {
1645 err = EINVAL;
1646 }
1647 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1648 err = EAFNOSUPPORT;
1649 }
1650 break;
1651 #endif
1652 default:
1653 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1654 s, optname));
1655 err = ENOPROTOOPT;
1656 }
1657 break;
1658
1659 #if LWIP_TCP
1660
1661 case IPPROTO_TCP:
1662 if (optlen < sizeof(int)) {
1663 err = EINVAL;
1664 break;
1665 }
1666
1667
1668 if (sock->conn->type != NETCONN_TCP)
1669 return 0;
1670
1671 switch (optname) {
1672 case TCP_NODELAY:
1673 case TCP_KEEPALIVE:
1674 #if LWIP_TCP_KEEPALIVE
1675 case TCP_KEEPIDLE:
1676 case TCP_KEEPINTVL:
1677 case TCP_KEEPCNT:
1678 #endif
1679 break;
1680
1681 default:
1682 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1683 s, optname));
1684 err = ENOPROTOOPT;
1685 }
1686 break;
1687 #endif
1688 #if LWIP_UDP && LWIP_UDPLITE
1689
1690 case IPPROTO_UDPLITE:
1691 if (optlen < sizeof(int)) {
1692 err = EINVAL;
1693 break;
1694 }
1695
1696
1697 if (sock->conn->type != NETCONN_UDPLITE)
1698 return 0;
1699
1700 switch (optname) {
1701 case UDPLITE_SEND_CSCOV:
1702 case UDPLITE_RECV_CSCOV:
1703 break;
1704
1705 default:
1706 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
1707 s, optname));
1708 err = ENOPROTOOPT;
1709 }
1710 break;
1711 #endif
1712
1713 default:
1714 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
1715 s, level, optname));
1716 err = ENOPROTOOPT;
1717 }
1718
1719
1720 if (err != ERR_OK) {
1721 sock_set_errno(sock, err);
1722 return -1;
1723 }
1724
1725
1726
1727 data.sock = sock;
1728 data.level = level;
1729 data.optname = optname;
1730 data.optval = (void*)optval;
1731 data.optlen = &optlen;
1732 data.err = err;
1733 tcpip_callback(lwip_setsockopt_internal, &data);
1734 sys_arch_sem_wait(sock->conn->op_completed, 0);
1735
1736 err = data.err;
1737
1738 sock_set_errno(sock, err);
1739 return err ? -1 : 0;
1740 }
1741
1742 static void
1743 lwip_setsockopt_internal(void *arg)
1744 {
1745 struct lwip_socket *sock;
1746 #ifdef LWIP_DEBUG
1747 int s;
1748 #endif
1749 int level, optname;
1750 const void *optval;
1751 struct lwip_setgetsockopt_data *data;
1752
1753 LWIP_ASSERT("arg != NULL", arg != NULL);
1754
1755 data = (struct lwip_setgetsockopt_data*)arg;
1756 sock = data->sock;
1757 #ifdef LWIP_DEBUG
1758 s = data->s;
1759 #endif
1760 level = data->level;
1761 optname = data->optname;
1762 optval = data->optval;
1763
1764 switch (level) {
1765
1766
1767 case SOL_SOCKET:
1768 switch (optname) {
1769
1770
1771 case SO_BROADCAST:
1772
1773
1774 case SO_KEEPALIVE:
1775
1776 #if SO_REUSE
1777 case SO_REUSEADDR:
1778 case SO_REUSEPORT:
1779 #endif
1780
1781 if (*(int*)optval) {
1782 sock->conn->pcb.ip->so_options |= optname;
1783 } else {
1784 sock->conn->pcb.ip->so_options &= ~optname;
1785 }
1786 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
1787 s, optname, (*(int*)optval?"on":"off")));
1788 break;
1789 #if LWIP_SO_RCVTIMEO
1790 case SO_RCVTIMEO:
1791 sock->conn->recv_timeout = ( *(int*)optval );
1792 break;
1793 #endif
1794 #if LWIP_SO_RCVBUF
1795 case SO_RCVBUF:
1796 sock->conn->recv_bufsize = ( *(int*)optval );
1797 break;
1798 #endif
1799 #if LWIP_UDP
1800 case SO_NO_CHECK:
1801 if (*(int*)optval) {
1802 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
1803 } else {
1804 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
1805 }
1806 break;
1807 #endif
1808 }
1809 break;
1810
1811
1812 case IPPROTO_IP:
1813 switch (optname) {
1814 case IP_TTL:
1815 sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
1816 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
1817 s, sock->conn->pcb.ip->ttl));
1818 break;
1819 case IP_TOS:
1820 sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
1821 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
1822 s, sock->conn->pcb.ip->tos));
1823 break;
1824 #if LWIP_IGMP
1825 case IP_MULTICAST_TTL:
1826 sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
1827 break;
1828 case IP_MULTICAST_IF:
1829 sock->conn->pcb.udp->multicast_ip.addr = ((struct in_addr*) optval)->s_addr;
1830 break;
1831 case IP_ADD_MEMBERSHIP:
1832 case IP_DROP_MEMBERSHIP:
1833 {
1834
1835 struct ip_mreq *imr = (struct ip_mreq *)optval;
1836 if(optname == IP_ADD_MEMBERSHIP){
1837 data->err = igmp_joingroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
1838 } else {
1839 data->err = igmp_leavegroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
1840 }
1841 if(data->err != ERR_OK) {
1842 data->err = EADDRNOTAVAIL;
1843 }
1844 }
1845 break;
1846 #endif
1847 }
1848 break;
1849
1850 #if LWIP_TCP
1851
1852 case IPPROTO_TCP:
1853 switch (optname) {
1854 case TCP_NODELAY:
1855 if (*(int*)optval) {
1856 tcp_nagle_disable(sock->conn->pcb.tcp);
1857 } else {
1858 tcp_nagle_enable(sock->conn->pcb.tcp);
1859 }
1860 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
1861 s, (*(int *)optval)?"on":"off") );
1862 break;
1863 case TCP_KEEPALIVE:
1864 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
1865 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
1866 s, sock->conn->pcb.tcp->keep_idle));
1867 break;
1868
1869 #if LWIP_TCP_KEEPALIVE
1870 case TCP_KEEPIDLE:
1871 sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
1872 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
1873 s, sock->conn->pcb.tcp->keep_idle));
1874 break;
1875 case TCP_KEEPINTVL:
1876 sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
1877 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
1878 s, sock->conn->pcb.tcp->keep_intvl));
1879 break;
1880 case TCP_KEEPCNT:
1881 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
1882 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
1883 s, sock->conn->pcb.tcp->keep_cnt));
1884 break;
1885 #endif
1886
1887 }
1888 break;
1889 #endif
1890 #if LWIP_UDP && LWIP_UDPLITE
1891
1892 case IPPROTO_UDPLITE:
1893 switch (optname) {
1894 case UDPLITE_SEND_CSCOV:
1895 if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
1896
1897 sock->conn->pcb.udp->chksum_len_tx = 8;
1898 } else {
1899 sock->conn->pcb.udp->chksum_len_tx = *(int*)optval;
1900 }
1901 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
1902 s, (*(int*)optval)) );
1903 break;
1904 case UDPLITE_RECV_CSCOV:
1905 if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
1906
1907 sock->conn->pcb.udp->chksum_len_rx = 8;
1908 } else {
1909 sock->conn->pcb.udp->chksum_len_rx = *(int*)optval;
1910 }
1911 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
1912 s, (*(int*)optval)) );
1913 break;
1914 }
1915 break;
1916 #endif
1917 }
1918 sys_sem_signal(sock->conn->op_completed);
1919 }
1920
1921 int
1922 lwip_ioctl(int s, long cmd, void *argp)
1923 {
1924 struct lwip_socket *sock = get_socket(s);
1925 u16_t buflen = 0;
1926 s16_t recv_avail;
1927
1928 if (!sock)
1929 return -1;
1930
1931 switch (cmd) {
1932 case FIONREAD:
1933 if (!argp) {
1934 sock_set_errno(sock, EINVAL);
1935 return -1;
1936 }
1937
1938 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
1939 if (recv_avail < 0)
1940 recv_avail = 0;
1941 *((u16_t*)argp) = (u16_t)recv_avail;
1942
1943
1944 if (sock->lastdata) {
1945 buflen = netbuf_len(sock->lastdata);
1946 buflen -= sock->lastoffset;
1947
1948 *((u16_t*)argp) += buflen;
1949 }
1950
1951 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
1952 sock_set_errno(sock, 0);
1953 return 0;
1954
1955 case FIONBIO:
1956 if (argp && *(u32_t*)argp)
1957 sock->flags |= O_NONBLOCK;
1958 else
1959 sock->flags &= ~O_NONBLOCK;
1960 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
1961 sock_set_errno(sock, 0);
1962 return 0;
1963
1964 default:
1965 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
1966 sock_set_errno(sock, ENOSYS);
1967 return -1;
1968 }
1969 }
1970
1971 #endif