From owner-freebsd-net@FreeBSD.ORG Fri Mar 14 00:40:08 2008 Return-Path: Delivered-To: freebsd-net@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B15AB106567D; Fri, 14 Mar 2008 00:40:08 +0000 (UTC) (envelope-from snow@teardrop.org) Received: from silver.teardrop.org (silver.teardrop.org [66.92.75.234]) by mx1.freebsd.org (Postfix) with ESMTP id 79A218FC13; Fri, 14 Mar 2008 00:40:08 +0000 (UTC) (envelope-from snow@teardrop.org) Received: by silver.teardrop.org (Postfix, from userid 100) id C5B6A958B7; Thu, 13 Mar 2008 20:40:07 -0400 (EDT) Date: Thu, 13 Mar 2008 20:40:07 -0400 From: James Snow To: "Bruce M. Simpson" Message-ID: <20080314004007.GC92537@teardrop.org> References: <200802222124.m1MLO7qq012802@freefall.freebsd.org> <47BF46DC.6030700@FreeBSD.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="dTy3Mrz/UPE2dbVg" Content-Disposition: inline In-Reply-To: <47BF46DC.6030700@FreeBSD.org> User-Agent: Mutt/1.4.2.3i Cc: freebsd-net@FreeBSD.org Subject: [PATCH] kern/120958: no response to ICMP traffic on interface configured with a link-local address X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Mar 2008 00:40:08 -0000 --dTy3Mrz/UPE2dbVg Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Feb 22, 2008 at 10:04:12PM +0000, Bruce M. Simpson wrote: > I looked at this very briefly. > > It's gnarly because in_canforward() is a candidate for inlining and is a > predicate which is being overloaded with different meanings by > ip_forward()/ip_input() and icmp_reflect(). > > So whilst the fix is most likely a 3 liner, it risks making the code > look crap. We genuinely don't want to forward 169.254.0.0/16 traffic, > however we genuinely need to reply to ICMP which originates from these > ranges. Attached is a patch that fixes the failure to respond to ICMP for link-local addresses. I reworked the opening if statement in icmp_reflect() to make it a touch more readable, and eliminated the call to in_canforward() since its logic doesn't work in this context. Also, I took a cue from the IN_LINKLOCAL() macro and added two new macros to sys/netinet/in.h to perform checks for the loopback network and the "zero" network. IN_LOOPBACK() and IN_ZERONET(), respectively. IN_ZERONET seems like a lousy name, but the only alternative I could find in RFC3330 was "'this' net," and IN_THISNET wasn't an improvement. -Snow --dTy3Mrz/UPE2dbVg Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="link-local-icmp.patch" diff -ru /usr/src/sys/netinet/in.h /usr/src.new/sys/netinet/in.h --- /usr/src/sys/netinet/in.h 2007-06-12 16:24:53.000000000 +0000 +++ /usr/src.new/sys/netinet/in.h 2008-03-13 10:44:29.000000000 +0000 @@ -379,6 +379,8 @@ #define IN_BADCLASS(i) (((u_int32_t)(i) & 0xf0000000) == 0xf0000000) #define IN_LINKLOCAL(i) (((u_int32_t)(i) & 0xffff0000) == 0xa9fe0000) +#define IN_LOOPBACK(i) (((u_int32_t)(i) & 0xff000000) == 0x7f000000) +#define IN_ZERONET(i) (((u_int32_t)(i) & 0xff000000) == 0) #define IN_PRIVATE(i) ((((u_int32_t)(i) & 0xff000000) == 0x0a000000) || \ (((u_int32_t)(i) & 0xfff00000) == 0xac100000) || \ diff -ru /usr/src/sys/netinet/ip_icmp.c /usr/src.new/sys/netinet/ip_icmp.c --- /usr/src/sys/netinet/ip_icmp.c 2007-10-07 20:44:23.000000000 +0000 +++ /usr/src.new/sys/netinet/ip_icmp.c 2008-03-13 11:03:44.000000000 +0000 @@ -622,13 +622,14 @@ struct mbuf *opts = 0; int optlen = (ip->ip_hl << 2) - sizeof(struct ip); - if (!in_canforward(ip->ip_src) && - ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) != - (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { + if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)) || + IN_ZERONET(ntohl(ip->ip_src.s_addr)) ) { m_freem(m); /* Bad return address */ icmpstat.icps_badaddr++; goto done; /* Ip_output() will check for broadcast */ } + t = ip->ip_dst; ip->ip_dst = ip->ip_src; --dTy3Mrz/UPE2dbVg--