diff --git a/CHANGELOG b/CHANGELOG index 8f39859c..3ffd93fb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -161,7 +161,41 @@ HISTORY ++ Bugfixes: - 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) + 2014-03-14: Simon Goldschmidt + * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 + + 2014-03-11: Simon Goldschmidt (patch by Mason) + * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for + POSIX-compliance + + 2014-02-27: Simon Goldschmidt + * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST + + 2014-02-27: Simon Goldschmidt + * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when + IP_SOF_BROADCAST_RECV==1 + + 2014-02-27: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on + unconnected/listening TCP sockets + + 2014-02-27: Simon Goldschmidt + * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1 + + 2014-02-25: Simon Goldschmidt + * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface + + 2014-02-25: Simon Goldschmidt, patch by Fatih Asici + * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind() + + 2014-02-25: Simon Goldschmidt + * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly; + renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match() + + 2014-02-25: Simon Goldschmidt + * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1 + + 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3) 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 7f7138ed..f39d7359 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -1455,7 +1455,13 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg) #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: - API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); + if ((msg->msg.ad.local == 0) && + ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { + /* pcb is not connected and remote name is requested */ + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); + } break; #endif /* LWIP_TCP */ default: diff --git a/src/api/sockets.c b/src/api/sockets.c index a298869d..19edfc57 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -223,13 +223,13 @@ static const int err_to_errno_table[] = { ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ err_to_errno_table[-(err)] : EIO) -#ifdef ERRNO +#if LWIP_SOCKET_SET_ERRNO #ifndef set_errno #define set_errno(err) do { if (err) { errno = (err); } } while(0) #endif -#else /* ERRNO */ +#else /* LWIP_SOCKET_SET_ERRNO */ #define set_errno(err) -#endif /* ERRNO */ +#endif /* LWIP_SOCKET_SET_ERRNO */ #define sock_set_errno(sk, e) do { \ sk->err = (e); \ @@ -612,7 +612,7 @@ lwip_listen(int s, int backlog) LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { sock_set_errno(sock, EOPNOTSUPP); - return EOPNOTSUPP; + return -1; } sock_set_errno(sock, err_to_errno(err)); return -1; @@ -1447,11 +1447,11 @@ lwip_shutdown(int s, int how) if (sock->conn != NULL) { if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { sock_set_errno(sock, EOPNOTSUPP); - return EOPNOTSUPP; + return -1; } } else { sock_set_errno(sock, ENOTCONN); - return ENOTCONN; + return -1; } if (how == SHUT_RD) { @@ -1463,7 +1463,7 @@ lwip_shutdown(int s, int how) shut_tx = 1; } else { sock_set_errno(sock, EINVAL); - return EINVAL; + return -1; } err = netconn_shutdown(sock->conn, shut_rx, shut_tx); @@ -1478,6 +1478,7 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) union sockaddr_aligned saddr; ipX_addr_t naddr; u16_t port; + err_t err; sock = get_socket(s); if (!sock) { @@ -1486,7 +1487,11 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) /* get the IP address and port */ /* @todo: this does not work for IPv6, yet */ - netconn_getaddr(sock->conn, ipX_2_ip(&naddr), &port, local); + err = netconn_getaddr(sock->conn, ipX_2_ip(&naddr), &port, local); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &saddr, &naddr, port); diff --git a/src/core/dhcp.c b/src/core/dhcp.c index 21fd7845..4c605212 100644 --- a/src/core/dhcp.c +++ b/src/core/dhcp.c @@ -1671,15 +1671,18 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", (dhcp->p_out->len >= sizeof(struct dhcp_msg))); - /* reuse transaction identifier in retransmissions */ - if (dhcp->tries == 0) { + /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ + if (message_type != DHCP_REQUEST) { + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) - xid = LWIP_RAND(); + xid = LWIP_RAND(); #else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - xid++; + xid++; #endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + } + dhcp->xid = xid; } - dhcp->xid = xid; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("transaction id xid(%"X32_F")\n", xid)); diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index 107c0e9a..2e79f545 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -271,7 +271,7 @@ igmp_report_groups(struct netif *netif) LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif)); while (group != NULL) { - if (group->netif == netif) { + if ((group->netif == netif) && (!(ip_addr_cmp(&(group->group_address), &allsystems)))) { igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); } group = group->next; @@ -674,8 +674,10 @@ igmp_tmr(void) static void igmp_timeout(struct igmp_group *group) { - /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */ - if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group + (unless it is the allsystems group) */ + if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + (!(ip_addr_cmp(&(group->group_address), &allsystems)))) { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); ip_addr_debug_print(IGMP_DEBUG, &(group->group_address)); LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c index 04a36111..48d2a391 100644 --- a/src/core/ipv4/ip4.c +++ b/src/core/ipv4/ip4.c @@ -123,7 +123,12 @@ ip_route(ip_addr_t *dest) /* iterate through netifs */ for (netif = netif_list; netif != NULL; netif = netif->next) { /* network mask matches? */ - if (netif_is_up(netif)) { + if ((netif_is_up(netif)) +#if LWIP_IPV6 + /* prevent using IPv6-only interfaces */ + && (!ip_addr_isany(&(netif->ip_addr))) +#endif /* LWIP_IPV6 */ + ) { if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { /* return netif on which to forward IP packet */ return netif; diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c index 5976986b..da373bd3 100644 --- a/src/core/ipv6/nd6.c +++ b/src/core/ipv6/nd6.c @@ -723,7 +723,7 @@ nd6_tmr(void) /* Try to get an address on this netif that is invalid. * Skip 0 index (link-local address) */ for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { - if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDRESS_STATE_INVALID) { + if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { /* Generate an address using this prefix and interface ID from link-local address. */ prefix_list[i].netif->ip6_addr[j].addr[0] = prefix_list[i].prefix.addr[0]; prefix_list[i].netif->ip6_addr[j].addr[1] = prefix_list[i].prefix.addr[1]; diff --git a/src/core/netif.c b/src/core/netif.c index ce448858..36e801b3 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -872,7 +872,7 @@ netif_poll_all(void) #if LWIP_IPV6 s8_t -netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr) +netif_get_ip6_addr_match(struct netif * netif, ip6_addr_t * ip6addr) { s8_t i; for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { diff --git a/src/core/pbuf.c b/src/core/pbuf.c index 0e5981bd..27130455 100644 --- a/src/core/pbuf.c +++ b/src/core/pbuf.c @@ -1192,12 +1192,10 @@ pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) u16_t i; u16_t max = p->tot_len - mem_len; if (p->tot_len >= mem_len + start_offset) { - for(i = start_offset; i <= max; ) { + for(i = start_offset; i <= max; i++) { u16_t plus = pbuf_memcmp(p, i, mem, mem_len); if (plus == 0) { return i; - } else { - i += plus; } } } diff --git a/src/core/raw.c b/src/core/raw.c index 6b597352..2843f352 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -82,18 +82,15 @@ raw_input(struct pbuf *p, struct netif *inp) struct ip_hdr *iphdr; s16_t proto; u8_t eaten = 0; -#if LWIP_IPV6 - struct ip6_hdr *ip6hdr; -#endif /* LWIP_IPV6 */ - LWIP_UNUSED_ARG(inp); iphdr = (struct ip_hdr *)p->payload; #if LWIP_IPV6 if (IPH_V(iphdr) == 6) { - ip6hdr = (struct ip6_hdr *)p->payload; + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; proto = IP6H_NEXTH(ip6hdr); + iphdr = NULL; } else #endif /* LWIP_IPV6 */ @@ -113,7 +110,7 @@ raw_input(struct pbuf *p, struct netif *inp) /* broadcast filter? */ if ((ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), inp)) #if LWIP_IPV6 - && !PCB_ISIPV6(pcb) + || PCB_ISIPV6(pcb) #endif /* LWIP_IPV6 */ ) #endif /* IP_SOF_BROADCAST_RECV */ @@ -124,7 +121,14 @@ raw_input(struct pbuf *p, struct netif *inp) void* old_payload = p->payload; #endif /* the receive callback function did not eat the packet? */ - eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr()); +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + eaten = pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr()); + } else +#endif /* LWIP_IPV6 */ + { + eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr()); + } if (eaten != 0) { /* receive function ate the packet */ p = NULL; @@ -282,7 +286,6 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) #if IP_SOF_BROADCAST #if LWIP_IPV6 - /* @todo: why does IPv6 not filter broadcast with SOF_BROADCAST enabled? */ if (!PCB_ISIPV6(pcb)) #endif /* LWIP_IPV6 */ { diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 6eb2d64f..9e842780 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -172,6 +172,7 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, seg->flags = optflags; seg->next = NULL; seg->p = p; + LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); seg->len = p->tot_len - optlen; #if TCP_OVERSIZE_DBGCHECK seg->oversize_left = 0; @@ -397,6 +398,8 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) agreed about it with the remote host. */ optflags = TF_SEG_OPTS_TS; optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + /* ensure that segments can hold at least one data byte... */ + mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); } #endif /* LWIP_TCP_TIMESTAMPS */ @@ -434,6 +437,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) /* Usable space at the end of the last unsent segment */ unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); space = mss_local - (last_unsent->len + unsent_optlen); /* @@ -658,6 +662,10 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) last_unsent->len += concat_p->tot_len; #if TCP_CHECKSUM_ON_COPY if (concat_chksummed) { + /*if concat checksumm swapped - swap it back */ + if (concat_chksum_swapped){ + concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); + } tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, &last_unsent->chksum_swapped); last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; diff --git a/src/core/udp.c b/src/core/udp.c index ac0e56d1..986e6992 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -307,7 +307,7 @@ udp_input(struct pbuf *p, struct netif *inp) } else { #if LWIP_IPV6 if (ip_current_is_v6()) { - for_us = netif_matches_ip6_addr(inp, ip6_current_dest_addr()); + for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; } else #endif /* LWIP_IPV6 */ { @@ -721,7 +721,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, } } else { /* use UDP PCB local IPv6 address as source address, if still valid. */ - if (netif_matches_ip6_addr(netif, ipX_2_ip6(&pcb->local_ip)) < 0) { + if (netif_get_ip6_addr_match(netif, ipX_2_ip6(&pcb->local_ip)) < 0) { /* Address isn't valid anymore. */ if (q != p) { /* free the header pbuf */ diff --git a/src/include/ipv6/lwip/nd6.h b/src/include/ipv6/lwip/nd6.h index 28636e89..193788fb 100644 --- a/src/include/ipv6/lwip/nd6.h +++ b/src/include/ipv6/lwip/nd6.h @@ -328,13 +328,6 @@ PACK_STRUCT_END # include "arch/epstruct.h" #endif -/* the possible states of an IP address */ -#define IP6_ADDRESS_STATE_INVALID (0) -#define IP6_ADDRESS_STATE_VALID (0x4) -#define IP6_ADDRESS_STATE_PREFERRED (0x5) /* includes valid */ -#define IP6_ADDRESS_STATE_DEPRECATED (0x6) /* includes valid */ -#define IP6_ADDRESS_STATE_TENTATIV (0x8) - /** 1 second period */ #define ND6_TMR_INTERVAL 1000 diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index 35fee3c8..426e8141 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -370,7 +370,7 @@ void netif_poll_all(void); #define netif_ip6_addr(netif, i) (&((netif)->ip6_addr[(i)])) #define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[(i)]) #define netif_ip6_addr_set_state(netif, i, state) ((netif)->ip6_addr_state[(i)] = (state)) -s8_t netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr); +s8_t netif_get_ip6_addr_match(struct netif * netif, ip6_addr_t * ip6addr); void netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit); #endif /* LWIP_IPV6 */ diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 78361421..8e779153 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -1484,6 +1484,13 @@ #define LWIP_SOCKET 1 #endif +/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete + * successfully, as required by POSIX. Default is POSIX-compliant. + */ +#ifndef LWIP_SOCKET_SET_ERRNO +#define LWIP_SOCKET_SET_ERRNO 1 +#endif + /** * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. * (only used if you use sockets.c) @@ -1707,6 +1714,7 @@ #else #define LINK_STATS 0 +#define ETHARP_STATS 0 #define IP_STATS 0 #define IPFRAG_STATS 0 #define ICMP_STATS 0 diff --git a/src/netif/etharp.c b/src/netif/etharp.c index b5b0b825..dd1621da 100644 --- a/src/netif/etharp.c +++ b/src/netif/etharp.c @@ -77,7 +77,7 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}}; * for ARP_TMR_INTERVAL = 1000, this is * (60 * 20) seconds = 20 minutes. */ -#define ARP_MAXAGE (60*20) +#define ARP_MAXAGE 1200 /** Re-request a used ARP entry 1 minute before it would expire to prevent * breaking a steadily used connection because the ARP entry timed out. */ #define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 60) @@ -114,8 +114,8 @@ struct etharp_entry { ip_addr_t ipaddr; struct netif *netif; struct eth_addr ethaddr; + u16_t ctime; u8_t state; - u8_t ctime; }; static struct etharp_entry arp_table[ARP_TABLE_SIZE];