57#if LWIP_CHECKSUM_ON_COPY
61#if LWIP_COMPAT_SOCKETS == 2 && LWIP_POSIX_SOCKETS_IO_NAMES
67#ifdef LWIP_HOOK_FILENAME
68#include LWIP_HOOK_FILENAME
83#define API_SELECT_CB_VAR_REF(name) API_VAR_REF(name)
84#define API_SELECT_CB_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_select_cb, name)
85#define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock)
86#define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name)
88#ifndef LWIP_SOCKET_HAVE_SA_LEN
89#define LWIP_SOCKET_HAVE_SA_LEN 0
93#if LWIP_SOCKET_HAVE_SA_LEN
96#define IP4ADDR_SOCKADDR_SET_LEN(sin) \
97 (sin)->sin_len = sizeof(struct sockaddr_in)
101#define IP6ADDR_SOCKADDR_SET_LEN(sin6) \
102 (sin6)->sin6_len = sizeof(struct sockaddr_in6)
105#define IPADDR_SOCKADDR_GET_LEN(addr) \
111#define IP4ADDR_SOCKADDR_SET_LEN(addr)
115#define IP6ADDR_SOCKADDR_SET_LEN(addr)
118#if LWIP_IPV4 && LWIP_IPV6
119#define IPADDR_SOCKADDR_GET_LEN(addr) \
120 ((addr)->sa.sa_family == AF_INET ? sizeof(struct sockaddr_in) \
121 : ((addr)->sa.sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : 0))
123#define IPADDR_SOCKADDR_GET_LEN(addr) sizeof(struct sockaddr_in)
125#define IPADDR_SOCKADDR_GET_LEN(addr) sizeof(struct sockaddr_in6)
127#define IPADDR_SOCKADDR_GET_LEN(addr) sizeof(struct sockaddr)
133#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
134 IP4ADDR_SOCKADDR_SET_LEN(sin); \
135 (sin)->sin_family = AF_INET; \
136 (sin)->sin_port = lwip_htons((port)); \
137 inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
138 memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
139#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
140 inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
141 (port) = lwip_ntohs((sin)->sin_port); }while(0)
145#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \
146 IP6ADDR_SOCKADDR_SET_LEN(sin6); \
147 (sin6)->sin6_family = AF_INET6; \
148 (sin6)->sin6_port = lwip_htons((port)); \
149 (sin6)->sin6_flowinfo = 0; \
150 inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \
151 (sin6)->sin6_scope_id = ip6_addr_zone(ipaddr); }while(0)
152#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \
153 inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \
154 if (ip6_addr_has_scope(ip_2_ip6(ipaddr), IP6_UNKNOWN)) { \
155 ip6_addr_set_zone(ip_2_ip6(ipaddr), (u8_t)((sin6)->sin6_scope_id)); \
157 (port) = lwip_ntohs((sin6)->sin6_port); }while(0)
160#if LWIP_IPV4 && LWIP_IPV6
161static void sockaddr_to_ipaddr_port(
const struct sockaddr *
sockaddr, ip_addr_t *ipaddr, u16_t *port);
163#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \
164 ((namelen) == sizeof(struct sockaddr_in6)))
165#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \
166 ((name)->sa_family == AF_INET6))
167#define SOCK_ADDR_TYPE_MATCH(name, sock) \
168 ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \
169 (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type))))
170#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \
171 if (IP_IS_ANY_TYPE_VAL(*ipaddr) || IP_IS_V6_VAL(*ipaddr)) { \
172 IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \
174 IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \
176#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port))
177#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \
178 (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6))
180#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6))
181#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6)
182#define SOCK_ADDR_TYPE_MATCH(name, sock) 1
183#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
184 IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port)
185#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
186 SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port)
187#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
189#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in))
190#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET)
191#define SOCK_ADDR_TYPE_MATCH(name, sock) 1
192#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
193 IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port)
194#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
195 SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port)
196#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
199#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \
200 IS_SOCK_ADDR_TYPE_VALID(name))
201#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \
202 SOCK_ADDR_TYPE_MATCH(name, sock))
203#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % LWIP_MIN(4, MEM_ALIGNMENT)) == 0)
206#define LWIP_SOCKOPT_CHECK_OPTLEN(sock, optlen, opttype) do { if ((optlen) < sizeof(opttype)) { done_socket(sock); return EINVAL; }}while(0)
207#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \
208 LWIP_SOCKOPT_CHECK_OPTLEN(sock, optlen, opttype); \
209 if ((sock)->conn == NULL) { done_socket(sock); return EINVAL; } }while(0)
210#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \
211 LWIP_SOCKOPT_CHECK_OPTLEN(sock, optlen, opttype); \
212 if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { done_socket(sock); return EINVAL; } }while(0)
213#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \
214 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \
215 if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { done_socket(sock); return ENOPROTOOPT; } }while(0)
218#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name)
219#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name)
220#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name)
221#if LWIP_MPU_COMPATIBLE
222#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \
223 name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \
224 if (name == NULL) { \
230#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock)
233#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
234#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int
235#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val))
236#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((long)*(const int*)(optval))
238#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval
239#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \
241 ((struct timeval *)(optval))->tv_sec = (long)((loc) / 1000U); \
242 ((struct timeval *)(optval))->tv_usec = (long)(((loc) % 1000U) * 1000U); }while(0)
243#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000) + (((const struct timeval *)(optval))->tv_usec / 1000))
250union sockaddr_aligned {
253 struct sockaddr_in6 sin6;
256 struct sockaddr_in sin;
261#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
262#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS
268struct lwip_socket_multicast_pair {
270 struct lwip_sock *sock;
277static struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
279static int lwip_socket_register_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
280static void lwip_socket_unregister_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
281static void lwip_socket_drop_registered_memberships(
int s);
287struct lwip_socket_multicast_mld6_pair {
289 struct lwip_sock *sock;
296static struct lwip_socket_multicast_mld6_pair socket_ipv6_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
298static int lwip_socket_register_mld6_membership(
int s,
unsigned int if_idx,
const ip6_addr_t *multi_addr);
299static void lwip_socket_unregister_mld6_membership(
int s,
unsigned int if_idx,
const ip6_addr_t *multi_addr);
300static void lwip_socket_drop_registered_mld6_memberships(
int s);
304static struct lwip_sock sockets[NUM_SOCKETS];
306#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
307#if LWIP_TCPIP_CORE_LOCKING
309#define LWIP_SOCKET_SELECT_DECL_PROTECT(lev)
310#define LWIP_SOCKET_SELECT_PROTECT(lev) LOCK_TCPIP_CORE()
311#define LWIP_SOCKET_SELECT_UNPROTECT(lev) UNLOCK_TCPIP_CORE()
314#define LWIP_SOCKET_SELECT_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev)
315#define LWIP_SOCKET_SELECT_PROTECT(lev) SYS_ARCH_PROTECT(lev)
316#define LWIP_SOCKET_SELECT_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev)
319static volatile int select_cb_ctr;
322static struct lwip_select_cb *select_cb_list;
326#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
327static void event_callback(
struct netconn *conn,
enum netconn_evt evt, u16_t len);
328#define DEFAULT_SOCKET_EVENTCB event_callback
329static void select_check_waiters(
int s,
int has_recvevent,
int has_sendevent,
int has_errevent);
331#define DEFAULT_SOCKET_EVENTCB NULL
333#if !LWIP_TCPIP_CORE_LOCKING
334static void lwip_getsockopt_callback(
void *arg);
335static void lwip_setsockopt_callback(
void *arg);
337static int lwip_getsockopt_impl(
int s,
int level,
int optname,
void *optval, socklen_t *optlen);
338static int lwip_setsockopt_impl(
int s,
int level,
int optname,
const void *optval, socklen_t optlen);
339static int free_socket_locked(
struct lwip_sock *sock,
int is_tcp,
struct netconn **conn,
340 union lwip_sock_lastdata *lastdata);
341static void free_socket_free_elements(
int is_tcp,
struct netconn *conn,
union lwip_sock_lastdata *lastdata);
343#if LWIP_IPV4 && LWIP_IPV6
345sockaddr_to_ipaddr_port(
const struct sockaddr *
sockaddr, ip_addr_t *ipaddr, u16_t *port)
347 if ((
sockaddr->sa_family) == AF_INET6) {
348 SOCKADDR6_TO_IP6ADDR_PORT((
const struct sockaddr_in6 *)(
const void *)(
sockaddr), ipaddr, *port);
351 SOCKADDR4_TO_IP4ADDR_PORT((
const struct sockaddr_in *)(
const void *)(
sockaddr), ipaddr, *port);
359lwip_socket_thread_init(
void)
361 netconn_thread_init();
366lwip_socket_thread_cleanup(
void)
368 netconn_thread_cleanup();
371#if LWIP_NETCONN_FULLDUPLEX
374sock_inc_used(
struct lwip_sock *sock)
379 LWIP_ASSERT(
"sock != NULL", sock != NULL);
381 SYS_ARCH_PROTECT(lev);
382 if (sock->fd_free_pending) {
388 LWIP_ASSERT(
"sock->fd_used != 0", sock->fd_used != 0);
390 SYS_ARCH_UNPROTECT(lev);
396sock_inc_used_locked(
struct lwip_sock *sock)
398 LWIP_ASSERT(
"sock != NULL", sock != NULL);
400 if (sock->fd_free_pending) {
401 LWIP_ASSERT(
"sock->fd_used != 0", sock->fd_used != 0);
406 LWIP_ASSERT(
"sock->fd_used != 0", sock->fd_used != 0);
416done_socket(
struct lwip_sock *sock)
420 struct netconn *conn = NULL;
421 union lwip_sock_lastdata lastdata;
423 LWIP_ASSERT(
"sock != NULL", sock != NULL);
425 SYS_ARCH_PROTECT(lev);
426 LWIP_ASSERT(
"sock->fd_used > 0", sock->fd_used > 0);
427 if (--sock->fd_used == 0) {
428 if (sock->fd_free_pending) {
431 is_tcp = sock->fd_free_pending & LWIP_SOCK_FD_FREE_TCP;
432 freed = free_socket_locked(sock, is_tcp, &conn, &lastdata);
435 SYS_ARCH_UNPROTECT(lev);
438 free_socket_free_elements(is_tcp, conn, &lastdata);
443#define sock_inc_used(sock) 1
444#define sock_inc_used_locked(sock) 1
445#define done_socket(sock)
449static struct lwip_sock *
450tryget_socket_unconn_nouse(
int fd)
452 int s = fd - LWIP_SOCKET_OFFSET;
453 if ((s < 0) || (s >= NUM_SOCKETS)) {
454 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"tryget_socket_unconn(%d): invalid\n", fd));
461lwip_socket_dbg_get_socket(
int fd)
463 return tryget_socket_unconn_nouse(fd);
467static struct lwip_sock *
468tryget_socket_unconn(
int fd)
470 struct lwip_sock *ret = tryget_socket_unconn_nouse(fd);
472 if (!sock_inc_used(ret)) {
480static struct lwip_sock *
481tryget_socket_unconn_locked(
int fd)
483 struct lwip_sock *ret = tryget_socket_unconn_nouse(fd);
485 if (!sock_inc_used_locked(ret)) {
498static struct lwip_sock *
501 struct lwip_sock *sock = tryget_socket_unconn(fd);
517static struct lwip_sock *
520 struct lwip_sock *sock = tryget_socket(fd);
522 if ((fd < LWIP_SOCKET_OFFSET) || (fd >= (LWIP_SOCKET_OFFSET + NUM_SOCKETS))) {
523 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"get_socket(%d): invalid\n", fd));
540alloc_socket(
struct netconn *newconn,
int accepted)
547 for (i = 0; i < NUM_SOCKETS; ++i) {
549 SYS_ARCH_PROTECT(lev);
550 if (!sockets[i].conn) {
551#if LWIP_NETCONN_FULLDUPLEX
552 if (sockets[i].fd_used) {
553 SYS_ARCH_UNPROTECT(lev);
556 sockets[i].fd_used = 1;
557 sockets[i].fd_free_pending = 0;
559 sockets[i].conn = newconn;
562 SYS_ARCH_UNPROTECT(lev);
563 sockets[i].lastdata.pbuf = NULL;
564#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
565 LWIP_ASSERT(
"sockets[i].select_waiting == 0", sockets[i].select_waiting == 0);
566 sockets[i].rcvevent = 0;
569 sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
570 sockets[i].errevent = 0;
572 return i + LWIP_SOCKET_OFFSET;
574 SYS_ARCH_UNPROTECT(lev);
587free_socket_locked(
struct lwip_sock *sock,
int is_tcp,
struct netconn **conn,
588 union lwip_sock_lastdata *lastdata)
590#if LWIP_NETCONN_FULLDUPLEX
591 LWIP_ASSERT(
"sock->fd_used > 0", sock->fd_used > 0);
593 if (sock->fd_used > 0) {
594 sock->fd_free_pending = LWIP_SOCK_FD_FREE_FREE | (is_tcp ? LWIP_SOCK_FD_FREE_TCP : 0);
601 *lastdata = sock->lastdata;
602 sock->lastdata.pbuf = NULL;
611free_socket_free_elements(
int is_tcp,
struct netconn *conn,
union lwip_sock_lastdata *lastdata)
613 if (lastdata->pbuf != NULL) {
617 netbuf_delete(lastdata->netbuf);
622 netconn_delete(conn);
633free_socket(
struct lwip_sock *sock,
int is_tcp)
636 struct netconn *conn;
637 union lwip_sock_lastdata lastdata;
641 SYS_ARCH_PROTECT(lev);
643 freed = free_socket_locked(sock, is_tcp, &conn, &lastdata);
644 SYS_ARCH_UNPROTECT(lev);
648 free_socket_free_elements(is_tcp, conn, &lastdata);
659lwip_accept(
int s,
struct sockaddr *addr, socklen_t *addrlen)
661 struct lwip_sock *sock, *nsock;
662 struct netconn *newconn;
663 ip_addr_t naddr = {0};
671 sock = get_socket(s);
677 err = netconn_accept(sock->conn, &newconn);
679 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
680 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
685 set_errno(err_to_errno(err));
690 LWIP_ASSERT(
"newconn != NULL", newconn != NULL);
692 newsock = alloc_socket(newconn, 1);
694 netconn_delete(newconn);
699 LWIP_ASSERT(
"invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET));
700 nsock = &sockets[newsock - LWIP_SOCKET_OFFSET];
705 if ((addr != NULL) && (addrlen != NULL)) {
706 union sockaddr_aligned tempaddr;
708 err = netconn_peer(newconn, &naddr, &port);
710 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
711 free_socket(nsock, 1);
712 set_errno(err_to_errno(err));
717 IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port);
718 if (*addrlen > IPADDR_SOCKADDR_GET_LEN(&tempaddr)) {
719 *addrlen = IPADDR_SOCKADDR_GET_LEN(&tempaddr);
721 MEMCPY(addr, &tempaddr, *addrlen);
729 SYS_ARCH_PROTECT(lev);
730 recvevent = (s16_t)(-1 - newconn->callback_arg.socket);
731 newconn->callback_arg.socket = newsock;
732 SYS_ARCH_UNPROTECT(lev);
734 if (newconn->callback) {
736 while (recvevent > 0) {
738 newconn->callback(newconn, NETCONN_EVT_RCVPLUS, 0);
743 if ((addr != NULL) && (addrlen != NULL)) {
744 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_accept(%d) returning new sock=%d addr=", s, newsock));
748 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_accept(%d) returning new sock=%d\n", s, newsock));
758lwip_bind(
int s,
const struct sockaddr *name, socklen_t namelen)
760 struct lwip_sock *sock;
761 ip_addr_t local_addr;
765 sock = get_socket(s);
770 if (!SOCK_ADDR_TYPE_MATCH(name, sock)) {
772 set_errno(err_to_errno(
ERR_VAL));
778 LWIP_ERROR(
"lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) &&
779 IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)),
780 set_errno(err_to_errno(
ERR_ARG)); done_socket(sock);
return -1;);
783 SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port);
786 LWIP_DEBUGF(
SOCKETS_DEBUG, (
" port=%"U16_F
")\n", local_port));
788#if LWIP_IPV4 && LWIP_IPV6
790 if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) {
791 unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
796 err = netconn_bind(sock->conn, &local_addr, local_port);
799 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_bind(%d) failed, err=%d\n", s, err));
800 set_errno(err_to_errno(err));
805 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_bind(%d) succeeded\n", s));
814 struct lwip_sock *sock;
820 sock = get_socket(s);
825 if (sock->conn != NULL) {
826 is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
828 LWIP_ASSERT(
"sock->lastdata == NULL", sock->lastdata.pbuf == NULL);
833 lwip_socket_drop_registered_memberships(s);
837 lwip_socket_drop_registered_mld6_memberships(s);
840 err = netconn_prepare_delete(sock->conn);
842 set_errno(err_to_errno(err));
847 free_socket(sock, is_tcp);
853lwip_connect(
int s,
const struct sockaddr *name, socklen_t namelen)
855 struct lwip_sock *sock;
858 sock = get_socket(s);
863 if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) {
865 set_errno(err_to_errno(
ERR_VAL));
871 if (name->sa_family == AF_UNSPEC) {
872 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_connect(%d, AF_UNSPEC)\n", s));
873 err = netconn_disconnect(sock->conn);
875 ip_addr_t remote_addr;
879 LWIP_ERROR(
"lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) &&
880 IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name),
881 set_errno(err_to_errno(
ERR_ARG)); done_socket(sock);
return -1;);
883 SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port);
886 LWIP_DEBUGF(
SOCKETS_DEBUG, (
" port=%"U16_F
")\n", remote_port));
888#if LWIP_IPV4 && LWIP_IPV6
890 if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) {
891 unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
896 err = netconn_connect(sock->conn, &remote_addr, remote_port);
900 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_connect(%d) failed, err=%d\n", s, err));
901 set_errno(err_to_errno(err));
906 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_connect(%d) succeeded\n", s));
921lwip_listen(
int s,
int backlog)
923 struct lwip_sock *sock;
926 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_listen(%d, backlog=%d)\n", s, backlog));
928 sock = get_socket(s);
934 backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
936 err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
939 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_listen(%d) failed, err=%d\n", s, err));
940 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
943 set_errno(err_to_errno(err));
960lwip_recv_tcp(
struct lwip_sock *sock,
void *
mem,
size_t len,
int flags)
962 u8_t apiflags = NETCONN_NOAUTORCVD;
964 ssize_t recv_left = (len <= SSIZE_MAX) ? (ssize_t)len : SSIZE_MAX;
966 LWIP_ASSERT(
"no socket given", sock != NULL);
967 LWIP_ASSERT(
"this should be checked internally", NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP);
969 if (flags & MSG_DONTWAIT) {
970 apiflags |= NETCONN_DONTBLOCK;
978 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recv_tcp: top while sock->lastdata=%p\n", (
void *)sock->lastdata.pbuf));
980 if (sock->lastdata.pbuf) {
981 p = sock->lastdata.pbuf;
985 err = netconn_recv_tcp_pbuf_flags(sock->conn, &p, apiflags);
986 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recv_tcp: netconn_recv err=%d, pbuf=%p\n",
993 goto lwip_recv_tcp_done;
996 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recv_tcp: p == NULL, error is \"%s\"!\n",
998 set_errno(err_to_errno(err));
1005 LWIP_ASSERT(
"p != NULL", p != NULL);
1006 sock->lastdata.pbuf = p;
1009 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recv_tcp: buflen=%"U16_F
" recv_left=%d off=%d\n",
1010 p->tot_len, (
int)recv_left, (
int)recvd));
1012 if (recv_left > p->tot_len) {
1013 copylen = p->tot_len;
1015 copylen = (u16_t)recv_left;
1017 if (recvd > SSIZE_MAX - copylen) {
1019 copylen = (u16_t)(SSIZE_MAX - recvd);
1029 LWIP_ASSERT(
"invalid copylen, len would underflow", recv_left >= copylen);
1030 recv_left -= copylen;
1033 if ((flags & MSG_PEEK) == 0) {
1035 LWIP_ASSERT(
"invalid copylen", p->tot_len >= copylen);
1036 if (p->tot_len - copylen > 0) {
1040 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recv_tcp: lastdata now pbuf=%p\n", (
void *)sock->lastdata.pbuf));
1042 sock->lastdata.pbuf = NULL;
1043 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recv_tcp: deleting pbuf=%p\n", (
void *)p));
1048 apiflags |= NETCONN_DONTBLOCK | NETCONN_NOFIN;
1050 }
while ((recv_left > 0) && !(flags & MSG_PEEK));
1052 if ((recvd > 0) && !(flags & MSG_PEEK)) {
1054 netconn_tcp_recvd(sock->conn, (
size_t)recvd);
1063lwip_sock_make_addr(
struct netconn *conn, ip_addr_t *fromaddr, u16_t port,
1064 struct sockaddr *from, socklen_t *fromlen)
1067 union sockaddr_aligned saddr;
1071 LWIP_ASSERT(
"fromaddr != NULL", fromaddr != NULL);
1072 LWIP_ASSERT(
"from != NULL", from != NULL);
1073 LWIP_ASSERT(
"fromlen != NULL", fromlen != NULL);
1075#if LWIP_IPV4 && LWIP_IPV6
1077 if (NETCONNTYPE_ISIPV6(netconn_type(conn)) && IP_IS_V4(fromaddr)) {
1078 ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
1083 IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
1084 if (*fromlen < IPADDR_SOCKADDR_GET_LEN(&saddr)) {
1086 }
else if (*fromlen > IPADDR_SOCKADDR_GET_LEN(&saddr)) {
1087 *fromlen = IPADDR_SOCKADDR_GET_LEN(&saddr);
1089 MEMCPY(from, &saddr, *fromlen);
1096lwip_recv_tcp_from(
struct lwip_sock *sock,
struct sockaddr *from, socklen_t *fromlen,
const char *dbg_fn,
int dbg_s, ssize_t dbg_ret)
1106 if (from && fromlen)
1112 netconn_getaddr(sock->conn, &tmpaddr, &port, 0);
1113 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"%s(%d): addr=", dbg_fn, dbg_s));
1115 LWIP_DEBUGF(
SOCKETS_DEBUG, (
" port=%"U16_F
" len=%d\n", port, (
int)dbg_ret));
1116 if (from && fromlen) {
1117 return lwip_sock_make_addr(sock->conn, &tmpaddr, port, from, fromlen);
1128lwip_recvfrom_udp_raw(
struct lwip_sock *sock,
int flags,
struct msghdr *msg, u16_t *datagram_len,
int dbg_s)
1133 u16_t buflen, copylen, copied;
1137 LWIP_ERROR(
"lwip_recvfrom_udp_raw: invalid arguments", (msg->msg_iov != NULL) || (msg->msg_iovlen <= 0),
return ERR_ARG;);
1139 if (flags & MSG_DONTWAIT) {
1140 apiflags = NETCONN_DONTBLOCK;
1145 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvfrom_udp_raw[UDP/RAW]: top sock->lastdata=%p\n", (
void *)sock->lastdata.netbuf));
1147 buf = sock->lastdata.netbuf;
1151 err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &buf, apiflags);
1152 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvfrom_udp_raw[UDP/RAW]: netconn_recv err=%d, netbuf=%p\n",
1158 LWIP_ASSERT(
"buf != NULL", buf != NULL);
1159 sock->lastdata.netbuf = buf;
1161 buflen = buf->p->tot_len;
1162 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvfrom_udp_raw: buflen=%"U16_F
"\n", buflen));
1166 for (i = 0; (i < msg->msg_iovlen) && (copied < buflen); i++) {
1167 u16_t len_left = (u16_t)(buflen - copied);
1168 if (msg->msg_iov[i].iov_len > len_left) {
1171 copylen = (u16_t)msg->msg_iov[i].iov_len;
1177 copied = (u16_t)(copied + copylen);
1182 if (msg->msg_name && msg->msg_namelen)
1185 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvfrom_udp_raw(%d): addr=", dbg_s));
1186 ip_addr_debug_print_val(
SOCKETS_DEBUG, *netbuf_fromaddr(buf));
1187 LWIP_DEBUGF(
SOCKETS_DEBUG, (
" port=%"U16_F
" len=%d\n", netbuf_fromport(buf), copied));
1188 if (msg->msg_name && msg->msg_namelen) {
1189 lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf),
1190 (
struct sockaddr *)msg->msg_name, &msg->msg_namelen);
1197 if (msg->msg_control) {
1199#if LWIP_NETBUF_RECVINFO
1201 if (buf->flags & NETBUF_FLAG_DESTADDR) {
1202 if (IP_IS_V4(&buf->toaddr)) {
1204 if (msg->msg_controllen >= CMSG_SPACE(
sizeof(
struct in_pktinfo))) {
1205 struct cmsghdr *chdr = CMSG_FIRSTHDR(msg);
1206 struct in_pktinfo *pkti = (
struct in_pktinfo *)CMSG_DATA(chdr);
1207 chdr->cmsg_level = IPPROTO_IP;
1208 chdr->cmsg_type = IP_PKTINFO;
1209 chdr->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
1210 pkti->ipi_ifindex = buf->p->if_idx;
1211 inet_addr_from_ip4addr(&pkti->ipi_addr, ip_2_ip4(netbuf_destaddr(buf)));
1212 msg->msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
1215 msg->msg_flags |= MSG_CTRUNC;
1223 msg->msg_controllen = 0;
1228 if ((flags & MSG_PEEK) == 0) {
1229 sock->lastdata.netbuf = NULL;
1233 *datagram_len = buflen;
1239lwip_recvfrom(
int s,
void *
mem,
size_t len,
int flags,
1240 struct sockaddr *from, socklen_t *fromlen)
1242 struct lwip_sock *sock;
1245 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvfrom(%d, %p, %"SZT_F
", 0x%x, ..)\n", s,
mem, len, flags));
1246 sock = get_socket(s);
1251 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
1252 ret = lwip_recv_tcp(sock,
mem, len, flags);
1253 lwip_recv_tcp_from(sock, from, fromlen,
"lwip_recvfrom", s, ret);
1259 u16_t datagram_len = 0;
1265 msg.msg_control = NULL;
1266 msg.msg_controllen = 0;
1270 msg.msg_name = from;
1271 msg.msg_namelen = (fromlen ? *fromlen : 0);
1272 err = lwip_recvfrom_udp_raw(sock, flags, &msg, &datagram_len, s);
1274 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvfrom[UDP/RAW](%d): buf == NULL, error is \"%s\"!\n",
1275 s, lwip_strerr(err)));
1276 set_errno(err_to_errno(err));
1280 ret = (ssize_t)LWIP_MIN(LWIP_MIN(len, datagram_len), SSIZE_MAX);
1282 *fromlen = msg.msg_namelen;
1292lwip_read(
int s,
void *
mem,
size_t len)
1294 return lwip_recvfrom(s,
mem, len, 0, NULL, NULL);
1298lwip_readv(
int s,
const struct iovec *iov,
int iovcnt)
1302 msg.msg_name = NULL;
1303 msg.msg_namelen = 0;
1307 msg.msg_iovlen = iovcnt;
1308 msg.msg_control = NULL;
1309 msg.msg_controllen = 0;
1311 return lwip_recvmsg(s, &msg, 0);
1315lwip_recv(
int s,
void *
mem,
size_t len,
int flags)
1317 return lwip_recvfrom(s,
mem, len, flags, NULL, NULL);
1321lwip_recvmsg(
int s,
struct msghdr *message,
int flags)
1323 struct lwip_sock *sock;
1327 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvmsg(%d, message=%p, flags=0x%x)\n", s, (
void *)message, flags));
1328 LWIP_ERROR(
"lwip_recvmsg: invalid message pointer", message != NULL,
return ERR_ARG;);
1329 LWIP_ERROR(
"lwip_recvmsg: unsupported flags", (flags & ~(MSG_PEEK|MSG_DONTWAIT)) == 0,
1332 if ((message->msg_iovlen <= 0) || (message->msg_iovlen > IOV_MAX)) {
1337 sock = get_socket(s);
1344 for (i = 0; i < message->msg_iovlen; i++) {
1345 if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len <= 0) ||
1346 ((
size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) ||
1347 ((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) <= 0)) {
1348 set_errno(err_to_errno(
ERR_VAL));
1352 buflen = (ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len);
1355 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
1357 int recv_flags = flags;
1358 message->msg_flags = 0;
1361 for (i = 0; i < message->msg_iovlen; i++) {
1363 ssize_t recvd_local = lwip_recv_tcp(sock, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, recv_flags);
1364 if (recvd_local > 0) {
1366 buflen += recvd_local;
1368 if ((recvd_local < 0) || (recvd_local < (
int)message->msg_iov[i].iov_len) ||
1369 (flags & MSG_PEEK)) {
1373 buflen = recvd_local;
1378 recv_flags |= MSG_DONTWAIT;
1388 set_errno(err_to_errno(
ERR_ARG));
1394#if LWIP_UDP || LWIP_RAW
1396 u16_t datagram_len = 0;
1398 err = lwip_recvfrom_udp_raw(sock, flags, message, &datagram_len, s);
1400 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_recvmsg[UDP/RAW](%d): buf == NULL, error is \"%s\"!\n",
1401 s, lwip_strerr(err)));
1402 set_errno(err_to_errno(err));
1406 if (datagram_len > buflen) {
1407 message->msg_flags |= MSG_TRUNC;
1412 return (
int)datagram_len;
1415 set_errno(err_to_errno(
ERR_ARG));
1422lwip_send(
int s,
const void *data,
size_t size,
int flags)
1424 struct lwip_sock *sock;
1429 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_send(%d, data=%p, size=%"SZT_F
", flags=0x%x)\n",
1430 s, data, size, flags));
1432 sock = get_socket(s);
1437 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
1438#if (LWIP_UDP || LWIP_RAW)
1440 return lwip_sendto(s, data, size, flags, NULL, 0);
1442 set_errno(err_to_errno(
ERR_ARG));
1448 write_flags = (u8_t)(NETCONN_COPY |
1449 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
1450 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0));
1452 err = netconn_write_partly(sock->conn, data, size, write_flags, &written);
1454 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_send(%d) err=%d written=%"SZT_F
"\n", s, err, written));
1455 set_errno(err_to_errno(err));
1458 return (err ==
ERR_OK ? (ssize_t)written : -1);
1462lwip_sendmsg(
int s,
const struct msghdr *msg,
int flags)
1464 struct lwip_sock *sock;
1471 sock = get_socket(s);
1476 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr", msg != NULL,
1477 set_errno(err_to_errno(
ERR_ARG)); done_socket(sock);
return -1;);
1478 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr iov", msg->msg_iov != NULL,
1479 set_errno(err_to_errno(
ERR_ARG)); done_socket(sock);
return -1;);
1480 LWIP_ERROR(
"lwip_sendmsg: maximum iovs exceeded", (msg->msg_iovlen > 0) && (msg->msg_iovlen <= IOV_MAX),
1481 set_errno(
EMSGSIZE); done_socket(sock);
return -1;);
1482 LWIP_ERROR(
"lwip_sendmsg: unsupported flags", (flags & ~(MSG_DONTWAIT | MSG_MORE)) == 0,
1483 set_errno(
EOPNOTSUPP); done_socket(sock);
return -1;);
1489 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
1491 write_flags = (u8_t)(NETCONN_COPY |
1492 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
1493 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0));
1496 err = netconn_write_vectors_partly(sock->conn, (
struct netvector *)msg->msg_iov, (u16_t)msg->msg_iovlen, write_flags, &written);
1497 set_errno(err_to_errno(err));
1500 return (err ==
ERR_OK ? (ssize_t)written : -1);
1502 set_errno(err_to_errno(
ERR_ARG));
1508#if LWIP_UDP || LWIP_RAW
1510 struct netbuf chain_buf;
1515 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) ||
1516 IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)),
1517 set_errno(err_to_errno(
ERR_ARG)); done_socket(sock);
return -1;);
1520 memset(&chain_buf, 0,
sizeof(
struct netbuf));
1521 if (msg->msg_name) {
1523 SOCKADDR_TO_IPADDR_PORT((
const struct sockaddr *)msg->msg_name, &chain_buf.addr, remote_port);
1524 netbuf_fromport(&chain_buf) = remote_port;
1526#if LWIP_NETIF_TX_SINGLE_PBUF
1527 for (i = 0; i < msg->msg_iovlen; i++) {
1528 size += msg->msg_iov[i].iov_len;
1529 if ((msg->msg_iov[i].iov_len > INT_MAX) || (size < (
int)msg->msg_iov[i].iov_len)) {
1531 goto sendmsg_emsgsize;
1534 if (size > 0xFFFF) {
1536 goto sendmsg_emsgsize;
1539 if (netbuf_alloc(&chain_buf, (u16_t)size) == NULL) {
1544 for (i = 0; i < msg->msg_iovlen; i++) {
1545 MEMCPY(&((u8_t *)chain_buf.p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
1546 offset += msg->msg_iov[i].iov_len;
1548#if LWIP_CHECKSUM_ON_COPY
1552 netbuf_set_chksum(&chain_buf, chksum);
1560 for (i = 0; i < msg->msg_iovlen; i++) {
1562 if (msg->msg_iov[i].iov_len > 0xFFFF) {
1564 goto sendmsg_emsgsize;
1571 p->payload = msg->msg_iov[i].iov_base;
1572 p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len;
1574 if (chain_buf.p == NULL) {
1575 chain_buf.p = chain_buf.ptr = p;
1578 if (chain_buf.p->tot_len + p->len > 0xffff) {
1581 goto sendmsg_emsgsize;
1588 size = netbuf_len(&chain_buf);
1593#if LWIP_IPV4 && LWIP_IPV6
1595 if (IP_IS_V6_VAL(chain_buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf.addr))) {
1596 unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf.addr), ip_2_ip6(&chain_buf.addr));
1602 err = netconn_send(sock->conn, &chain_buf);
1606 netbuf_free(&chain_buf);
1608 set_errno(err_to_errno(err));
1610 return (err ==
ERR_OK ? size : -1);
1613 netbuf_free(&chain_buf);
1618 set_errno(err_to_errno(
ERR_ARG));
1625lwip_sendto(
int s,
const void *data,
size_t size,
int flags,
1626 const struct sockaddr *to, socklen_t tolen)
1628 struct lwip_sock *sock;
1634 sock = get_socket(s);
1639 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
1642 return lwip_send(s, data, size, flags);
1645 set_errno(err_to_errno(
ERR_ARG));
1651 if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) {
1657 short_size = (u16_t)size;
1658 LWIP_ERROR(
"lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
1659 (IS_SOCK_ADDR_LEN_VALID(tolen) &&
1660 ((to != NULL) && (IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))))),
1661 set_errno(err_to_errno(
ERR_ARG)); done_socket(sock);
return -1;);
1665 buf.p = buf.ptr = NULL;
1666#if LWIP_CHECKSUM_ON_COPY
1670 SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port);
1673 ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr);
1675 netbuf_fromport(&buf) = remote_port;
1678 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_sendto(%d, data=%p, short_size=%"U16_F
", flags=0x%x to=",
1679 s, data, short_size, flags));
1681 LWIP_DEBUGF(
SOCKETS_DEBUG, (
" port=%"U16_F
"\n", remote_port));
1684#if LWIP_NETIF_TX_SINGLE_PBUF
1686 if (netbuf_alloc(&buf, short_size) == NULL) {
1689#if LWIP_CHECKSUM_ON_COPY
1690 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
1691 u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
1692 netbuf_set_chksum(&buf, chksum);
1696 MEMCPY(buf.p->payload, data, short_size);
1701 err = netbuf_ref(&buf, data, short_size);
1704#if LWIP_IPV4 && LWIP_IPV6
1706 if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) {
1707 unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
1713 err = netconn_send(sock->conn, &buf);
1719 set_errno(err_to_errno(err));
1721 return (err ==
ERR_OK ? short_size : -1);
1725lwip_socket(
int domain,
int type,
int protocol)
1727 struct netconn *conn;
1735 conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW),
1736 (u8_t)protocol, DEFAULT_SOCKET_EVENTCB);
1737 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_socket(%s, SOCK_RAW, %d) = ",
1738 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1741 conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain,
1742 ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)),
1743 DEFAULT_SOCKET_EVENTCB);
1744 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_socket(%s, SOCK_DGRAM, %d) = ",
1745 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1746#if LWIP_NETBUF_RECVINFO
1749 conn->flags &= ~NETCONN_FLAG_PKTINFO;
1754 conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), DEFAULT_SOCKET_EVENTCB);
1755 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_socket(%s, SOCK_STREAM, %d) = ",
1756 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1759 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
1760 domain, type, protocol));
1766 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"-1 / ENOBUFS (could not create netconn)\n"));
1771 i = alloc_socket(conn, 0);
1774 netconn_delete(conn);
1778 conn->callback_arg.socket = i;
1779 done_socket(&sockets[i - LWIP_SOCKET_OFFSET]);
1786lwip_write(
int s,
const void *data,
size_t size)
1788 return lwip_send(s, data, size, 0);
1792lwip_writev(
int s,
const struct iovec *iov,
int iovcnt)
1796 msg.msg_name = NULL;
1797 msg.msg_namelen = 0;
1801 msg.msg_iovlen = iovcnt;
1802 msg.msg_control = NULL;
1803 msg.msg_controllen = 0;
1805 return lwip_sendmsg(s, &msg, 0);
1808#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
1811lwip_link_select_cb(
struct lwip_select_cb *select_cb)
1813 LWIP_SOCKET_SELECT_DECL_PROTECT(lev);
1816 LWIP_SOCKET_SELECT_PROTECT(lev);
1819 select_cb->next = select_cb_list;
1820 if (select_cb_list != NULL) {
1821 select_cb_list->prev = select_cb;
1823 select_cb_list = select_cb;
1824#if !LWIP_TCPIP_CORE_LOCKING
1830 LWIP_SOCKET_SELECT_UNPROTECT(lev);
1835lwip_unlink_select_cb(
struct lwip_select_cb *select_cb)
1837 LWIP_SOCKET_SELECT_DECL_PROTECT(lev);
1840 LWIP_SOCKET_SELECT_PROTECT(lev);
1841 if (select_cb->next != NULL) {
1842 select_cb->next->prev = select_cb->prev;
1844 if (select_cb_list == select_cb) {
1845 LWIP_ASSERT(
"select_cb->prev == NULL", select_cb->prev == NULL);
1846 select_cb_list = select_cb->next;
1848 LWIP_ASSERT(
"select_cb->prev != NULL", select_cb->prev != NULL);
1849 select_cb->prev->next = select_cb->next;
1851#if !LWIP_TCPIP_CORE_LOCKING
1855 LWIP_SOCKET_SELECT_UNPROTECT(lev);
1859#if LWIP_SOCKET_SELECT
1875lwip_selscan(
int maxfdp1,
fd_set *readset_in,
fd_set *writeset_in,
fd_set *exceptset_in,
1879 fd_set lreadset, lwriteset, lexceptset;
1880 struct lwip_sock *sock;
1884 FD_ZERO(&lwriteset);
1885 FD_ZERO(&lexceptset);
1889 for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
1891 if (!(readset_in && FD_ISSET(i, readset_in)) &&
1892 !(writeset_in && FD_ISSET(i, writeset_in)) &&
1893 !(exceptset_in && FD_ISSET(i, exceptset_in))) {
1897 SYS_ARCH_PROTECT(lev);
1898 sock = tryget_socket_unconn_locked(i);
1900 void *lastdata = sock->lastdata.pbuf;
1901 s16_t rcvevent = sock->rcvevent;
1902 u16_t sendevent = sock->sendevent;
1903 u16_t errevent = sock->errevent;
1904 SYS_ARCH_UNPROTECT(lev);
1908 if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
1909 FD_SET(i, &lreadset);
1910 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_selscan: fd=%d ready for reading\n", i));
1914 if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
1915 FD_SET(i, &lwriteset);
1916 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_selscan: fd=%d ready for writing\n", i));
1920 if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
1921 FD_SET(i, &lexceptset);
1922 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_selscan: fd=%d ready for exception\n", i));
1927 SYS_ARCH_UNPROTECT(lev);
1933 *readset_out = lreadset;
1934 *writeset_out = lwriteset;
1935 *exceptset_out = lexceptset;
1937 LWIP_ASSERT(
"nready >= 0", nready >= 0);
1941#if LWIP_NETCONN_FULLDUPLEX
1947lwip_select_inc_sockets_used_set(
int maxfdp,
fd_set *fdset,
fd_set *used_sockets)
1952 for (i = LWIP_SOCKET_OFFSET; i < maxfdp; i++) {
1954 if (FD_ISSET(i, fdset) && !FD_ISSET(i, used_sockets)) {
1955 struct lwip_sock *sock;
1956 SYS_ARCH_PROTECT(lev);
1957 sock = tryget_socket_unconn_locked(i);
1960 FD_SET(i, used_sockets);
1962 SYS_ARCH_UNPROTECT(lev);
1976 FD_ZERO(used_sockets);
1977 lwip_select_inc_sockets_used_set(maxfdp, fdset1, used_sockets);
1978 lwip_select_inc_sockets_used_set(maxfdp, fdset2, used_sockets);
1979 lwip_select_inc_sockets_used_set(maxfdp, fdset3, used_sockets);
1984lwip_select_dec_sockets_used(
int maxfdp,
fd_set *used_sockets)
1987 for (i = LWIP_SOCKET_OFFSET; i < maxfdp; i++) {
1989 if (FD_ISSET(i, used_sockets)) {
1990 struct lwip_sock *sock = tryget_socket_unconn_nouse(i);
1991 LWIP_ASSERT(
"socket gone at the end of select", sock != NULL);
1999#define lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, used_sockets)
2000#define lwip_select_dec_sockets_used(maxfdp1, used_sockets)
2009 fd_set lreadset, lwriteset, lexceptset;
2013#if LWIP_NETCONN_SEM_PER_THREAD
2016#if LWIP_NETCONN_FULLDUPLEX
2021 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_select(%d, %p, %p, %p, tvsec=%"S32_F
" tvusec=%"S32_F
")\n",
2022 maxfdp1, (
void *)readset, (
void *) writeset, (
void *) exceptset,
2023 timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1,
2024 timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1));
2026 if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) {
2031 lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets);
2035 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
2040 lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
2042 }
else if (nready > 0) {
2044 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_select: nready=%d\n", nready));
2047 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
2048 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_select: no timeout, returning 0\n"));
2057 API_SELECT_CB_VAR_DECLARE(select_cb);
2058 API_SELECT_CB_VAR_ALLOC(select_cb, set_errno(
ENOMEM); lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
return -1);
2059 memset(&API_SELECT_CB_VAR_REF(select_cb), 0,
sizeof(
struct lwip_select_cb));
2061 API_SELECT_CB_VAR_REF(select_cb).readset = readset;
2062 API_SELECT_CB_VAR_REF(select_cb).writeset = writeset;
2063 API_SELECT_CB_VAR_REF(select_cb).exceptset = exceptset;
2064#if LWIP_NETCONN_SEM_PER_THREAD
2065 API_SELECT_CB_VAR_REF(select_cb).sem = LWIP_NETCONN_THREAD_SEM_GET();
2070 lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
2071 API_SELECT_CB_VAR_FREE(select_cb);
2076 lwip_link_select_cb(&API_SELECT_CB_VAR_REF(select_cb));
2080 for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) {
2081 if ((readset && FD_ISSET(i, readset)) ||
2082 (writeset && FD_ISSET(i, writeset)) ||
2083 (exceptset && FD_ISSET(i, exceptset))) {
2084 struct lwip_sock *sock;
2085 SYS_ARCH_PROTECT(lev);
2086 sock = tryget_socket_unconn_locked(i);
2088 sock->select_waiting++;
2089 if (sock->select_waiting == 0) {
2091 sock->select_waiting--;
2094 SYS_ARCH_UNPROTECT(lev);
2099 SYS_ARCH_UNPROTECT(lev);
2105 SYS_ARCH_UNPROTECT(lev);
2115 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
2118 }
else if (!nready) {
2120 if (timeout == NULL) {
2124 long msecs_long = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500) / 1000));
2125 if (msecs_long <= 0) {
2129 msectimeout = (u32_t)msecs_long;
2133 waitres =
sys_arch_sem_wait(SELECT_SEM_PTR(API_SELECT_CB_VAR_REF(select_cb).sem), msectimeout);
2134#if LWIP_NETCONN_SEM_PER_THREAD
2141 for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) {
2142 if ((readset && FD_ISSET(i, readset)) ||
2143 (writeset && FD_ISSET(i, writeset)) ||
2144 (exceptset && FD_ISSET(i, exceptset))) {
2145 struct lwip_sock *sock;
2146 SYS_ARCH_PROTECT(lev);
2147 sock = tryget_socket_unconn_nouse(i);
2148 LWIP_ASSERT(
"socket gone at the end of select", sock != NULL);
2151 LWIP_ASSERT(
"sock->select_waiting > 0", sock->select_waiting > 0);
2152 if (sock->select_waiting > 0) {
2153 sock->select_waiting--;
2155 SYS_ARCH_UNPROTECT(lev);
2157 SYS_ARCH_UNPROTECT(lev);
2165 lwip_unlink_select_cb(&API_SELECT_CB_VAR_REF(select_cb));
2167#if LWIP_NETCONN_SEM_PER_THREAD
2168 if (API_SELECT_CB_VAR_REF(select_cb).sem_signalled && (!waited || (waitres ==
SYS_ARCH_TIMEOUT))) {
2175 API_SELECT_CB_VAR_FREE(select_cb);
2179 lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
2185 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_select: timeout expired\n"));
2190 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
2191 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_select: nready=%d\n", nready));
2194 lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
2201 lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
2204 *readset = lreadset;
2207 *writeset = lwriteset;
2210 *exceptset = lexceptset;
2218enum lwip_pollscan_opts
2221 LWIP_POLLSCAN_CLEAR = 1,
2224 LWIP_POLLSCAN_INC_WAIT = 2,
2227 LWIP_POLLSCAN_DEC_WAIT = 4
2240lwip_pollscan(
struct pollfd *fds, nfds_t nfds,
enum lwip_pollscan_opts opts)
2244 struct lwip_sock *sock;
2248 for (fdi = 0; fdi < nfds; fdi++) {
2249 if ((opts & LWIP_POLLSCAN_CLEAR) != 0) {
2250 fds[fdi].revents = 0;
2257 if (fds[fdi].fd >= 0 && (fds[fdi].revents & POLLNVAL) == 0) {
2259 SYS_ARCH_PROTECT(lev);
2260 sock = tryget_socket_unconn_locked(fds[fdi].fd);
2262 void* lastdata = sock->lastdata.pbuf;
2263 s16_t rcvevent = sock->rcvevent;
2264 u16_t sendevent = sock->sendevent;
2265 u16_t errevent = sock->errevent;
2267 if ((opts & LWIP_POLLSCAN_INC_WAIT) != 0) {
2268 sock->select_waiting++;
2269 if (sock->select_waiting == 0) {
2271 sock->select_waiting--;
2273 SYS_ARCH_UNPROTECT(lev);
2277 }
else if ((opts & LWIP_POLLSCAN_DEC_WAIT) != 0) {
2279 LWIP_ASSERT(
"sock->select_waiting > 0", sock->select_waiting > 0);
2280 if (sock->select_waiting > 0) {
2281 sock->select_waiting--;
2284 SYS_ARCH_UNPROTECT(lev);
2289 if ((fds[fdi].events & POLLIN) != 0 && ((lastdata != NULL) || (rcvevent > 0))) {
2290 fds[fdi].revents |= POLLIN;
2291 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_pollscan: fd=%d ready for reading\n", fds[fdi].fd));
2294 if ((fds[fdi].events & POLLOUT) != 0 && (sendevent != 0)) {
2295 fds[fdi].revents |= POLLOUT;
2296 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_pollscan: fd=%d ready for writing\n", fds[fdi].fd));
2299 if (errevent != 0) {
2301 fds[fdi].revents |= POLLERR;
2302 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_pollscan: fd=%d ready for exception\n", fds[fdi].fd));
2306 SYS_ARCH_UNPROTECT(lev);
2308 fds[fdi].revents |= POLLNVAL;
2315 if (fds[fdi].revents != 0) {
2320 LWIP_ASSERT(
"nready >= 0", nready >= 0);
2324#if LWIP_NETCONN_FULLDUPLEX
2331lwip_poll_inc_sockets_used(
struct pollfd *fds, nfds_t nfds)
2337 for (fdi = 0; fdi < nfds; fdi++) {
2339 tryget_socket_unconn(fds[fdi].fd);
2346lwip_poll_dec_sockets_used(
struct pollfd *fds, nfds_t nfds)
2352 for (fdi = 0; fdi < nfds; fdi++) {
2353 struct lwip_sock *sock = tryget_socket_unconn_nouse(fds[fdi].fd);
2361#define lwip_poll_inc_sockets_used(fds, nfds)
2362#define lwip_poll_dec_sockets_used(fds, nfds)
2366lwip_poll(
struct pollfd *fds, nfds_t nfds,
int timeout)
2371#if LWIP_NETCONN_SEM_PER_THREAD
2376 (
void*)fds, (
int)nfds, timeout));
2377 LWIP_ERROR(
"lwip_poll: invalid fds", ((fds != NULL && nfds > 0) || (fds == NULL && nfds == 0)),
2378 set_errno(
EINVAL);
return -1;);
2380 lwip_poll_inc_sockets_used(fds, nfds);
2384 nready = lwip_pollscan(fds, nfds, LWIP_POLLSCAN_CLEAR);
2387 lwip_poll_dec_sockets_used(fds, nfds);
2393 API_SELECT_CB_VAR_DECLARE(select_cb);
2396 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_poll: no timeout, returning 0\n"));
2397 goto return_success;
2399 API_SELECT_CB_VAR_ALLOC(select_cb, set_errno(
EAGAIN); lwip_poll_dec_sockets_used(fds, nfds);
return -1);
2400 memset(&API_SELECT_CB_VAR_REF(select_cb), 0,
sizeof(
struct lwip_select_cb));
2407 API_SELECT_CB_VAR_REF(select_cb).poll_fds = fds;
2408 API_SELECT_CB_VAR_REF(select_cb).poll_nfds = nfds;
2409#if LWIP_NETCONN_SEM_PER_THREAD
2410 API_SELECT_CB_VAR_REF(select_cb).sem = LWIP_NETCONN_THREAD_SEM_GET();
2415 lwip_poll_dec_sockets_used(fds, nfds);
2416 API_SELECT_CB_VAR_FREE(select_cb);
2421 lwip_link_select_cb(&API_SELECT_CB_VAR_REF(select_cb));
2426 nready = lwip_pollscan(fds, nfds, LWIP_POLLSCAN_INC_WAIT);
2435 LWIP_ASSERT(
"timeout > 0", timeout > 0);
2436 msectimeout = timeout;
2438 waitres =
sys_arch_sem_wait(SELECT_SEM_PTR(API_SELECT_CB_VAR_REF(select_cb).sem), msectimeout);
2439#if LWIP_NETCONN_SEM_PER_THREAD
2446 nready = lwip_pollscan(fds, nfds, LWIP_POLLSCAN_DEC_WAIT);
2448 lwip_unlink_select_cb(&API_SELECT_CB_VAR_REF(select_cb));
2450#if LWIP_NETCONN_SEM_PER_THREAD
2451 if (select_cb.sem_signalled && (!waited || (waitres ==
SYS_ARCH_TIMEOUT))) {
2458 API_SELECT_CB_VAR_FREE(select_cb);
2462 lwip_poll_dec_sockets_used(fds, nfds);
2468 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_poll: timeout expired\n"));
2469 goto return_success;
2473 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_poll: nready=%d\n", nready));
2475 lwip_poll_dec_sockets_used(fds, nfds);
2485lwip_poll_should_wake(
const struct lwip_select_cb *scb,
int fd,
int has_recvevent,
int has_sendevent,
int has_errevent)
2488 for (fdi = 0; fdi < scb->poll_nfds; fdi++) {
2489 const struct pollfd *pollfd = &scb->poll_fds[fdi];
2490 if (pollfd->fd == fd) {
2494 if (has_recvevent && (pollfd->events & POLLIN) != 0) {
2497 if (has_sendevent && (pollfd->events & POLLOUT) != 0) {
2510#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
2524event_callback(
struct netconn *conn,
enum netconn_evt evt, u16_t len)
2526 int s, check_waiters;
2527 struct lwip_sock *sock;
2534 s = conn->callback_arg.socket;
2541 SYS_ARCH_PROTECT(lev);
2542 if (conn->callback_arg.socket < 0) {
2543 if (evt == NETCONN_EVT_RCVPLUS) {
2546 conn->callback_arg.socket--;
2548 SYS_ARCH_UNPROTECT(lev);
2551 s = conn->callback_arg.socket;
2552 SYS_ARCH_UNPROTECT(lev);
2555 sock = get_socket(s);
2564 SYS_ARCH_PROTECT(lev);
2567 case NETCONN_EVT_RCVPLUS:
2569 if (sock->rcvevent > 1) {
2573 case NETCONN_EVT_RCVMINUS:
2577 case NETCONN_EVT_SENDPLUS:
2578 if (sock->sendevent) {
2581 sock->sendevent = 1;
2583 case NETCONN_EVT_SENDMINUS:
2584 sock->sendevent = 0;
2587 case NETCONN_EVT_ERROR:
2591 LWIP_ASSERT(
"unknown event", 0);
2595 if (sock->select_waiting && check_waiters) {
2597 int has_recvevent, has_sendevent, has_errevent;
2598 has_recvevent = sock->rcvevent > 0;
2599 has_sendevent = sock->sendevent != 0;
2600 has_errevent = sock->errevent != 0;
2601 SYS_ARCH_UNPROTECT(lev);
2603 select_check_waiters(s, has_recvevent, has_sendevent, has_errevent);
2605 SYS_ARCH_UNPROTECT(lev);
2623static void select_check_waiters(
int s,
int has_recvevent,
int has_sendevent,
int has_errevent)
2625 struct lwip_select_cb *scb;
2626#if !LWIP_TCPIP_CORE_LOCKING
2627 int last_select_cb_ctr;
2633#if !LWIP_TCPIP_CORE_LOCKING
2634 SYS_ARCH_PROTECT(lev);
2637 last_select_cb_ctr = select_cb_ctr;
2639 for (scb = select_cb_list; scb != NULL; scb = scb->next) {
2640 if (scb->sem_signalled == 0) {
2644 if (scb->poll_fds != NULL) {
2645 do_signal = lwip_poll_should_wake(scb, s, has_recvevent, has_sendevent, has_errevent);
2648#if LWIP_SOCKET_SELECT && LWIP_SOCKET_POLL
2651#if LWIP_SOCKET_SELECT
2654 if (has_recvevent) {
2655 if (scb->readset && FD_ISSET(s, scb->readset)) {
2659 if (has_sendevent) {
2660 if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
2665 if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
2672 scb->sem_signalled = 1;
2679#if LWIP_TCPIP_CORE_LOCKING
2683 SYS_ARCH_UNPROTECT(lev);
2685 SYS_ARCH_PROTECT(lev);
2686 if (last_select_cb_ctr != select_cb_ctr) {
2691 last_select_cb_ctr = select_cb_ctr;
2693 SYS_ARCH_UNPROTECT(lev);
2702lwip_shutdown(
int s,
int how)
2704 struct lwip_sock *sock;
2706 u8_t shut_rx = 0, shut_tx = 0;
2708 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_shutdown(%d, how=%d)\n", s, how));
2710 sock = get_socket(s);
2715 if (sock->conn != NULL) {
2716 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
2727 if (how == SHUT_RD) {
2729 }
else if (how == SHUT_WR) {
2731 }
else if (how == SHUT_RDWR) {
2739 err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
2741 set_errno(err_to_errno(err));
2743 return (err ==
ERR_OK ? 0 : -1);
2747lwip_getaddrname(
int s,
struct sockaddr *name, socklen_t *namelen, u8_t local)
2749 struct lwip_sock *sock;
2750 union sockaddr_aligned saddr;
2755 sock = get_socket(s);
2761 err = netconn_getaddr(sock->conn, &naddr, &port, local);
2763 set_errno(err_to_errno(err));
2768#if LWIP_IPV4 && LWIP_IPV6
2770 if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
2771 IP_IS_V4_VAL(naddr)) {
2772 ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr));
2777 IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
2779 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getaddrname(%d, addr=", s));
2783 if (*namelen > IPADDR_SOCKADDR_GET_LEN(&saddr)) {
2784 *namelen = IPADDR_SOCKADDR_GET_LEN(&saddr);
2786 MEMCPY(name, &saddr, *namelen);
2794lwip_getpeername(
int s,
struct sockaddr *name, socklen_t *namelen)
2796 return lwip_getaddrname(s, name, namelen, 0);
2800lwip_getsockname(
int s,
struct sockaddr *name, socklen_t *namelen)
2802 return lwip_getaddrname(s, name, namelen, 1);
2806lwip_getsockopt(
int s,
int level,
int optname,
void *optval, socklen_t *optlen)
2809 struct lwip_sock *sock = get_socket(s);
2810#if !LWIP_TCPIP_CORE_LOCKING
2812 LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
2819 if ((NULL == optval) || (NULL == optlen)) {
2825#if LWIP_TCPIP_CORE_LOCKING
2828 err = lwip_getsockopt_impl(s, level, optname, optval, optlen);
2829 UNLOCK_TCPIP_CORE();
2833#if LWIP_MPU_COMPATIBLE
2835 if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
2842 LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
2843 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
2844 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
2845 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
2846 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen;
2847#if !LWIP_MPU_COMPATIBLE
2848 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval;
2850 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
2851#if LWIP_NETCONN_SEM_PER_THREAD
2852 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
2854 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
2856 cberr =
tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
2858 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
2859 set_errno(err_to_errno(cberr));
2863 sys_arch_sem_wait((sys_sem_t *)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
2866 *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen;
2867#if LWIP_MPU_COMPATIBLE
2868 MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
2869 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen);
2873 err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
2874 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
2879 return err ? -1 : 0;
2882#if !LWIP_TCPIP_CORE_LOCKING
2887lwip_getsockopt_callback(
void *arg)
2889 struct lwip_setgetsockopt_data *data;
2890 LWIP_ASSERT(
"arg != NULL", arg != NULL);
2891 data = (
struct lwip_setgetsockopt_data *)arg;
2893 data->err = lwip_getsockopt_impl(data->s, data->level, data->optname,
2906lwip_sockopt_to_ipopt(
int optname)
2914 return SOF_BROADCAST;
2916 return SOF_KEEPALIVE;
2918 return SOF_REUSEADDR;
2920 LWIP_ASSERT(
"Unknown socket option", 0);
2925#if LWIP_IPV6 && LWIP_RAW
2927lwip_getsockopt_impl_ipv6_checksum(
int s,
struct lwip_sock* sock,
void* optval)
2929 if (sock->conn->pcb.raw->chksum_reqd == 0) {
2933 *(
int*)optval = sock->conn->pcb.raw->chksum_offset;
2935 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n",
2936 s, (*(
int*)optval)));
2940lwip_setsockopt_impl_ipv6_checksum(
int s,
struct lwip_sock* sock,
const void* optval, socklen_t optlen)
2944 if (sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) {
2949 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_RAW);
2950 if (*(
const int*)optval < 0) {
2951 sock->conn->pcb.raw->chksum_reqd = 0;
2953 else if (*(
const int*)optval & 1) {
2959 sock->conn->pcb.raw->chksum_reqd = 1;
2960 sock->conn->pcb.raw->chksum_offset = (u16_t) * (
const int*)optval;
2962 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n",
2963 s, sock->conn->pcb.raw->chksum_reqd));
2972lwip_getsockopt_impl(
int s,
int level,
int optname,
void *optval, socklen_t *optlen)
2975 struct lwip_sock *sock = tryget_socket(s);
2980#ifdef LWIP_HOOK_SOCKETS_GETSOCKOPT
2981 if (LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, &err)) {
2995 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
2996 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) {
3000 if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) {
3014 if ((optname == SO_BROADCAST) &&
3015 (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) {
3020 optname = lwip_sockopt_to_ipopt(optname);
3022 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
3023 *(
int *)optval =
ip_get_option(sock->conn->pcb.ip, optname);
3024 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
3025 s, optname, (*(
int *)optval ?
"on" :
"off")));
3029 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
3030 switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
3032 *(
int *)optval = SOCK_RAW;
3035 *(
int *)optval = SOCK_STREAM;
3038 *(
int *)optval = SOCK_DGRAM;
3041 *(
int *)optval = netconn_type(sock->conn);
3043 (
"lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
3044 s, *(
int *)optval));
3046 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
3047 s, *(
int *)optval));
3051 LWIP_SOCKOPT_CHECK_OPTLEN(sock, *optlen,
int);
3052 *(
int *)optval = err_to_errno(netconn_err(sock->conn));
3053 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
3054 s, *(
int *)optval));
3059 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
3060 LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn));
3065 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
3066 LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn));
3071 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
3072 *(
int *)optval = netconn_get_recvbufsize(sock->conn);
3079 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
struct linger);
3080 conn_linger = sock->conn->linger;
3081 if (conn_linger >= 0) {
3083 linger->l_linger = (int)conn_linger;
3093 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_UDP);
3095 if (udp_is_flag_set(sock->conn->pcb.udp, UDP_FLAGS_UDPLITE)) {
3101 *(
int *)optval = udp_is_flag_set(sock->conn->pcb.udp, UDP_FLAGS_NOCHKSUM) ? 1 : 0;
3105 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
3116 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
3117 *(
int *)optval = sock->conn->pcb.ip->ttl;
3118 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
3119 s, *(
int *)optval));
3122 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
3123 *(
int *)optval = sock->conn->pcb.ip->tos;
3124 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
3125 s, *(
int *)optval));
3127#if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS && LWIP_UDP
3128 case IP_MULTICAST_TTL:
3129 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
3130 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
3134 *(u8_t *)optval = udp_get_multicast_ttl(sock->conn->pcb.udp);
3135 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
3136 s, *(
int *)optval));
3138 case IP_MULTICAST_IF:
3139 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
struct in_addr);
3140 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
3144 inet_addr_from_ip4addr((
struct in_addr *)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
3145 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F
"\n",
3146 s, *(u32_t *)optval));
3148 case IP_MULTICAST_LOOP:
3149 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
3150 if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
3151 *(u8_t *)optval = 1;
3153 *(u8_t *)optval = 0;
3155 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
3156 s, *(
int *)optval));
3160 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
3171 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_TCP);
3172 if (sock->conn->pcb.tcp->state == LISTEN) {
3178 *(
int *)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
3179 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
3180 s, (*(
int *)optval) ?
"on" :
"off") );
3183 *(
int *)optval = (
int)sock->conn->pcb.tcp->keep_idle;
3184 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n",
3185 s, *(
int *)optval));
3188#if LWIP_TCP_KEEPALIVE
3190 *(
int *)optval = (
int)(sock->conn->pcb.tcp->keep_idle / 1000);
3191 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n",
3192 s, *(
int *)optval));
3195 *(
int *)optval = (
int)(sock->conn->pcb.tcp->keep_intvl / 1000);
3196 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n",
3197 s, *(
int *)optval));
3200 *(
int *)optval = (
int)sock->conn->pcb.tcp->keep_cnt;
3201 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n",
3202 s, *(
int *)optval));
3206 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
3218#if LWIP_IPV6 && LWIP_RAW
3220 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_RAW);
3221 lwip_getsockopt_impl_ipv6_checksum(s, sock, optval);
3225 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
3226 *(
int *)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
3227 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
3228 s, *(
int *)optval));
3231 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
3239#if LWIP_UDP && LWIP_UDPLITE
3241 case IPPROTO_UDPLITE:
3243 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
3245 if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
3250 case UDPLITE_SEND_CSCOV:
3251 *(
int *)optval = sock->conn->pcb.udp->chksum_len_tx;
3252 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
3253 s, (*(
int *)optval)) );
3255 case UDPLITE_RECV_CSCOV:
3256 *(
int *)optval = sock->conn->pcb.udp->chksum_len_rx;
3257 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
3258 s, (*(
int *)optval)) );
3261 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
3271#if LWIP_IPV6 && LWIP_RAW
3273 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_RAW);
3274 lwip_getsockopt_impl_ipv6_checksum(s, sock, optval);
3278 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
3285 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
3286 s, level, optname));
3296lwip_setsockopt(
int s,
int level,
int optname,
const void *optval, socklen_t optlen)
3299 struct lwip_sock *sock = get_socket(s);
3300#if !LWIP_TCPIP_CORE_LOCKING
3302 LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
3309 if (NULL == optval) {
3315#if LWIP_TCPIP_CORE_LOCKING
3318 err = lwip_setsockopt_impl(s, level, optname, optval, optlen);
3319 UNLOCK_TCPIP_CORE();
3323#if LWIP_MPU_COMPATIBLE
3325 if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
3332 LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
3333 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
3334 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
3335 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
3336 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen;
3337#if LWIP_MPU_COMPATIBLE
3338 MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
3340 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (
const void *)optval;
3342 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
3343#if LWIP_NETCONN_SEM_PER_THREAD
3344 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
3346 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
3348 cberr =
tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
3350 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
3351 set_errno(err_to_errno(cberr));
3355 sys_arch_sem_wait((sys_sem_t *)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
3358 err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
3359 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
3364 return err ? -1 : 0;
3367#if !LWIP_TCPIP_CORE_LOCKING
3372lwip_setsockopt_callback(
void *arg)
3374 struct lwip_setgetsockopt_data *data;
3375 LWIP_ASSERT(
"arg != NULL", arg != NULL);
3376 data = (
struct lwip_setgetsockopt_data *)arg;
3378 data->err = lwip_setsockopt_impl(data->s, data->level, data->optname,
3394lwip_setsockopt_impl(
int s,
int level,
int optname,
const void *optval, socklen_t optlen)
3397 struct lwip_sock *sock = tryget_socket(s);
3402#ifdef LWIP_HOOK_SOCKETS_SETSOCKOPT
3403 if (LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, &err)) {
3423 if ((optname == SO_BROADCAST) &&
3424 (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) {
3429 optname = lwip_sockopt_to_ipopt(optname);
3431 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
3432 if (*(
const int *)optval) {
3437 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
3438 s, optname, (*(
const int *)optval ?
"on" :
"off")));
3447 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
3448 ms_long = LWIP_SO_SNDRCVTIMEO_GET_MS(optval);
3453 netconn_set_sendtimeout(sock->conn, ms_long);
3460 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
3461 ms_long = LWIP_SO_SNDRCVTIMEO_GET_MS(optval);
3466 netconn_set_recvtimeout(sock->conn, (u32_t)ms_long);
3472 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen,
int);
3473 netconn_set_recvbufsize(sock->conn, *(
const int *)optval);
3479 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen,
struct linger);
3481 int lingersec =
linger->l_linger;
3482 if (lingersec < 0) {
3486 if (lingersec > 0xFFFF) {
3489 sock->conn->linger = (s16_t)lingersec;
3491 sock->conn->linger = -1;
3498 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_UDP);
3500 if (udp_is_flag_set(sock->conn->pcb.udp, UDP_FLAGS_UDPLITE)) {
3506 if (*(
const int *)optval) {
3507 udp_set_flags(sock->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
3509 udp_clear_flags(sock->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
3513 case SO_BINDTODEVICE: {
3514 const struct ifreq *iface;
3515 struct netif *n = NULL;
3517 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen,
struct ifreq);
3519 iface = (
const struct ifreq *)optval;
3520 if (iface->ifr_name[0] != 0) {
3528 switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
3531 tcp_bind_netif(sock->conn->pcb.tcp, n);
3536 udp_bind_netif(sock->conn->pcb.udp, n);
3541 raw_bind_netif(sock->conn->pcb.raw, n);
3545 LWIP_ASSERT(
"Unhandled netconn type in SO_BINDTODEVICE", 0);
3551 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
3562 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
3563 sock->conn->pcb.ip->ttl = (u8_t)(*(
const int *)optval);
3564 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
3565 s, sock->conn->pcb.ip->ttl));
3568 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
3569 sock->conn->pcb.ip->tos = (u8_t)(*(
const int *)optval);
3570 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
3571 s, sock->conn->pcb.ip->tos));
3573#if LWIP_NETBUF_RECVINFO
3575 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_UDP);
3576 if (*(
const int *)optval) {
3577 sock->conn->flags |= NETCONN_FLAG_PKTINFO;
3579 sock->conn->flags &= ~NETCONN_FLAG_PKTINFO;
3583#if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS && LWIP_UDP
3584 case IP_MULTICAST_TTL:
3585 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
3586 udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(
const u8_t *)optval));
3588 case IP_MULTICAST_IF: {
3590 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
struct in_addr, NETCONN_UDP);
3591 inet_addr_to_ip4addr(&if_addr, (
const struct in_addr *)optval);
3592 udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
3595 case IP_MULTICAST_LOOP:
3596 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
3597 if (*(
const u8_t *)optval) {
3598 udp_set_flags(sock->conn->pcb.udp, UDP_FLAGS_MULTICAST_LOOP);
3600 udp_clear_flags(sock->conn->pcb.udp, UDP_FLAGS_MULTICAST_LOOP);
3605 case IP_ADD_MEMBERSHIP:
3606 case IP_DROP_MEMBERSHIP: {
3609 const struct ip_mreq *imr = (
const struct ip_mreq *)optval;
3612 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
struct ip_mreq, NETCONN_UDP);
3613 inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
3614 inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
3615 if (optname == IP_ADD_MEMBERSHIP) {
3616 if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
3621 igmp_err = igmp_joingroup(&if_addr, &multi_addr);
3624 igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
3625 lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
3627 if (igmp_err !=
ERR_OK) {
3634 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
3645 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_TCP);
3646 if (sock->conn->pcb.tcp->state == LISTEN) {
3652 if (*(
const int *)optval) {
3653 tcp_nagle_disable(sock->conn->pcb.tcp);
3655 tcp_nagle_enable(sock->conn->pcb.tcp);
3657 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
3658 s, (*(
const int *)optval) ?
"on" :
"off") );
3661 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(
const int *)optval);
3662 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F
"\n",
3663 s, sock->conn->pcb.tcp->keep_idle));
3666#if LWIP_TCP_KEEPALIVE
3668 sock->conn->pcb.tcp->keep_idle = 1000 * (u32_t)(*(
const int *)optval);
3669 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F
"\n",
3670 s, sock->conn->pcb.tcp->keep_idle));
3673 sock->conn->pcb.tcp->keep_intvl = 1000 * (u32_t)(*(
const int *)optval);
3674 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F
"\n",
3675 s, sock->conn->pcb.tcp->keep_intvl));
3678 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(
const int *)optval);
3679 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F
"\n",
3680 s, sock->conn->pcb.tcp->keep_cnt));
3684 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
3696#if LWIP_IPV6 && LWIP_RAW
3698 err = lwip_setsockopt_impl_ipv6_checksum(s, sock, optval, optlen);
3705 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
3706 if (*(
const int *)optval) {
3707 netconn_set_ipv6only(sock->conn, 1);
3709 netconn_set_ipv6only(sock->conn, 0);
3711 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
3712 s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
3715 case IPV6_JOIN_GROUP:
3716 case IPV6_LEAVE_GROUP: {
3721 const struct ipv6_mreq *imr = (
const struct ipv6_mreq *)optval;
3722 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
struct ipv6_mreq, NETCONN_UDP);
3723 inet6_addr_to_ip6addr(&multi_addr, &imr->ipv6mr_multiaddr);
3724 LWIP_ASSERT(
"Invalid netif index", imr->ipv6mr_interface <= 0xFFu);
3726 if (
netif == NULL) {
3731 if (optname == IPV6_JOIN_GROUP) {
3732 if (!lwip_socket_register_mld6_membership(s, imr->ipv6mr_interface, &multi_addr)) {
3737 mld6_err = mld6_joingroup_netif(
netif, &multi_addr);
3740 mld6_err = mld6_leavegroup_netif(
netif, &multi_addr);
3741 lwip_socket_unregister_mld6_membership(s, imr->ipv6mr_interface, &multi_addr);
3743 if (mld6_err !=
ERR_OK) {
3750 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
3758#if LWIP_UDP && LWIP_UDPLITE
3760 case IPPROTO_UDPLITE:
3762 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
3764 if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
3769 case UDPLITE_SEND_CSCOV:
3770 if ((*(
const int *)optval != 0) && ((*(
const int *)optval < 8) || (*(
const int *)optval > 0xffff))) {
3772 sock->conn->pcb.udp->chksum_len_tx = 8;
3774 sock->conn->pcb.udp->chksum_len_tx = (u16_t) * (
const int *)optval;
3776 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
3777 s, (*(
const int *)optval)) );
3779 case UDPLITE_RECV_CSCOV:
3780 if ((*(
const int *)optval != 0) && ((*(
const int *)optval < 8) || (*(
const int *)optval > 0xffff))) {
3782 sock->conn->pcb.udp->chksum_len_rx = 8;
3784 sock->conn->pcb.udp->chksum_len_rx = (u16_t) * (
const int *)optval;
3786 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
3787 s, (*(
const int *)optval)) );
3790 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
3800#if LWIP_IPV6 && LWIP_RAW
3802 err = lwip_setsockopt_impl_ipv6_checksum(s, sock, optval, optlen);
3809 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n",
3816 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
3817 s, level, optname));
3827lwip_ioctl(
int s,
long cmd,
void *argp)
3829 struct lwip_sock *sock = get_socket(s);
3840#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE
3847#if LWIP_FIONREAD_LINUXMODE
3848 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
3850 if (sock->lastdata.netbuf) {
3851 nb = sock->lastdata.netbuf;
3852 *((
int *)argp) = nb->p->tot_len;
3854 struct netbuf *rxbuf;
3855 err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK);
3859 sock->lastdata.netbuf = rxbuf;
3860 *((
int *)argp) = rxbuf->p->tot_len;
3870 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
3871 if (recv_avail < 0) {
3876 if (sock->lastdata.netbuf) {
3877 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
3878 recv_avail += sock->lastdata.pbuf->tot_len;
3880 recv_avail += sock->lastdata.netbuf->p->tot_len;
3883 *((
int *)argp) = recv_avail;
3885 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_ioctl(%d, FIONREAD, %p) = %"U16_F
"\n", s, argp, *((u16_t *)argp)));
3896 if (argp && *(
int *)argp) {
3899 netconn_set_nonblocking(sock->conn, val);
3900 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
3908 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
3920lwip_fcntl(
int s,
int cmd,
int val)
3922 struct lwip_sock *sock = get_socket(s);
3932 ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
3935 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
3936#if LWIP_TCPIP_CORE_LOCKING
3942 SYS_ARCH_PROTECT(lev);
3945 if (sock->conn->pcb.tcp) {
3946 if (!(sock->conn->pcb.tcp->flags & TF_RXCLOSED)) {
3947 op_mode |= O_RDONLY;
3949 if (!(sock->conn->pcb.tcp->flags & TF_FIN)) {
3950 op_mode |= O_WRONLY;
3954#if LWIP_TCPIP_CORE_LOCKING
3955 UNLOCK_TCPIP_CORE();
3957 SYS_ARCH_UNPROTECT(lev);
3964 ret |= (op_mode == (O_RDONLY | O_WRONLY)) ? O_RDWR : op_mode;
3969 val &= ~(O_RDONLY | O_WRONLY | O_RDWR);
3970 if ((val & ~O_NONBLOCK) == 0) {
3972 netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
3980 LWIP_DEBUGF(
SOCKETS_DEBUG, (
"lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
3988#if LWIP_COMPAT_SOCKETS == 2 && LWIP_POSIX_SOCKETS_IO_NAMES
3990fcntl(
int s,
int cmd, ...)
3996 val = va_arg(ap,
int);
3998 return lwip_fcntl(s, cmd, val);
4003lwip_inet_ntop(
int af,
const void *src,
char *dst, socklen_t size)
4005 const char *ret = NULL;
4006 int size_int = (int)size;
4014 ret = ip4addr_ntoa_r((
const ip4_addr_t *)src, dst, size_int);
4022 ret = ip6addr_ntoa_r((
const ip6_addr_t *)src, dst, size_int);
4036lwip_inet_pton(
int af,
const char *src,
void *dst)
4050 err = ip6addr_aton(src, &addr);
4052 memcpy(dst, &addr.addr,
sizeof(addr.addr));
4075 struct lwip_sock *sock = get_socket(s);
4082 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
4083 if (socket_ipv4_multicast_memberships[i].sock == NULL) {
4084 socket_ipv4_multicast_memberships[i].sock = sock;
4085 ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr);
4086 ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr);
4101lwip_socket_unregister_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr)
4103 struct lwip_sock *sock = get_socket(s);
4110 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
4111 if ((socket_ipv4_multicast_memberships[i].sock == sock) &&
4112 ip4_addr_eq(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) &&
4113 ip4_addr_eq(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) {
4114 socket_ipv4_multicast_memberships[i].sock = NULL;
4128lwip_socket_drop_registered_memberships(
int s)
4130 struct lwip_sock *sock = get_socket(s);
4137 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
4138 if (socket_ipv4_multicast_memberships[i].sock == sock) {
4139 ip_addr_t multi_addr, if_addr;
4140 ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr);
4141 ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr);
4142 socket_ipv4_multicast_memberships[i].sock = NULL;
4146 netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE);
4161lwip_socket_register_mld6_membership(
int s,
unsigned int if_idx,
const ip6_addr_t *multi_addr)
4163 struct lwip_sock *sock = get_socket(s);
4170 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
4171 if (socket_ipv6_multicast_memberships[i].sock == NULL) {
4172 socket_ipv6_multicast_memberships[i].sock = sock;
4173 socket_ipv6_multicast_memberships[i].if_idx = (u8_t)if_idx;
4174 ip6_addr_copy(socket_ipv6_multicast_memberships[i].multi_addr, *multi_addr);
4189lwip_socket_unregister_mld6_membership(
int s,
unsigned int if_idx,
const ip6_addr_t *multi_addr)
4191 struct lwip_sock *sock = get_socket(s);
4198 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
4199 if ((socket_ipv6_multicast_memberships[i].sock == sock) &&
4200 (socket_ipv6_multicast_memberships[i].if_idx == if_idx) &&
4201 ip6_addr_eq(&socket_ipv6_multicast_memberships[i].multi_addr, multi_addr)) {
4202 socket_ipv6_multicast_memberships[i].sock = NULL;
4203 socket_ipv6_multicast_memberships[i].if_idx = NETIF_NO_INDEX;
4216lwip_socket_drop_registered_mld6_memberships(
int s)
4218 struct lwip_sock *sock = get_socket(s);
4225 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
4226 if (socket_ipv6_multicast_memberships[i].sock == sock) {
4227 ip_addr_t multi_addr;
4230 ip_addr_copy_from_ip6(multi_addr, socket_ipv6_multicast_memberships[i].multi_addr);
4231 if_idx = socket_ipv6_multicast_memberships[i].if_idx;
4233 socket_ipv6_multicast_memberships[i].sock = NULL;
4234 socket_ipv6_multicast_memberships[i].if_idx = NETIF_NO_INDEX;
4237 netconn_join_leave_group_netif(sock->conn, &multi_addr, if_idx, NETCONN_LEAVE);
#define ip4_addr_copy(dest, src)
#define ip6_addr_copy(dest, src)
#define ip4_addr_set_zero(ipaddr)
struct ip6_addr ip6_addr_t
#define ip6_addr_set_zero(ip6addr)
#define LWIP_UNUSED_ARG(x)
#define LWIP_CONST_CAST(target_type, val)
err_t tcpip_callback(tcpip_callback_fn function, void *ctx)
#define LWIP_ASSERT_CORE_LOCKED()
#define LWIP_MPU_COMPATIBLE
#define MEMCPY(dst, src, len)
struct netif * netif_find(const char *name)
struct netif * netif_get_by_index(u8_t idx)
void pbuf_cat(struct pbuf *head, struct pbuf *tail)
u8 pbuf_free(struct pbuf *p)
u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
void sys_sem_free(sys_sem_t *sem)
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
void sys_sem_signal(sys_sem_t *sem)
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
u16_t inet_chksum_pbuf(struct pbuf *p)
#define ip_set_option(pcb, opt)
#define ip_get_option(pcb, opt)
#define ip_reset_option(pcb, opt)
struct pbuf * pbuf_free_header(struct pbuf *q, u16_t size)
struct ip4_addr ip4_addr_t
#define SYS_ARCH_DECL_PROTECT(lev)