Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Jun 2011 20:22:19 +1200
From:      Matthew Luckie <mjl@luckie.org.nz>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/145733: [patch] ipfw flaws with ipv6 fragments
Message-ID:  <4E04493B.8030203@luckie.org.nz>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------070209090203080600040202
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

On world IPv6 day I was asked by bz@ to re-spin the patch supplied in 
the PR with the second and third IPv6 fragment issues listed in the PR 
fixed, but not the first (discarding IPv6 packets with a fragment header 
but not fragmented).  Attached is the revised patch, against 8.2R

--------------070209090203080600040202
Content-Type: text/plain;
 name="patch-ipfw2-ip6frag"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="patch-ipfw2-ip6frag"

--- ip_fw_log.c.orig	2011-06-24 19:46:44.000000000 +1200
+++ ip_fw_log.c	2011-06-24 20:14:55.724751000 +1200
@@ -168,6 +168,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 	char *action;
 	int limit_reached = 0;
 	char action2[40], proto[128], fragment[32];
+	u_short mf = 0;
 
 	if (V_fw_verbose == 0) {
 #ifndef WITHOUT_BPF
@@ -337,6 +338,8 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 			snprintf(dst, sizeof(dst), "[%s]",
 			    ip6_sprintf(ip6buf, &args->f_id.dst_ip6));
 
+			mf = offset & IP6F_MORE_FRAG;
+			offset &= IP6F_OFF_MASK;
 			ip6 = (struct ip6_hdr *)ip;
 			tcp = (struct tcphdr *)(((char *)ip) + hlen);
 			udp = (struct udphdr *)(((char *)ip) + hlen);
@@ -406,13 +409,13 @@ ipfw_log(struct ip_fw *f, u_int hlen, st
 
 #ifdef INET6
 		if (IS_IP6_FLOW_ID(&(args->f_id))) {
-			if (offset & (IP6F_OFF_MASK | IP6F_MORE_FRAG))
+		  if (offset || mf)
 				snprintf(SNPARGS(fragment, 0),
 				    " (frag %08x:%d@%d%s)",
 				    args->f_id.extra,
 				    ntohs(ip6->ip6_plen) - hlen,
-				    ntohs(offset & IP6F_OFF_MASK) << 3,
-				    (offset & IP6F_MORE_FRAG) ? "+" : "");
+				    ntohs(offset) << 3,
+				    mf ? "+" : "");
 		} else
 #endif
 		{
--- ip_fw2.c.orig	2011-06-24 19:31:28.000000000 +1200
+++ ip_fw2.c	2011-06-24 20:14:55.724751000 +1200
@@ -838,16 +838,13 @@ ipfw_chk(struct ip_fw_args *args)
 
 	/*
 	 * offset	The offset of a fragment. offset != 0 means that
-	 *	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. 
-	 *	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 fragment which would
-	 *	otherwise have offset = 0.
+	 *	we have a fragment at this offset.
+	 *	offset == 0 means that this is the first or only fragment.
+	 *
+	 * mf The MF bit masked out of IPv6 packets.
 	 */
 	u_short offset = 0;
+	u_short mf = 0;
 
 	/*
 	 * Local copies of addresses. They are only valid if we have
@@ -940,7 +937,7 @@ do {								\
 		proto = ip6->ip6_nxt;
 
 		/* Search extension headers to find upper layer protocols */
-		while (ulp == NULL) {
+		while (ulp == NULL && offset == 0) {
 			switch (proto) {
 			case IPPROTO_ICMPV6:
 				PULLUP_TO(hlen, ulp, struct icmp6_hdr);
@@ -1005,11 +1002,9 @@ 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. */
-				offset |= ((struct ip6_frag *)ulp)->ip6f_offlg &
+				mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
 					IP6F_MORE_FRAG;
-				if (offset == 0) {
+				if (offset == 0 && mf == 0) {
 					printf("IPFW2: IPV6 - Invalid Fragment "
 					    "Header\n");
 					if (V_fw_deny_unknown_exthdrs)
@@ -1650,7 +1645,7 @@ do {								\
 
 			case O_LOG:
 				ipfw_log(f, hlen, args, m,
-					    oif, offset, tablearg, ip);
+					    oif, offset|mf, tablearg, ip);
 				match = 1;
 				break;
 

--------------070209090203080600040202--



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