bug #52937: raw_input() must tell ip4/6_input() if protocol has been received

This also moves "raw_input" and "raw_netif_ip_addr_changed" to a new file
raw_priv.h
This commit is contained in:
goldsimon
2018-01-25 12:51:46 +01:00
parent ebda5cb04e
commit fe2c249fb7
6 changed files with 127 additions and 36 deletions

View File

@@ -50,7 +50,7 @@
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/igmp.h"
#include "lwip/raw.h"
#include "lwip/priv/raw_priv.h"
#include "lwip/udp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/autoip.h"
@@ -423,6 +423,9 @@ ip4_input(struct pbuf *p, struct netif *inp)
#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP
int check_ip_src = 1;
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */
#if LWIP_RAW
raw_input_state_t raw_status;
#endif /* LWIP_RAW */
LWIP_ASSERT_CORE_LOCKED();
@@ -675,7 +678,8 @@ ip4_input(struct pbuf *p, struct netif *inp)
#if LWIP_RAW
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0)
raw_status = raw_input(p, inp);
if (raw_status != RAW_INPUT_EATEN)
#endif /* LWIP_RAW */
{
pbuf_remove_header(p, iphdr_hlen); /* Move to payload, no check necessary. */
@@ -708,21 +712,29 @@ ip4_input(struct pbuf *p, struct netif *inp)
break;
#endif /* LWIP_IGMP */
default:
#if LWIP_RAW
if (raw_status == RAW_INPUT_DELIVERED) {
MIB2_STATS_INC(mib2.ipindelivers);
} else
#endif /* LWIP_RAW */
{
#if LWIP_ICMP
/* send ICMP destination protocol unreachable unless is was a broadcast */
if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) &&
!ip4_addr_ismulticast(ip4_current_dest_addr())) {
pbuf_header_force(p, (s16_t)iphdr_hlen); /* Move to ip header, no check necessary. */
icmp_dest_unreach(p, ICMP_DUR_PROTO);
}
/* send ICMP destination protocol unreachable unless is was a broadcast */
if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) &&
!ip4_addr_ismulticast(ip4_current_dest_addr())) {
pbuf_header_force(p, (s16_t)iphdr_hlen); /* Move to ip header, no check necessary. */
icmp_dest_unreach(p, ICMP_DUR_PROTO);
}
#endif /* LWIP_ICMP */
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", (u16_t)IPH_PROTO(iphdr)));
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
MIB2_STATS_INC(mib2.ipinunknownprotos);
}
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", (u16_t)IPH_PROTO(iphdr)));
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
MIB2_STATS_INC(mib2.ipinunknownprotos);
break;
}
}

View File

@@ -51,7 +51,7 @@
#include "lwip/ip6_addr.h"
#include "lwip/ip6_frag.h"
#include "lwip/icmp6.h"
#include "lwip/raw.h"
#include "lwip/priv/raw_priv.h"
#include "lwip/udp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/dhcp6.h"
@@ -516,6 +516,9 @@ ip6_input(struct pbuf *p, struct netif *inp)
@todo
int check_ip_src=1;
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
#if LWIP_RAW
raw_input_state_t raw_status;
#endif /* LWIP_RAW */
LWIP_ASSERT_CORE_LOCKED();
@@ -1055,7 +1058,8 @@ options_done:
/* p points to IPv6 header again for raw_input. */
pbuf_header_force(p, (s16_t)hlen_tot);
/* raw input did not eat the packet? */
if (raw_input(p, inp) == 0)
raw_status = raw_input(p, inp);
if (raw_status != RAW_INPUT_EATEN)
{
/* Point to payload. */
pbuf_remove_header(p, hlen_tot);
@@ -1085,19 +1089,26 @@ options_done:
break;
#endif /* LWIP_ICMP */
default:
#if LWIP_RAW
if (raw_status == RAW_INPUT_DELIVERED) {
/* @todo: ipv6 mib in-delivers? */
} else
#endif /* LWIP_RAW */
{
#if LWIP_ICMP6
/* p points to IPv6 header again for raw_input. */
pbuf_header_force(p, (s16_t)hlen_tot);
/* send ICMP parameter problem unless it was a multicast or ICMPv6 */
if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
(IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
}
/* p points to IPv6 header again for raw_input. */
pbuf_header_force(p, (s16_t)hlen_tot);
/* send ICMP parameter problem unless it was a multicast or ICMPv6 */
if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
(IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
}
#endif /* LWIP_ICMP */
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
IP6_STATS_INC(ip6.proterr);
IP6_STATS_INC(ip6.drop);
}
pbuf_free(p);
IP6_STATS_INC(ip6.proterr);
IP6_STATS_INC(ip6.drop);
break;
}
}

View File

@@ -59,7 +59,7 @@
#include "lwip/netif.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/udp.h"
#include "lwip/raw.h"
#include "lwip/priv/raw_priv.h"
#include "lwip/snmp.h"
#include "lwip/igmp.h"
#include "lwip/etharp.h"

View File

@@ -54,6 +54,7 @@
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/raw.h"
#include "lwip/priv/raw_priv.h"
#include "lwip/stats.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
@@ -130,12 +131,12 @@ raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast)
* caller).
*
*/
u8_t
raw_input_state_t
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb, *prev;
s16_t proto;
u8_t eaten = 0;
raw_input_state_t ret = RAW_INPUT_NONE;
u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif());
LWIP_UNUSED_ARG(inp);
@@ -162,21 +163,22 @@ raw_input(struct pbuf *p, struct netif *inp)
pcb = raw_pcbs;
/* loop through all raw pcbs until the packet is eaten by one */
/* this allows multiple pcbs to match against the packet by design */
while ((eaten == 0) && (pcb != NULL)) {
while (pcb != NULL) {
if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) &&
(((pcb->flags & RAW_FLAGS_CONNECTED) == 0) ||
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) {
/* receive callback function available? */
if (pcb->recv != NULL) {
u8_t eaten;
#ifndef LWIP_NOASSERT
void *old_payload = p->payload;
#endif
ret = RAW_INPUT_DELIVERED;
/* the receive callback function did not eat the packet? */
eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
if (eaten != 0) {
/* receive function ate the packet */
p = NULL;
eaten = 1;
if (prev != NULL) {
/* move the pcb to the front of raw_pcbs so that is
found faster next time */
@@ -184,6 +186,7 @@ raw_input(struct pbuf *p, struct netif *inp)
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return RAW_INPUT_EATEN;
} else {
/* sanity-check that the receive callback did not alter the pbuf */
LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet",
@@ -196,7 +199,7 @@ raw_input(struct pbuf *p, struct netif *inp)
prev = pcb;
pcb = pcb->next;
}
return eaten;
return ret;
}
/**