Subject: kern/7818: ICMP protocol packets are not handled for localhost
To: None <tech-net@netbsd.org>
From: Darren Reed <darrenr@reed.wattle.id.au>
List: tech-net
Date: 06/20/1999 20:00:30
Folks,
      I've submitted a PR on bad ICMP behaviour and in researching a fix,
found that the bug which causes the "unknown protocol" counter to get
increased is what (on BSD) makes the UDP traceroute possible.  The bug
appears to be that in ip_icmp.c, at about line 363 (in the code section
after the "deliver" label) there's a "break" rather than a "return".  The
subsequent effect is to let the packet drop through to the "raw" label
and get fed into rip_input() and hence traceroute is able to get it.  I'm
sure there's a good reason to pass processed packets on to rip_input()
that have already been processed...I'm just not sure I understand what
that would be and if so, why it would be limited to ICMP (other than to
support traceroute).  Anyway, the easiest fix I can think of which won't
disturb anything (except for correcting the "unknown protocol" statistics
count) is to add another mbuf flag - M_DELIVERED (0x800) - set that in
icmp_input() before calling rip_input() and not fiddle with the statistics
counters in the tail end of rip_input() if M_DELIVERED is set.  If this
is an acceptable patch, I'd like for it to be pulled up into 1.4.1.

Darren

*** sys/mbuf.h.dist	Sun Jun 20 19:53:16 1999
--- sys/mbuf.h	Sun Jun 20 19:55:30 1999
***************
*** 171,176 ****
--- 171,178 ----
  #define	M_MCAST		0x0200	/* send/received as link-level multicast */
  #define	M_CANFASTFWD	0x0400	/* used by filters to indicate packet can
  				   be fast-forwarded */
+ #define	M_DELIVERED	0x0800	/* used to tell rip_input that it isn't an
+ 				   unknown packet and has been delivered */
  #define	M_LINK0		0x1000	/* link layer specific flag */
  #define	M_LINK1		0x2000	/* link layer specific flag */
  #define	M_LINK2		0x4000	/* link layer specific flag */
*** netinet/ip_icmp.c.dist	Sun Jun 20 19:53:23 1999
--- netinet/ip_icmp.c	Sun Jun 20 19:56:38 1999
***************
*** 458,463 ****
--- 458,464 ----
  	}
  
  raw:
+ 	m->m_flags |= M_DELIVERED;
  	rip_input(m);
  	return;
  
*** netinet/raw_ip.c.dist	Sun Jun 20 19:53:27 1999
--- netinet/raw_ip.c	Sun Jun 20 19:54:42 1999
***************
*** 160,168 ****
  		} else
  			sorwakeup(last->inp_socket);
  	} else {
  		m_freem(m);
- 		ipstat.ips_noproto++;
- 		ipstat.ips_delivered--;
  	}
  }
  
--- 160,170 ----
  		} else
  			sorwakeup(last->inp_socket);
  	} else {
+ 		if ((m->m_flags & M_DELIVERED) == 0) {
+ 			ipstat.ips_noproto++;
+ 			ipstat.ips_delivered--;
+ 		}
  		m_freem(m);
  	}
  }