Pull up revisions: netbsd-6
authorjdc <jdc@NetBSD.org>
Wed, 25 Jul 2012 20:45:23 +0000
branchnetbsd-6
changeset 256002 c9ca6dedcbd1
parent 256001 ea959923f511
child 256003 d70ee580ce3d
Pull up revisions: src/usr.sbin/npf/npfctl/npfctl.c revisions 1.16,1.17 src/sys/net/npf/npf.h revision 1.20 src/sys/net/npf/npf_alg_icmp.c revision 1.11 src/sys/net/npf/npf_impl.h revision 1.19 src/sys/net/npf/npf_inet.c revisions 1.15,1.16 src/sys/net/npf/npf_instr.c revision 1.14 src/sys/net/npf/npf_ncode.h revision 1.10 src/sys/net/npf/npf_processor.c revision 1.12 src/sys/net/npf/npf_session.c revision 1.16 src/usr.sbin/npf/npfctl/npf_build.c revision 1.12 src/usr.sbin/npf/npfctl/npf_data.c revisions 1.16,1.17 src/usr.sbin/npf/npfctl/npf_disassemble.c revision 1.8 src/usr.sbin/npf/npfctl/npf_ncgen.c revision 1.13 src/usr.sbin/npf/npfctl/npf_parse.y revision 1.11 src/usr.sbin/npf/npfctl/npf_scan.l revision 1.5 src/usr.sbin/npf/npfctl/npf_var.h revision 1.3 src/usr.sbin/npf/npfctl/npfctl.h revision 1.18 src/sys/net/npf/npf_state.c revision 1.10 src/sys/net/npf/npf_state_tcp.c revision 1.10 src/usr.sbin/npf/npftest/npfstream.c revision 1.2 src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c revision 1.2 (requested by rmind in ticket #435). Add missing __dead. teach npf ipv6-icmp reviewed by rmind@ - npfctl_print_stats: beautification a la French style. - npfctl_icmpcode: fix the build break. - npf_fetch_tcpopts: fix off-by-one when validating TCP option length against the maximum allowed. - npf_tcp_inwindow: be more liberal with npf_fetch_tcpopts(). - Few minor improvements to npftest.
sys/net/npf/npf.h
sys/net/npf/npf_alg_icmp.c
sys/net/npf/npf_impl.h
sys/net/npf/npf_inet.c
sys/net/npf/npf_instr.c
sys/net/npf/npf_ncode.h
sys/net/npf/npf_processor.c
sys/net/npf/npf_session.c
sys/net/npf/npf_state.c
sys/net/npf/npf_state_tcp.c
usr.sbin/npf/npfctl/npf_build.c
usr.sbin/npf/npfctl/npf_data.c
usr.sbin/npf/npfctl/npf_disassemble.c
usr.sbin/npf/npfctl/npf_ncgen.c
usr.sbin/npf/npfctl/npf_parse.y
usr.sbin/npf/npfctl/npf_scan.l
usr.sbin/npf/npfctl/npf_var.h
usr.sbin/npf/npfctl/npfctl.c
usr.sbin/npf/npfctl/npfctl.h
usr.sbin/npf/npftest/libnpftest/npf_test_subr.c
usr.sbin/npf/npftest/npfstream.c
--- a/sys/net/npf/npf.h	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf.h	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf.h,v 1.14.2.5 2012/07/16 22:13:26 riz Exp $	*/
+/*	$NetBSD: npf.h,v 1.14.2.6 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -74,6 +74,7 @@
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
 
 #define	NPC_IP4		0x01	/* Indicates fetched IPv4 header. */
 #define	NPC_IP6		0x02	/* Indicates IPv6 header. */
@@ -104,9 +105,10 @@
 	} npc_ip;
 	/* TCP, UDP, ICMP. */
 	union {
-		struct tcphdr	tcp;
-		struct udphdr	udp;
-		struct icmp	icmp;
+		struct tcphdr		tcp;
+		struct udphdr		udp;
+		struct icmp		icmp;
+		struct icmp6_hdr	icmp6;
 	} npc_l4;
 } npf_cache_t;
 
--- a/sys/net/npf/npf_alg_icmp.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_alg_icmp.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_alg_icmp.c,v 1.8.4.2 2012/07/16 22:13:26 riz Exp $	*/
+/*	$NetBSD: npf_alg_icmp.c,v 1.8.4.3 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.8.4.2 2012/07/16 22:13:26 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.8.4.3 2012/07/25 20:45:23 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/module.h>
@@ -46,6 +46,7 @@
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
 #include <net/pfil.h>
 
 #include "npf_impl.h"
@@ -156,54 +157,102 @@
 static bool
 npf_icmp_uniqid(const int type, npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
 {
-	struct icmp *ic;
-	u_int offby;
+	struct icmp      *ic;
+	struct icmp6_hdr *ic6;
+	u_int            offby;
 
-	/* Per RFC 792. */
-	switch (type) {
-	case ICMP_UNREACH:
-	case ICMP_SOURCEQUENCH:
-	case ICMP_REDIRECT:
-	case ICMP_TIMXCEED:
-	case ICMP_PARAMPROB:
-		/* Should contain original IP header. */
-		offby = offsetof(struct icmp, icmp_ip);
-		if ((n_ptr = nbuf_advance(&nbuf, n_ptr, offby)) == NULL) {
-			return false;
-		}
-		/* Fetch into the cache. */
-		if (!npf_fetch_ip(npc, nbuf, n_ptr)) {
-			return false;
+	if (npf_iscached(npc, NPC_IP4)) {
+		/* Per RFC 792. */
+		switch (type) {
+		case ICMP_UNREACH:
+		case ICMP_SOURCEQUENCH:
+		case ICMP_REDIRECT:
+		case ICMP_TIMXCEED:
+		case ICMP_PARAMPROB:
+			/* Should contain original IP header. */
+			offby = offsetof(struct icmp, icmp_ip);
+			if ((n_ptr = nbuf_advance(&nbuf, n_ptr, offby)) == NULL) {
+				return false;
+			}
+			/* Fetch into the cache. */
+			if (!npf_fetch_ip(npc, nbuf, n_ptr)) {
+				return false;
+			}
+			switch (npf_cache_ipproto(npc)) {
+			case IPPROTO_TCP:
+				return npf_fetch_tcp(npc, nbuf, n_ptr);
+			case IPPROTO_UDP:
+				return npf_fetch_udp(npc, nbuf, n_ptr);
+			default:
+				return false;
+			}
+			return true;
+
+		case ICMP_ECHOREPLY:
+		case ICMP_ECHO:
+		case ICMP_TSTAMP:
+		case ICMP_TSTAMPREPLY:
+		case ICMP_IREQ:
+		case ICMP_IREQREPLY:
+			/* Should contain ICMP query ID. */
+			ic = &npc->npc_l4.icmp;
+			offby = offsetof(struct icmp, icmp_id);
+			if (nbuf_advfetch(&nbuf, &n_ptr, offby,
+			    sizeof(uint16_t), &ic->icmp_id)) {
+				return false;
+			}
+			npc->npc_info |= NPC_ICMP_ID;
+			return true;
+		default:
+			break;
 		}
-		switch (npf_cache_ipproto(npc)) {
-		case IPPROTO_TCP:
-			return npf_fetch_tcp(npc, nbuf, n_ptr);
-		case IPPROTO_UDP:
-			return npf_fetch_udp(npc, nbuf, n_ptr);
-		default:
-			return false;
-		}
-		return true;
+		/* No unique IDs. */
+		return false;
+	}
+	if (npf_iscached(npc, NPC_IP6)) {
+		switch (type) {
+		/* Per RFC 4443. */
+		case ICMP6_DST_UNREACH:
+		case ICMP6_PACKET_TOO_BIG:
+		case ICMP6_TIME_EXCEEDED:
+		case ICMP6_PARAM_PROB:
+			/* Should contain original IP header. */
+			offby = sizeof(struct icmp6_hdr);
+			if ((n_ptr = nbuf_advance(&nbuf, n_ptr, offby)) == NULL) {
+				return false;
+			}
+			/* Fetch into the cache. */
+			if (!npf_fetch_ip(npc, nbuf, n_ptr)) {
+				return false;
+			}
+			switch (npf_cache_ipproto(npc)) {
+			case IPPROTO_TCP:
+				return npf_fetch_tcp(npc, nbuf, n_ptr);
+			case IPPROTO_UDP:
+				return npf_fetch_udp(npc, nbuf, n_ptr);
+			default:
+				return false;
+			}
+			return true;
 
-	case ICMP_ECHOREPLY:
-	case ICMP_ECHO:
-	case ICMP_TSTAMP:
-	case ICMP_TSTAMPREPLY:
-	case ICMP_IREQ:
-	case ICMP_IREQREPLY:
-		/* Should contain ICMP query ID. */
-		ic = &npc->npc_l4.icmp;
-		offby = offsetof(struct icmp, icmp_id);
-		if (nbuf_advfetch(&nbuf, &n_ptr, offby,
-		    sizeof(uint16_t), &ic->icmp_id)) {
-			return false;
+		case ICMP6_ECHO_REQUEST:
+		case ICMP6_ECHO_REPLY:
+			/* Should contain ICMP query ID. */
+			ic6 = &npc->npc_l4.icmp6;
+			offby = offsetof(struct icmp6_hdr, icmp6_id);
+			if (nbuf_advfetch(&nbuf, &n_ptr, offby,
+			    sizeof(uint16_t), &ic6->icmp6_id)) {
+				return false;
+			}
+			npc->npc_info |= NPC_ICMP_ID;
+			return true;
+		default:
+			break;
 		}
-		npc->npc_info |= NPC_ICMP_ID;
-		return true;
-	default:
-		break;
+		/* No unique IDs. */
+		return false;
 	}
-	/* No unique IDs. */
+	/* Whatever protocol that may have been ... */
 	return false;
 }
 
--- a/sys/net/npf/npf_impl.h	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_impl.h	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_impl.h,v 1.10.2.5 2012/07/16 22:13:27 riz Exp $	*/
+/*	$NetBSD: npf_impl.h,v 1.10.2.6 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -208,6 +208,7 @@
 int		npf_match_udp_ports(npf_cache_t *, nbuf_t *, void *,
 		    const int, const uint32_t);
 int		npf_match_icmp4(npf_cache_t *, nbuf_t *, void *, uint32_t);
+int		npf_match_icmp6(npf_cache_t *, nbuf_t *, void *, uint32_t);
 int		npf_match_tcpfl(npf_cache_t *, nbuf_t *, void *, uint32_t);
 
 /* Tableset interface. */
--- a/sys/net/npf/npf_inet.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_inet.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_inet.c,v 1.10.4.4 2012/07/16 22:13:25 riz Exp $	*/
+/*	$NetBSD: npf_inet.c,v 1.10.4.5 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.10.4.4 2012/07/16 22:13:25 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.10.4.5 2012/07/25 20:45:23 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -277,7 +277,7 @@
 		if (nbuf_advfetch(&nbuf, &n_ptr, 1, sizeof(val), &val)) {
 			return false;
 		}
-		if (val < 2 || val >= topts_len) {
+		if (val < 2 || val > topts_len) {
 			return false;
 		}
 		topts_len -= val;
@@ -463,14 +463,18 @@
 	if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
 		return false;
 	}
-	if (npf_cache_ipproto(npc) != IPPROTO_ICMP) {
+	if (npf_cache_ipproto(npc) != IPPROTO_ICMP &&
+	    npf_cache_ipproto(npc) != IPPROTO_ICMPV6) {
 		return false;
 	}
 	ic = &npc->npc_l4.icmp;
 	hlen = npf_cache_hlen(npc);
 
 	/* Fetch basic ICMP header, up to the "data" point. */
-	iclen = offsetof(struct icmp, icmp_data);
+	CTASSERT(offsetof(struct icmp, icmp_void) ==
+	         offsetof(struct icmp6_hdr, icmp6_data32));
+
+	iclen = offsetof(struct icmp, icmp_void);
 	if (nbuf_advfetch(&nbuf, &n_ptr, hlen, iclen, ic)) {
 		return false;
 	}
@@ -503,6 +507,7 @@
 		(void)npf_fetch_udp(npc, nbuf, n_ptr);
 		break;
 	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6:
 		(void)npf_fetch_icmp(npc, nbuf, n_ptr);
 		break;
 	}
--- a/sys/net/npf/npf_instr.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_instr.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_instr.c,v 1.9.2.4 2012/07/16 22:13:26 riz Exp $	*/
+/*	$NetBSD: npf_instr.c,v 1.9.2.5 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.9.2.4 2012/07/16 22:13:26 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.9.2.5 2012/07/25 20:45:23 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -237,6 +237,37 @@
 }
 
 /*
+ * npf_match_icmp6: match ICMPv6 packet.
+ */
+int
+npf_match_icmp6(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, uint32_t tc)
+{
+	struct icmp6_hdr *ic6 = &npc->npc_l4.icmp6;
+
+	if (!npf_iscached(npc, NPC_ICMP)) {
+		if (!npf_fetch_icmp(npc, nbuf, n_ptr)) {
+			return -1;
+		}
+		KASSERT(npf_iscached(npc, NPC_ICMP));
+	}
+
+	/* Match code/type, if required. */
+	if ((1 << 31) & tc) {
+		const uint8_t type = (tc >> 8) & 0xff;
+		if (type != ic6->icmp6_type) {
+			return -1;
+		}
+	}
+	if ((1 << 30) & tc) {
+		const uint8_t code = tc & 0xff;
+		if (code != ic6->icmp6_code) {
+			return -1;
+		}
+	}
+	return 0;
+}
+
+/*
  * npf_match_tcpfl: match TCP flags.
  */
 int
--- a/sys/net/npf/npf_ncode.h	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_ncode.h	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_ncode.h,v 1.5.6.3 2012/07/05 17:48:42 riz Exp $	*/
+/*	$NetBSD: npf_ncode.h,v 1.5.6.4 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@@ -118,6 +118,7 @@
 #define	NPF_OPCODE_TABLE		0x91
 #define	NPF_OPCODE_ICMP4		0x92
 #define	NPF_OPCODE_IP6MASK		0x93
+#define	NPF_OPCODE_ICMP6		0x94
 
 #define	NPF_OPCODE_TCP_PORTS		0xa0
 #define	NPF_OPCODE_UDP_PORTS		0xa1
@@ -139,7 +140,7 @@
 # define	NPF_OPERAND_SUBNET		9
 # define	NPF_OPERAND_LENGTH		10
 # define	NPF_OPERAND_TABLE_ID		11
-# define	NPF_OPERAND_ICMP4_TYPE_CODE	12
+# define	NPF_OPERAND_ICMP_TYPE_CODE	12
 # define	NPF_OPERAND_TCP_FLAGS_MASK	13
 # define	NPF_OPERAND_PORT_RANGE		14
 # define	NPF_OPERAND_PROTO		15
@@ -330,7 +331,13 @@
 	[NPF_OPCODE_ICMP4] = {
 		.name = "icmp4",
 		.op = {
-			[0] = NPF_OPERAND_ICMP4_TYPE_CODE,
+			[0] = NPF_OPERAND_ICMP_TYPE_CODE,
+		},
+	},
+	[NPF_OPCODE_ICMP6] = {
+		.name = "icmp6",
+		.op = {
+			[0] = NPF_OPERAND_ICMP_TYPE_CODE,
 		},
 	},
 	[NPF_OPCODE_IP6MASK] = {
--- a/sys/net/npf/npf_processor.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_processor.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_processor.c,v 1.9.2.2 2012/07/05 17:48:42 riz Exp $	*/
+/*	$NetBSD: npf_processor.c,v 1.9.2.3 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@@ -50,7 +50,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.9.2.2 2012/07/05 17:48:42 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_processor.c,v 1.9.2.3 2012/07/25 20:45:23 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -316,6 +316,11 @@
 		i_ptr = nc_fetch_word(i_ptr, &n);
 		cmpval = npf_match_icmp4(npc, nbuf, n_ptr, n);
 		break;
+	case NPF_OPCODE_ICMP6:
+		/* ICMP type/code. */
+		i_ptr = nc_fetch_word(i_ptr, &n);
+		cmpval = npf_match_icmp6(npc, nbuf, n_ptr, n);
+		break;
 	case NPF_OPCODE_PROTO:
 		i_ptr = nc_fetch_word(i_ptr, &n);
 		cmpval = npf_match_proto(npc, nbuf, n_ptr, n);
@@ -480,6 +485,7 @@
 		error = nc_ptr_check(&iptr, nc, sz, 1, NULL, 0);
 		break;
 	case NPF_OPCODE_ICMP4:
+	case NPF_OPCODE_ICMP6:
 		error = nc_ptr_check(&iptr, nc, sz, 1, NULL, 0);
 		break;
 	case NPF_OPCODE_PROTO:
--- a/sys/net/npf/npf_session.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_session.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_session.c,v 1.10.4.4 2012/07/16 22:13:25 riz Exp $	*/
+/*	$NetBSD: npf_session.c,v 1.10.4.5 2012/07/25 20:45:24 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.10.4.4 2012/07/16 22:13:25 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.10.4.5 2012/07/25 20:45:24 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -495,7 +495,15 @@
 			senkey.se_dst_id = ic->icmp_id;
 			break;
 		}
-		/* FALLTHROUGH */
+		return NULL;
+	case IPPROTO_ICMPV6:
+		if (npf_iscached(key, NPC_ICMP_ID)) {
+			const struct icmp6_hdr *ic6 = &key->npc_l4.icmp6;
+			senkey.se_src_id = ic6->icmp6_id;
+			senkey.se_dst_id = ic6->icmp6_id;
+			break;
+		}
+		return NULL;
 	default:
 		/* Unsupported protocol. */
 		return NULL;
@@ -636,7 +644,18 @@
 			fw->se_dst_id = ic->icmp_id;
 			break;
 		}
-		/* FALLTHROUGH */
+		ok = false;
+		goto out;
+	case IPPROTO_ICMPV6:
+		if (npf_iscached(npc, NPC_ICMP_ID)) {
+			/* ICMP query ID. */
+			const struct icmp6_hdr *ic6 = &npc->npc_l4.icmp6;
+			fw->se_src_id = ic6->icmp6_id;
+			fw->se_dst_id = ic6->icmp6_id;
+			break;
+		}
+		ok = false;
+		goto out;
 	default:
 		/* Unsupported. */
 		ok = false;
--- a/sys/net/npf/npf_state.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_state.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_state.c,v 1.6.4.3 2012/07/05 17:48:42 riz Exp $	*/
+/*	$NetBSD: npf_state.c,v 1.6.4.4 2012/07/25 20:45:24 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.6.4.3 2012/07/05 17:48:42 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.6.4.4 2012/07/25 20:45:24 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -107,6 +107,7 @@
 	default:
 		ret = false;
 	}
+	NPF_TCP_STATE_SAMPLE(nst, ret);
 	return ret;
 }
 
--- a/sys/net/npf/npf_state_tcp.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/sys/net/npf/npf_state_tcp.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_state_tcp.c,v 1.3.2.4 2012/07/16 22:13:25 riz Exp $	*/
+/*	$NetBSD: npf_state_tcp.c,v 1.3.2.5 2012/07/25 20:45:24 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.3.2.4 2012/07/16 22:13:25 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.3.2.5 2012/07/25 20:45:24 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -300,7 +300,7 @@
 	const struct tcphdr * const th = &npc->npc_l4.tcp;
 	const int tcpfl = th->th_flags;
 	npf_tcpstate_t *fstate, *tstate;
-	int tcpdlen, wscale, ackskew;
+	int tcpdlen, ackskew;
 	tcp_seq seq, ack, end;
 	uint32_t win;
 
@@ -359,11 +359,9 @@
 		 * Handle TCP Window Scaling (RFC 1323).  Both sides may
 		 * send this option in their SYN packets.
 		 */
-		if (npf_fetch_tcpopts(npc, nbuf, NULL, &wscale)) {
-			fstate->nst_wscale = wscale;
-		} else {
-			fstate->nst_wscale = 0;
-		}
+		fstate->nst_wscale = 0;
+		(void)npf_fetch_tcpopts(npc, nbuf, NULL, &fstate->nst_wscale);
+
 		tstate->nst_wscale = 0;
 
 		/* Done. */
@@ -377,12 +375,12 @@
 		fstate->nst_end = end;
 		fstate->nst_maxend = end + 1;
 		fstate->nst_maxwin = win;
+		fstate->nst_wscale = 0;
 
 		/* Handle TCP Window Scaling (must be ignored if no SYN). */
 		if (tcpfl & TH_SYN) {
-			fstate->nst_wscale =
-			    npf_fetch_tcpopts(npc, nbuf, NULL, &wscale) ?
-			    wscale : 0;
+			(void)npf_fetch_tcpopts(npc, nbuf, NULL,
+			    &fstate->nst_wscale);
 		}
 	}
 
--- a/usr.sbin/npf/npfctl/npf_build.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npf_build.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_build.c,v 1.4.2.4 2012/07/16 22:13:28 riz Exp $	*/
+/*	$NetBSD: npf_build.c,v 1.4.2.5 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.4.2.4 2012/07/16 22:13:28 riz Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.4.2.5 2012/07/25 20:45:23 jdc Exp $");
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -246,6 +246,21 @@
 		npfctl_gennc_icmp(nc, *icmp_type, *icmp_code);
 		nop = false;
 		break;
+	case IPPROTO_ICMPV6:
+		/*
+		 * Build ICMP block.
+		 */
+		if (!nop) {
+			goto invop;
+		}
+		assert(npfvar_get_count(popts) == 2);
+
+		int *icmp6_type, *icmp6_code;
+		icmp6_type = npfvar_get_data(popts, NPFVAR_ICMP6, 0);
+		icmp6_code = npfvar_get_data(popts, NPFVAR_ICMP6, 1);
+		npfctl_gennc_icmp6(nc, *icmp6_type, *icmp6_code);
+		nop = false;
+		break;
 	case -1:
 		pflag = NC_MATCH_TCP | NC_MATCH_UDP;
 		nop = false;
--- a/usr.sbin/npf/npfctl/npf_data.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npf_data.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_data.c,v 1.10.2.3 2012/07/16 22:13:28 riz Exp $	*/
+/*	$NetBSD: npf_data.c,v 1.10.2.4 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_data.c,v 1.10.2.3 2012/07/16 22:13:28 riz Exp $");
+__RCSID("$NetBSD: npf_data.c,v 1.10.2.4 2012/07/25 20:45:23 jdc Exp $");
 
 #include <sys/types.h>
 #include <sys/null.h>
@@ -41,6 +41,8 @@
 #include <netinet/ip.h>
 #define ICMP_STRINGS
 #include <netinet/ip_icmp.h>
+#define ICMP6_STRINGS
+#include <netinet/icmp6.h>
 #include <netinet/tcp.h>
 #include <net/if.h>
 
@@ -440,71 +442,142 @@
 }
 
 uint8_t
-npfctl_icmptype(const char *type)
+npfctl_icmptype(int proto, const char *type)
 {
-	for (uint8_t ul = 0; icmp_type[ul]; ul++)
-		if (strcmp(icmp_type[ul], type) == 0)
-			return ul;
+	uint8_t ul;
+
+	switch (proto) {
+	case IPPROTO_ICMP:
+		for (ul = 0; icmp_type[ul]; ul++)
+			if (strcmp(icmp_type[ul], type) == 0)
+				return ul;
+		break;
+	case IPPROTO_ICMPV6:
+		for (ul = 0; icmp6_type_err[ul]; ul++)
+			if (strcmp(icmp6_type_err[ul], type) == 0)
+				return ul;
+		for (ul = 0; icmp6_type_info[ul]; ul++)
+			if (strcmp(icmp6_type_info[ul], type) == 0)
+				return (ul+128);
+		break;
+	default:
+		assert(false);
+	}
+
+	yyerror("unknown icmp-type %s", type);
 	return ~0;
 }
 
 uint8_t
-npfctl_icmpcode(uint8_t type, const char *code)
+npfctl_icmpcode(int proto, uint8_t type, const char *code)
 {
-	const char **arr;
+	const char * const *arr;
 
-	switch (type) {
-	case ICMP_ECHOREPLY:
-	case ICMP_SOURCEQUENCH:
-	case ICMP_ALTHOSTADDR:
-	case ICMP_ECHO:
-	case ICMP_ROUTERSOLICIT:
-	case ICMP_TSTAMP:
-	case ICMP_TSTAMPREPLY:
-	case ICMP_IREQ:
-	case ICMP_IREQREPLY:
-	case ICMP_MASKREQ:
-	case ICMP_MASKREPLY:
-		arr = icmp_code_none;
+	switch (proto) {
+	case IPPROTO_ICMP:
+		switch (type) {
+		case ICMP_ECHOREPLY:
+		case ICMP_SOURCEQUENCH:
+		case ICMP_ALTHOSTADDR:
+		case ICMP_ECHO:
+		case ICMP_ROUTERSOLICIT:
+		case ICMP_TSTAMP:
+		case ICMP_TSTAMPREPLY:
+		case ICMP_IREQ:
+		case ICMP_IREQREPLY:
+		case ICMP_MASKREQ:
+		case ICMP_MASKREPLY:
+			arr = icmp_code_none;
+			break;
+		case ICMP_ROUTERADVERT:
+			arr = icmp_code_routeradvert;
+			break;
+		case ICMP_UNREACH:
+			arr = icmp_code_unreach;
+			break;
+		case ICMP_REDIRECT:
+			arr = icmp_code_redirect;
+			break;
+		case ICMP_TIMXCEED:
+			arr = icmp_code_timxceed;
+			break;
+		case ICMP_PARAMPROB:
+			arr = icmp_code_paramprob;
+			break;
+		case ICMP_PHOTURIS:
+			arr = icmp_code_photuris;
+			break;
+		default:
+			yyerror("unknown icmp-type %d while parsing code %s",
+				type, code);
+			return ~0;
+		}
 		break;
-	case ICMP_ROUTERADVERT:
-		arr = icmp_code_routeradvert;
-		break;
-	case ICMP_UNREACH:
-		arr = icmp_code_unreach;
-		break;
-	case ICMP_REDIRECT:
-		arr = icmp_code_redirect;
-		break;
-	case ICMP_TIMXCEED:
-		arr = icmp_code_timxceed;
-		break;
-	case ICMP_PARAMPROB:
-		arr = icmp_code_paramprob;
-		break;
-	case ICMP_PHOTURIS:
-		arr = icmp_code_photuris;
+	case IPPROTO_ICMPV6:
+		switch (type) {
+		case ICMP6_DST_UNREACH:
+			arr = icmp6_code_unreach;
+			break;
+		case ICMP6_TIME_EXCEEDED:
+			arr = icmp6_code_timxceed;
+			break;
+		case ICMP6_PARAM_PROB:
+			arr = icmp6_code_paramprob;
+			break;
+		case ICMP6_PACKET_TOO_BIG:
+		/* code-less info ICMPs */
+		case ICMP6_ECHO_REQUEST:
+		case ICMP6_ECHO_REPLY:
+		case MLD_LISTENER_QUERY:
+		case MLD_LISTENER_REPORT:
+		case MLD_LISTENER_DONE:
+		case ND_ROUTER_SOLICIT:
+		case ND_ROUTER_ADVERT:
+		case ND_NEIGHBOR_SOLICIT:
+		case ND_NEIGHBOR_ADVERT:
+		case ND_REDIRECT:
+			arr = icmp6_code_none;
+			break;
+		/* XXX TODO: info ICMPs with code values */
+		default:
+			yyerror("unknown icmp-type %d while parsing code %s",
+				type, code);
+			return ~0;
+		}
 		break;
 	default:
-		return ~0;
+		assert(false);
 	}
 
 	for (uint8_t ul = 0; arr[ul]; ul++) {
 		if (strcmp(arr[ul], code) == 0)
 			return ul;
 	}
+	yyerror("unknown code %s for icmp-type %d", code, type);
 	return ~0;
 }
 
 npfvar_t *
-npfctl_parse_icmp(int type, int code)
+npfctl_parse_icmp(int proto, int type, int code)
 {
-	npfvar_t *vp = npfvar_create(".icmp");
+	npfvar_t *vp=npfvar_create(".icmp");
+	int      varnum;
 
-	if (!npfvar_add_element(vp, NPFVAR_ICMP, &type, sizeof(type)))
+	switch (proto) {
+	case IPPROTO_ICMP:
+		varnum = NPFVAR_ICMP;
+		break;
+	case IPPROTO_ICMPV6:
+		varnum = NPFVAR_ICMP6;
+		break;
+	default:
+		assert(false);
+	}
+
+	if (!npfvar_add_element(vp, varnum, &type, sizeof(type)))
 		goto out;
 
-	if (!npfvar_add_element(vp, NPFVAR_ICMP, &code, sizeof(code)))
+	if (!npfvar_add_element(vp, varnum, &code, sizeof(code)))
 		goto out;
 
 	return vp;
@@ -512,3 +585,4 @@
 	npfvar_destroy(vp);
 	return NULL;
 }
+
--- a/usr.sbin/npf/npfctl/npf_disassemble.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npf_disassemble.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_disassemble.c,v 1.3.2.5 2012/07/16 22:13:28 riz Exp $	*/
+/*	$NetBSD: npf_disassemble.c,v 1.3.2.6 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_disassemble.c,v 1.3.2.5 2012/07/16 22:13:28 riz Exp $");
+__RCSID("$NetBSD: npf_disassemble.c,v 1.3.2.6 2012/07/25 20:45:23 jdc Exp $");
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -232,7 +232,7 @@
 		snprintf(buf, bufsiz, "id=%d", op);
 		break;
 
-	case NPF_OPERAND_ICMP4_TYPE_CODE: {
+	case NPF_OPERAND_ICMP_TYPE_CODE: {
 		uint8_t type = (op & 31) ? op >> 8 : 0;
 		uint8_t code = (op & 30) ? op & 0xff : 0;
 
--- a/usr.sbin/npf/npfctl/npf_ncgen.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npf_ncgen.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_ncgen.c,v 1.7.2.4 2012/07/16 22:13:28 riz Exp $	*/
+/*	$NetBSD: npf_ncgen.c,v 1.7.2.5 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_ncgen.c,v 1.7.2.4 2012/07/16 22:13:28 riz Exp $");
+__RCSID("$NetBSD: npf_ncgen.c,v 1.7.2.5 2012/07/25 20:45:23 jdc Exp $");
 
 #include <stdlib.h>
 #include <stddef.h>
@@ -343,6 +343,26 @@
 }
 
 /*
+ * npfctl_gennc_icmp6: fragment to match ICMPV6 type and code.
+ */
+void
+npfctl_gennc_icmp6(nc_ctx_t *ctx, int type, int code)
+{
+	uint32_t *nc = npfctl_ncgen_getptr(ctx, 4 /* words */);
+
+	/* OP, code, type (2 words) */
+	*nc++ = NPF_OPCODE_ICMP6;
+	*nc++ = (type == -1 ? 0 : (1 << 31) | ((type & 0xff) << 8)) |
+		(code == -1 ? 0 : (1 << 30) | (code & 0xff));
+
+	/* Comparison block (2 words). */
+	npfctl_ncgen_addjmp(ctx, &nc);
+
+	/* + 4 words. */
+	npfctl_ncgen_putptr(ctx, nc);
+}
+
+/*
  * npfctl_gennc_tbl: fragment to match IPv4 source/destination address of
  * the packet against table specified by ID.
  */
--- a/usr.sbin/npf/npfctl/npf_parse.y	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npf_parse.y	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_parse.y,v 1.3.2.4 2012/07/16 22:13:28 riz Exp $	*/
+/*	$NetBSD: npf_parse.y,v 1.3.2.5 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -120,7 +120,8 @@
 %token			TO
 %token			TREE
 %token			TYPE
-%token			ICMP
+%token	<num>		ICMP
+%token	<num>		ICMP6
 
 %token	<num>		HEX
 %token	<str>		IDENTIFIER
@@ -471,6 +472,11 @@
 		$$.op_proto = IPPROTO_ICMP;
 		$$.op_opts = $3;
 	}
+	| PROTO ICMP6 icmp_type_and_code
+	{
+		$$.op_proto = IPPROTO_ICMPV6;
+		$$.op_opts = $3;
+	}
 	| PROTO some_name
 	{
 		$$.op_proto = npfctl_protono($2);
@@ -633,24 +639,24 @@
 icmp_type_and_code
 	: ICMPTYPE icmp_type
 	{
-		$$ = npfctl_parse_icmp($2, -1);
+		$$ = npfctl_parse_icmp($<num>0, $2, -1);
 	}
 	| ICMPTYPE icmp_type CODE NUM
 	{
-		$$ = npfctl_parse_icmp($2, $4);
+		$$ = npfctl_parse_icmp($<num>0, $2, $4);
 	}
 	| ICMPTYPE icmp_type CODE IDENTIFIER
 	{
-		$$ = npfctl_parse_icmp($2, npfctl_icmpcode($2, $4));
+		$$ = npfctl_parse_icmp($<num>0, $2, npfctl_icmpcode($<num>0, $2, $4));
 	}
 	| ICMPTYPE icmp_type CODE VAR_ID
 	{
 		char *s = npfvar_expand_string(npfvar_lookup($4));
-		$$ = npfctl_parse_icmp($2, npfctl_icmpcode($2, s));
+		$$ = npfctl_parse_icmp($<num>0, $2, npfctl_icmpcode($<num>0, $2, s));
 	}
 	|
 	{
-		$$ = npfctl_parse_icmp(-1, -1);
+		$$ = npfctl_parse_icmp($<num>0, -1, -1);
 	}
 	;
 
@@ -675,11 +681,11 @@
 
 icmp_type
 	: NUM		{ $$ = $1; }
-	| IDENTIFIER	{ $$ = npfctl_icmptype($1); }
+	| IDENTIFIER	{ $$ = npfctl_icmptype($<num>-1, $1); }
 	| VAR_ID
 	{
 		char *s = npfvar_expand_string(npfvar_lookup($1));
-		$$ = npfctl_icmptype(s);
+		$$ = npfctl_icmptype($<num>-1, s);
 	}
 	;
 
--- a/usr.sbin/npf/npfctl/npf_scan.l	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npf_scan.l	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_scan.l,v 1.1.2.2 2012/07/05 17:48:44 riz Exp $	*/
+/*	$NetBSD: npf_scan.l,v 1.1.2.3 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -85,7 +85,9 @@
 proto			return PROTO;
 family			return FAMILY;
 tcp			return TCP;
-icmp			return ICMP;
+icmp			{ yylval.num = IPPROTO_ICMP; return ICMP; }
+ipv6-icmp		{ yylval.num = IPPROTO_ICMPV6; return ICMP6; }
+\"ipv6-icmp\"		{ yylval.num = IPPROTO_ICMPV6; return ICMP6; }
 return-rst		return RETURNRST;
 return-icmp		return RETURNICMP;
 return			return RETURN;
--- a/usr.sbin/npf/npfctl/npf_var.h	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npf_var.h	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_var.h,v 1.1.2.1 2012/06/26 00:07:20 riz Exp $	*/
+/*	$NetBSD: npf_var.h,v 1.1.2.2 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -48,11 +48,12 @@
 #define	NPFVAR_ICMP		8
 #define	NPFVAR_PROC_OP		9
 #define	NPFVAR_MODULE_ARG	10
+#define	NPFVAR_ICMP6		11
 
 #ifdef _NPFVAR_PRIVATE
 static const char *npfvar_types[ ] = {
 	"string", "identifier", "var_id", "num", "table", "fam", "port_range",
-	"tcpflag", "icmp", "proc_op", "module_arg"
+	"tcpflag", "icmp", "proc_op", "module_arg", "icmp6"
 };
 #endif
 
--- a/usr.sbin/npf/npfctl/npfctl.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npfctl.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npfctl.c,v 1.10.2.3 2012/07/16 22:13:28 riz Exp $	*/
+/*	$NetBSD: npfctl.c,v 1.10.2.4 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npfctl.c,v 1.10.2.3 2012/07/16 22:13:28 riz Exp $");
+__RCSID("$NetBSD: npfctl.c,v 1.10.2.4 2012/07/25 20:45:23 jdc Exp $");
 
 #include <sys/ioctl.h>
 #include <sys/stat.h>
@@ -171,48 +171,64 @@
 static int
 npfctl_print_stats(int fd)
 {
+	static const struct stats_s {
+		/* Note: -1 indicates a new section. */
+		int		index;
+		const char *	name;
+	} stats[] = {
+		{ -1, "Packets passed"					},
+		{ NPF_STAT_PASS_DEFAULT,	"default pass"		},
+		{ NPF_STAT_PASS_RULESET,	"ruleset pass"		},
+		{ NPF_STAT_PASS_SESSION,	"session pass"		},
+
+		{ -1, "Packets blocked"					},
+		{ NPF_STAT_BLOCK_DEFAULT,	"default block"		},
+		{ NPF_STAT_BLOCK_RULESET,	"ruleset block"		},
+
+		{ -1, "Session and NAT entries"				},
+		{ NPF_STAT_SESSION_CREATE,	"session allocations"	},
+		{ NPF_STAT_SESSION_DESTROY,	"session destructions"	},
+		{ NPF_STAT_NAT_CREATE,		"NAT entry allocations"	},
+		{ NPF_STAT_NAT_DESTROY,		"NAT entry destructions"},
+
+		{ -1, "Invalid packet state cases"			},
+		{ NPF_STAT_INVALID_STATE,	"cases in total"	},
+		{ NPF_STAT_INVALID_STATE_TCP1,	"TCP case I"		},
+		{ NPF_STAT_INVALID_STATE_TCP2,	"TCP case II"		},
+		{ NPF_STAT_INVALID_STATE_TCP3,	"TCP case III"		},
+
+		{ -1, "Packet race cases"				},
+		{ NPF_STAT_RACE_NAT,		"NAT association race"	},
+		{ NPF_STAT_RACE_SESSION,	"duplicate session race"},
+
+		{ -1, "Rule procedure cases"				},
+		{ NPF_STAT_RPROC_LOG,		"packets logged"	},
+		{ NPF_STAT_RPROC_NORM,		"packets normalised"	},
+
+		{ -1, "Fragmentation"					},
+		{ NPF_STAT_FRAGMENTS,		"fragments"		},
+		{ NPF_STAT_REASSEMBLY,		"reassembled"		},
+		{ NPF_STAT_REASSFAIL,		"failed reassembly"	},
+
+		{ -1, "Other"						},
+		{ NPF_STAT_ERROR,		"unexpected errors"	},
+	};
 	uint64_t *st = zalloc(NPF_STATS_SIZE);
 
 	if (ioctl(fd, IOC_NPF_STATS, &st) != 0) {
 		err(EXIT_FAILURE, "ioctl(IOC_NPF_STATS)");
 	}
 
-	printf("Packets passed:\n\t%"PRIu64" default pass\n\t"
-	    "%"PRIu64 " ruleset pass\n\t%"PRIu64" session pass\n\n",
-	    st[NPF_STAT_PASS_DEFAULT], st[NPF_STAT_PASS_RULESET],
-	    st[NPF_STAT_PASS_SESSION]);
-
-	printf("Packets blocked:\n\t%"PRIu64" default block\n\t"
-	    "%"PRIu64 " ruleset block\n\n", st[NPF_STAT_BLOCK_DEFAULT],
-	    st[NPF_STAT_BLOCK_RULESET]);
-
-	printf("Session and NAT entries:\n\t%"PRIu64" session allocations\n\t"
-	    "%"PRIu64" session destructions\n\t%"PRIu64" NAT entry allocations\n\t"
-	    "%"PRIu64" NAT entry destructions\n\n", st[NPF_STAT_SESSION_CREATE],
-	    st[NPF_STAT_SESSION_DESTROY], st[NPF_STAT_NAT_CREATE],
-	    st[NPF_STAT_NAT_DESTROY]);
+	for (unsigned i = 0; i < __arraycount(stats); i++) {
+		const char *sname = stats[i].name;
+		int sidx = stats[i].index;
 
-	printf("Invalid packet state cases:\n\t%"PRIu64" cases in total\n\t"
-	    "%"PRIu64" TCP case I\n\t%"PRIu64" TCP case II\n\t%"PRIu64
-	    " TCP case III\n\n", st[NPF_STAT_INVALID_STATE],
-	    st[NPF_STAT_INVALID_STATE_TCP1], st[NPF_STAT_INVALID_STATE_TCP2],
-	    st[NPF_STAT_INVALID_STATE_TCP3]);
-
-	printf("Packet race cases:\n\t%"PRIu64" NAT association race\n\t"
-	    "%"PRIu64" duplicate session race\n\n", st[NPF_STAT_RACE_NAT],
-	    st[NPF_STAT_RACE_SESSION]);
-
-	printf("Rule processing procedure cases:\n"
-	    "\t%"PRIu64" packets logged\n\t%"PRIu64" packets normalized\n\n",
-	    st[NPF_STAT_RPROC_LOG], st[NPF_STAT_RPROC_NORM]);
-
-	printf("Fragmentation:\n"
-	    "\t%"PRIu64" fragments\n\t%"PRIu64" reassembled\n"
-	    "\t%"PRIu64" failed reassembly\n\n",
-	    st[NPF_STAT_FRAGMENTS], st[NPF_STAT_REASSEMBLY],
-	    st[NPF_STAT_REASSFAIL]);
-
-	printf("Unexpected error cases:\n\t%"PRIu64"\n", st[NPF_STAT_ERROR]);
+		if (sidx == -1) {
+			printf("%s:\n", sname);
+		} else {
+			printf("\t%"PRIu64" %s\n", st[sidx], sname);
+		}
+	}
 
 	free(st);
 	return 0;
@@ -243,7 +259,7 @@
 	}
 }
 
-static void
+__dead static void
 npfctl_table(int fd, char **argv)
 {
 	static const struct tblops_s {
--- a/usr.sbin/npf/npfctl/npfctl.h	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npfctl/npfctl.h	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npfctl.h,v 1.11.2.4 2012/07/16 22:13:28 riz Exp $	*/
+/*	$NetBSD: npfctl.h,v 1.11.2.5 2012/07/25 20:45:23 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -99,13 +99,12 @@
 bool		npfctl_table_exists_p(const char *);
 int		npfctl_protono(const char *);
 in_port_t	npfctl_portno(const char *);
-uint8_t		npfctl_icmpcode(uint8_t, const char *);
-uint8_t		npfctl_icmptype(const char *);
+uint8_t		npfctl_icmpcode(int, uint8_t, const char *);
+uint8_t		npfctl_icmptype(int, const char *);
 unsigned long   npfctl_find_ifindex(const char *);
 npfvar_t *	npfctl_parse_tcpflag(const char *);
 npfvar_t *	npfctl_parse_table_id(const char *);
-npfvar_t * 	npfctl_parse_icmpcode(const char *);
-npfvar_t * 	npfctl_parse_icmp(int, int);
+npfvar_t * 	npfctl_parse_icmp(int, int, int);
 npfvar_t *	npfctl_parse_iface(const char *);
 npfvar_t *	npfctl_parse_port_range(in_port_t, in_port_t);
 npfvar_t *	npfctl_parse_port_range_variable(const char *);
@@ -125,6 +124,7 @@
 #define	NC_MATCH_TCP		0x04
 #define	NC_MATCH_UDP		0x08
 #define	NC_MATCH_ICMP		0x10
+#define	NC_MATCH_ICMP6		0x20
 
 nc_ctx_t *	npfctl_ncgen_create(void);
 void *		npfctl_ncgen_complete(nc_ctx_t *, size_t *);
@@ -139,6 +139,7 @@
 		    const npf_netmask_t);
 void		npfctl_gennc_ports(nc_ctx_t *, int, in_port_t, in_port_t);
 void		npfctl_gennc_icmp(nc_ctx_t *, int, int);
+void		npfctl_gennc_icmp6(nc_ctx_t *, int, int);
 void		npfctl_gennc_tbl(nc_ctx_t *, int, u_int);
 void		npfctl_gennc_tcpfl(nc_ctx_t *, uint8_t, uint8_t);
 void		npfctl_gennc_proto(nc_ctx_t *ctx, uint8_t, uint8_t);
--- a/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_test_subr.c,v 1.1.2.2 2012/06/26 00:07:19 riz Exp $	*/
+/*	$NetBSD: npf_test_subr.c,v 1.1.2.3 2012/07/25 20:45:24 jdc Exp $	*/
 
 /*
  * NPF initialisation and handler routines.
@@ -65,10 +65,12 @@
 	result[i++] = fstate->nst_end;
 	result[i++] = fstate->nst_maxend;
 	result[i++] = fstate->nst_maxwin;
+	result[i++] = fstate->nst_wscale;
 
 	result[i++] = tstate->nst_end;
 	result[i++] = tstate->nst_maxend;
 	result[i++] = tstate->nst_maxwin;
+	result[i++] = tstate->nst_wscale;
 
 	return 0;
 }
--- a/usr.sbin/npf/npftest/npfstream.c	Wed Jul 25 20:33:28 2012 +0000
+++ b/usr.sbin/npf/npftest/npfstream.c	Wed Jul 25 20:45:23 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npfstream.c,v 1.1.2.2 2012/06/26 00:07:17 riz Exp $	*/
+/*	$NetBSD: npfstream.c,v 1.1.2.3 2012/07/25 20:45:24 jdc Exp $	*/
 
 /*
  * NPF stream processor.
@@ -67,7 +67,7 @@
 	forw = (initial_ip.s_addr == ip->ip_src.s_addr);
 	packetno = forw ? ++snd_packet_no : ++rcv_packet_no;
 
-	int64_t result[9];
+	int64_t result[11];
 	memset(result, 0, sizeof(result));
 
 	len = ntohs(ip->ip_len);
@@ -76,7 +76,7 @@
 	fprintf(fp, "%s%2x %5d %3d %11u %11u %11u %11u %12lx",
 	    forw ? ">" : "<", (th->th_flags & (TH_SYN | TH_ACK | TH_FIN)),
 	    packetno, error, (u_int)seq, (u_int)ntohl(th->th_ack),
-	    (u_int)(seq + tcpdlen), ntohs(th->th_win), (uintptr_t)result[0]);
+	    tcpdlen, ntohs(th->th_win), (uintptr_t)result[0]);
 
 	for (unsigned i = 1; i < __arraycount(result); i++) {
 		fprintf(fp, "%11" PRIu64 " ", result[i]);
@@ -101,9 +101,12 @@
 	if (fp == NULL) {
 		err(EXIT_FAILURE, "fopen");
 	}
-	fprintf(fp, "#   %5s %3s %11s %11s %11s %11s %11s %11s %11s\n",
+	fprintf(fp, "#FL %5s %3s %11s %11s %11s %11s %11s %11s %11s "
+	    "%11s %11s %11s %5s %11s %11s %11s %5s\n",
 	    "No", "Err", "Seq", "Ack", "TCP Len", "Win",
-	    "Stream", "RetVal", "State");
+	    "Stream", "RetVal", "State",
+	    "F.END", "F.MAXEND", "F.MAXWIN", "F.WSC",
+	    "T.END", "T.MAXEND", "T.MAXWIN", "T.WSC");
 	while (pcap_next_ex(pcap, &phdr, &data) > 0) {
 		if (phdr->len != phdr->caplen) {
 			warnx("process_stream: truncated packet");