implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) (fixes bug #35061)

This commit is contained in:
goldsimon 2011-12-17 22:12:01 +01:00
parent 5546e46c60
commit 1d96195f47
7 changed files with 36 additions and 25 deletions

View File

@ -9,11 +9,9 @@ HISTORY
2012-01-16: Simon Goldschmidt 2012-01-16: Simon Goldschmidt
* opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP
2011-07-21: Simon Goldschmidt (patch by hanhui) 2011-12-17: Simon Goldschmidt
* ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW)
Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. (fixes bug #35061)
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-09-27: Simon Goldschmidt 2011-09-27: Simon Goldschmidt
* opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) * 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 * 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) 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) 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman)
* tcp.c, tcp_out.c: bug #33604: added some more asserts to check that * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that
pcb->state != LISTEN pcb->state != LISTEN

View File

@ -1691,7 +1691,7 @@ lwip_getsockopt_internal(void *arg)
case SO_REUSEPORT: case SO_REUSEPORT:
#endif /* SO_REUSE */ #endif /* SO_REUSE */
/*case SO_USELOOPBACK: UNIMPL */ /*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", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
s, optname, (*(int*)optval?"on":"off"))); s, optname, (*(int*)optval?"on":"off")));
break; break;
@ -2108,9 +2108,9 @@ lwip_setsockopt_internal(void *arg)
#endif /* SO_REUSE */ #endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */ /* UNIMPL case SO_USELOOPBACK: */
if (*(int*)optval) { if (*(int*)optval) {
sock->conn->pcb.ip->so_options |= optname; ip_set_option(sock->conn->pcb.ip, optname);
} else { } 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", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
s, optname, (*(int*)optval?"on":"off"))); s, optname, (*(int*)optval?"on":"off")));

View File

@ -680,7 +680,7 @@ dhcp_start(struct netif *netif)
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
return ERR_MEM; 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 */ /* set up local and remote port for the pcb */
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
@ -730,7 +730,7 @@ dhcp_inform(struct netif *netif)
return; return;
} }
dhcp.pcb = pcb; 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); udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
} }

View File

@ -95,7 +95,7 @@ raw_input(struct pbuf *p, struct netif *inp)
ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest))) { ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest))) {
#if IP_SOF_BROADCAST_RECV #if IP_SOF_BROADCAST_RECV
/* broadcast filter? */ /* broadcast filter? */
if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&current_iphdr_dest, inp)) if (ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(&current_iphdr_dest, inp))
#endif /* IP_SOF_BROADCAST_RECV */ #endif /* IP_SOF_BROADCAST_RECV */
{ {
/* receive callback function available? */ /* 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 #if IP_SOF_BROADCAST
/* broadcast filter? */ /* 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)); 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() */ /* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) { if (q != p) {

View File

@ -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 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. 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; max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
} }
#endif /* SO_REUSE */ #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. /* 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 For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in
tcp_connect. */ tcp_connect. */
if (((pcb->so_options & SOF_REUSEADDR) == 0) || if (!ip_get_option(pcb, SOF_REUSEADDR) ||
((cpcb->so_options & SOF_REUSEADDR) == 0)) !ip_get_option(cpcb, SOF_REUSEADDR))
#endif /* SO_REUSE */ #endif /* SO_REUSE */
{ {
if (ip_addr_isany(&(cpcb->local_ip)) || if (ip_addr_isany(&(cpcb->local_ip)) ||
@ -521,7 +521,7 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
return pcb; return pcb;
} }
#if SO_REUSE #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 /* 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 is declared (listen-/connection-pcb), we have to make sure now that
this port is only used once for every local IP. */ 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->state = LISTEN;
lpcb->prio = pcb->prio; lpcb->prio = pcb->prio;
lpcb->so_options = pcb->so_options; lpcb->so_options = pcb->so_options;
lpcb->so_options |= SOF_ACCEPTCONN; ip_set_option(lpcb, SOF_ACCEPTCONN);
lpcb->ttl = pcb->ttl; lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos; lpcb->tos = pcb->tos;
ip_addr_copy(lpcb->local_ip, pcb->local_ip); 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 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 /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure
now that the 5-tuple is unique. */ now that the 5-tuple is unique. */
struct tcp_pcb *cpcb; struct tcp_pcb *cpcb;
@ -880,7 +880,7 @@ tcp_slowtmr_start:
} }
/* Check if KEEPALIVE should be sent */ /* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && if(ip_get_option(pcb, SOF_KEEPALIVE) &&
((pcb->state == ESTABLISHED) || ((pcb->state == ESTABLISHED) ||
(pcb->state == CLOSE_WAIT))) { (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > if((u32_t)(tcp_ticks - pcb->tmr) >

View File

@ -246,7 +246,7 @@ udp_input(struct pbuf *p, struct netif *inp)
ip_addr_ismulticast(&current_iphdr_dest) || ip_addr_ismulticast(&current_iphdr_dest) ||
#endif /* LWIP_IGMP */ #endif /* LWIP_IGMP */
#if IP_SOF_BROADCAST_RECV #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_isany(&pcb->local_ip) ||
ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) {
#else /* IP_SOF_BROADCAST_RECV */ #else /* IP_SOF_BROADCAST_RECV */
@ -351,7 +351,7 @@ udp_input(struct pbuf *p, struct netif *inp)
snmp_inc_udpindatagrams(); snmp_inc_udpindatagrams();
#if SO_REUSE && SO_REUSE_RXTOALL #if SO_REUSE && SO_REUSE_RXTOALL
if ((broadcast || ip_addr_ismulticast(&current_iphdr_dest)) && if ((broadcast || ip_addr_ismulticast(&current_iphdr_dest)) &&
((pcb->so_options & SOF_REUSEADDR) != 0)) { ip_get_option(pcb, SOF_REUSEADDR)) {
/* pass broadcast- or multicast packets to all multicast pcbs /* pass broadcast- or multicast packets to all multicast pcbs
if SOF_REUSEADDR is set on the first match */ if SOF_REUSEADDR is set on the first match */
struct udp_pcb *mpcb; struct udp_pcb *mpcb;
@ -366,7 +366,7 @@ udp_input(struct pbuf *p, struct netif *inp)
ip_addr_ismulticast(&current_iphdr_dest) || ip_addr_ismulticast(&current_iphdr_dest) ||
#endif /* LWIP_IGMP */ #endif /* LWIP_IGMP */
#if IP_SOF_BROADCAST_RECV #if IP_SOF_BROADCAST_RECV
(broadcast && (mpcb->so_options & SOF_BROADCAST)))) { (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))) {
#else /* IP_SOF_BROADCAST_RECV */ #else /* IP_SOF_BROADCAST_RECV */
(broadcast))) { (broadcast))) {
#endif /* IP_SOF_BROADCAST_RECV */ #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 #if IP_SOF_BROADCAST
/* broadcast filter? */ /* 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, LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
return ERR_VAL; 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 PCB is alread bound to, unless *all* PCBs with that port have tha
REUSEADDR flag set. */ REUSEADDR flag set. */
#if SO_REUSE #if SO_REUSE
else if (((pcb->so_options & SOF_REUSEADDR) == 0) && else if (!ip_get_option(pcb, SOF_REUSEADDR) &&
((ipcb->so_options & SOF_REUSEADDR) == 0)) { !ip_get_option(ipcb, SOF_REUSEADDR)) {
#else /* SO_REUSE */ #else /* SO_REUSE */
/* port matches that of PCB in list and REUSEADDR not set -> reject */ /* port matches that of PCB in list and REUSEADDR not set -> reject */
else { else {

View File

@ -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 */ /** Destination IP address of current_header */
#define ip_current_dest_addr() (&current_iphdr_dest) #define ip_current_dest_addr() (&current_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 #if IP_DEBUG
void ip_debug_print(struct pbuf *p); void ip_debug_print(struct pbuf *p);
#else #else