49 #include "lwip/inet.h"
55 #if LWIP_CHECKSUM_ON_COPY
61 #define NUM_SOCKETS MEMP_NUM_NETCONN
86 struct lwip_select_cb {
88 struct lwip_select_cb *next;
90 struct lwip_select_cb *prev;
105 struct lwip_setgetsockopt_data {
107 struct lwip_sock *sock;
126 static struct lwip_sock sockets[NUM_SOCKETS];
128 static struct lwip_select_cb *select_cb_list;
131 static volatile int select_cb_ctr;
135 static const int err_to_errno_table[] = {
154 #define ERR_TO_ERRNO_TABLE_SIZE \
155 (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
157 #define err_to_errno(err) \
158 ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
159 err_to_errno_table[-(err)] : EIO)
163 #define set_errno(err) errno = (err)
166 #define set_errno(err)
169 #define sock_set_errno(sk, e) do { \
171 set_errno(sk->err); \
175 static void event_callback(
struct netconn *conn,
enum netconn_evt evt,
u16_t len);
176 static void lwip_getsockopt_internal(
void *arg);
177 static void lwip_setsockopt_internal(
void *arg);
184 lwip_socket_init(
void)
194 static struct lwip_sock *
197 struct lwip_sock *sock;
199 if ((s < 0) || (s >= NUM_SOCKETS)) {
222 static struct lwip_sock *
225 if ((s < 0) || (s >= NUM_SOCKETS)) {
228 if (!sockets[s].conn) {
243 alloc_socket(
struct netconn *newconn,
int accepted)
249 for (i = 0; i < NUM_SOCKETS; ++i) {
252 if (!sockets[i].conn) {
253 sockets[i].conn = newconn;
257 sockets[i].lastdata =
NULL;
258 sockets[i].lastoffset = 0;
259 sockets[i].rcvevent = 0;
262 sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
263 sockets[i].errevent = 0;
265 sockets[i].select_waiting = 0;
280 free_socket(
struct lwip_sock *sock,
int is_tcp)
285 lastdata = sock->lastdata;
286 sock->lastdata =
NULL;
287 sock->lastoffset = 0;
296 if (lastdata !=
NULL) {
312 lwip_accept(
int s,
struct sockaddr *addr, socklen_t *addrlen)
314 struct lwip_sock *sock, *nsock;
315 struct netconn *newconn;
319 struct sockaddr_in
sin;
324 sock = get_socket(s);
329 if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
336 err = netconn_accept(sock->conn, &newconn);
339 sock_set_errno(sock, err_to_errno(err));
344 netconn_set_noautorecved(newconn, 1);
347 err = netconn_peer(newconn, &naddr, &port);
350 netconn_delete(newconn);
351 sock_set_errno(sock, err_to_errno(err));
360 memset(&
sin, 0,
sizeof(
sin));
361 sin.sin_len =
sizeof(
sin);
362 sin.sin_family = AF_INET;
366 if (*addrlen >
sizeof(
sin))
367 *addrlen =
sizeof(
sin);
372 newsock = alloc_socket(newconn, 1);
374 netconn_delete(newconn);
375 sock_set_errno(sock,
ENFILE);
378 LWIP_ASSERT(
"invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
379 LWIP_ASSERT(
"newconn->callback == event_callback", newconn->callback == event_callback);
380 nsock = &sockets[newsock];
388 nsock->rcvevent += (
s16_t)(-1 - newconn->socket);
389 newconn->socket = newsock;
396 sock_set_errno(sock, 0);
401 lwip_bind(
int s,
const struct sockaddr *name, socklen_t namelen)
403 struct lwip_sock *sock;
407 const struct sockaddr_in *name_in;
409 sock = get_socket(s);
415 LWIP_ERROR(
"lwip_bind: invalid address", ((namelen ==
sizeof(
struct sockaddr_in)) &&
416 ((name->sa_family) == AF_INET) && ((((
mem_ptr_t)name) % 4) == 0)),
417 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
418 name_in = (
const struct sockaddr_in *)(
void*)name;
421 local_port = name_in->sin_port;
427 err = netconn_bind(sock->conn, &local_addr,
ntohs(local_port));
431 sock_set_errno(sock, err_to_errno(err));
436 sock_set_errno(sock, 0);
443 struct lwip_sock *sock;
448 sock = get_socket(s);
453 if(sock->conn !=
NULL) {
454 is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
459 netconn_delete(sock->conn);
461 free_socket(sock, is_tcp);
467 lwip_connect(
int s,
const struct sockaddr *name, socklen_t namelen)
469 struct lwip_sock *sock;
471 const struct sockaddr_in *name_in;
473 sock = get_socket(s);
479 LWIP_ERROR(
"lwip_connect: invalid address", ((namelen ==
sizeof(
struct sockaddr_in)) &&
480 ((name->sa_family) == AF_INET) && ((((
mem_ptr_t)name) % 4) == 0)),
481 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
482 name_in = (
const struct sockaddr_in *)(
void*)name;
484 if (name_in->sin_family == AF_UNSPEC) {
486 err = netconn_disconnect(sock->conn);
492 remote_port = name_in->sin_port;
498 err = netconn_connect(sock->conn, &remote_addr,
ntohs(remote_port));
503 sock_set_errno(sock, err_to_errno(err));
508 sock_set_errno(sock, 0);
521 lwip_listen(
int s,
int backlog)
523 struct lwip_sock *sock;
528 sock = get_socket(s);
536 err = netconn_listen_with_backlog(sock->conn, (
u8_t)backlog);
540 sock_set_errno(sock, err_to_errno(err));
544 sock_set_errno(sock, 0);
549 lwip_recvfrom(
int s,
void *
mem,
size_t len,
int flags,
550 struct sockaddr *from, socklen_t *fromlen)
552 struct lwip_sock *sock;
555 u16_t buflen, copylen;
563 sock = get_socket(s);
571 if (sock->lastdata) {
572 buf = sock->lastdata;
575 if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
576 (sock->rcvevent <= 0)) {
579 netconn_recved(sock->conn, (
u32_t)off);
581 sock_set_errno(sock, 0);
591 if (netconn_type(sock->conn) == NETCONN_TCP) {
592 err = netconn_recv_tcp_pbuf(sock->conn, (
struct pbuf **)&buf);
594 err = netconn_recv(sock->conn, (
struct netbuf **)&buf);
602 netconn_recved(sock->conn, (
u32_t)off);
604 sock_set_errno(sock, 0);
610 sock_set_errno(sock, err_to_errno(err));
618 sock->lastdata = buf;
621 if (netconn_type(sock->conn) == NETCONN_TCP) {
622 p = (
struct pbuf *)buf;
624 p = ((
struct netbuf *)buf)->p;
628 buflen, len, off, sock->lastoffset));
630 buflen -= sock->lastoffset;
635 copylen = (
u16_t)len;
644 if (netconn_type(sock->conn) == NETCONN_TCP) {
645 LWIP_ASSERT(
"invalid copylen, len would underflow", len >= copylen);
649 (sock->rcvevent <= 0) ||
650 ((flags & MSG_PEEK)!=0)) {
660 if (from && fromlen) {
661 struct sockaddr_in
sin;
663 if (netconn_type(sock->conn) == NETCONN_TCP) {
665 netconn_getaddr(sock->conn, addr, &port, 0);
671 memset(&
sin, 0,
sizeof(
sin));
672 sin.sin_len =
sizeof(
sin);
673 sin.sin_family = AF_INET;
677 if (*fromlen >
sizeof(
sin)) {
678 *fromlen =
sizeof(
sin);
688 if (netconn_type(sock->conn) == NETCONN_TCP) {
690 netconn_getaddr(sock->conn, addr, &port, 0);
704 if ((flags & MSG_PEEK) == 0) {
708 if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
709 sock->lastdata = buf;
710 sock->lastoffset += copylen;
713 sock->lastdata =
NULL;
714 sock->lastoffset = 0;
716 if (netconn_type(sock->conn) == NETCONN_TCP) {
727 netconn_recved(sock->conn, (
u32_t)off);
729 sock_set_errno(sock, 0);
734 lwip_read(
int s,
void *mem,
size_t len)
736 return lwip_recvfrom(s, mem, len, 0,
NULL,
NULL);
740 lwip_recv(
int s,
void *mem,
size_t len,
int flags)
742 return lwip_recvfrom(s, mem, len, flags,
NULL,
NULL);
746 lwip_send(
int s,
const void *data,
size_t size,
int flags)
748 struct lwip_sock *sock;
753 s, data, size, flags));
755 sock = get_socket(s);
760 if (sock->conn->type != NETCONN_TCP) {
761 #if (LWIP_UDP || LWIP_RAW)
762 return lwip_sendto(s, data, size, flags,
NULL, 0);
764 sock_set_errno(sock, err_to_errno(
ERR_ARG));
769 if ((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) {
777 write_flags = NETCONN_COPY |
778 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
779 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
780 err = netconn_write(sock->conn, data, size, write_flags);
783 sock_set_errno(sock, err_to_errno(err));
784 return (err ==
ERR_OK ? (
int)size : -1);
788 lwip_sendto(
int s,
const void *data,
size_t size,
int flags,
789 const struct sockaddr *to, socklen_t tolen)
791 struct lwip_sock *sock;
794 const struct sockaddr_in *to_in;
796 #if !LWIP_TCPIP_CORE_LOCKING
800 sock = get_socket(s);
805 if (sock->conn->type == NETCONN_TCP) {
807 return lwip_send(s, data, size, flags);
810 sock_set_errno(sock, err_to_errno(
ERR_ARG));
816 LWIP_ASSERT(
"lwip_sendto: size must fit in u16_t", size <= 0xffff);
817 short_size = (
u16_t)size;
818 LWIP_ERROR(
"lwip_sendto: invalid address", (((to ==
NULL) && (tolen == 0)) ||
819 ((tolen ==
sizeof(
struct sockaddr_in)) &&
820 ((to->sa_family) == AF_INET) && ((((
mem_ptr_t)to) % 4) == 0))),
821 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
822 to_in = (
const struct sockaddr_in *)(
void*)to;
824 #if LWIP_TCPIP_CORE_LOCKING
830 #if LWIP_NETIF_TX_SINGLE_PBUF
833 #if LWIP_CHECKSUM_ON_COPY
835 if (sock->conn->type != NETCONN_RAW) {
836 chksum = LWIP_CHKSUM_COPY(p->
payload, data, short_size);
848 remote_port =
ntohs(to_in->sin_port);
855 if (sock->conn->type == NETCONN_RAW) {
856 err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
859 #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
860 err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
861 remote_addr, remote_port, 1, chksum);
863 err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
864 remote_addr, remote_port);
879 buf.p = buf.ptr =
NULL;
880 #if LWIP_CHECKSUM_ON_COPY
885 remote_port =
ntohs(to_in->sin_port);
894 s, data, short_size, flags));
899 #if LWIP_NETIF_TX_SINGLE_PBUF
904 #if LWIP_CHECKSUM_ON_COPY
905 if (sock->conn->type != NETCONN_RAW) {
906 u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
907 netbuf_set_chksum(&buf, chksum);
920 err = netconn_send(sock->conn, &buf);
926 sock_set_errno(sock, err_to_errno(err));
927 return (err ==
ERR_OK ? short_size : -1);
931 lwip_socket(
int domain,
int type,
int protocol)
933 struct netconn *conn;
941 conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (
u8_t)protocol, event_callback);
943 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
946 conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
947 NETCONN_UDPLITE : NETCONN_UDP, event_callback);
949 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
952 conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
954 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
957 netconn_set_noautorecved(conn, 1);
962 domain, type, protocol));
973 i = alloc_socket(conn, 0);
976 netconn_delete(conn);
987 lwip_write(
int s,
const void *data,
size_t size)
989 return lwip_send(s, data, size, 0);
1009 lwip_selscan(
int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
1010 fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
1013 fd_set lreadset, lwriteset, lexceptset;
1014 struct lwip_sock *sock;
1018 FD_ZERO(&lwriteset);
1019 FD_ZERO(&lexceptset);
1023 for(i = 0; i < maxfdp1; i++) {
1024 void* lastdata =
NULL;
1026 u16_t sendevent = 0;
1030 sock = tryget_socket(i);
1032 lastdata = sock->lastdata;
1033 rcvevent = sock->rcvevent;
1034 sendevent = sock->sendevent;
1035 errevent = sock->errevent;
1040 if (readset_in && FD_ISSET(i, readset_in) && ((lastdata !=
NULL) || (rcvevent > 0))) {
1041 FD_SET(i, &lreadset);
1046 if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
1047 FD_SET(i, &lwriteset);
1052 if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
1053 FD_SET(i, &lexceptset);
1059 *readset_out = lreadset;
1060 *writeset_out = lwriteset;
1061 *exceptset_out = lexceptset;
1071 lwip_select(
int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
1072 struct timeval *timeout)
1076 fd_set lreadset, lwriteset, lexceptset;
1078 struct lwip_select_cb select_cb;
1084 maxfdp1, (
void *)readset, (
void *) writeset, (
void *) exceptset,
1085 timeout ? (
s32_t)timeout->tv_sec : (
s32_t)-1,
1086 timeout ? (
s32_t)timeout->tv_usec : (
s32_t)-1));
1090 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1094 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
1098 goto return_copy_fdsets;
1106 select_cb.next =
NULL;
1107 select_cb.prev =
NULL;
1108 select_cb.readset = readset;
1109 select_cb.writeset = writeset;
1110 select_cb.exceptset = exceptset;
1111 select_cb.sem_signalled = 0;
1123 select_cb.next = select_cb_list;
1124 if (select_cb_list !=
NULL) {
1125 select_cb_list->prev = &select_cb;
1127 select_cb_list = &select_cb;
1135 for(i = 0; i < maxfdp1; i++) {
1136 if ((readset && FD_ISSET(i, readset)) ||
1137 (writeset && FD_ISSET(i, writeset)) ||
1138 (exceptset && FD_ISSET(i, exceptset))) {
1139 struct lwip_sock *sock = tryget_socket(i);
1142 sock->select_waiting++;
1143 LWIP_ASSERT(
"sock->select_waiting > 0", sock->select_waiting > 0);
1150 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1157 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
1158 if (msectimeout == 0) {
1167 for(i = 0; i < maxfdp1; i++) {
1168 if ((readset && FD_ISSET(i, readset)) ||
1169 (writeset && FD_ISSET(i, writeset)) ||
1170 (exceptset && FD_ISSET(i, exceptset))) {
1171 struct lwip_sock *sock = tryget_socket(i);
1174 sock->select_waiting--;
1175 LWIP_ASSERT(
"sock->select_waiting >= 0", sock->select_waiting >= 0);
1181 if (select_cb.next !=
NULL) {
1182 select_cb.next->prev = select_cb.prev;
1184 if (select_cb_list == &select_cb) {
1186 select_cb_list = select_cb.next;
1189 select_cb.prev->next = select_cb.next;
1201 goto return_copy_fdsets;
1205 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1212 *readset = lreadset;
1215 *writeset = lwriteset;
1218 *exceptset = lexceptset;
1230 event_callback(
struct netconn *conn,
enum netconn_evt evt,
u16_t len)
1233 struct lwip_sock *sock;
1234 struct lwip_select_cb *scb;
1235 int last_select_cb_ctr;
1250 if (conn->socket < 0) {
1251 if (evt == NETCONN_EVT_RCVPLUS) {
1261 sock = get_socket(s);
1272 case NETCONN_EVT_RCVPLUS:
1275 case NETCONN_EVT_RCVMINUS:
1278 case NETCONN_EVT_SENDPLUS:
1279 sock->sendevent = 1;
1281 case NETCONN_EVT_SENDMINUS:
1282 sock->sendevent = 0;
1284 case NETCONN_EVT_ERROR:
1292 if (sock->select_waiting == 0) {
1305 for (scb = select_cb_list; scb !=
NULL; scb = scb->next) {
1306 if (scb->sem_signalled == 0) {
1310 if (sock->rcvevent > 0) {
1311 if (scb->readset && FD_ISSET(s, scb->readset)) {
1315 if (sock->sendevent != 0) {
1316 if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
1320 if (sock->errevent != 0) {
1321 if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
1326 scb->sem_signalled = 1;
1333 last_select_cb_ctr = select_cb_ctr;
1337 if (last_select_cb_ctr != select_cb_ctr) {
1350 lwip_shutdown(
int s,
int how)
1352 struct lwip_sock *sock;
1354 u8_t shut_rx = 0, shut_tx = 0;
1358 sock = get_socket(s);
1363 if (sock->conn !=
NULL) {
1364 if (netconn_type(sock->conn) != NETCONN_TCP) {
1373 if (how == SHUT_RD) {
1375 }
else if (how == SHUT_WR) {
1377 }
else if(how == SHUT_RDWR) {
1381 sock_set_errno(sock,
EINVAL);
1384 err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
1386 sock_set_errno(sock, err_to_errno(err));
1387 return (err ==
ERR_OK ? 0 : -1);
1391 lwip_getaddrname(
int s,
struct sockaddr *name, socklen_t *namelen,
u8_t local)
1393 struct lwip_sock *sock;
1394 struct sockaddr_in
sin;
1397 sock = get_socket(s);
1402 memset(&
sin, 0,
sizeof(
sin));
1403 sin.sin_len =
sizeof(
sin);
1404 sin.sin_family = AF_INET;
1407 netconn_getaddr(sock->conn, &naddr, &
sin.sin_port, local);
1416 if (*namelen >
sizeof(
sin)) {
1417 *namelen =
sizeof(
sin);
1421 sock_set_errno(sock, 0);
1426 lwip_getpeername(
int s,
struct sockaddr *name, socklen_t *namelen)
1428 return lwip_getaddrname(s, name, namelen, 0);
1432 lwip_getsockname(
int s,
struct sockaddr *name, socklen_t *namelen)
1434 return lwip_getaddrname(s, name, namelen, 1);
1438 lwip_getsockopt(
int s,
int level,
int optname,
void *optval, socklen_t *optlen)
1441 struct lwip_sock *sock = get_socket(s);
1442 struct lwip_setgetsockopt_data data;
1448 if ((
NULL == optval) || (
NULL == optlen)) {
1449 sock_set_errno(sock,
EFAULT);
1468 #if LWIP_SO_RCVTIMEO
1484 if (*optlen <
sizeof(
int)) {
1490 if (*optlen <
sizeof(
int)) {
1494 if ((sock->conn->type != NETCONN_UDP) ||
1495 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1517 if (*optlen <
sizeof(
int)) {
1522 case IP_MULTICAST_TTL:
1523 if (*optlen <
sizeof(
u8_t)) {
1527 case IP_MULTICAST_IF:
1528 if (*optlen <
sizeof(
struct in_addr)) {
1532 case IP_MULTICAST_LOOP:
1533 if (*optlen <
sizeof(
u8_t)) {
1536 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1552 if (*optlen <
sizeof(
int)) {
1558 if (sock->conn->type != NETCONN_TCP)
1564 #if LWIP_TCP_KEEPALIVE
1578 #if LWIP_UDP && LWIP_UDPLITE
1580 case IPPROTO_UDPLITE:
1581 if (*optlen <
sizeof(
int)) {
1587 if (sock->conn->type != NETCONN_UDPLITE) {
1592 case UDPLITE_SEND_CSCOV:
1593 case UDPLITE_RECV_CSCOV:
1606 s, level, optname));
1612 sock_set_errno(sock, err);
1622 data.optname = optname;
1623 data.optval = optval;
1624 data.optlen = optlen;
1631 sock_set_errno(sock, err);
1632 return err ? -1 : 0;
1636 lwip_getsockopt_internal(
void *arg)
1638 struct lwip_sock *sock;
1644 struct lwip_setgetsockopt_data *data;
1648 data = (
struct lwip_setgetsockopt_data*)arg;
1653 level = data->level;
1654 optname = data->optname;
1655 optval = data->optval;
1675 *(
int*)optval = sock->conn->pcb.ip->so_options & optname;
1677 s, optname, (*(
int*)optval?
"on":
"off")));
1681 switch (NETCONNTYPE_GROUP(sock->conn->type)) {
1683 *(
int*)optval = SOCK_RAW;
1686 *(
int*)optval = SOCK_STREAM;
1689 *(
int*)optval = SOCK_DGRAM;
1692 *(
int*)optval = sock->conn->type;
1694 (
"lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
1695 s, *(
int *)optval));
1698 s, *(
int *)optval));
1703 if ((sock->err == 0) || (sock->err ==
EINPROGRESS)) {
1704 sock_set_errno(sock, err_to_errno(sock->conn->last_err));
1706 *(
int *)optval = sock->err;
1709 s, *(
int *)optval));
1712 #if LWIP_SO_RCVTIMEO
1714 *(
int *)optval = netconn_get_recvtimeout(sock->conn);
1719 *(
int *)optval = netconn_get_recvbufsize(sock->conn);
1724 *(
int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
1737 *(
int*)optval = sock->conn->pcb.ip->ttl;
1739 s, *(
int *)optval));
1742 *(
int*)optval = sock->conn->pcb.ip->tos;
1744 s, *(
int *)optval));
1747 case IP_MULTICAST_TTL:
1748 *(
u8_t*)optval = sock->conn->pcb.ip->ttl;
1750 s, *(
int *)optval));
1752 case IP_MULTICAST_IF:
1755 s, *(
u32_t *)optval));
1757 case IP_MULTICAST_LOOP:
1758 if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
1764 s, *(
int *)optval));
1778 *(
int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
1780 s, (*(
int*)optval)?
"on":
"off") );
1783 *(
int*)optval = (
int)sock->conn->pcb.tcp->keep_idle;
1785 s, *(
int *)optval));
1788 #if LWIP_TCP_KEEPALIVE
1790 *(
int*)optval = (
int)(sock->conn->pcb.tcp->keep_idle/1000);
1792 s, *(
int *)optval));
1795 *(
int*)optval = (
int)(sock->conn->pcb.tcp->keep_intvl/1000);
1797 s, *(
int *)optval));
1800 *(
int*)optval = (
int)sock->conn->pcb.tcp->keep_cnt;
1802 s, *(
int *)optval));
1811 #if LWIP_UDP && LWIP_UDPLITE
1813 case IPPROTO_UDPLITE:
1815 case UDPLITE_SEND_CSCOV:
1816 *(
int*)optval = sock->conn->pcb.udp->chksum_len_tx;
1818 s, (*(
int*)optval)) );
1820 case UDPLITE_RECV_CSCOV:
1821 *(
int*)optval = sock->conn->pcb.udp->chksum_len_rx;
1823 s, (*(
int*)optval)) );
1839 lwip_setsockopt(
int s,
int level,
int optname,
const void *optval, socklen_t optlen)
1841 struct lwip_sock *sock = get_socket(s);
1843 struct lwip_setgetsockopt_data data;
1849 if (
NULL == optval) {
1850 sock_set_errno(sock,
EFAULT);
1867 #if LWIP_SO_RCVTIMEO
1882 if (optlen <
sizeof(
int)) {
1887 if (optlen <
sizeof(
int)) {
1891 if ((sock->conn->type != NETCONN_UDP) ||
1892 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1913 if (optlen <
sizeof(
int)) {
1918 case IP_MULTICAST_TTL:
1919 if (optlen <
sizeof(
u8_t)) {
1922 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1926 case IP_MULTICAST_IF:
1927 if (optlen <
sizeof(
struct in_addr)) {
1930 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1934 case IP_MULTICAST_LOOP:
1935 if (optlen <
sizeof(
u8_t)) {
1938 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1942 case IP_ADD_MEMBERSHIP:
1943 case IP_DROP_MEMBERSHIP:
1944 if (optlen <
sizeof(
struct ip_mreq)) {
1947 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1962 if (optlen <
sizeof(
int)) {
1968 if (sock->conn->type != NETCONN_TCP)
1974 #if LWIP_TCP_KEEPALIVE
1988 #if LWIP_UDP && LWIP_UDPLITE
1990 case IPPROTO_UDPLITE:
1991 if (optlen <
sizeof(
int)) {
1997 if (sock->conn->type != NETCONN_UDPLITE)
2001 case UDPLITE_SEND_CSCOV:
2002 case UDPLITE_RECV_CSCOV:
2015 s, level, optname));
2021 sock_set_errno(sock, err);
2032 data.optname = optname;
2033 data.optval = (
void*)optval;
2034 data.optlen = &optlen;
2041 sock_set_errno(sock, err);
2042 return err ? -1 : 0;
2046 lwip_setsockopt_internal(
void *arg)
2048 struct lwip_sock *sock;
2054 struct lwip_setgetsockopt_data *data;
2058 data = (
struct lwip_setgetsockopt_data*)arg;
2063 level = data->level;
2064 optname = data->optname;
2065 optval = data->optval;
2084 if (*(
int*)optval) {
2085 sock->conn->pcb.ip->so_options |= optname;
2087 sock->conn->pcb.ip->so_options &= ~optname;
2090 s, optname, (*(
int*)optval?
"on":
"off")));
2092 #if LWIP_SO_RCVTIMEO
2094 netconn_set_recvtimeout(sock->conn, *(
int*)optval);
2099 netconn_set_recvbufsize(sock->conn, *(
int*)optval);
2104 if (*(
int*)optval) {
2105 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
2107 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
2121 sock->conn->pcb.ip->ttl = (
u8_t)(*(
int*)optval);
2123 s, sock->conn->pcb.ip->ttl));
2126 sock->conn->pcb.ip->tos = (
u8_t)(*(
int*)optval);
2128 s, sock->conn->pcb.ip->tos));
2131 case IP_MULTICAST_TTL:
2132 sock->conn->pcb.udp->ttl = (
u8_t)(*(
u8_t*)optval);
2134 case IP_MULTICAST_IF:
2137 case IP_MULTICAST_LOOP:
2138 if (*(
u8_t*)optval) {
2139 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
2141 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
2144 case IP_ADD_MEMBERSHIP:
2145 case IP_DROP_MEMBERSHIP:
2148 struct ip_mreq *imr = (
struct ip_mreq *)optval;
2153 if(optname == IP_ADD_MEMBERSHIP){
2154 data->err = igmp_joingroup(&if_addr, &multi_addr);
2156 data->err = igmp_leavegroup(&if_addr, &multi_addr);
2158 if(data->err !=
ERR_OK) {
2175 if (*(
int*)optval) {
2176 tcp_nagle_disable(sock->conn->pcb.tcp);
2178 tcp_nagle_enable(sock->conn->pcb.tcp);
2181 s, (*(
int *)optval)?
"on":
"off") );
2184 sock->conn->pcb.tcp->keep_idle = (
u32_t)(*(
int*)optval);
2186 s, sock->conn->pcb.tcp->keep_idle));
2189 #if LWIP_TCP_KEEPALIVE
2191 sock->conn->pcb.tcp->keep_idle = 1000*(
u32_t)(*(
int*)optval);
2193 s, sock->conn->pcb.tcp->keep_idle));
2196 sock->conn->pcb.tcp->keep_intvl = 1000*(
u32_t)(*(
int*)optval);
2198 s, sock->conn->pcb.tcp->keep_intvl));
2201 sock->conn->pcb.tcp->keep_cnt = (
u32_t)(*(
int*)optval);
2203 s, sock->conn->pcb.tcp->keep_cnt));
2212 #if LWIP_UDP && LWIP_UDPLITE
2214 case IPPROTO_UDPLITE:
2216 case UDPLITE_SEND_CSCOV:
2217 if ((*(
int*)optval != 0) && ((*(
int*)optval < 8)) || (*(
int*)optval > 0xffff)) {
2219 sock->conn->pcb.udp->chksum_len_tx = 8;
2221 sock->conn->pcb.udp->chksum_len_tx = (
u16_t)*(
int*)optval;
2224 s, (*(
int*)optval)) );
2226 case UDPLITE_RECV_CSCOV:
2227 if ((*(
int*)optval != 0) && ((*(
int*)optval < 8)) || (*(
int*)optval > 0xffff)) {
2229 sock->conn->pcb.udp->chksum_len_rx = 8;
2231 sock->conn->pcb.udp->chksum_len_rx = (
u16_t)*(
int*)optval;
2234 s, (*(
int*)optval)) );
2250 lwip_ioctl(
int s,
long cmd,
void *argp)
2252 struct lwip_sock *sock = get_socket(s);
2267 sock_set_errno(sock,
EINVAL);
2272 if (recv_avail < 0) {
2278 if (sock->lastdata) {
2279 struct pbuf *p = (
struct pbuf *)sock->lastdata;
2280 if (netconn_type(sock->conn) != NETCONN_TCP) {
2281 p = ((
struct netbuf *)p)->p;
2284 buflen -= sock->lastoffset;
2286 *((
u16_t*)argp) += buflen;
2290 sock_set_errno(sock, 0);
2296 if (argp && *(
u32_t*)argp) {
2299 netconn_set_nonblocking(sock->conn, val);
2301 sock_set_errno(sock, 0);
2306 sock_set_errno(sock,
ENOSYS);
2316 lwip_fcntl(
int s,
int cmd,
int val)
2318 struct lwip_sock *sock = get_socket(s);
2321 if (!sock || !sock->conn) {
2327 ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
2330 if ((val & ~O_NONBLOCK) == 0) {
2332 netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);