diff --git a/CHANGELOG b/CHANGELOG index e41e80bf..fdbebc20 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,11 +9,9 @@ HISTORY 2012-01-16: Simon Goldschmidt * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP - 2011-07-21: Simon Goldschmidt (patch by hanhui) - * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: - Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. - Also added code to allow ip_forward() to forward non-broadcast packets to - the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + 2011-12-17: Simon Goldschmidt + * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) + (fixes bug #35061) 2011-09-27: Simon Goldschmidt * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) @@ -47,6 +45,12 @@ HISTORY * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) + 2011-07-21: Simon Goldschmidt (patch by hanhui) + * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: + Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. + Also added code to allow ip_forward() to forward non-broadcast packets to + the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that pcb->state != LISTEN diff --git a/src/api/sockets.c b/src/api/sockets.c index 27f0672e..359919e7 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -1691,7 +1691,7 @@ lwip_getsockopt_internal(void *arg) case SO_REUSEPORT: #endif /* SO_REUSE */ /*case SO_USELOOPBACK: UNIMPL */ - *(int*)optval = sock->conn->pcb.ip->so_options & optname; + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off"))); break; @@ -2108,9 +2108,9 @@ lwip_setsockopt_internal(void *arg) #endif /* SO_REUSE */ /* UNIMPL case SO_USELOOPBACK: */ if (*(int*)optval) { - sock->conn->pcb.ip->so_options |= optname; + ip_set_option(sock->conn->pcb.ip, optname); } else { - sock->conn->pcb.ip->so_options &= ~optname; + ip_reset_option(sock->conn->pcb.ip, optname); } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off"))); diff --git a/src/core/dhcp.c b/src/core/dhcp.c index 489e6bc9..7c1fc4d5 100644 --- a/src/core/dhcp.c +++ b/src/core/dhcp.c @@ -680,7 +680,7 @@ dhcp_start(struct netif *netif) LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); return ERR_MEM; } - dhcp->pcb->so_options |= SOF_BROADCAST; + ip_set_option(dhcp->pcb, SOF_BROADCAST); /* set up local and remote port for the pcb */ udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); @@ -730,7 +730,7 @@ dhcp_inform(struct netif *netif) return; } dhcp.pcb = pcb; - dhcp.pcb->so_options |= SOF_BROADCAST; + ip_set_option(dhcp.pcb, SOF_BROADCAST); udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); } diff --git a/src/core/raw.c b/src/core/raw.c index a245cc55..7160c0fb 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -95,7 +95,7 @@ raw_input(struct pbuf *p, struct netif *inp) ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest))) { #if IP_SOF_BROADCAST_RECV /* broadcast filter? */ - if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp)) + if (ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp)) #endif /* IP_SOF_BROADCAST_RECV */ { /* receive callback function available? */ @@ -245,7 +245,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) #if IP_SOF_BROADCAST /* broadcast filter? */ - if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) { + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); /* free any temporary header pbuf allocated by pbuf_header() */ if (q != p) { diff --git a/src/core/tcp.c b/src/core/tcp.c index 81576d3c..5c9796ee 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -437,7 +437,7 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) We do not dump TIME_WAIT pcb's; they can still be matched by incoming packets using both local and remote IP addresses and ports to distinguish. */ - if ((pcb->so_options & SOF_REUSEADDR) != 0) { + if (ip_get_option(pcb, SOF_REUSEADDR)) { max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; } #endif /* SO_REUSE */ @@ -457,8 +457,8 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) /* Omit checking for the same port if both pcbs have REUSEADDR set. For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in tcp_connect. */ - if (((pcb->so_options & SOF_REUSEADDR) == 0) || - ((cpcb->so_options & SOF_REUSEADDR) == 0)) + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) #endif /* SO_REUSE */ { if (ip_addr_isany(&(cpcb->local_ip)) || @@ -521,7 +521,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) return pcb; } #if SO_REUSE - if ((pcb->so_options & SOF_REUSEADDR) != 0) { + if (ip_get_option(pcb, SOF_REUSEADDR)) { /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage is declared (listen-/connection-pcb), we have to make sure now that this port is only used once for every local IP. */ @@ -544,7 +544,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) lpcb->state = LISTEN; lpcb->prio = pcb->prio; lpcb->so_options = pcb->so_options; - lpcb->so_options |= SOF_ACCEPTCONN; + ip_set_option(lpcb, SOF_ACCEPTCONN); lpcb->ttl = pcb->ttl; lpcb->tos = pcb->tos; ip_addr_copy(lpcb->local_ip, pcb->local_ip); @@ -712,7 +712,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, } } #if SO_REUSE - if ((pcb->so_options & SOF_REUSEADDR) != 0) { + if (ip_get_option(pcb, SOF_REUSEADDR)) { /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure now that the 5-tuple is unique. */ struct tcp_pcb *cpcb; @@ -880,7 +880,7 @@ tcp_slowtmr_start: } /* Check if KEEPALIVE should be sent */ - if((pcb->so_options & SOF_KEEPALIVE) && + if(ip_get_option(pcb, SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { if((u32_t)(tcp_ticks - pcb->tmr) > diff --git a/src/core/udp.c b/src/core/udp.c index 96d67e00..32c7d384 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -246,7 +246,7 @@ udp_input(struct pbuf *p, struct netif *inp) ip_addr_ismulticast(¤t_iphdr_dest) || #endif /* LWIP_IGMP */ #if IP_SOF_BROADCAST_RECV - (broadcast && (pcb->so_options & SOF_BROADCAST) && + (broadcast && ip_get_option(pcb, SOF_BROADCAST) && (ip_addr_isany(&pcb->local_ip) || ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { #else /* IP_SOF_BROADCAST_RECV */ @@ -351,7 +351,7 @@ udp_input(struct pbuf *p, struct netif *inp) snmp_inc_udpindatagrams(); #if SO_REUSE && SO_REUSE_RXTOALL if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) && - ((pcb->so_options & SOF_REUSEADDR) != 0)) { + ip_get_option(pcb, SOF_REUSEADDR)) { /* pass broadcast- or multicast packets to all multicast pcbs if SOF_REUSEADDR is set on the first match */ struct udp_pcb *mpcb; @@ -366,7 +366,7 @@ udp_input(struct pbuf *p, struct netif *inp) ip_addr_ismulticast(¤t_iphdr_dest) || #endif /* LWIP_IGMP */ #if IP_SOF_BROADCAST_RECV - (broadcast && (mpcb->so_options & SOF_BROADCAST)))) { + (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))) { #else /* IP_SOF_BROADCAST_RECV */ (broadcast))) { #endif /* IP_SOF_BROADCAST_RECV */ @@ -567,7 +567,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, #if IP_SOF_BROADCAST /* broadcast filter? */ - if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) { + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) { LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); return ERR_VAL; @@ -787,8 +787,8 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) PCB is alread bound to, unless *all* PCBs with that port have tha REUSEADDR flag set. */ #if SO_REUSE - else if (((pcb->so_options & SOF_REUSEADDR) == 0) && - ((ipcb->so_options & SOF_REUSEADDR) == 0)) { + else if (!ip_get_option(pcb, SOF_REUSEADDR) && + !ip_get_option(ipcb, SOF_REUSEADDR)) { #else /* SO_REUSE */ /* port matches that of PCB in list and REUSEADDR not set -> reject */ else { diff --git a/src/include/ipv4/lwip/ip.h b/src/include/ipv4/lwip/ip.h index 33319f4c..00c83a0a 100644 --- a/src/include/ipv4/lwip/ip.h +++ b/src/include/ipv4/lwip/ip.h @@ -201,6 +201,13 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, /** Destination IP address of current_header */ #define ip_current_dest_addr() (¤t_iphdr_dest) +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + #if IP_DEBUG void ip_debug_print(struct pbuf *p); #else