From fe2c249fb717db077c5d3cd352ca64dba4ef0a9d Mon Sep 17 00:00:00 2001 From: goldsimon Date: Thu, 25 Jan 2018 12:51:46 +0100 Subject: [PATCH] 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 --- src/core/ipv4/ip4.c | 40 +++++++++++------- src/core/ipv6/ip6.c | 35 ++++++++++------ src/core/netif.c | 2 +- src/core/raw.c | 13 +++--- src/include/lwip/priv/raw_priv.h | 69 ++++++++++++++++++++++++++++++++ src/include/lwip/raw.h | 4 -- 6 files changed, 127 insertions(+), 36 deletions(-) create mode 100644 src/include/lwip/priv/raw_priv.h diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c index 3e2ad2b6..f836852e 100644 --- a/src/core/ipv4/ip4.c +++ b/src/core/ipv4/ip4.c @@ -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; } } diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c index fa4f6eac..993a65fb 100644 --- a/src/core/ipv6/ip6.c +++ b/src/core/ipv6/ip6.c @@ -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; } } diff --git a/src/core/netif.c b/src/core/netif.c index d48d23a5..e68545c5 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -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" diff --git a/src/core/raw.c b/src/core/raw.c index ae5e339b..3b34544b 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -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; } /** diff --git a/src/include/lwip/priv/raw_priv.h b/src/include/lwip/priv/raw_priv.h new file mode 100644 index 00000000..d4561d4f --- /dev/null +++ b/src/include/lwip/priv/raw_priv.h @@ -0,0 +1,69 @@ +/** + * @file + * raw API internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_RAW_PRIV_H +#define LWIP_HDR_RAW_PRIV_H + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/raw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** return codes for raw_input */ +typedef enum raw_input_state +{ + RAW_INPUT_NONE = 0, /* pbuf did not match any pcbs */ + RAW_INPUT_EATEN, /* pbuf handed off and delivered to pcb */ + RAW_INPUT_DELIVERED /* pbuf only delivered to pcb (pbuf can still be referenced) */ +} raw_input_state_t; + +/* The following functions are the lower layer interface to RAW. */ +raw_input_state_t raw_input(struct pbuf *p, struct netif *inp); + +void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* LWIP_HDR_RAW_PRIV_H */ diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index 8a872a55..c94f3bf4 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -122,12 +122,8 @@ void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *re #define raw_clear_flags(pcb, clr_flags) do { (pcb)->flags = (u8_t)((pcb)->flags & ~(clr_flags)); } while(0) #define raw_is_flag_set(pcb, flag) (((pcb)->flags & (flag)) != 0) -/* The following functions are the lower layer interface to RAW. */ -u8_t raw_input (struct pbuf *p, struct netif *inp); #define raw_init() /* Compatibility define, no init needed. */ -void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); - /* for compatibility with older implementation */ #define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto)