This updates lwIP to the STABLE-2_1_3_RELEASE tag. --- lwip/src/api/api_lib.c | 12 ++-- lwip/src/api/api_msg.c | 3 + lwip/src/api/netdb.c | 9 ++- lwip/src/api/sockets.c | 14 +++-- lwip/src/api/tcpip.c | 2 +- lwip/src/core/altcp.c | 36 ++++++++++++ lwip/src/core/altcp_tcp.c | 52 ++++++++++++++--- lwip/src/core/init.c | 5 +- lwip/src/core/ipv4/dhcp.c | 57 +++++++++--------- lwip/src/core/ipv4/etharp.c | 8 +++ lwip/src/core/ipv4/icmp.c | 18 ++++-- lwip/src/core/ipv4/ip4_addr.c | 2 + lwip/src/core/ipv6/dhcp6.c | 13 ++++- lwip/src/core/ipv6/icmp6.c | 27 ++++++--- lwip/src/core/ipv6/ip6.c | 2 + lwip/src/core/ipv6/ip6_frag.c | 2 +- lwip/src/core/ipv6/mld6.c | 4 +- lwip/src/core/ipv6/nd6.c | 30 +++++++--- lwip/src/core/netif.c | 44 ++++++++++---- lwip/src/core/pbuf.c | 58 +++++++++++++++---- lwip/src/core/tcp.c | 6 +- lwip/src/core/tcp_in.c | 5 +- lwip/src/core/tcp_out.c | 7 ++- lwip/src/core/udp.c | 12 +++- lwip/src/include/lwip/altcp.h | 5 ++ lwip/src/include/lwip/altcp_tls.h | 28 ++++++++- .../lwip/apps/altcp_tls_mbedtls_opts.h | 42 +++++++++++++- lwip/src/include/lwip/apps/sntp.h | 6 +- lwip/src/include/lwip/apps/sntp_opts.h | 6 ++ lwip/src/include/lwip/debug.h | 4 +- lwip/src/include/lwip/if_api.h | 2 + lwip/src/include/lwip/init.h | 2 +- lwip/src/include/lwip/netif.h | 6 +- lwip/src/include/lwip/opt.h | 25 +++++--- lwip/src/include/lwip/pbuf.h | 4 ++ lwip/src/include/lwip/priv/altcp_priv.h | 13 +++++ lwip/src/include/lwip/prot/icmp6.h | 2 + lwip/src/include/lwip/prot/ip6.h | 2 + lwip/src/include/netif/ppp/ppp_opts.h | 7 +++ lwip/src/include/netif/ppp/pppoe.h | 8 +-- lwip/src/netif/lowpan6.c | 2 +- lwip/src/netif/lowpan6_ble.c | 2 +- lwip/src/netif/lowpan6_common.c | 8 +-- lwip/src/netif/ppp/ppp.c | 5 +- lwip/src/netif/ppp/pppoe.c | 43 +++++++------- lwip/src/netif/zepif.c | 2 +- 46 files changed, 483 insertions(+), 169 deletions(-)
diff --git a/lwip/src/api/api_lib.c b/lwip/src/api/api_lib.c index e03b8b7..ffa14d6 100644 --- a/lwip/src/api/api_lib.c +++ b/lwip/src/api/api_lib.c @@ -201,16 +201,16 @@ netconn_prepare_delete(struct netconn *conn) API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; +#if LWIP_TCP #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER /* get the time we started, which is later compared to sys_now() + conn->send_timeout */ API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ -#if LWIP_TCP API_MSG_VAR_REF(msg).msg.sd.polls_left = ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; -#endif /* LWIP_TCP */ #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ +#endif /* LWIP_TCP */ err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg)); API_MSG_VAR_FREE(msg); @@ -500,7 +500,7 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn) NETCONN_MBOX_WAITING_INC(conn); if (netconn_is_nonblocking(conn)) { - if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_ARCH_TIMEOUT) { + if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_MBOX_EMPTY) { API_MSG_VAR_FREE_ACCEPT(msg); NETCONN_MBOX_WAITING_DEC(conn); return ERR_WOULDBLOCK; @@ -597,7 +597,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf, u8_t apiflags) NETCONN_MBOX_WAITING_INC(conn); if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { - if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_ARCH_TIMEOUT) { + if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_MBOX_EMPTY) { err_t err; NETCONN_MBOX_WAITING_DEC(conn); err = netconn_err(conn); @@ -1346,7 +1346,7 @@ void netconn_thread_init(void) { sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); - if ((sem == NULL) || !sys_sem_valid(sem)) { + if (!sys_sem_valid(sem)) { /* call alloc only once */ LWIP_NETCONN_THREAD_SEM_ALLOC(); LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET())); @@ -1357,7 +1357,7 @@ void netconn_thread_cleanup(void) { sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); - if ((sem != NULL) && sys_sem_valid(sem)) { + if (sys_sem_valid(sem)) { /* call free only once */ LWIP_NETCONN_THREAD_SEM_FREE(); } diff --git a/lwip/src/api/api_msg.c b/lwip/src/api/api_msg.c index 3953102..3f08e03 100644 --- a/lwip/src/api/api_msg.c +++ b/lwip/src/api/api_msg.c @@ -716,6 +716,9 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) conn->pending_err = ERR_OK; conn->type = t; conn->pcb.tcp = NULL; +#if LWIP_NETCONN_FULLDUPLEX + conn->mbox_threads_waiting = 0; +#endif /* If all sizes are the same, every compiler should optimize this switch to nothing */ switch (NETCONNTYPE_GROUP(t)) { diff --git a/lwip/src/api/netdb.c b/lwip/src/api/netdb.c index 8771425..ee78297 100644 --- a/lwip/src/api/netdb.c +++ b/lwip/src/api/netdb.c @@ -128,8 +128,7 @@ lwip_gethostbyname(const char *name) if (s_hostent.h_addr_list != NULL) { u8_t idx; for (idx = 0; s_hostent.h_addr_list[idx]; idx++) { - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t *)s_hostent.h_addr_list[idx]))); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa(s_phostent_addr[idx]))); } } #endif /* DNS_DEBUG */ @@ -306,7 +305,11 @@ lwip_getaddrinfo(const char *nodename, const char *servname, /* service name specified: convert to port number * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ port_nr = atoi(servname); - if ((port_nr <= 0) || (port_nr > 0xffff)) { + if (port_nr == 0 && (servname[0] != '0')) { + /* atoi failed - service was not numeric */ + return EAI_SERVICE; + } + if ((port_nr < 0) || (port_nr > 0xffff)) { return EAI_SERVICE; } } diff --git a/lwip/src/api/sockets.c b/lwip/src/api/sockets.c index cb7df91..7852635 100644 --- a/lwip/src/api/sockets.c +++ b/lwip/src/api/sockets.c @@ -688,7 +688,6 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) err = netconn_peer(newconn, &naddr, &port); if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); - netconn_delete(newconn); free_socket(nsock, 1); sock_set_errno(sock, err_to_errno(err)); done_socket(sock); @@ -2073,7 +2072,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, /* Call lwip_selscan again: there could have been events between the last scan (without us on the list) and putting us on the list! */ nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - if (!nready) { + if (nready < 0) { + set_errno(EBADF); + } else if (!nready) { /* Still none ready, just wait to be woken */ if (timeout == 0) { /* Wait forever */ @@ -2102,7 +2103,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, (exceptset && FD_ISSET(i, exceptset))) { struct lwip_sock *sock; SYS_ARCH_PROTECT(lev); - sock = tryget_socket_unconn_locked(i); + sock = tryget_socket_unconn_nouse(i); + LWIP_ASSERT("socket gone at the end of select", sock != NULL); if (sock != NULL) { /* for now, handle select_waiting==0... */ LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); @@ -2110,7 +2112,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, sock->select_waiting--; } SYS_ARCH_UNPROTECT(lev); - done_socket(sock); } else { SYS_ARCH_UNPROTECT(lev); /* Not a valid socket */ @@ -2147,6 +2148,11 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, /* See what's set now after waiting */ nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); + if (nready < 0) { + set_errno(EBADF); + lwip_select_dec_sockets_used(maxfdp1, &used_sockets); + return -1; + } } } } diff --git a/lwip/src/api/tcpip.c b/lwip/src/api/tcpip.c index 743553a..a7e312a 100644 --- a/lwip/src/api/tcpip.c +++ b/lwip/src/api/tcpip.c @@ -217,7 +217,7 @@ tcpip_thread_poll_one(void) int ret = 0; struct tcpip_msg *msg; - if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_ARCH_TIMEOUT) { + if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_MBOX_EMPTY) { LOCK_TCPIP_CORE(); if (msg != NULL) { tcpip_thread_handle_msg(msg); diff --git a/lwip/src/core/altcp.c b/lwip/src/core/altcp.c index d46d6cd..4abef7c 100644 --- a/lwip/src/core/altcp.c +++ b/lwip/src/core/altcp.c @@ -501,6 +501,24 @@ altcp_get_port(struct altcp_pcb *conn, int local) return 0; } +#if LWIP_TCP_KEEPALIVE +void +altcp_keepalive_disable(struct altcp_pcb *conn) +{ + if (conn && conn->fns && conn->fns->keepalive_disable) { + conn->fns->keepalive_disable(conn); + } +} + +void +altcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count) +{ + if (conn && conn->fns && conn->fns->keepalive_enable) { + conn->fns->keepalive_enable(conn, idle, intvl, count); + } +} +#endif + #ifdef LWIP_DEBUG enum tcp_state altcp_dbg_get_tcp_state(struct altcp_pcb *conn) @@ -666,6 +684,24 @@ altcp_default_get_port(struct altcp_pcb *conn, int local) return 0; } +#if LWIP_TCP_KEEPALIVE +void +altcp_default_keepalive_disable(struct altcp_pcb *conn) +{ + if (conn && conn->inner_conn) { + altcp_keepalive_disable(conn->inner_conn); + } +} + +void +altcp_default_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count) +{ + if (conn && conn->inner_conn) { + altcp_keepalive_enable(conn->inner_conn, idle, intvl, count); + } +} +#endif + #ifdef LWIP_DEBUG enum tcp_state altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn) diff --git a/lwip/src/core/altcp_tcp.c b/lwip/src/core/altcp_tcp.c index b715f04..1869e2a 100644 --- a/lwip/src/core/altcp_tcp.c +++ b/lwip/src/core/altcp_tcp.c @@ -49,6 +49,7 @@ #include "lwip/altcp_tcp.h" #include "lwip/priv/altcp_priv.h" #include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" #include "lwip/mem.h" #include <string.h> @@ -160,21 +161,25 @@ static void altcp_tcp_remove_callbacks(struct tcp_pcb *tpcb) { tcp_arg(tpcb, NULL); - tcp_recv(tpcb, NULL); - tcp_sent(tpcb, NULL); - tcp_err(tpcb, NULL); - tcp_poll(tpcb, NULL, tpcb->pollinterval); + if (tpcb->state != LISTEN) { + tcp_recv(tpcb, NULL); + tcp_sent(tpcb, NULL); + tcp_err(tpcb, NULL); + tcp_poll(tpcb, NULL, tpcb->pollinterval); + } } static void altcp_tcp_setup_callbacks(struct altcp_pcb *conn, struct tcp_pcb *tpcb) { tcp_arg(tpcb, conn); - tcp_recv(tpcb, altcp_tcp_recv); - tcp_sent(tpcb, altcp_tcp_sent); - tcp_err(tpcb, altcp_tcp_err); - /* tcp_poll is set when interval is set by application */ - /* listen is set totally different :-) */ + /* this might be called for LISTN when close fails... */ + if (tpcb->state != LISTEN) { + tcp_recv(tpcb, altcp_tcp_recv); + tcp_sent(tpcb, altcp_tcp_sent); + tcp_err(tpcb, altcp_tcp_err); + /* tcp_poll is set when interval is set by application */ + } } static void @@ -446,6 +451,31 @@ altcp_tcp_setprio(struct altcp_pcb *conn, u8_t prio) } } +#if LWIP_TCP_KEEPALIVE +static void +altcp_tcp_keepalive_disable(struct altcp_pcb *conn) +{ + if (conn && conn->state) { + struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; + ALTCP_TCP_ASSERT_CONN(conn); + ip_reset_option(pcb, SOF_KEEPALIVE); + } +} + +static void +altcp_tcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t cnt) +{ + if (conn && conn->state) { + struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; + ALTCP_TCP_ASSERT_CONN(conn); + ip_set_option(pcb, SOF_KEEPALIVE); + pcb->keep_idle = idle ? idle : TCP_KEEPIDLE_DEFAULT; + pcb->keep_intvl = intvl ? intvl : TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = cnt ? cnt : TCP_KEEPCNT_DEFAULT; + } +} +#endif + static void altcp_tcp_dealloc(struct altcp_pcb *conn) { @@ -535,6 +565,10 @@ const struct altcp_functions altcp_tcp_functions = { altcp_tcp_get_tcp_addrinfo, altcp_tcp_get_ip, altcp_tcp_get_port +#if LWIP_TCP_KEEPALIVE + , altcp_tcp_keepalive_disable + , altcp_tcp_keepalive_enable +#endif #ifdef LWIP_DEBUG , altcp_tcp_dbg_get_tcp_state #endif diff --git a/lwip/src/core/init.c b/lwip/src/core/init.c index b3737a3..3620e1d 100644 --- a/lwip/src/core/init.c +++ b/lwip/src/core/init.c @@ -237,8 +237,9 @@ PACK_STRUCT_END #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" #endif #endif /* LWIP_NETCONN && LWIP_TCP */ -#if LWIP_SOCKET -#endif /* LWIP_SOCKET */ +#if LWIP_NETCONN_FULLDUPLEX && !LWIP_NETCONN_SEM_PER_THREAD +#error "For LWIP_NETCONN_FULLDUPLEX to work, LWIP_NETCONN_SEM_PER_THREAD is required" +#endif /* Compile-time checks for deprecated options. diff --git a/lwip/src/core/ipv4/dhcp.c b/lwip/src/core/ipv4/dhcp.c index 534574f..76b9f68 100644 --- a/lwip/src/core/ipv4/dhcp.c +++ b/lwip/src/core/ipv4/dhcp.c @@ -127,6 +127,11 @@ #define LWIP_DHCP_PROVIDE_DNS_SERVERS 0 #endif +#ifndef LWIP_DHCP_INPUT_ERROR +#define LWIP_DHCP_INPUT_ERROR(message, expression, handler) do { if (!(expression)) { \ + handler;} } while(0) +#endif + /** Option handling: options are parsed in dhcp_parse_reply * and saved in an array where other functions can load them from. * This might be moved into the struct dhcp (not necessarily since @@ -1115,13 +1120,6 @@ dhcp_bind(struct netif *netif) } ip4_addr_copy(gw_addr, dhcp->offered_gw_addr); - /* gateway address not given? */ - if (ip4_addr_isany_val(gw_addr)) { - /* copy network address */ - ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); - /* use first host address on network as gateway */ - ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); - } #if LWIP_DHCP_AUTOIP_COOP if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { @@ -1349,6 +1347,7 @@ dhcp_release_and_stop(struct netif *netif) /* create and initialize the DHCP message header */ struct pbuf *p_out; u16_t options_out_len; + dhcp_set_state(dhcp, DHCP_STATE_OFF); p_out = dhcp_create_msg(netif, dhcp, DHCP_RELEASE, &options_out_len); if (p_out != NULL) { struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload; @@ -1365,10 +1364,12 @@ dhcp_release_and_stop(struct netif *netif) /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); } - } - /* remove IP address from interface (prevents routing from selecting this interface) */ - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + /* remove IP address from interface (prevents routing from selecting this interface) */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + } else { + dhcp_set_state(dhcp, DHCP_STATE_OFF); + } #if LWIP_DHCP_AUTOIP_COOP if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { @@ -1377,8 +1378,6 @@ dhcp_release_and_stop(struct netif *netif) } #endif /* LWIP_DHCP_AUTOIP_COOP */ - dhcp_set_state(dhcp, DHCP_STATE_OFF); - if (dhcp->pcb_allocated != 0) { dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ dhcp->pcb_allocated = 0; @@ -1509,6 +1508,7 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp) u8_t *options; u16_t offset; u16_t offset_max; + u16_t options_offset; u16_t options_idx; u16_t options_idx_max; struct pbuf *q; @@ -1541,6 +1541,7 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp) options_idx_max = p->tot_len; again: q = p; + options_offset = options_idx; while ((q != NULL) && (options_idx >= q->len)) { options_idx = (u16_t)(options_idx - q->len); options_idx_max = (u16_t)(options_idx_max - q->len); @@ -1579,58 +1580,58 @@ again: /* will be increased below */ break; case (DHCP_OPTION_SUBNET_MASK): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; break; case (DHCP_OPTION_ROUTER): decode_len = 4; /* only copy the first given router */ - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_ROUTER; break; #if LWIP_DHCP_PROVIDE_DNS_SERVERS case (DHCP_OPTION_DNS_SERVER): /* special case: there might be more than one server */ - LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); /* limit number of DNS servers */ decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_DNS_SERVER; break; #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ case (DHCP_OPTION_LEASE_TIME): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_LEASE_TIME; break; #if LWIP_DHCP_GET_NTP_SRV case (DHCP_OPTION_NTP): /* special case: there might be more than one server */ - LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); /* limit number of NTP servers */ decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS); - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_NTP_SERVER; break; #endif /* LWIP_DHCP_GET_NTP_SRV*/ case (DHCP_OPTION_OVERLOAD): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;); /* decode overload only in options, not in file/sname: invalid packet */ - LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("overload in file/sname", options_offset == DHCP_OPTIONS_OFS, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_OVERLOAD; break; case (DHCP_OPTION_MESSAGE_TYPE): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_MSG_TYPE; break; case (DHCP_OPTION_SERVER_ID): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_SERVER_ID; break; case (DHCP_OPTION_T1): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_T1; break; case (DHCP_OPTION_T2): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;); decode_idx = DHCP_OPTION_IDX_T2; break; default: @@ -1662,7 +1663,7 @@ decode_next: if (decode_len > 4) { /* decode more than one u32_t */ u16_t next_val_offset; - LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;); dhcp_got_option(dhcp, decode_idx); dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value)); decode_len = (u8_t)(decode_len - 4); @@ -1677,7 +1678,7 @@ decode_next: } else if (decode_len == 4) { value = lwip_ntohl(value); } else { - LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); value = ((u8_t *)&value)[0]; } dhcp_got_option(dhcp, decode_idx); @@ -1690,7 +1691,7 @@ decode_next: offset_max = (u16_t)(offset_max - q->len); if (offset < offset_max) { q = q->next; - LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;); + LWIP_DHCP_INPUT_ERROR("next pbuf was null", q != NULL, return ERR_VAL;); options = (u8_t *)q->payload; } else { /* We've run out of bytes, probably no end marker. Don't proceed. */ diff --git a/lwip/src/core/ipv4/etharp.c b/lwip/src/core/ipv4/etharp.c index 442aac0..c3a5a10 100644 --- a/lwip/src/core/ipv4/etharp.c +++ b/lwip/src/core/ipv4/etharp.c @@ -983,6 +983,14 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) /* We don't re-send arp request in etharp_tmr, but we still queue packets, since this failure could be temporary, and the next packet calling etharp_query again could lead to sending the queued packets. */ + } else { + /* ARP request successfully sent */ + if ((arp_table[i].state == ETHARP_STATE_PENDING) && !is_new_entry) { + /* A new ARP request has been sent for a pending entry. Reset the ctime to + not let it expire too fast. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: reset ctime for entry %"S16_F"\n", (s16_t)i)); + arp_table[i].ctime = 0; + } } if (q == NULL) { return result; diff --git a/lwip/src/core/ipv4/icmp.c b/lwip/src/core/ipv4/icmp.c index a462ccd..59b493a 100644 --- a/lwip/src/core/ipv4/icmp.c +++ b/lwip/src/core/ipv4/icmp.c @@ -62,7 +62,7 @@ #define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 #endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ -/* The amount of data from the original packet to return in a dest-unreachable */ +/* The maximum amount of data from the original packet to return in a dest-unreachable */ #define ICMP_DEST_UNREACH_DATASIZE 8 static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); @@ -345,20 +345,26 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code) struct icmp_echo_hdr *icmphdr; ip4_addr_t iphdr_src; struct netif *netif; + u16_t response_pkt_len; /* increase number of messages attempted to send */ MIB2_STATS_INC(mib2.icmpoutmsgs); - /* ICMP header + IP header + 8 bytes of data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, - PBUF_RAM); + /* Keep IP header + up to 8 bytes */ + response_pkt_len = IP_HLEN + ICMP_DEST_UNREACH_DATASIZE; + if (p->tot_len < response_pkt_len) { + response_pkt_len = p->tot_len; + } + + /* ICMP header + part of original packet */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + response_pkt_len, PBUF_RAM); if (q == NULL) { LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); MIB2_STATS_INC(mib2.icmpouterrors); return; } LWIP_ASSERT("check that first pbuf can hold icmp message", - (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + (q->len >= (sizeof(struct icmp_echo_hdr) + response_pkt_len))); iphdr = (struct ip_hdr *)p->payload; LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); @@ -375,7 +381,7 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code) /* copy fields from original packet */ SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, - IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + response_pkt_len); ip4_addr_copy(iphdr_src, iphdr->src); #ifdef LWIP_HOOK_IP4_ROUTE_SRC diff --git a/lwip/src/core/ipv4/ip4_addr.c b/lwip/src/core/ipv4/ip4_addr.c index 33204d1..f99d8dd 100644 --- a/lwip/src/core/ipv4/ip4_addr.c +++ b/lwip/src/core/ipv4/ip4_addr.c @@ -173,6 +173,8 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr) } for (;;) { if (lwip_isdigit(c)) { + if((base == 8) && ((u32_t)(c - '0') >= 8)) + break; val = (val * base) + (u32_t)(c - '0'); c = *++cp; } else if (base == 16 && lwip_isxdigit(c)) { diff --git a/lwip/src/core/ipv6/dhcp6.c b/lwip/src/core/ipv6/dhcp6.c index 7cf98a5..41444a4 100644 --- a/lwip/src/core/ipv6/dhcp6.c +++ b/lwip/src/core/ipv6/dhcp6.c @@ -451,7 +451,16 @@ dhcp6_msg_finalize(u16_t options_out_len, struct pbuf *p_out) static void dhcp6_information_request(struct netif *netif, struct dhcp6 *dhcp6) { - const u16_t requested_options[] = {DHCP6_OPTION_DNS_SERVERS, DHCP6_OPTION_DOMAIN_LIST, DHCP6_OPTION_SNTP_SERVERS}; + const u16_t requested_options[] = { +#if LWIP_DHCP6_PROVIDE_DNS_SERVERS + DHCP6_OPTION_DNS_SERVERS, + DHCP6_OPTION_DOMAIN_LIST +#endif +#if LWIP_DHCP6_GET_NTP_SRV + , DHCP6_OPTION_SNTP_SERVERS +#endif + }; + u16_t msecs; struct pbuf *p_out; u16_t options_out_len; @@ -527,7 +536,7 @@ dhcp6_handle_config_reply(struct netif *netif, struct pbuf *p_msg_in) u16_t idx; u8_t n; - memset(&dns_addr, 0, sizeof(dns_addr)); + ip_addr_set_zero_ip6(&dns_addr); dns_addr6 = ip_2_ip6(&dns_addr); for (n = 0, idx = op_start; (idx < op_start + op_len) && (n < LWIP_DHCP6_PROVIDE_DNS_SERVERS); n++, idx += sizeof(struct ip6_addr_packed)) { diff --git a/lwip/src/core/ipv6/icmp6.c b/lwip/src/core/ipv6/icmp6.c index 167738a..4fd1021 100644 --- a/lwip/src/core/ipv6/icmp6.c +++ b/lwip/src/core/ipv6/icmp6.c @@ -57,9 +57,9 @@ #include <string.h> -#if LWIP_ICMP6_DATASIZE == 0 +#if !LWIP_ICMP6_DATASIZE || (LWIP_ICMP6_DATASIZE > (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN)) #undef LWIP_ICMP6_DATASIZE -#define LWIP_ICMP6_DATASIZE 8 +#define LWIP_ICMP6_DATASIZE (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN) #endif /* Forward declarations */ @@ -387,26 +387,35 @@ icmp6_send_response_with_addrs_and_netif(struct pbuf *p, u8_t code, u32_t data, { struct pbuf *q; struct icmp6_hdr *icmp6hdr; + u16_t datalen = LWIP_MIN(p->tot_len, LWIP_ICMP6_DATASIZE); + u16_t offset; - /* ICMPv6 header + IPv6 header + data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + /* ICMPv6 header + datalen (as much of the offending packet as possible) */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + datalen, PBUF_RAM); if (q == NULL) { LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); ICMP6_STATS_INC(icmp6.memerr); return; } - LWIP_ASSERT("check that first pbuf can hold icmp 6message", - (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + LWIP_ASSERT("check that first pbuf can hold icmp6 header", + (q->len >= (sizeof(struct icmp6_hdr)))); icmp6hdr = (struct icmp6_hdr *)q->payload; icmp6hdr->type = type; icmp6hdr->code = code; icmp6hdr->data = lwip_htonl(data); - /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, - IP6_HLEN + LWIP_ICMP6_DATASIZE); + /* copy fields from original packet (which may be a chain of pbufs) */ + offset = sizeof(struct icmp6_hdr); + while (p && datalen) { + u16_t len = LWIP_MIN(datalen, p->len); + err_t res = pbuf_take_at(q, p->payload, len, offset); + if (res != ERR_OK) break; + datalen -= len; + offset += len; + p = p->next; + } /* calculate checksum */ icmp6hdr->chksum = 0; diff --git a/lwip/src/core/ipv6/ip6.c b/lwip/src/core/ipv6/ip6.c index eda11dc..060d5f3 100644 --- a/lwip/src/core/ipv6/ip6.c +++ b/lwip/src/core/ipv6/ip6.c @@ -1305,6 +1305,7 @@ ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, ip6_addr_copy_from_packed(src_addr, ip6hdr->src); ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); netif = ip6_route(&src_addr, &dest_addr); + dest = &dest_addr; } if (netif == NULL) { @@ -1364,6 +1365,7 @@ ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, ip6_addr_copy_from_packed(src_addr, ip6hdr->src); ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); netif = ip6_route(&src_addr, &dest_addr); + dest = &dest_addr; } if (netif == NULL) { diff --git a/lwip/src/core/ipv6/ip6_frag.c b/lwip/src/core/ipv6/ip6_frag.c index d6c5d22..8b352f5 100644 --- a/lwip/src/core/ipv6/ip6_frag.c +++ b/lwip/src/core/ipv6/ip6_frag.c @@ -781,7 +781,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) return ERR_MEM; } LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP6_HLEN))); + (rambuf->len >= (IP6_HLEN))); SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); ip6hdr = (struct ip6_hdr *)rambuf->payload; frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); diff --git a/lwip/src/core/ipv6/mld6.c b/lwip/src/core/ipv6/mld6.c index 6387d46..a9c917d 100644 --- a/lwip/src/core/ipv6/mld6.c +++ b/lwip/src/core/ipv6/mld6.c @@ -253,7 +253,7 @@ mld6_input(struct pbuf *p, struct netif *inp) while (group != NULL) { if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { - mld6_delayed_report(group, mld_hdr->max_resp_delay); + mld6_delayed_report(group, lwip_ntohs(mld_hdr->max_resp_delay)); } group = group->next; } @@ -265,7 +265,7 @@ mld6_input(struct pbuf *p, struct netif *inp) group = mld6_lookfor_group(inp, ip6_current_dest_addr()); if (group != NULL) { /* Schedule a report. */ - mld6_delayed_report(group, mld_hdr->max_resp_delay); + mld6_delayed_report(group, lwip_ntohs(mld_hdr->max_resp_delay)); } } break; /* ICMP6_TYPE_MLQ */ diff --git a/lwip/src/core/ipv6/nd6.c b/lwip/src/core/ipv6/nd6.c index db0c132..81992fa 100644 --- a/lwip/src/core/ipv6/nd6.c +++ b/lwip/src/core/ipv6/nd6.c @@ -693,11 +693,11 @@ nd6_input(struct pbuf *p, struct netif *inp) } mtu_opt = (struct mtu_option *)buffer; mtu32 = lwip_htonl(mtu_opt->mtu); - if ((mtu32 >= 1280) && (mtu32 <= 0xffff)) { + if ((mtu32 >= IP6_MIN_MTU_LENGTH) && (mtu32 <= 0xffff)) { #if LWIP_ND6_ALLOW_RA_UPDATES if (inp->mtu) { /* don't set the mtu for IPv6 higher than the netif driver supports */ - inp->mtu6 = LWIP_MIN(inp->mtu, (u16_t)mtu32); + inp->mtu6 = LWIP_MIN(LWIP_MIN(inp->mtu, inp->mtu6), (u16_t)mtu32); } else { inp->mtu6 = (u16_t)mtu32; } @@ -766,7 +766,7 @@ nd6_input(struct pbuf *p, struct netif *inp) rdnss_opt = (struct rdnss_option *)buffer; num = (rdnss_opt->length - 1) / 2; - for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { + for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++, copy_offset += sizeof(ip6_addr_p_t)) { ip_addr_t rdnss_address; /* Copy directly from pbuf to get an aligned, zoned copy of the prefix. */ @@ -1182,15 +1182,27 @@ nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) { struct ns_header *ns_hdr; struct pbuf *p; - const ip6_addr_t *src_addr; + const ip6_addr_t *src_addr = NULL; u16_t lladdr_opt_len; LWIP_ASSERT("target address is required", target_addr != NULL); - if (!(flags & ND6_SEND_FLAG_ANY_SRC) && - ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(netif, 0); + if (!(flags & ND6_SEND_FLAG_ANY_SRC)) { + int i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(target_addr, netif_ip6_addr(netif, i))) { + src_addr = netif_ip6_addr(netif, i); + break; + } + } + + if (i == LWIP_IPV6_NUM_ADDRESSES) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("ICMPv6 NS: no available src address\n")); + ND6_STATS_INC(nd6.err); + return; + } + /* calculate option length (in 8-byte-blocks) */ lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3; } else { @@ -2300,7 +2312,7 @@ nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) return netif_mtu6(netif); } - return 1280; /* Minimum MTU */ + return IP6_MIN_MTU_LENGTH; /* Minimum MTU */ } diff --git a/lwip/src/core/netif.c b/lwip/src/core/netif.c index 15200a2..088b50e 100644 --- a/lwip/src/core/netif.c +++ b/lwip/src/core/netif.c @@ -348,10 +348,6 @@ netif_add(struct netif *netif, #if LWIP_IPV6 && LWIP_IPV6_MLD netif->mld_mac_filter = NULL; #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ -#if ENABLE_LOOPBACK - netif->loop_first = NULL; - netif->loop_last = NULL; -#endif /* ENABLE_LOOPBACK */ /* remember netif specific state information data */ netif->state = state; @@ -359,9 +355,16 @@ netif_add(struct netif *netif, netif->input = input; NETIF_RESET_HINTS(netif); -#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#if LWIP_LOOPBACK_MAX_PBUFS netif->loop_cnt_current = 0; -#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + netif->reschedule_poll = 0; +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ #if LWIP_IPV4 netif_set_addr(netif, ipaddr, netmask, gw); @@ -1031,6 +1034,10 @@ netif_set_link_down(struct netif *netif) if (netif->flags & NETIF_FLAG_LINK_UP) { netif_clear_flags(netif, NETIF_FLAG_LINK_UP); +#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES + netif->mtu6 = netif->mtu; +#endif + NETIF_LINK_CALLBACK(netif); #if LWIP_NETIF_EXT_STATUS_CALLBACK { @@ -1062,11 +1069,12 @@ netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callb /** * @ingroup netif * Send an IP packet to be received on the same netif (loopif-like). - * The pbuf is simply copied and handed back to netif->input. - * In multithreaded mode, this is done directly since netif->input must put - * the packet on a queue. - * In callback mode, the packet is put on an internal queue and is fed to + * The pbuf is copied and added to an internal queue which is fed to * netif->input by netif_poll(). + * In multithreaded mode, the call to netif_poll() is queued to be done on the + * TCP/IP thread. + * In callback mode, the user has the responsibility to call netif_poll() in + * the main loop of their application. * * @param netif the lwip network interface structure * @param p the (IP) packet to 'send' @@ -1143,6 +1151,12 @@ netif_loop_output(struct netif *netif, struct pbuf *p) LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); netif->loop_last->next = r; netif->loop_last = last; +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + if (netif->reschedule_poll) { + schedule_poll = 1; + netif->reschedule_poll = 0; + } +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ } else { netif->loop_first = r; netif->loop_last = last; @@ -1160,7 +1174,11 @@ netif_loop_output(struct netif *netif, struct pbuf *p) #if LWIP_NETIF_LOOPBACK_MULTITHREADING /* For multithreading environment, schedule a call to netif_poll */ if (schedule_poll) { - tcpip_try_callback((tcpip_callback_fn)netif_poll, netif); + if (tcpip_try_callback((tcpip_callback_fn)netif_poll, netif) != ERR_OK) { + SYS_ARCH_PROTECT(lev); + netif->reschedule_poll = 1; + SYS_ARCH_UNPROTECT(lev); + } } #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ @@ -1710,6 +1728,10 @@ netif_find(const char *name) } num = (u8_t)atoi(&name[2]); + if (!num && (name[2] != '0')) { + /* this means atoi has failed */ + return NULL; + } NETIF_FOREACH(netif) { if (num == netif->num && diff --git a/lwip/src/core/pbuf.c b/lwip/src/core/pbuf.c index a209e0c..7638dfd 100644 --- a/lwip/src/core/pbuf.c +++ b/lwip/src/core/pbuf.c @@ -271,7 +271,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) break; } case PBUF_RAM: { - u16_t payload_len = (u16_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length)); + mem_size_t payload_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length)); mem_size_t alloc_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF) + payload_len); /* bug #50040: Check for integer overflow when calculating alloc_len */ @@ -960,54 +960,88 @@ pbuf_dechain(struct pbuf *p) err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) { - size_t offset_to = 0, offset_from = 0, len; - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", (const void *)p_to, (const void *)p_from)); + LWIP_ERROR("pbuf_copy: invalid source", p_from != NULL, return ERR_ARG;); + return pbuf_copy_partial_pbuf(p_to, p_from, p_from->tot_len, 0); +} + +/** + * @ingroup pbuf + * Copy part or all of one packet buffer into another, to a specified offset. + * + * @note Only data in one packet is copied, no packet queue! + * @note Argument order is shared with pbuf_copy, but different than pbuf_copy_partial. + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * @param copy_len number of bytes to copy + * @param offset offset in destination pbuf where to copy to + * + * @return ERR_OK if copy_len bytes were copied + * ERR_ARG if one of the pbufs is NULL or p_from is shorter than copy_len + * or p_to is not big enough to hold copy_len at offset + * ERR_VAL if any of the pbufs are part of a queue + */ +err_t +pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset) +{ + size_t offset_to = offset, offset_from = 0, len_calc; + u16_t len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf(%p, %p, %"U16_F", %"U16_F")\n", + (const void *)p_to, (const void *)p_from, copy_len, offset)); + + /* is the copy_len in range? */ + LWIP_ERROR("pbuf_copy_partial_pbuf: copy_len bigger than source", ((p_from != NULL) && + (p_from->tot_len >= copy_len)), return ERR_ARG;); /* is the target big enough to hold the source? */ - LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && - (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + LWIP_ERROR("pbuf_copy_partial_pbuf: target not big enough", ((p_to != NULL) && + (p_to->tot_len >= (offset + copy_len))), return ERR_ARG;); /* iterate through pbuf chain */ do { /* copy one part of the original chain */ if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { /* complete current p_from fits into current p_to */ - len = p_from->len - offset_from; + len_calc = p_from->len - offset_from; } else { /* current p_from does not fit into current p_to */ - len = p_to->len - offset_to; + len_calc = p_to->len - offset_to; } + len = (u16_t)LWIP_MIN(copy_len, len_calc); MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len); offset_to += len; offset_from += len; + copy_len -= len; LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); if (offset_from >= p_from->len) { /* on to next p_from (if any) */ offset_from = 0; p_from = p_from->next; + LWIP_ERROR("p_from != NULL", (p_from != NULL) || (copy_len == 0), return ERR_ARG;); } if (offset_to == p_to->len) { /* on to next p_to (if any) */ offset_to = 0; p_to = p_to->next; - LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL), return ERR_ARG;); + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (copy_len == 0), return ERR_ARG;); } if ((p_from != NULL) && (p_from->len == p_from->tot_len)) { /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!", + LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!", (p_from->next == NULL), return ERR_VAL;); } if ((p_to != NULL) && (p_to->len == p_to->tot_len)) { /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!", + LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!", (p_to->next == NULL), return ERR_VAL;); } - } while (p_from); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + } while (copy_len); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf: copy complete.\n")); return ERR_OK; } diff --git a/lwip/src/core/tcp.c b/lwip/src/core/tcp.c index bd7d64e..371db2b 100644 --- a/lwip/src/core/tcp.c +++ b/lwip/src/core/tcp.c @@ -647,6 +647,7 @@ tcp_abort(struct tcp_pcb *pcb) * bound to all local IP addresses. * If another connection is bound to the same port, the function will * return ERR_USE, otherwise ERR_OK is returned. + * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB * * @param pcb the tcp_pcb to bind (no check is done whether this pcb is * already bound!) @@ -889,7 +890,7 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) lpcb->state = LISTEN; lpcb->prio = pcb->prio; lpcb->so_options = pcb->so_options; - lpcb->netif_idx = NETIF_NO_INDEX; + lpcb->netif_idx = pcb->netif_idx; lpcb->ttl = pcb->ttl; lpcb->tos = pcb->tos; #if LWIP_IPV4 && LWIP_IPV6 @@ -1933,6 +1934,7 @@ tcp_alloc(u8_t prio) * any of the TCP PCB lists. * The pcb is not put on any list until binding using tcp_bind(). * If memory is not available for creating the new pcb, NULL is returned. + * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB * * @internal: Maybe there should be a idle TCP PCB list where these * PCBs are put on. Port reservation using tcp_bind() is implemented but @@ -1952,6 +1954,7 @@ tcp_new(void) * Creates a new TCP protocol control block but doesn't * place it on any of the TCP PCB lists. * The pcb is not put on any list until binding using tcp_bind(). + * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB * * @param type IP address type, see @ref lwip_ip_addr_type definitions. * If you want to listen to IPv4 and IPv6 (dual-stack) connections, @@ -2067,6 +2070,7 @@ tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) * @ingroup tcp_raw * Used for specifying the function that should be called when a * LISTENing connection has been connected to another host. + * @see MEMP_NUM_TCP_PCB_LISTEN and MEMP_NUM_TCP_PCB * * @param pcb tcp_pcb to set the accept callback * @param accept callback function to call for this pcb when LISTENing diff --git a/lwip/src/core/tcp_in.c b/lwip/src/core/tcp_in.c index 428a6f4..2202e38 100644 --- a/lwip/src/core/tcp_in.c +++ b/lwip/src/core/tcp_in.c @@ -852,8 +852,9 @@ tcp_process(struct tcp_pcb *pcb) /* Do different things depending on the TCP state. */ switch (pcb->state) { case SYN_SENT: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, - pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno))); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %s %"U32_F"\n", + ackno, pcb->snd_nxt, pcb->unacked ? "" : " empty:", + pcb->unacked ? lwip_ntohl(pcb->unacked->tcphdr->seqno) : 0)); /* received SYN ACK with expected sequence number? */ if ((flags & TCP_ACK) && (flags & TCP_SYN) && (ackno == pcb->lastack + 1)) { diff --git a/lwip/src/core/tcp_out.c b/lwip/src/core/tcp_out.c index 724df10..8149d39 100644 --- a/lwip/src/core/tcp_out.c +++ b/lwip/src/core/tcp_out.c @@ -913,6 +913,7 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split) seg = tcp_create_segment(pcb, p, remainder_flags, lwip_ntohl(useg->tcphdr->seqno) + split, optflags); if (seg == NULL) { + p = NULL; /* Freed by tcp_create_segment */ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_split_unsent_seg: could not create new TCP segment\n")); goto memerr; @@ -2002,7 +2003,7 @@ tcp_rst(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno, LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); return; } - tcp_output_fill_options(pcb, p, 0, optlen); + tcp_output_fill_options(pcb, p, 0, 0); MIB2_STATS_INC(mib2.tcpoutrsts); @@ -2096,7 +2097,7 @@ tcp_keepalive(struct tcp_pcb *pcb) ("tcp_keepalive: could not allocate memory for pbuf\n")); return ERR_MEM; } - tcp_output_fill_options(pcb, p, 0, optlen); + tcp_output_fill_options(pcb, p, 0, 0); err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip); LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n", @@ -2178,7 +2179,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { pcb->snd_nxt = snd_nxt; } - tcp_output_fill_options(pcb, p, 0, optlen); + tcp_output_fill_options(pcb, p, 0, 0); err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip); diff --git a/lwip/src/core/udp.c b/lwip/src/core/udp.c index 9d2cb4a..0b609d3 100644 --- a/lwip/src/core/udp.c +++ b/lwip/src/core/udp.c @@ -997,9 +997,13 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) { /* port matches that of PCB in list and REUSEADDR not set -> reject */ if ((ipcb->local_port == port) && + (((IP_GET_TYPE(&ipcb->local_ip) == IP_GET_TYPE(ipaddr)) && /* IP address matches or any IP used? */ - (ip_addr_cmp(&ipcb->local_ip, ipaddr) || ip_addr_isany(ipaddr) || - ip_addr_isany(&ipcb->local_ip))) { + (ip_addr_cmp(&ipcb->local_ip, ipaddr) || + ip_addr_isany(ipaddr) || + ip_addr_isany(&ipcb->local_ip))) || + (IP_GET_TYPE(&ipcb->local_ip) == IPADDR_TYPE_ANY) || + (IP_GET_TYPE(ipaddr) == IPADDR_TYPE_ANY))) { /* other PCB already binds to this local IP and port */ LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); @@ -1208,6 +1212,7 @@ udp_remove(struct udp_pcb *pcb) * Creates a new UDP pcb which can be used for UDP communication. The * pcb is not active until it has either been bound to a local address * or connected to a remote address. + * @see MEMP_NUM_UDP_PCB * * @return The UDP PCB which was created. NULL if the PCB data structure * could not be allocated. @@ -1242,7 +1247,8 @@ udp_new(void) * Create a UDP PCB for specific IP type. * The pcb is not active until it has either been bound to a local address * or connected to a remote address. - * + * @see MEMP_NUM_UDP_PCB + * * @param type IP address type, see @ref lwip_ip_addr_type definitions. * If you want to listen to IPv4 and IPv6 (dual-stack) packets, * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. diff --git a/lwip/src/include/lwip/altcp.h b/lwip/src/include/lwip/altcp.h index 97abc54..1b24544 100644 --- a/lwip/src/include/lwip/altcp.h +++ b/lwip/src/include/lwip/altcp.h @@ -129,6 +129,11 @@ err_t altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, ip_addr_t *altcp_get_ip(struct altcp_pcb *conn, int local); u16_t altcp_get_port(struct altcp_pcb *conn, int local); +#if LWIP_TCP_KEEPALIVE +void altcp_keepalive_disable(struct altcp_pcb *conn); +void altcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count); +#endif + #ifdef LWIP_DEBUG enum tcp_state altcp_dbg_get_tcp_state(struct altcp_pcb *conn); #endif diff --git a/lwip/src/include/lwip/altcp_tls.h b/lwip/src/include/lwip/altcp_tls.h index 7b17c60..ff797f2 100644 --- a/lwip/src/include/lwip/altcp_tls.h +++ b/lwip/src/include/lwip/altcp_tls.h @@ -61,7 +61,22 @@ extern "C" { struct altcp_tls_config; /** @ingroup altcp_tls - * Create an ALTCP_TLS server configuration handle + * Create an ALTCP_TLS server configuration handle prepared for multiple certificates + */ +struct altcp_tls_config *altcp_tls_create_config_server(uint8_t cert_count); + +/** @ingroup altcp_tls + * Add a certificate to an ALTCP_TLS server configuration handle + */ +err_t altcp_tls_config_server_add_privkey_cert(struct altcp_tls_config *config, + const u8_t *privkey, size_t privkey_len, + const u8_t *privkey_pass, size_t privkey_pass_len, + const u8_t *cert, size_t cert_len); + +/** @ingroup altcp_tls + * Create an ALTCP_TLS server configuration handle with one certificate + * (short version of calling @ref altcp_tls_create_config_server and + * @ref altcp_tls_config_server_add_privkey_cert) */ struct altcp_tls_config *altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len, const u8_t *privkey_pass, size_t privkey_pass_len, @@ -84,6 +99,17 @@ struct altcp_tls_config *altcp_tls_create_config_client_2wayauth(const u8_t *ca, */ void altcp_tls_free_config(struct altcp_tls_config *conf); +/** @ingroup altcp_tls + * Free an ALTCP_TLS global entropy instance. + * All ALTCP_TLS configuration are linked to one altcp_tls_entropy_rng structure + * that handle an unique system entropy & ctr_drbg instance. + * This function allow application to free this altcp_tls_entropy_rng structure + * when all configuration referencing it were destroyed. + * This function does nothing if some ALTCP_TLS configuration handle are still + * active. + */ +void altcp_tls_free_entropy(void); + /** @ingroup altcp_tls * Create new ALTCP_TLS layer wrapping an existing pcb as inner connection (e.g. TLS over TCP) */ diff --git a/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h b/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h index 36cddd9..71aa599 100644 --- a/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h +++ b/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h @@ -55,11 +55,49 @@ #define ALTCP_MBEDTLS_DEBUG LWIP_DBG_OFF #endif -/** Set a session timeout in seconds for the basic session cache +/** Configure lwIP debug level of the mbedTLS library */ +#ifndef ALTCP_MBEDTLS_LIB_DEBUG +#define ALTCP_MBEDTLS_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** Configure minimum internal debug level of the mbedTLS library */ +#ifndef ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN +#define ALTCP_MBEDTLS_LIB_DEBUG_LEVEL_MIN 0 +#endif + +/** Enable the basic session cache * ATTENTION: Using a session cache can lower security by reusing keys! */ +#ifndef ALTCP_MBEDTLS_USE_SESSION_CACHE +#define ALTCP_MBEDTLS_USE_SESSION_CACHE 0 +#endif + +/** Maximum cache size of the basic session cache */ +#ifndef ALTCP_MBEDTLS_SESSION_CACHE_SIZE +#define ALTCP_MBEDTLS_SESSION_CACHE_SIZE 30 +#endif + +/** Set a session timeout in seconds for the basic session cache */ #ifndef ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS -#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS 0 +#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS (60 * 60) +#endif + +/** Use session tickets to speed up connection setup (needs + * MBEDTLS_SSL_SESSION_TICKETS enabled in mbedTLS config). + * ATTENTION: Using session tickets can lower security by reusing keys! + */ +#ifndef ALTCP_MBEDTLS_USE_SESSION_TICKETS +#define ALTCP_MBEDTLS_USE_SESSION_TICKETS 0 +#endif + +/** Session ticket cipher */ +#ifndef ALTCP_MBEDTLS_SESSION_TICKET_CIPHER +#define ALTCP_MBEDTLS_SESSION_TICKET_CIPHER MBEDTLS_CIPHER_AES_256_GCM +#endif + +/** Maximum timeout for session tickets */ +#ifndef ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS +#define ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS (60 * 60 * 24) #endif #endif /* LWIP_ALTCP */ diff --git a/lwip/src/include/lwip/apps/sntp.h b/lwip/src/include/lwip/apps/sntp.h index 3c0f95f..c415253 100644 --- a/lwip/src/include/lwip/apps/sntp.h +++ b/lwip/src/include/lwip/apps/sntp.h @@ -67,11 +67,11 @@ void sntp_setservername(u8_t idx, const char *server); const char *sntp_getservername(u8_t idx); #endif /* SNTP_SERVER_DNS */ -#if SNTP_GET_SERVERS_FROM_DHCP +#if SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 void sntp_servermode_dhcp(int set_servers_from_dhcp); -#else /* SNTP_GET_SERVERS_FROM_DHCP */ +#else /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */ #define sntp_servermode_dhcp(x) -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ +#endif /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */ #ifdef __cplusplus } diff --git a/lwip/src/include/lwip/apps/sntp_opts.h b/lwip/src/include/lwip/apps/sntp_opts.h index ed98040..cb62771 100644 --- a/lwip/src/include/lwip/apps/sntp_opts.h +++ b/lwip/src/include/lwip/apps/sntp_opts.h @@ -67,6 +67,12 @@ #define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV #endif +/** Set this to 1 to implement the callback function called by dhcpv6 when + * NTP servers are received. */ +#if !defined SNTP_GET_SERVERS_FROM_DHCPV6 || defined __DOXYGEN__ +#define SNTP_GET_SERVERS_FROM_DHCPV6 LWIP_DHCP6_GET_NTP_SRV +#endif + /** Set this to 1 to support DNS names (or IP address strings) to set sntp servers * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: * \#define SNTP_SERVER_ADDRESS "pool.ntp.org" diff --git a/lwip/src/include/lwip/debug.h b/lwip/src/include/lwip/debug.h index baa6a40..579fd24 100644 --- a/lwip/src/include/lwip/debug.h +++ b/lwip/src/include/lwip/debug.h @@ -120,9 +120,7 @@ #endif /* LWIP_NOASSERT */ #ifndef LWIP_ERROR -#ifndef LWIP_NOASSERT -#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message) -#elif defined LWIP_DEBUG +#ifdef LWIP_DEBUG #define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message)) #else #define LWIP_PLATFORM_ERROR(message) diff --git a/lwip/src/include/lwip/if_api.h b/lwip/src/include/lwip/if_api.h index 39017ab..b7269e2 100644 --- a/lwip/src/include/lwip/if_api.h +++ b/lwip/src/include/lwip/if_api.h @@ -49,7 +49,9 @@ extern "C" { #endif +#ifndef IF_NAMESIZE #define IF_NAMESIZE NETIF_NAMESIZE +#endif char * lwip_if_indextoname(unsigned int ifindex, char *ifname); unsigned int lwip_if_nametoindex(const char *ifname); diff --git a/lwip/src/include/lwip/init.h b/lwip/src/include/lwip/init.h index a149be1..6cabfc8 100644 --- a/lwip/src/include/lwip/init.h +++ b/lwip/src/include/lwip/init.h @@ -54,7 +54,7 @@ extern "C" { /** x.X.x: Minor version of the stack */ #define LWIP_VERSION_MINOR 1 /** x.x.X: Revision of the stack */ -#define LWIP_VERSION_REVISION 2 +#define LWIP_VERSION_REVISION 3 /** For release candidates, this is set to 1..254 * For official releases, this is set to 255 (LWIP_RC_RELEASE) * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ diff --git a/lwip/src/include/lwip/netif.h b/lwip/src/include/lwip/netif.h index 911196a..9a16ded 100644 --- a/lwip/src/include/lwip/netif.h +++ b/lwip/src/include/lwip/netif.h @@ -386,6 +386,10 @@ struct netif { #if LWIP_LOOPBACK_MAX_PBUFS u16_t loop_cnt_current; #endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* Used if the original scheduling failed. */ + u8_t reschedule_poll; +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ #endif /* ENABLE_LOOPBACK */ }; @@ -451,7 +455,7 @@ void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); #define netif_set_flags(netif, set_flags) do { (netif)->flags = (u8_t)((netif)->flags | (set_flags)); } while(0) #define netif_clear_flags(netif, clr_flags) do { (netif)->flags = (u8_t)((netif)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0) -#define netif_is_flag_set(nefif, flag) (((netif)->flags & (flag)) != 0) +#define netif_is_flag_set(netif, flag) (((netif)->flags & (flag)) != 0) void netif_set_up(struct netif *netif); void netif_set_down(struct netif *netif); diff --git a/lwip/src/include/lwip/opt.h b/lwip/src/include/lwip/opt.h index 38edf41..34e4fd0 100644 --- a/lwip/src/include/lwip/opt.h +++ b/lwip/src/include/lwip/opt.h @@ -1551,7 +1551,7 @@ * TCP_MSS, IP header, and link header. */ #if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__ -#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+PBUF_IP_HLEN+PBUF_TRANSPORT_HLEN+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) #endif /** @@ -1561,6 +1561,14 @@ #if !defined LWIP_PBUF_REF_T || defined __DOXYGEN__ #define LWIP_PBUF_REF_T u8_t #endif + +/** + * LWIP_PBUF_CUSTOM_DATA: Store private data on pbufs (e.g. timestamps) + * This extends struct pbuf so user can store custom data on every pbuf. + */ +#if !defined LWIP_PBUF_CUSTOM_DATA || defined __DOXYGEN__ +#define LWIP_PBUF_CUSTOM_DATA +#endif /** * @} */ @@ -1918,11 +1926,8 @@ /** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, * writing from a 2nd thread and closing from a 3rd thread at the same time. - * ATTENTION: This is currently really alpha! Some requirements: - * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from - * multiple threads at once - * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox - * and prevent a task pending on this during/after deletion + * LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from + * multiple threads at once! */ #if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__ #define LWIP_NETCONN_FULLDUPLEX 0 @@ -2452,7 +2457,7 @@ * network startup. */ #if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__ -#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#define LWIP_IPV6_SEND_ROUTER_SOLICIT LWIP_IPV6 #endif /** @@ -2497,10 +2502,12 @@ /** * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in - * ICMPv6 error messages. + * ICMPv6 error messages (0 = default of IP6_MIN_MTU_LENGTH) + * ATTENTION: RFC4443 section 2.4 says IP6_MIN_MTU_LENGTH is a MUST, + * so override this only if you absolutely have to! */ #if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__ -#define LWIP_ICMP6_DATASIZE 8 +#define LWIP_ICMP6_DATASIZE 0 #endif /** diff --git a/lwip/src/include/lwip/pbuf.h b/lwip/src/include/lwip/pbuf.h index 82902a4..e5daf96 100644 --- a/lwip/src/include/lwip/pbuf.h +++ b/lwip/src/include/lwip/pbuf.h @@ -219,6 +219,9 @@ struct pbuf { /** For incoming packets, this contains the input netif's index */ u8_t if_idx; + + /** In case the user needs to store data custom data on a pbuf */ + LWIP_PBUF_CUSTOM_DATA }; @@ -293,6 +296,7 @@ void pbuf_cat(struct pbuf *head, struct pbuf *tail); void pbuf_chain(struct pbuf *head, struct pbuf *tail); struct pbuf *pbuf_dechain(struct pbuf *p); err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from); +err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset); u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); void *pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset); err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); diff --git a/lwip/src/include/lwip/priv/altcp_priv.h b/lwip/src/include/lwip/priv/altcp_priv.h index 2d3b2fd..d1de9b1 100644 --- a/lwip/src/include/lwip/priv/altcp_priv.h +++ b/lwip/src/include/lwip/priv/altcp_priv.h @@ -85,6 +85,11 @@ typedef err_t (*altcp_get_tcp_addrinfo_fn)(struct altcp_pcb *conn, int local, ip typedef ip_addr_t *(*altcp_get_ip_fn)(struct altcp_pcb *conn, int local); typedef u16_t (*altcp_get_port_fn)(struct altcp_pcb *conn, int local); +#if LWIP_TCP_KEEPALIVE +typedef void (*altcp_keepalive_disable_fn)(struct altcp_pcb *conn); +typedef void (*altcp_keepalive_enable_fn)(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count); +#endif + #ifdef LWIP_DEBUG typedef enum tcp_state (*altcp_dbg_get_tcp_state_fn)(struct altcp_pcb *conn); #endif @@ -111,6 +116,10 @@ struct altcp_functions { altcp_get_tcp_addrinfo_fn addrinfo; altcp_get_ip_fn getip; altcp_get_port_fn getport; +#if LWIP_TCP_KEEPALIVE + altcp_keepalive_disable_fn keepalive_disable; + altcp_keepalive_enable_fn keepalive_enable; +#endif #ifdef LWIP_DEBUG altcp_dbg_get_tcp_state_fn dbg_get_tcp_state; #endif @@ -133,6 +142,10 @@ void altcp_default_dealloc(struct altcp_pcb *conn); err_t altcp_default_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port); ip_addr_t *altcp_default_get_ip(struct altcp_pcb *conn, int local); u16_t altcp_default_get_port(struct altcp_pcb *conn, int local); +#if LWIP_TCP_KEEPALIVE +void altcp_default_keepalive_disable(struct altcp_pcb *conn); +void altcp_default_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count); +#endif #ifdef LWIP_DEBUG enum tcp_state altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn); #endif diff --git a/lwip/src/include/lwip/prot/icmp6.h b/lwip/src/include/lwip/prot/icmp6.h index 3461120..36989f6 100644 --- a/lwip/src/include/lwip/prot/icmp6.h +++ b/lwip/src/include/lwip/prot/icmp6.h @@ -146,6 +146,8 @@ PACK_STRUCT_END # include "arch/epstruct.h" #endif +#define ICMP6_HLEN 8 + /** This is the ICMP6 header adapted for echo req/resp. */ #ifdef PACK_STRUCT_USE_INCLUDES # include "arch/bpstruct.h" diff --git a/lwip/src/include/lwip/prot/ip6.h b/lwip/src/include/lwip/prot/ip6.h index 0f6de45..7df81ed 100644 --- a/lwip/src/include/lwip/prot/ip6.h +++ b/lwip/src/include/lwip/prot/ip6.h @@ -44,6 +44,8 @@ extern "C" { #endif +#define IP6_MIN_MTU_LENGTH 1280 + /** This is the packed version of ip6_addr_t, used in network headers that are itself packed */ #ifdef PACK_STRUCT_USE_INCLUDES diff --git a/lwip/src/include/netif/ppp/ppp_opts.h b/lwip/src/include/netif/ppp/ppp_opts.h index 6702bec..479a006 100644 --- a/lwip/src/include/netif/ppp/ppp_opts.h +++ b/lwip/src/include/netif/ppp/ppp_opts.h @@ -44,6 +44,13 @@ #define PPPOE_SUPPORT 0 #endif +/** + * PPPOE_SCNAME_SUPPORT==1: Enable PPP Over Ethernet Service Name and Concentrator Name support + */ +#ifndef PPPOE_SCNAME_SUPPORT +#define PPPOE_SCNAME_SUPPORT 0 +#endif + /** * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP */ diff --git a/lwip/src/include/netif/ppp/pppoe.h b/lwip/src/include/netif/ppp/pppoe.h index 08ab7ab..8994d38 100644 --- a/lwip/src/include/netif/ppp/pppoe.h +++ b/lwip/src/include/netif/ppp/pppoe.h @@ -149,10 +149,10 @@ struct pppoe_softc { u16_t sc_session; /* PPPoE session id */ u8_t sc_state; /* discovery phase or session connected */ -#ifdef PPPOE_TODO - u8_t *sc_service_name; /* if != NULL: requested name of service */ - u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */ -#endif /* PPPOE_TODO */ +#if PPPOE_SCNAME_SUPPORT + const char *sc_service_name; /* if != NULL: requested name of service */ + const char *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_SCNAME_SUPPORT */ u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ u8_t sc_ac_cookie_len; /* length of cookie data */ #ifdef PPPOE_SERVER diff --git a/lwip/src/netif/lowpan6.c b/lwip/src/netif/lowpan6.c index 7f0d276..5e6f009 100644 --- a/lwip/src/netif/lowpan6.c +++ b/lwip/src/netif/lowpan6.c @@ -881,7 +881,7 @@ lowpan6_if_init(struct netif *netif) MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); /* maximum transfer unit */ - netif->mtu = 1280; + netif->mtu = IP6_MIN_MTU_LENGTH; /* broadcast capability */ netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */; diff --git a/lwip/src/netif/lowpan6_ble.c b/lwip/src/netif/lowpan6_ble.c index d89816d..6de0ae3 100644 --- a/lwip/src/netif/lowpan6_ble.c +++ b/lwip/src/netif/lowpan6_ble.c @@ -417,7 +417,7 @@ rfc7668_if_init(struct netif *netif) MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); /* maximum transfer unit, set according to RFC7668 ch2.4 */ - netif->mtu = 1280; + netif->mtu = IP6_MIN_MTU_LENGTH; /* no flags set (no broadcast, ethernet,...)*/ netif->flags = 0; diff --git a/lwip/src/netif/lowpan6_common.c b/lwip/src/netif/lowpan6_common.c index baea206..4db1ebb 100644 --- a/lwip/src/netif/lowpan6_common.c +++ b/lwip/src/netif/lowpan6_common.c @@ -440,7 +440,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize, if ((lowpan6_buffer[0] & 0x18) == 0x00) { header_temp = ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | \ (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3]; - LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 00, ECN: 0x%2x, Flowlabel+DSCP: 0x%8X\n", \ + LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 00, ECN: 0x%"X8_F", Flowlabel+DSCP: 0x%8"X32_F"\n", \ lowpan6_buffer[lowpan6_offset],header_temp)); IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], header_temp); /* increase offset, processed 4 bytes here: @@ -448,14 +448,14 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize, lowpan6_offset += 4; } else if ((lowpan6_buffer[0] & 0x18) == 0x08) { header_temp = ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2]; - LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 01, ECN: 0x%2x, Flowlabel: 0x%2X, DSCP ignored\n", \ + LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 01, ECN: 0x%"X8_F", Flowlabel: 0x%2"X32_F", DSCP ignored\n", \ lowpan6_buffer[lowpan6_offset] & 0xc0,header_temp)); IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, header_temp); /* increase offset, processed 3 bytes here: * TF=01: ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided.*/ lowpan6_offset += 3; } else if ((lowpan6_buffer[0] & 0x18) == 0x10) { - LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 10, DCSP+ECN: 0x%2x, Flowlabel ignored\n", lowpan6_buffer[lowpan6_offset])); + LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("TF: 10, DCSP+ECN: 0x%"X8_F", Flowlabel ignored\n", lowpan6_buffer[lowpan6_offset])); IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0); /* increase offset, processed 1 byte here: * ECN + DSCP (1 byte), Flow Label is elided.*/ @@ -564,7 +564,7 @@ lowpan6_decompress_hdr(u8_t *lowpan6_buffer, size_t lowpan6_bufsize, #if LWIP_6LOWPAN_NUM_CONTEXTS > 0 ip6hdr->src.addr[0] = lowpan6_contexts[i].addr[0]; ip6hdr->src.addr[1] = lowpan6_contexts[i].addr[1]; - LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == xx, context compression found @%d: %8X, %8X\n", (int)i, ip6hdr->src.addr[0], ip6hdr->src.addr[1])); + LWIP_DEBUGF(LWIP_LOWPAN6_DECOMPRESSION_DEBUG, ("SAM == xx, context compression found @%d: %8"X32_F", %8"X32_F"\n", (int)i, ip6hdr->src.addr[0], ip6hdr->src.addr[1])); #else LWIP_UNUSED_ARG(lowpan6_contexts); #endif diff --git a/lwip/src/netif/ppp/ppp.c b/lwip/src/netif/ppp/ppp.c index a9c18e3..be58553 100644 --- a/lwip/src/netif/ppp/ppp.c +++ b/lwip/src/netif/ppp/ppp.c @@ -216,7 +216,8 @@ static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protoc /***********************************/ #if PPP_AUTH_SUPPORT void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { - LWIP_ASSERT_CORE_LOCKED(); + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD", pcb->phase == PPP_PHASE_DEAD); + #if PAP_SUPPORT pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP); #endif /* PAP_SUPPORT */ @@ -238,6 +239,8 @@ void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *pas #if MPPE_SUPPORT /* Set MPPE configuration */ void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) { + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD", pcb->phase == PPP_PHASE_DEAD); + if (flags == PPP_MPPE_DISABLE) { pcb->settings.require_mppe = 0; return; diff --git a/lwip/src/netif/ppp/pppoe.c b/lwip/src/netif/ppp/pppoe.c index 8ed2d63..971b36b 100644 --- a/lwip/src/netif/ppp/pppoe.c +++ b/lwip/src/netif/ppp/pppoe.c @@ -175,8 +175,10 @@ ppp_pcb *pppoe_create(struct netif *pppif, { ppp_pcb *ppp; struct pppoe_softc *sc; +#if !PPPOE_SCNAME_SUPPORT LWIP_UNUSED_ARG(service_name); LWIP_UNUSED_ARG(concentrator_name); +#endif /* !PPPOE_SCNAME_SUPPORT */ LWIP_ASSERT_CORE_LOCKED(); sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF); @@ -193,6 +195,10 @@ ppp_pcb *pppoe_create(struct netif *pppif, memset(sc, 0, sizeof(struct pppoe_softc)); sc->pcb = ppp; sc->sc_ethif = ethif; +#if PPPOE_SCNAME_SUPPORT + sc->sc_service_name = service_name; + sc->sc_concentrator_name = concentrator_name; +#endif /* PPPOE_SCNAME_SUPPORT */ /* put the new interface at the head of the list */ sc->next = pppoe_softc_list; pppoe_softc_list = sc; @@ -300,15 +306,6 @@ pppoe_destroy(ppp_pcb *ppp, void *ctx) break; } } - -#ifdef PPPOE_TODO - if (sc->sc_concentrator_name) { - mem_free(sc->sc_concentrator_name); - } - if (sc->sc_service_name) { - mem_free(sc->sc_service_name); - } -#endif /* PPPOE_TODO */ LWIP_MEMPOOL_FREE(PPPOE_IF, sc); return ERR_OK; @@ -757,13 +754,13 @@ pppoe_send_padi(struct pppoe_softc *sc) struct pbuf *pb; u8_t *p; int len; -#ifdef PPPOE_TODO +#if PPPOE_SCNAME_SUPPORT int l1 = 0, l2 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ +#endif /* PPPOE_SCNAME_SUPPORT */ /* calculate length of frame (excluding ethernet header + pppoe header) */ len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ -#ifdef PPPOE_TODO +#if PPPOE_SCNAME_SUPPORT if (sc->sc_service_name != NULL) { l1 = (int)strlen(sc->sc_service_name); len += l1; @@ -772,7 +769,7 @@ pppoe_send_padi(struct pppoe_softc *sc) l2 = (int)strlen(sc->sc_concentrator_name); len += 2 + 2 + l2; } -#endif /* PPPOE_TODO */ +#endif /* PPPOE_SCNAME_SUPPORT */ LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); @@ -787,24 +784,24 @@ pppoe_send_padi(struct pppoe_softc *sc) /* fill in pkt */ PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO +#if PPPOE_SCNAME_SUPPORT if (sc->sc_service_name != NULL) { PPPOE_ADD_16(p, l1); MEMCPY(p, sc->sc_service_name, l1); p += l1; } else -#endif /* PPPOE_TODO */ +#endif /* PPPOE_SCNAME_SUPPORT */ { PPPOE_ADD_16(p, 0); } -#ifdef PPPOE_TODO +#if PPPOE_SCNAME_SUPPORT if (sc->sc_concentrator_name != NULL) { PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); PPPOE_ADD_16(p, l2); MEMCPY(p, sc->sc_concentrator_name, l2); p += l2; } -#endif /* PPPOE_TODO */ +#endif /* PPPOE_SCNAME_SUPPORT */ PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); PPPOE_ADD_16(p, sizeof(sc)); MEMCPY(p, &sc, sizeof sc); @@ -982,17 +979,17 @@ pppoe_send_padr(struct pppoe_softc *sc) struct pbuf *pb; u8_t *p; size_t len; -#ifdef PPPOE_TODO +#if PPPOE_SCNAME_SUPPORT size_t l1 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ +#endif /* PPPOE_SCNAME_SUPPORT */ len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ -#ifdef PPPOE_TODO +#if PPPOE_SCNAME_SUPPORT if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ l1 = strlen(sc->sc_service_name); len += l1; } -#endif /* PPPOE_TODO */ +#endif /* PPPOE_SCNAME_SUPPORT */ if (sc->sc_ac_cookie_len > 0) { len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ } @@ -1006,13 +1003,13 @@ pppoe_send_padr(struct pppoe_softc *sc) p = (u8_t*)pb->payload; PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO +#if PPPOE_SCNAME_SUPPORT if (sc->sc_service_name != NULL) { PPPOE_ADD_16(p, l1); MEMCPY(p, sc->sc_service_name, l1); p += l1; } else -#endif /* PPPOE_TODO */ +#endif /* PPPOE_SCNAME_SUPPORT */ { PPPOE_ADD_16(p, 0); } diff --git a/lwip/src/netif/zepif.c b/lwip/src/netif/zepif.c index b403303..de43b99 100644 --- a/lwip/src/netif/zepif.c +++ b/lwip/src/netif/zepif.c @@ -201,7 +201,7 @@ zepif_linkoutput(struct netif *netif, struct pbuf *p) state->seqno++; zep->len = (u8_t)p->tot_len; - err = pbuf_take_at(q, p->payload, p->tot_len, sizeof(struct zep_hdr)); + err = pbuf_copy_partial_pbuf(q, p, p->tot_len, sizeof(struct zep_hdr)); if (err == ERR_OK) { #if ZEPIF_LOOPBACK zepif_udp_recv(netif, state->pcb, pbuf_clone(PBUF_RAW, PBUF_RAM, q), NULL, 0); -- 2.30.2 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel