Blob Blame History Raw
diff --git a/gencode.c b/gencode.c
index 1f2e6a3..2b624df 100644
--- a/gencode.c
+++ b/gencode.c
@@ -5160,7 +5160,7 @@ gen_ipfrag()
 	struct slist *s;
 	struct block *b;
 
-	/* not ip frag */
+	/* not IPv4 frag other than the first frag */
 	s = gen_load_a(OR_NET, 6, BPF_H);
 	b = new_block(JMP(BPF_JSET));
 	b->s.k = 0x1fff;
@@ -5203,7 +5203,7 @@ gen_portop(port, proto, dir)
 {
 	struct block *b0, *b1, *tmp;
 
-	/* ip proto 'proto' */
+	/* ip proto 'proto' and not a fragment other than the first fragment */
 	tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
 	b0 = gen_ipfrag();
 	gen_and(tmp, b0);
@@ -5295,6 +5295,7 @@ gen_portop6(port, proto, dir)
 	struct block *b0, *b1, *tmp;
 
 	/* ip6 proto 'proto' */
+	/* XXX - catch the first fragment of a fragmented packet? */
 	b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
 
 	switch (dir) {
@@ -5396,7 +5397,7 @@ gen_portrangeop(port1, port2, proto, dir)
 {
 	struct block *b0, *b1, *tmp;
 
-	/* ip proto 'proto' */
+	/* ip proto 'proto' and not a fragment other than the first fragment */
 	tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
 	b0 = gen_ipfrag();
 	gen_and(tmp, b0);
@@ -5500,6 +5501,7 @@ gen_portrangeop6(port1, port2, proto, dir)
 	struct block *b0, *b1, *tmp;
 
 	/* ip6 proto 'proto' */
+	/* XXX - catch the first fragment of a fragmented packet? */
 	b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
 
 	switch (dir) {
@@ -5976,6 +5978,11 @@ gen_proto(v, proto, dir)
 	int dir;
 {
 	struct block *b0, *b1;
+#ifdef INET6
+#ifndef CHASE_CHAIN
+	struct block *b2;
+#endif
+#endif
 
 	if (dir != Q_DEFAULT)
 		bpf_error("direction applied to 'proto'");
@@ -6140,7 +6147,15 @@ gen_proto(v, proto, dir)
 	case Q_IPV6:
 		b0 = gen_linktype(ETHERTYPE_IPV6);
 #ifndef CHASE_CHAIN
-		b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+		/*
+		 * Also check for a fragment header before the final
+		 * header.
+		 */
+		b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT);
+		b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v);
+		gen_and(b2, b1);
+		b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
+		gen_or(b2, b1);
 #else
 		b1 = gen_protochain(v, Q_IPV6);
 #endif