Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Feb 2012 16:07:07 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r231209 - stable/7/sys/netinet
Message-ID:  <201202081607.q18G774q050262@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bz
Date: Wed Feb  8 16:07:07 2012
New Revision: 231209
URL: http://svn.freebsd.org/changeset/base/231209

Log:
  MFC r225032,225034:
  
   ipfw internally checks for offset == 0 to determine whether the
   packet is a/the first fragment or not.  For IPv6 we have added the
   "more fragments" flag as well to be able to determine on whether
   there will be more as we do not have the fragment header avaialble
   for logging, while for IPv4 this information can be derived directly
   from the IPv4 header.  This allowed fragmented packets to bypass
   normal rules as proper masking was not done when checking offset.
   Split variables to not need masking for IPv6 to avoid further errors.
  
   After r225032 fix logging in a similar way masking the the IPv6
   more fragments flag off so that offset == 0 checks work properly.
  
   Submitted by:	Matthew Luckie (mjl luckie.org.nz)
  PR:		kern/145733

Modified:
  stable/7/sys/netinet/ip_fw2.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/netinet/ip_fw2.c
==============================================================================
--- stable/7/sys/netinet/ip_fw2.c	Wed Feb  8 16:03:05 2012	(r231208)
+++ stable/7/sys/netinet/ip_fw2.c	Wed Feb  8 16:07:07 2012	(r231209)
@@ -897,10 +897,14 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 #ifdef INET6
 		struct ip6_hdr *ip6 = NULL;
 		struct icmp6_hdr *icmp6;
+		u_short ip6f_mf;
 #endif
 		src[0] = '\0';
 		dst[0] = '\0';
 #ifdef INET6
+		ip6f_mf = offset & IP6F_MORE_FRAG;
+		offset &= IP6F_OFF_MASK;
+
 		if (IS_IP6_FLOW_ID(&(args->f_id))) {
 			char ip6buf[INET6_ADDRSTRLEN];
 			snprintf(src, sizeof(src), "[%s]",
@@ -982,8 +986,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 				    " (frag %08x:%d@%d%s)",
 				    args->f_id.frag_id6,
 				    ntohs(ip6->ip6_plen) - hlen,
-				    ntohs(offset & IP6F_OFF_MASK) << 3,
-				    (offset & IP6F_MORE_FRAG) ? "+" : "");
+				    ntohs(offset) << 3, ip6f_mf ? "+" : "");
 		} else
 #endif
 		{
@@ -2161,17 +2164,14 @@ ipfw_chk(struct ip_fw_args *args)
 	 *	we have a fragment at this offset of an IPv4 packet.
 	 *	offset == 0 means that (if this is an IPv4 packet)
 	 *	this is the first or only fragment.
-	 *	For IPv6 offset == 0 means there is no Fragment Header or there
-	 *	is a single packet fragement (fragement header added without
-	 *	needed).  We will treat a single packet fragment as if there
-	 *	was no fragment header (or log/block depending on the
+	 *	For IPv6 offset|ip6f_mf == 0 means there is no Fragment Header
+	 *	or there is a single packet fragement (fragement header added
+	 *	without needed).  We will treat a single packet fragment as if
+	 *	there was no fragment header (or log/block depending on the
 	 *	fw_permit_single_frag6 sysctl setting).
-	 *	If offset != 0 for IPv6 always use correct mask to
-	 *	get the correct offset because we add IP6F_MORE_FRAG to be able
-	 *	to dectect the first of multiple fragments which would
-	 *	otherwise have offset = 0.
 	 */
 	u_short offset = 0;
+	u_short ip6f_mf = 0;
 
 	/*
 	 * Local copies of addresses. They are only valid if we have
@@ -2324,12 +2324,10 @@ do {									\
 				proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
 				offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
 					IP6F_OFF_MASK;
-				/* Add IP6F_MORE_FRAG for offset of first
-				 * fragment to be != 0 if there shall be more. */
-				offset |= ((struct ip6_frag *)ulp)->ip6f_offlg &
+				ip6f_mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
 					IP6F_MORE_FRAG;
 				if (fw_permit_single_frag6 == 0 &&
-				    offset == 0) {
+				    offset == 0 && ip6f_mf == 0) {
 					printf("IPFW2: IPV6 - Invalid Fragment "
 					    "Header\n");
 					if (fw_deny_unknown_exthdrs)
@@ -2918,7 +2916,7 @@ check_body:
 			case O_LOG:
 				if (fw_verbose)
 					ipfw_log(f, hlen, args, m,
-					    oif, offset, tablearg, ip);
+					    oif, offset | ip6f_mf, tablearg, ip);
 				match = 1;
 				break;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202081607.q18G774q050262>