[Midnightbsd-cvs] src [9926] trunk/sys/netipsec: sync with freebsd 10-stable

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri May 25 09:07:23 EDT 2018


Revision: 9926
          http://svnweb.midnightbsd.org/src/?rev=9926
Author:   laffer1
Date:     2018-05-25 09:07:22 -0400 (Fri, 25 May 2018)
Log Message:
-----------
sync with freebsd 10-stable

Modified Paths:
--------------
    trunk/sys/netipsec/ah.h
    trunk/sys/netipsec/ah_var.h
    trunk/sys/netipsec/esp.h
    trunk/sys/netipsec/esp_var.h
    trunk/sys/netipsec/ipcomp.h
    trunk/sys/netipsec/ipcomp_var.h
    trunk/sys/netipsec/ipip_var.h
    trunk/sys/netipsec/ipsec.c
    trunk/sys/netipsec/ipsec.h
    trunk/sys/netipsec/ipsec6.h
    trunk/sys/netipsec/ipsec_input.c
    trunk/sys/netipsec/ipsec_mbuf.c
    trunk/sys/netipsec/ipsec_output.c
    trunk/sys/netipsec/key.c
    trunk/sys/netipsec/key.h
    trunk/sys/netipsec/key_debug.c
    trunk/sys/netipsec/key_debug.h
    trunk/sys/netipsec/key_var.h
    trunk/sys/netipsec/keydb.h
    trunk/sys/netipsec/keysock.c
    trunk/sys/netipsec/keysock.h
    trunk/sys/netipsec/xform.h
    trunk/sys/netipsec/xform_ah.c
    trunk/sys/netipsec/xform_esp.c
    trunk/sys/netipsec/xform_ipcomp.c
    trunk/sys/netipsec/xform_ipip.c
    trunk/sys/netipsec/xform_tcp.c

Modified: trunk/sys/netipsec/ah.h
===================================================================
--- trunk/sys/netipsec/ah.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ah.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ah.h 139823 2005-01-07 01:45:51Z imp $	*/
 /*	$KAME: ah.h,v 1.13 2000/10/18 21:28:00 itojun Exp $	*/
 
 /*-

Modified: trunk/sys/netipsec/ah_var.h
===================================================================
--- trunk/sys/netipsec/ah_var.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ah_var.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ah_var.h 253088 2013-07-09 10:08:13Z ae $	*/
 /*	$OpenBSD: ip_ah.h,v 1.29 2002/06/09 16:26:10 itojun Exp $	*/
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),
@@ -48,35 +49,39 @@
 #define	AH_ALG_MAX	16
 
 struct ahstat {
-	u_int32_t	ahs_hdrops;	/* Packet shorter than header shows */
-	u_int32_t	ahs_nopf;	/* Protocol family not supported */
-	u_int32_t	ahs_notdb;
-	u_int32_t	ahs_badkcr;
-	u_int32_t	ahs_badauth;
-	u_int32_t	ahs_noxform;
-	u_int32_t	ahs_qfull;
-	u_int32_t	ahs_wrap;
-	u_int32_t	ahs_replay;
-	u_int32_t	ahs_badauthl;	/* Bad authenticator length */
-	u_int32_t	ahs_input;	/* Input AH packets */
-	u_int32_t	ahs_output;	/* Output AH packets */
-	u_int32_t	ahs_invalid;	/* Trying to use an invalid TDB */
-	u_int64_t	ahs_ibytes;	/* Input bytes */
-	u_int64_t	ahs_obytes;	/* Output bytes */
-	u_int32_t	ahs_toobig;	/* Packet got larger than IP_MAXPACKET */
-	u_int32_t	ahs_pdrops;	/* Packet blocked due to policy */
-	u_int32_t	ahs_crypto;	/* Crypto processing failure */
-	u_int32_t	ahs_tunnel;	/* Tunnel sanity check failure */
-	u_int32_t	ahs_hist[AH_ALG_MAX];	/* Per-algorithm op count */
+	uint64_t	ahs_hdrops;	/* Packet shorter than header shows */
+	uint64_t	ahs_nopf;	/* Protocol family not supported */
+	uint64_t	ahs_notdb;
+	uint64_t	ahs_badkcr;
+	uint64_t	ahs_badauth;
+	uint64_t	ahs_noxform;
+	uint64_t	ahs_qfull;
+	uint64_t	ahs_wrap;
+	uint64_t	ahs_replay;
+	uint64_t	ahs_badauthl;	/* Bad authenticator length */
+	uint64_t	ahs_input;	/* Input AH packets */
+	uint64_t	ahs_output;	/* Output AH packets */
+	uint64_t	ahs_invalid;	/* Trying to use an invalid TDB */
+	uint64_t	ahs_ibytes;	/* Input bytes */
+	uint64_t	ahs_obytes;	/* Output bytes */
+	uint64_t	ahs_toobig;	/* Packet got larger than IP_MAXPACKET */
+	uint64_t	ahs_pdrops;	/* Packet blocked due to policy */
+	uint64_t	ahs_crypto;	/* Crypto processing failure */
+	uint64_t	ahs_tunnel;	/* Tunnel sanity check failure */
+	uint64_t	ahs_hist[AH_ALG_MAX];	/* Per-algorithm op count */
 };
 
 #ifdef _KERNEL
+#include <sys/counter.h>
+
 VNET_DECLARE(int, ah_enable);
 VNET_DECLARE(int, ah_cleartos);
-VNET_DECLARE(struct ahstat, ahstat);
+VNET_PCPUSTAT_DECLARE(struct ahstat, ahstat);
 
+#define	AHSTAT_ADD(name, val)	\
+    VNET_PCPUSTAT_ADD(struct ahstat, ahstat, name , (val))
+#define	AHSTAT_INC(name)	AHSTAT_ADD(name, 1)
 #define	V_ah_enable		VNET(ah_enable)
 #define	V_ah_cleartos		VNET(ah_cleartos)
-#define	V_ahstat		VNET(ahstat)
 #endif /* _KERNEL */
 #endif /*_NETIPSEC_AH_VAR_H_*/

Modified: trunk/sys/netipsec/esp.h
===================================================================
--- trunk/sys/netipsec/esp.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/esp.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/esp.h 139823 2005-01-07 01:45:51Z imp $	*/
 /*	$KAME: esp.h,v 1.16 2000/10/18 21:28:00 itojun Exp $	*/
 
 /*-

Modified: trunk/sys/netipsec/esp_var.h
===================================================================
--- trunk/sys/netipsec/esp_var.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/esp_var.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/esp_var.h 253088 2013-07-09 10:08:13Z ae $	*/
 /*	$OpenBSD: ip_esp.h,v 1.37 2002/06/09 16:26:10 itojun Exp $	*/
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),
@@ -48,34 +49,38 @@
 #define	ESP_ALG_MAX	256		/* NB: could be < but skipjack is 249 */
 
 struct espstat {
-	u_int32_t	esps_hdrops;	/* Packet shorter than header shows */
-	u_int32_t	esps_nopf;	/* Protocol family not supported */
-	u_int32_t	esps_notdb;
-	u_int32_t	esps_badkcr;
-	u_int32_t	esps_qfull;
-	u_int32_t	esps_noxform;
-	u_int32_t	esps_badilen;
-	u_int32_t	esps_wrap;	/* Replay counter wrapped around */
-	u_int32_t	esps_badenc;	/* Bad encryption detected */
-	u_int32_t	esps_badauth;	/* Only valid for transforms with auth */
-	u_int32_t	esps_replay;	/* Possible packet replay detected */
-	u_int32_t	esps_input;	/* Input ESP packets */
-	u_int32_t	esps_output;	/* Output ESP packets */
-	u_int32_t	esps_invalid;	/* Trying to use an invalid TDB */
-	u_int64_t	esps_ibytes;	/* Input bytes */
-	u_int64_t	esps_obytes;	/* Output bytes */
-	u_int32_t	esps_toobig;	/* Packet got larger than IP_MAXPACKET */
-	u_int32_t	esps_pdrops;	/* Packet blocked due to policy */
-	u_int32_t	esps_crypto;	/* Crypto processing failure */
-	u_int32_t	esps_tunnel;	/* Tunnel sanity check failure */
-	u_int32_t	esps_hist[ESP_ALG_MAX];	/* Per-algorithm op count */
+	uint64_t	esps_hdrops;	/* Packet shorter than header shows */
+	uint64_t	esps_nopf;	/* Protocol family not supported */
+	uint64_t	esps_notdb;
+	uint64_t	esps_badkcr;
+	uint64_t	esps_qfull;
+	uint64_t	esps_noxform;
+	uint64_t	esps_badilen;
+	uint64_t	esps_wrap;	/* Replay counter wrapped around */
+	uint64_t	esps_badenc;	/* Bad encryption detected */
+	uint64_t	esps_badauth;	/* Only valid for transforms with auth */
+	uint64_t	esps_replay;	/* Possible packet replay detected */
+	uint64_t	esps_input;	/* Input ESP packets */
+	uint64_t	esps_output;	/* Output ESP packets */
+	uint64_t	esps_invalid;	/* Trying to use an invalid TDB */
+	uint64_t	esps_ibytes;	/* Input bytes */
+	uint64_t	esps_obytes;	/* Output bytes */
+	uint64_t	esps_toobig;	/* Packet got larger than IP_MAXPACKET */
+	uint64_t	esps_pdrops;	/* Packet blocked due to policy */
+	uint64_t	esps_crypto;	/* Crypto processing failure */
+	uint64_t	esps_tunnel;	/* Tunnel sanity check failure */
+	uint64_t	esps_hist[ESP_ALG_MAX];	/* Per-algorithm op count */
 };
 
 #ifdef _KERNEL
+#include <sys/counter.h>
+
 VNET_DECLARE(int, esp_enable);
-VNET_DECLARE(struct espstat, espstat);
+VNET_PCPUSTAT_DECLARE(struct espstat, espstat);
 
+#define	ESPSTAT_ADD(name, val)	\
+    VNET_PCPUSTAT_ADD(struct espstat, espstat, name, (val))
+#define	ESPSTAT_INC(name)	ESPSTAT_ADD(name, 1)
 #define	V_esp_enable	VNET(esp_enable)
-#define	V_espstat	VNET(espstat)
 #endif /* _KERNEL */
 #endif /*_NETIPSEC_ESP_VAR_H_*/

Modified: trunk/sys/netipsec/ipcomp.h
===================================================================
--- trunk/sys/netipsec/ipcomp.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipcomp.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ipcomp.h 139823 2005-01-07 01:45:51Z imp $	*/
 /*	$KAME: ipcomp.h,v 1.8 2000/09/26 07:55:14 itojun Exp $	*/
 
 /*-

Modified: trunk/sys/netipsec/ipcomp_var.h
===================================================================
--- trunk/sys/netipsec/ipcomp_var.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipcomp_var.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ipcomp_var.h 253088 2013-07-09 10:08:13Z ae $	*/
 /*	$KAME: ipcomp.h,v 1.8 2000/09/26 07:55:14 itojun Exp $	*/
 
 /*-
@@ -41,34 +42,37 @@
  */
 #define	IPCOMP_ALG_MAX	8
 
-#define	IPCOMPSTAT_VERSION	1
+#define	IPCOMPSTAT_VERSION	2
 struct ipcompstat {
-	u_int32_t	ipcomps_hdrops;	/* Packet shorter than header shows */
-	u_int32_t	ipcomps_nopf;	/* Protocol family not supported */
-	u_int32_t	ipcomps_notdb;
-	u_int32_t	ipcomps_badkcr;
-	u_int32_t	ipcomps_qfull;
-	u_int32_t	ipcomps_noxform;
-	u_int32_t	ipcomps_wrap;
-	u_int32_t	ipcomps_input;	/* Input IPcomp packets */
-	u_int32_t	ipcomps_output;	/* Output IPcomp packets */
-	u_int32_t	ipcomps_invalid;/* Trying to use an invalid TDB */
-	u_int64_t	ipcomps_ibytes;	/* Input bytes */
-	u_int64_t	ipcomps_obytes;	/* Output bytes */
-	u_int32_t	ipcomps_toobig;	/* Packet got > IP_MAXPACKET */
-	u_int32_t	ipcomps_pdrops;	/* Packet blocked due to policy */
-	u_int32_t	ipcomps_crypto;	/* "Crypto" processing failure */
-	u_int32_t	ipcomps_hist[IPCOMP_ALG_MAX];/* Per-algorithm op count */
-	u_int32_t	version;	/* Version of this structure. */
-	u_int32_t	ipcomps_threshold; /* Packet < comp. algo. threshold. */
-	u_int32_t	ipcomps_uncompr; /* Compression was useles. */
+	uint64_t	ipcomps_hdrops;	/* Packet shorter than header shows */
+	uint64_t	ipcomps_nopf;	/* Protocol family not supported */
+	uint64_t	ipcomps_notdb;
+	uint64_t	ipcomps_badkcr;
+	uint64_t	ipcomps_qfull;
+	uint64_t	ipcomps_noxform;
+	uint64_t	ipcomps_wrap;
+	uint64_t	ipcomps_input;	/* Input IPcomp packets */
+	uint64_t	ipcomps_output;	/* Output IPcomp packets */
+	uint64_t	ipcomps_invalid;/* Trying to use an invalid TDB */
+	uint64_t	ipcomps_ibytes;	/* Input bytes */
+	uint64_t	ipcomps_obytes;	/* Output bytes */
+	uint64_t	ipcomps_toobig;	/* Packet got > IP_MAXPACKET */
+	uint64_t	ipcomps_pdrops;	/* Packet blocked due to policy */
+	uint64_t	ipcomps_crypto;	/* "Crypto" processing failure */
+	uint64_t	ipcomps_hist[IPCOMP_ALG_MAX];/* Per-algorithm op count */
+	uint64_t	ipcomps_threshold; /* Packet < comp. algo. threshold. */
+	uint64_t	ipcomps_uncompr; /* Compression was useles. */
 };
 
 #ifdef _KERNEL
+#include <sys/counter.h>
+
 VNET_DECLARE(int, ipcomp_enable);
-VNET_DECLARE(struct ipcompstat, ipcompstat);
+VNET_PCPUSTAT_DECLARE(struct ipcompstat, ipcompstat);
 
+#define	IPCOMPSTAT_ADD(name, val)	\
+    VNET_PCPUSTAT_ADD(struct ipcompstat, ipcompstat, name, (val))
+#define	IPCOMPSTAT_INC(name)		IPCOMPSTAT_ADD(name, 1)
 #define	V_ipcomp_enable		VNET(ipcomp_enable)
-#define	V_ipcompstat		VNET(ipcompstat)
 #endif /* _KERNEL */
 #endif /*_NETIPSEC_IPCOMP_VAR_H_*/

Modified: trunk/sys/netipsec/ipip_var.h
===================================================================
--- trunk/sys/netipsec/ipip_var.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipip_var.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ipip_var.h 253088 2013-07-09 10:08:13Z ae $	*/
 /*	$OpenBSD: ip_ipip.h,v 1.5 2002/06/09 16:26:10 itojun Exp $ */
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),
@@ -44,25 +45,28 @@
  * Not quite all the functionality of RFC-1853, but the main idea is there.
  */
 
-struct ipipstat
-{
-    u_int32_t	ipips_ipackets;		/* total input packets */
-    u_int32_t	ipips_opackets;		/* total output packets */
-    u_int32_t	ipips_hdrops;		/* packet shorter than header shows */
-    u_int32_t	ipips_qfull;
-    u_int64_t   ipips_ibytes;
-    u_int64_t   ipips_obytes;
-    u_int32_t	ipips_pdrops;		/* packet dropped due to policy */
-    u_int32_t	ipips_spoof;		/* IP spoofing attempts */
-    u_int32_t   ipips_family;		/* Protocol family mismatch */
-    u_int32_t   ipips_unspec;            /* Missing tunnel endpoint address */
+struct ipipstat {
+	uint64_t	ipips_ipackets;	/* total input packets */
+	uint64_t	ipips_opackets;	/* total output packets */
+	uint64_t	ipips_hdrops;	/* packet shorter than header shows */
+	uint64_t	ipips_qfull;
+	uint64_t	ipips_ibytes;
+	uint64_t	ipips_obytes;
+	uint64_t	ipips_pdrops;	/* packet dropped due to policy */
+	uint64_t	ipips_spoof;	/* IP spoofing attempts */
+	uint64_t	ipips_family;	/* Protocol family mismatch */
+	uint64_t	ipips_unspec;   /* Missing tunnel endpoint address */
 };
 
 #ifdef _KERNEL
+#include <sys/counter.h>
+
 VNET_DECLARE(int, ipip_allow);
-VNET_DECLARE(struct ipipstat, ipipstat);
+VNET_PCPUSTAT_DECLARE(struct ipipstat, ipipstat);
 
+#define	IPIPSTAT_ADD(name, val)	\
+    VNET_PCPUSTAT_ADD(struct ipipstat, ipipstat, name, (val))
+#define	IPIPSTAT_INC(name)	IPIPSTAT_ADD(name, 1)
 #define	V_ipip_allow		VNET(ipip_allow)
-#define	V_ipipstat		VNET(ipipstat)
 #endif /* _KERNEL */
 #endif /* _NETINET_IPIP_H_ */

Modified: trunk/sys/netipsec/ipsec.c
===================================================================
--- trunk/sys/netipsec/ipsec.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipsec.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ipsec.c 299627 2016-05-13 08:49:29Z ngie $	*/
 /*	$KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $	*/
 
 /*-
@@ -55,7 +56,6 @@
 #include <sys/proc.h>
 
 #include <net/if.h>
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netinet/in.h>
@@ -104,7 +104,13 @@
 #endif
 
 /* NB: name changed so netstat doesn't use it. */
-VNET_DEFINE(struct ipsecstat, ipsec4stat);
+VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec4stat);
+VNET_PCPUSTAT_SYSINIT(ipsec4stat);
+
+#ifdef VIMAGE
+VNET_PCPUSTAT_SYSUNINIT(ipsec4stat);
+#endif /* VIMAGE */
+
 VNET_DEFINE(int, ip4_ah_offsetmask) = 0;	/* maybe IP_DF? */
 /* DF bit on encap. 0: clear 1: set 2: copy */
 VNET_DEFINE(int, ip4_ipsec_dfbit) = 0;
@@ -167,9 +173,8 @@
 SYSCTL_VNET_INT(_net_inet_ipsec, OID_AUTO, crypto_support,
 	CTLFLAG_RW, &VNET_NAME(crypto_support), 0,
 	"Crypto driver selection.");
-SYSCTL_VNET_STRUCT(_net_inet_ipsec, OID_AUTO, ipsecstats,
-	CTLFLAG_RD, &VNET_NAME(ipsec4stat), ipsecstat,	
-	"IPsec IPv4 statistics.");
+SYSCTL_VNET_PCPUSTAT(_net_inet_ipsec, OID_AUTO, ipsecstats, struct ipsecstat,
+    ipsec4stat, "IPsec IPv4 statistics.");
 
 #ifdef REGRESSION
 /*
@@ -191,7 +196,13 @@
 #endif
 
 #ifdef INET6 
-VNET_DEFINE(struct ipsecstat, ipsec6stat);
+VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec6stat);
+VNET_PCPUSTAT_SYSINIT(ipsec6stat);
+
+#ifdef VIMAGE
+VNET_PCPUSTAT_SYSUNINIT(ipsec6stat);
+#endif /* VIMAGE */
+
 VNET_DEFINE(int, ip6_esp_trans_deflev) = IPSEC_LEVEL_USE;
 VNET_DEFINE(int, ip6_esp_net_deflev) = IPSEC_LEVEL_USE;
 VNET_DEFINE(int, ip6_ah_trans_deflev) = IPSEC_LEVEL_USE;
@@ -201,10 +212,6 @@
 SYSCTL_DECL(_net_inet6_ipsec6);
 
 /* net.inet6.ipsec6 */
-#ifdef COMPAT_KAME
-SYSCTL_OID(_net_inet6_ipsec6, IPSECCTL_STATS, stats, CTLFLAG_RD,
-    0, 0, compat_ipsecstats_sysctl, "S", "IPsec IPv6 statistics.");
-#endif /* COMPAT_KAME */
 SYSCTL_VNET_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy, CTLFLAG_RW,
 	&VNET_NAME(ip4_def_policy).policy, 0,
 	"IPsec default policy.");
@@ -226,22 +233,21 @@
 SYSCTL_VNET_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, debug, CTLFLAG_RW,
 	&VNET_NAME(ipsec_debug), 0,
 	"Enable IPsec debugging output when set.");
-SYSCTL_VNET_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS,
-	ipsecstats, CTLFLAG_RD, &VNET_NAME(ipsec6stat), ipsecstat,
-	"IPsec IPv6 statistics.");
+SYSCTL_VNET_PCPUSTAT(_net_inet6_ipsec6, IPSECCTL_STATS, ipsecstats,
+    struct ipsecstat, ipsec6stat, "IPsec IPv6 statistics.");
 #endif /* INET6 */
 
-static int ipsec_setspidx_inpcb __P((struct mbuf *, struct inpcb *));
-static int ipsec_setspidx __P((struct mbuf *, struct secpolicyindex *, int));
-static void ipsec4_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
-static int ipsec4_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
+static int ipsec_setspidx_inpcb(struct mbuf *, struct inpcb *);
+static int ipsec_setspidx(struct mbuf *, struct secpolicyindex *, int);
+static void ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *, int);
+static int ipsec4_setspidx_ipaddr(struct mbuf *, struct secpolicyindex *);
 #ifdef INET6
-static void ipsec6_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
-static int ipsec6_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
+static void ipsec6_get_ulp(struct mbuf *m, struct secpolicyindex *, int);
+static int ipsec6_setspidx_ipaddr(struct mbuf *, struct secpolicyindex *);
 #endif
-static void ipsec_delpcbpolicy __P((struct inpcbpolicy *));
-static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *src));
-static void vshiftl __P((unsigned char *, int, int));
+static void ipsec_delpcbpolicy(struct inpcbpolicy *);
+static struct secpolicy *ipsec_deepcopy_policy(struct secpolicy *src);
+static void vshiftl(unsigned char *, int, int);
 
 MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy");
 
@@ -454,7 +460,7 @@
 		sp = ipsec_getpolicybysock(m, dir, inp, error);
 	if (sp == NULL) {
 		IPSEC_ASSERT(*error != 0, ("getpolicy failed w/o error"));
-		V_ipsec4stat.ips_out_inval++;
+		IPSECSTAT_INC(ips_out_inval);
 		return (NULL);
 	}
 	IPSEC_ASSERT(*error == 0, ("sp w/ error set to %u", *error));
@@ -464,7 +470,7 @@
 		printf("%s: invalid policy %u\n", __func__, sp->policy);
 		/* FALLTHROUGH */
 	case IPSEC_POLICY_DISCARD:
-		V_ipsec4stat.ips_out_polvio++;
+		IPSECSTAT_INC(ips_out_polvio);
 		*error = -EINVAL;	/* Packet is discarded by caller. */
 		break;
 	case IPSEC_POLICY_BYPASS:
@@ -553,11 +559,7 @@
 		m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf);
 		ip = &ipbuf;
 	}
-#ifdef _IP_VHL
-	v = _IP_VHL_V(ip->ip_vhl);
-#else
 	v = ip->ip_v;
-#endif
 	switch (v) {
 	case 4:
 		error = ipsec4_setspidx_ipaddr(m, spidx);
@@ -597,28 +599,19 @@
 	IPSEC_ASSERT(m != NULL, ("null mbuf"));
 	IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip),("packet too short"));
 
-	/* NB: ip_input() flips it into host endian. XXX Need more checking. */
 	if (m->m_len >= sizeof (struct ip)) {
 		struct ip *ip = mtod(m, struct ip *);
-		if (ip->ip_off & (IP_MF | IP_OFFMASK))
+		if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
 			goto done;
-#ifdef _IP_VHL
-		off = _IP_VHL_HL(ip->ip_vhl) << 2;
-#else
 		off = ip->ip_hl << 2;
-#endif
 		nxt = ip->ip_p;
 	} else {
 		struct ip ih;
 
 		m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih);
-		if (ih.ip_off & (IP_MF | IP_OFFMASK))
+		if (ih.ip_off & htons(IP_MF | IP_OFFMASK))
 			goto done;
-#ifdef _IP_VHL
-		off = _IP_VHL_HL(ih.ip_vhl) << 2;
-#else
 		off = ih.ip_hl << 2;
-#endif
 		nxt = ih.ip_p;
 	}
 
@@ -948,6 +941,7 @@
 		ipsec_delisr(p);
 		p = NULL;
 	}
+	KEY_FREESP(&dst);
 	return (NULL);
 }
 
@@ -1281,6 +1275,9 @@
 	int error;
 	int result;
 
+	if (!key_havesp(IPSEC_DIR_INBOUND))
+		return 0;
+
 	IPSEC_ASSERT(m != NULL, ("null mbuf"));
 
 	/*
@@ -1315,7 +1312,7 @@
 
 	result = ipsec46_in_reject(m, inp);
 	if (result)
-		V_ipsec4stat.ips_in_polvio++;
+		IPSECSTAT_INC(ips_in_polvio);
 
 	return (result);
 }
@@ -1333,7 +1330,7 @@
 
 	result = ipsec46_in_reject(m, inp);
 	if (result)
-		V_ipsec6stat.ips_in_polvio++;
+		IPSEC6STAT_INC(ips_in_polvio);
 
 	return (result);
 }
@@ -1413,6 +1410,9 @@
 	int error;
 	size_t size;
 
+	if (!key_havesp(dir))
+		return 0;
+
 	IPSEC_ASSERT(m != NULL, ("null mbuf"));
 
 	/* Get SP for this packet.

Modified: trunk/sys/netipsec/ipsec.h
===================================================================
--- trunk/sys/netipsec/ipsec.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipsec.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ipsec.h 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: ipsec.h,v 1.53 2001/11/20 08:32:38 itojun Exp $	*/
 
 /*-
@@ -47,6 +48,10 @@
 
 #ifdef _KERNEL
 
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+#include <sys/_rwlock.h>
+
 #define	IPSEC_ASSERT(_c,_m) KASSERT(_c, _m)
 
 #define	IPSEC_IS_PRIVILEGED_SO(_so) \
@@ -86,7 +91,7 @@
 	u_int state;			/* 0: dead, others: alive */
 #define IPSEC_SPSTATE_DEAD	0
 #define IPSEC_SPSTATE_ALIVE	1
-	u_int16_t policy;		/* policy_type per pfkeyv2.h */
+	u_int policy;			/* policy_type per pfkeyv2.h */
 	u_int16_t scangen;		/* scan generation # */
 	struct ipsecrequest *req;
 				/* pointer to the ipsec request tree, */
@@ -217,54 +222,28 @@
 
 /* statistics for ipsec processing */
 struct ipsecstat {
-	u_quad_t in_success;  /* succeeded inbound process */
-	u_quad_t in_polvio;
-			/* security policy violation for inbound process */
-	u_quad_t in_nosa;     /* inbound SA is unavailable */
-	u_quad_t in_inval;    /* inbound processing failed due to EINVAL */
-	u_quad_t in_nomem;    /* inbound processing failed due to ENOBUFS */
-	u_quad_t in_badspi;   /* failed getting a SPI */
-	u_quad_t in_ahreplay; /* AH replay check failed */
-	u_quad_t in_espreplay; /* ESP replay check failed */
-	u_quad_t in_ahauthsucc; /* AH authentication success */
-	u_quad_t in_ahauthfail; /* AH authentication failure */
-	u_quad_t in_espauthsucc; /* ESP authentication success */
-	u_quad_t in_espauthfail; /* ESP authentication failure */
-	u_quad_t in_esphist[256];
-	u_quad_t in_ahhist[256];
-	u_quad_t in_comphist[256];
-	u_quad_t out_success; /* succeeded outbound process */
-	u_quad_t out_polvio;
-			/* security policy violation for outbound process */
-	u_quad_t out_nosa;    /* outbound SA is unavailable */
-	u_quad_t out_inval;   /* outbound process failed due to EINVAL */
-	u_quad_t out_nomem;    /* inbound processing failed due to ENOBUFS */
-	u_quad_t out_noroute; /* there is no route */
-	u_quad_t out_esphist[256];
-	u_quad_t out_ahhist[256];
-	u_quad_t out_comphist[256];
+	uint64_t ips_in_polvio;		/* input: sec policy violation */
+	uint64_t ips_in_nomem;		/* input: no memory available */
+	uint64_t ips_in_inval;		/* input: generic error */
 
-	u_quad_t spdcachelookup;
-	u_quad_t spdcachemiss;
+	uint64_t ips_out_polvio;	/* output: sec policy violation */
+	uint64_t ips_out_nosa;		/* output: SA unavailable  */
+	uint64_t ips_out_nomem;		/* output: no memory available */
+	uint64_t ips_out_noroute;	/* output: no route available */
+	uint64_t ips_out_inval;		/* output: generic error */
+	uint64_t ips_out_bundlesa;	/* output: bundled SA processed */
 
-	u_int32_t ips_in_polvio;	/* input: sec policy violation */
-	u_int32_t ips_out_polvio;	/* output: sec policy violation */
-	u_int32_t ips_out_nosa;		/* output: SA unavailable  */
-	u_int32_t ips_out_nomem;	/* output: no memory available */
-	u_int32_t ips_out_noroute;	/* output: no route available */
-	u_int32_t ips_out_inval;	/* output: generic error */
-	u_int32_t ips_out_bundlesa;	/* output: bundled SA processed */
-	u_int32_t ips_mbcoalesced;	/* mbufs coalesced during clone */
-	u_int32_t ips_clcoalesced;	/* clusters coalesced during clone */
-	u_int32_t ips_clcopied;		/* clusters copied during clone */
-	u_int32_t ips_mbinserted;	/* mbufs inserted during makespace */
+	uint64_t ips_mbcoalesced;	/* mbufs coalesced during clone */
+	uint64_t ips_clcoalesced;	/* clusters coalesced during clone */
+	uint64_t ips_clcopied;		/* clusters copied during clone */
+	uint64_t ips_mbinserted;	/* mbufs inserted during makespace */
 	/* 
 	 * Temporary statistics for performance analysis.
 	 */
 	/* See where ESP/AH/IPCOMP header land in mbuf on input */
-	u_int32_t ips_input_front;
-	u_int32_t ips_input_middle;
-	u_int32_t ips_input_end;
+	uint64_t ips_input_front;
+	uint64_t ips_input_middle;
+	uint64_t ips_input_end;
 };
 
 /*
@@ -290,41 +269,9 @@
 #define	IPSECCTL_ESP_RANDPAD		13
 #define IPSECCTL_MAXID			14
 
-#define IPSECCTL_NAMES { \
-	{ 0, 0 }, \
-	{ 0, 0 }, \
-	{ "def_policy", CTLTYPE_INT }, \
-	{ "esp_trans_deflev", CTLTYPE_INT }, \
-	{ "esp_net_deflev", CTLTYPE_INT }, \
-	{ "ah_trans_deflev", CTLTYPE_INT }, \
-	{ "ah_net_deflev", CTLTYPE_INT }, \
-	{ 0, 0 }, \
-	{ "ah_cleartos", CTLTYPE_INT }, \
-	{ "ah_offsetmask", CTLTYPE_INT }, \
-	{ "dfbit", CTLTYPE_INT }, \
-	{ "ecn", CTLTYPE_INT }, \
-	{ "debug", CTLTYPE_INT }, \
-	{ "esp_randpad", CTLTYPE_INT }, \
-}
+#ifdef _KERNEL
+#include <sys/counter.h>
 
-#define IPSEC6CTL_NAMES { \
-	{ 0, 0 }, \
-	{ 0, 0 }, \
-	{ "def_policy", CTLTYPE_INT }, \
-	{ "esp_trans_deflev", CTLTYPE_INT }, \
-	{ "esp_net_deflev", CTLTYPE_INT }, \
-	{ "ah_trans_deflev", CTLTYPE_INT }, \
-	{ "ah_net_deflev", CTLTYPE_INT }, \
-	{ 0, 0 }, \
-	{ 0, 0 }, \
-	{ 0, 0 }, \
-	{ 0, 0 }, \
-	{ "ecn", CTLTYPE_INT }, \
-	{ "debug", CTLTYPE_INT }, \
-	{ "esp_randpad", CTLTYPE_INT }, \
-}
-
-#ifdef _KERNEL
 struct ipsec_output_state {
 	struct mbuf *m;
 	struct route *ro;
@@ -347,7 +294,7 @@
 #define	V_ipsec_integrity	VNET(ipsec_integrity)
 #endif
 
-VNET_DECLARE(struct ipsecstat, ipsec4stat);
+VNET_PCPUSTAT_DECLARE(struct ipsecstat, ipsec4stat);
 VNET_DECLARE(struct secpolicy, ip4_def_policy);
 VNET_DECLARE(int, ip4_esp_trans_deflev);
 VNET_DECLARE(int, ip4_esp_net_deflev);
@@ -359,7 +306,8 @@
 VNET_DECLARE(int, ip4_esp_randpad);
 VNET_DECLARE(int, crypto_support);
 
-#define	V_ipsec4stat		VNET(ipsec4stat)
+#define	IPSECSTAT_INC(name)	\
+    VNET_PCPUSTAT_ADD(struct ipsecstat, ipsec4stat, name, 1)
 #define	V_ip4_def_policy	VNET(ip4_def_policy)
 #define	V_ip4_esp_trans_deflev	VNET(ip4_esp_trans_deflev)
 #define	V_ip4_esp_net_deflev	VNET(ip4_esp_net_deflev)
@@ -379,40 +327,39 @@
 extern	void ipsec_delisr(struct ipsecrequest *);
 
 struct tdb_ident;
-extern struct secpolicy *ipsec_getpolicy __P((struct tdb_ident*, u_int));
+extern struct secpolicy *ipsec_getpolicy(struct tdb_ident*, u_int);
 struct inpcb;
-extern struct secpolicy *ipsec4_checkpolicy __P((struct mbuf *, u_int, u_int,
-	int *, struct inpcb *));
+extern struct secpolicy *ipsec4_checkpolicy(struct mbuf *, u_int, u_int,
+	int *, struct inpcb *);
 extern struct secpolicy * ipsec_getpolicybyaddr(struct mbuf *, u_int,
 	int, int *);
 
 struct inpcb;
-extern int ipsec_init_policy __P((struct socket *so, struct inpcbpolicy **));
-extern int ipsec_copy_policy
-	__P((struct inpcbpolicy *, struct inpcbpolicy *));
-extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *));
-extern int ipsec_in_reject __P((struct secpolicy *, struct mbuf *));
+extern int ipsec_init_policy(struct socket *so, struct inpcbpolicy **);
+extern int ipsec_copy_policy(struct inpcbpolicy *, struct inpcbpolicy *);
+extern u_int ipsec_get_reqlevel(struct ipsecrequest *);
+extern int ipsec_in_reject(struct secpolicy *, struct mbuf *);
 
-extern int ipsec_set_policy __P((struct inpcb *inp, int optname,
-	caddr_t request, size_t len, struct ucred *cred));
-extern int ipsec_get_policy __P((struct inpcb *inpcb, caddr_t request,
-	size_t len, struct mbuf **mp));
-extern int ipsec_delete_pcbpolicy __P((struct inpcb *));
-extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *));
+extern int ipsec_set_policy(struct inpcb *inp, int optname,
+	caddr_t request, size_t len, struct ucred *cred);
+extern int ipsec_get_policy(struct inpcb *inpcb, caddr_t request,
+	size_t len, struct mbuf **mp);
+extern int ipsec_delete_pcbpolicy(struct inpcb *);
+extern int ipsec4_in_reject(struct mbuf *, struct inpcb *);
 
 struct secas;
 struct tcpcb;
-extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *));
-extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *));
+extern int ipsec_chkreplay(u_int32_t, struct secasvar *);
+extern int ipsec_updatereplay(u_int32_t, struct secasvar *);
 
-extern size_t ipsec_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
-extern size_t ipsec_hdrsiz_tcp __P((struct tcpcb *));
+extern size_t ipsec_hdrsiz(struct mbuf *, u_int, struct inpcb *);
+extern size_t ipsec_hdrsiz_tcp(struct tcpcb *);
 
 union sockaddr_union;
 extern char * ipsec_address(union sockaddr_union* sa);
-extern const char *ipsec_logsastr __P((struct secasvar *));
+extern const char *ipsec_logsastr(struct secasvar *);
 
-extern void ipsec_dumpmbuf __P((struct mbuf *));
+extern void ipsec_dumpmbuf(struct mbuf *);
 
 struct m_tag;
 extern void ah4_input(struct mbuf *m, int off);
@@ -423,11 +370,11 @@
 extern int ipsec4_common_input(struct mbuf *m, ...);
 extern int ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
 			int skip, int protoff, struct m_tag *mt);
-extern int ipsec4_process_packet __P((struct mbuf *, struct ipsecrequest *,
-			int, int));
-extern int ipsec_process_done __P((struct mbuf *, struct ipsecrequest *));
+extern int ipsec4_process_packet(struct mbuf *, struct ipsecrequest *,
+			int, int);
+extern int ipsec_process_done(struct mbuf *, struct ipsecrequest *);
 
-extern struct mbuf *ipsec_copypkt __P((struct mbuf *));
+extern struct mbuf *ipsec_copypkt(struct mbuf *);
 
 extern	void m_checkalignment(const char* where, struct mbuf *m0,
 		int off, int len);
@@ -446,12 +393,11 @@
 #endif /* _KERNEL */
 
 #ifndef _KERNEL
-extern caddr_t ipsec_set_policy __P((char *, int));
-extern int ipsec_get_policylen __P((caddr_t));
-extern char *ipsec_dump_policy __P((caddr_t, char *));
+extern caddr_t ipsec_set_policy(char *, int);
+extern int ipsec_get_policylen(caddr_t);
+extern char *ipsec_dump_policy(caddr_t, char *);
+extern const char *ipsec_strerror(void);
 
-extern const char *ipsec_strerror __P((void));
-
 #endif /* ! KERNEL */
 
 #endif /* _NETIPSEC_IPSEC_H_ */

Modified: trunk/sys/netipsec/ipsec6.h
===================================================================
--- trunk/sys/netipsec/ipsec6.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipsec6.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ipsec6.h 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: ipsec.h,v 1.44 2001/03/23 08:08:47 itojun Exp $	*/
 
 /*-
@@ -41,7 +42,9 @@
 #include <netipsec/keydb.h>
 
 #ifdef _KERNEL
-VNET_DECLARE(struct ipsecstat, ipsec6stat);
+#include <sys/counter.h>
+
+VNET_PCPUSTAT_DECLARE(struct ipsecstat, ipsec6stat);
 VNET_DECLARE(int, ip6_esp_trans_deflev);
 VNET_DECLARE(int, ip6_esp_net_deflev);
 VNET_DECLARE(int, ip6_ah_trans_deflev);
@@ -48,7 +51,8 @@
 VNET_DECLARE(int, ip6_ah_net_deflev);
 VNET_DECLARE(int, ip6_ipsec_ecn);
 
-#define	V_ipsec6stat		VNET(ipsec6stat)
+#define	IPSEC6STAT_INC(name)	\
+    VNET_PCPUSTAT_ADD(struct ipsecstat, ipsec6stat, name, 1)
 #define	V_ip6_esp_trans_deflev	VNET(ip6_esp_trans_deflev)
 #define	V_ip6_esp_net_deflev	VNET(ip6_esp_net_deflev)
 #define	V_ip6_ah_trans_deflev	VNET(ip6_ah_trans_deflev)
@@ -56,23 +60,14 @@
 #define	V_ip6_ipsec_ecn		VNET(ip6_ipsec_ecn)
 
 struct inpcb;
+extern int ipsec6_in_reject(struct mbuf *, struct inpcb *);
 
-extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *));
-
-struct ip6_hdr;
-extern const char *ipsec6_logpacketstr __P((struct ip6_hdr *, u_int32_t));
-
 struct m_tag;
 extern int ipsec6_common_input(struct mbuf **mp, int *offp, int proto);
 extern int ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav,
 			int skip, int protoff, struct m_tag *mt);
 extern void esp6_ctlinput(int, struct sockaddr *, void *);
-
-struct ipsec_output_state;
-extern int ipsec6_output_trans __P((struct ipsec_output_state *, u_char *,
-	struct mbuf *, struct secpolicy *, int, int *));
-extern int ipsec6_output_tunnel __P((struct ipsec_output_state *,
-	struct secpolicy *, int));
+extern int ipsec6_process_packet(struct mbuf *, struct ipsecrequest *);
 #endif /*_KERNEL*/
 
 #endif /*_NETIPSEC_IPSEC6_H_*/

Modified: trunk/sys/netipsec/ipsec_input.c
===================================================================
--- trunk/sys/netipsec/ipsec_input.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipsec_input.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/ipsec_input.c 283901 2015-06-02 03:14:42Z ae $	*/
 /*	$OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $	*/
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),
@@ -57,7 +58,6 @@
 
 #include <net/if.h>
 #include <net/pfil.h>
-#include <net/route.h>
 #include <net/netisr.h>
 #include <net/vnet.h>
 
@@ -99,8 +99,14 @@
 #endif
 
 
-#define IPSEC_ISTAT(p,x,y,z) ((p) == IPPROTO_ESP ? (x)++ : \
-			    (p) == IPPROTO_AH ? (y)++ : (z)++)
+#define	IPSEC_ISTAT(proto, name)	do {	\
+	if ((proto) == IPPROTO_ESP)		\
+		ESPSTAT_INC(esps_##name);	\
+	else if ((proto) == IPPROTO_AH)		\
+		AHSTAT_INC(ahs_##name);		\
+	else					\
+		IPCOMPSTAT_INC(ipcomps_##name);	\
+} while (0)
 
 #ifdef INET
 static void ipsec4_common_ctlinput(int, struct sockaddr *, void *, int);
@@ -125,8 +131,7 @@
 #endif
 #endif
 
-	IPSEC_ISTAT(sproto, V_espstat.esps_input, V_ahstat.ahs_input,
-		V_ipcompstat.ipcomps_input);
+	IPSEC_ISTAT(sproto, input);
 
 	IPSEC_ASSERT(m != NULL, ("null packet"));
 
@@ -138,15 +143,13 @@
 	    (sproto == IPPROTO_AH && !V_ah_enable) ||
 	    (sproto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
 		m_freem(m);
-		IPSEC_ISTAT(sproto, V_espstat.esps_pdrops, V_ahstat.ahs_pdrops,
-		    V_ipcompstat.ipcomps_pdrops);
+		IPSEC_ISTAT(sproto, pdrops);
 		return EOPNOTSUPP;
 	}
 
 	if (m->m_pkthdr.len - skip < 2 * sizeof (u_int32_t)) {
 		m_freem(m);
-		IPSEC_ISTAT(sproto, V_espstat.esps_hdrops, V_ahstat.ahs_hdrops,
-		    V_ipcompstat.ipcomps_hdrops);
+		IPSEC_ISTAT(sproto, hdrops);
 		DPRINTF(("%s: packet too small\n", __func__));
 		return EINVAL;
 	}
@@ -197,8 +200,7 @@
 	default:
 		DPRINTF(("%s: unsupported protocol family %u\n", __func__, af));
 		m_freem(m);
-		IPSEC_ISTAT(sproto, V_espstat.esps_nopf, V_ahstat.ahs_nopf,
-		    V_ipcompstat.ipcomps_nopf);
+		IPSEC_ISTAT(sproto, nopf);
 		return EPFNOSUPPORT;
 	}
 
@@ -208,8 +210,7 @@
 		DPRINTF(("%s: no key association found for SA %s/%08lx/%u\n",
 			  __func__, ipsec_address(&dst_address),
 			  (u_long) ntohl(spi), sproto));
-		IPSEC_ISTAT(sproto, V_espstat.esps_notdb, V_ahstat.ahs_notdb,
-		    V_ipcompstat.ipcomps_notdb);
+		IPSEC_ISTAT(sproto, notdb);
 		m_freem(m);
 		return ENOENT;
 	}
@@ -218,8 +219,7 @@
 		DPRINTF(("%s: attempted to use uninitialized SA %s/%08lx/%u\n",
 			 __func__, ipsec_address(&dst_address),
 			 (u_long) ntohl(spi), sproto));
-		IPSEC_ISTAT(sproto, V_espstat.esps_noxform, V_ahstat.ahs_noxform,
-		    V_ipcompstat.ipcomps_noxform);
+		IPSEC_ISTAT(sproto, noxform);
 		KEY_FREESAV(&sav);
 		m_freem(m);
 		return ENXIO;
@@ -295,7 +295,7 @@
 ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
 			int skip, int protoff, struct m_tag *mt)
 {
-	int prot, af, sproto;
+	int prot, af, sproto, isr_prot;
 	struct ip *ip;
 	struct m_tag *mtag;
 	struct tdb_ident *tdbi;
@@ -321,20 +321,21 @@
 	/* Sanity check */
 	if (m == NULL) {
 		DPRINTF(("%s: null mbuf", __func__));
-		IPSEC_ISTAT(sproto, V_espstat.esps_badkcr, V_ahstat.ahs_badkcr,
-		    V_ipcompstat.ipcomps_badkcr);
+		IPSEC_ISTAT(sproto, badkcr);
 		KEY_FREESAV(&sav);
 		return EINVAL;
 	}
 
 	if (skip != 0) {
-		/* Fix IPv4 header */
+		/*
+		 * Fix IPv4 header
+		 * XXXGL: do we need this entire block?
+		 */
 		if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) {
 			DPRINTF(("%s: processing failed for SA %s/%08lx\n",
 			    __func__, ipsec_address(&sav->sah->saidx.dst),
 			    (u_long) ntohl(sav->spi)));
-			IPSEC_ISTAT(sproto, V_espstat.esps_hdrops, V_ahstat.ahs_hdrops,
-			    V_ipcompstat.ipcomps_hdrops);
+			IPSEC_ISTAT(sproto, hdrops);
 			error = ENOBUFS;
 			goto bad;
 		}
@@ -341,7 +342,6 @@
 
 		ip = mtod(m, struct ip *);
 		ip->ip_len = htons(m->m_pkthdr.len);
-		ip->ip_off = htons(ip->ip_off);
 		ip->ip_sum = 0;
 		ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
 	} else {
@@ -349,22 +349,29 @@
 	}
 	prot = ip->ip_p;
 
-#ifdef notyet
+#ifdef DEV_ENC
+	encif->if_ipackets++;
+	encif->if_ibytes += m->m_pkthdr.len;
+
+	/* Pass the mbuf to enc0 for bpf and pfil. */
+	ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
+	if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
+		return (error);
+#endif /* DEV_ENC */
+
 	/* IP-in-IP encapsulation */
-	if (prot == IPPROTO_IPIP) {
-		struct ip ipn;
+	if (prot == IPPROTO_IPIP &&
+	    saidx->mode != IPSEC_MODE_TRANSPORT) {
 
 		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
-			IPSEC_ISTAT(sproto, V_espstat.esps_hdrops,
-			    V_ahstat.ahs_hdrops,
-			    V_ipcompstat.ipcomps_hdrops);
+			IPSEC_ISTAT(sproto, hdrops);
 			error = EINVAL;
 			goto bad;
 		}
-		/* ipn will now contain the inner IPv4 header */
-		m_copydata(m, ip->ip_hl << 2, sizeof(struct ip),
-		    (caddr_t) &ipn);
+		/* enc0: strip outer IPv4 header */
+		m_striphdr(m, 0, ip->ip_hl << 2);
 
+#ifdef notyet
 		/* XXX PROXY address isn't recorded in SAH */
 		/*
 		 * Check that the inner source address is the same as
@@ -386,29 +393,25 @@
 			    ipsp_address(saidx->dst),
 			    (u_long) ntohl(sav->spi)));
 
-			IPSEC_ISTAT(sproto, V_espstat.esps_pdrops,
-			    V_ahstat.ahs_pdrops,
-			    V_ipcompstat.ipcomps_pdrops);
+			IPSEC_ISTAT(sproto, pdrops);
 			error = EACCES;
 			goto bad;
 		}
+#endif /* notyet */
 	}
 #ifdef INET6
 	/* IPv6-in-IP encapsulation. */
-	if (prot == IPPROTO_IPV6) {
-		struct ip6_hdr ip6n;
+	else if (prot == IPPROTO_IPV6 &&
+	    saidx->mode != IPSEC_MODE_TRANSPORT) {
 
 		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
-			IPSEC_ISTAT(sproto, V_espstat.esps_hdrops,
-			    V_ahstat.ahs_hdrops,
-			    V_ipcompstat.ipcomps_hdrops);
+			IPSEC_ISTAT(sproto, hdrops);
 			error = EINVAL;
 			goto bad;
 		}
-		/* ip6n will now contain the inner IPv6 header. */
-		m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr),
-		    (caddr_t) &ip6n);
-
+		/* enc0: strip IPv4 header, keep IPv6 header only */
+		m_striphdr(m, 0, ip->ip_hl << 2);
+#ifdef notyet 
 		/*
 		 * Check that the inner source address is the same as
 		 * the proxy address, if available.
@@ -428,15 +431,22 @@
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
 
-			IPSEC_ISTAT(sproto, V_espstat.esps_pdrops,
-			    V_ahstat.ahs_pdrops,
-			    V_ipcompstat.ipcomps_pdrops);
+			IPSEC_ISTAT(sproto, pdrops);
 			error = EACCES;
 			goto bad;
 		}
+#endif /* notyet */
 	}
 #endif /* INET6 */
-#endif /*XXX*/
+	else if (prot != IPPROTO_IPV6 && saidx->mode == IPSEC_MODE_ANY) {
+		/*
+		 * When mode is wildcard, inner protocol is IPv6 and
+		 * we have no INET6 support - drop this packet a bit later.
+		 * In other cases we assume transport mode and outer
+		 * header was already stripped in xform_xxx_cb.
+		 */
+		prot = IPPROTO_IPIP;
+	}
 
 	/*
 	 * Record what we've done to the packet (under what SA it was
@@ -451,8 +461,7 @@
 		    sizeof(struct tdb_ident), M_NOWAIT);
 		if (mtag == NULL) {
 			DPRINTF(("%s: failed to get tag\n", __func__));
-			IPSEC_ISTAT(sproto, V_espstat.esps_hdrops,
-			    V_ahstat.ahs_hdrops, V_ipcompstat.ipcomps_hdrops);
+			IPSEC_ISTAT(sproto, hdrops);
 			error = ENOMEM;
 			goto bad;
 		}
@@ -473,30 +482,51 @@
 
 	key_sa_recordxfer(sav, m);		/* record data transfer */
 
-	m_addr_changed(m);
-
+	/*
+	 * In transport mode requeue decrypted mbuf back to IPv4 protocol
+	 * handler. This is necessary to correctly expose rcvif.
+	 */
+	if (saidx->mode == IPSEC_MODE_TRANSPORT)
+		prot = IPPROTO_IPIP;
 #ifdef DEV_ENC
-	encif->if_ipackets++;
-	encif->if_ibytes += m->m_pkthdr.len;
-
 	/*
-	 * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
-	 * packet later after it has been decapsulated.
+	 * Pass the mbuf to enc0 for bpf and pfil.
 	 */
-	ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
-
-	if (prot != IPPROTO_IPIP)
-		if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
-			return (error);
+	if (prot == IPPROTO_IPIP)
+		ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_AFTER);
+#ifdef INET6
+	if (prot == IPPROTO_IPV6)
+		ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_AFTER);
 #endif
 
+	if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER)) != 0)
+		return (error);
+#endif /* DEV_ENC */
+
 	/*
 	 * Re-dispatch via software interrupt.
 	 */
-	if ((error = netisr_queue_src(NETISR_IP, (uintptr_t)sav->spi, m))) {
-		IPSEC_ISTAT(sproto, V_espstat.esps_qfull, V_ahstat.ahs_qfull,
-			    V_ipcompstat.ipcomps_qfull);
 
+	switch (prot) {
+	case IPPROTO_IPIP:
+		isr_prot = NETISR_IP;
+		break;
+#ifdef INET6
+	case IPPROTO_IPV6:
+		isr_prot = NETISR_IPV6;
+		break;
+#endif
+	default:
+		DPRINTF(("%s: cannot handle inner ip proto %d\n",
+			    __func__, prot));
+		IPSEC_ISTAT(sproto, nopf);
+		error = EPFNOSUPPORT;
+		goto bad;
+	}
+
+	error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
+	if (error) {
+		IPSEC_ISTAT(sproto, qfull);
 		DPRINTF(("%s: queue full; proto %u packet dropped\n",
 			__func__, sproto));
 		return error;
@@ -548,9 +578,7 @@
 		if (protoff + l != *offp) {
 			DPRINTF(("%s: bad packet header chain, protoff %u, "
 				"l %u, off %u\n", __func__, protoff, l, *offp));
-			IPSEC_ISTAT(proto, V_espstat.esps_hdrops,
-				    V_ahstat.ahs_hdrops,
-				    V_ipcompstat.ipcomps_hdrops);
+			IPSEC_ISTAT(proto, hdrops);
 			m_freem(*mp);
 			*mp = NULL;
 			return IPPROTO_DONE;
@@ -595,8 +623,7 @@
 	/* Sanity check */
 	if (m == NULL) {
 		DPRINTF(("%s: null mbuf", __func__));
-		IPSEC_ISTAT(sproto, V_espstat.esps_badkcr, V_ahstat.ahs_badkcr,
-		    V_ipcompstat.ipcomps_badkcr);
+		IPSEC_ISTAT(sproto, badkcr);
 		error = EINVAL;
 		goto bad;
 	}
@@ -609,8 +636,7 @@
 		    __func__, ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi)));
 
-		IPSEC_ISTAT(sproto, V_espstat.esps_hdrops, V_ahstat.ahs_hdrops,
-		    V_ipcompstat.ipcomps_hdrops);
+		IPSEC_ISTAT(sproto, hdrops);
 		error = EACCES;
 		goto bad;
 	}
@@ -619,91 +645,97 @@
 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
 
 	/* Save protocol */
-	m_copydata(m, protoff, 1, (unsigned char *) &prot);
+	m_copydata(m, protoff, 1, &nxt8);
+	prot = nxt8;
 
-#ifdef notyet
-#ifdef INET
-	/* IP-in-IP encapsulation */
-	if (prot == IPPROTO_IPIP) {
-		struct ip ipn;
+#ifdef DEV_ENC
+	encif->if_ipackets++;
+	encif->if_ibytes += m->m_pkthdr.len;
 
-		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
-			IPSEC_ISTAT(sproto, V_espstat.esps_hdrops,
-			    V_ahstat.ahs_hdrops,
-			    V_ipcompstat.ipcomps_hdrops);
+	/* Pass the mbuf to enc0 for bpf and pfil. */
+	ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_BEFORE);
+	if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
+		return (error);
+#endif /* DEV_ENC */
+
+	/* IPv6-in-IP encapsulation */
+	if (prot == IPPROTO_IPV6 &&
+	    saidx->mode != IPSEC_MODE_TRANSPORT) {
+		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
+			IPSEC_ISTAT(sproto, hdrops);
 			error = EINVAL;
 			goto bad;
 		}
-		/* ipn will now contain the inner IPv4 header */
-		m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
-
+		/* ip6n will now contain the inner IPv6 header. */
+		m_striphdr(m, 0, skip);
+		skip = 0;
+#ifdef notyet
 		/*
 		 * Check that the inner source address is the same as
 		 * the proxy address, if available.
 		 */
-		if ((saidx->proxy.sa.sa_family == AF_INET &&
-		    saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY &&
-		    ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) ||
-		    (saidx->proxy.sa.sa_family != AF_INET &&
+		if ((saidx->proxy.sa.sa_family == AF_INET6 &&
+		    !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) &&
+		    !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
+			&saidx->proxy.sin6.sin6_addr)) ||
+		    (saidx->proxy.sa.sa_family != AF_INET6 &&
 			saidx->proxy.sa.sa_family != 0)) {
 
 			DPRINTF(("%s: inner source address %s doesn't "
 			    "correspond to expected proxy source %s, "
 			    "SA %s/%08lx\n", __func__,
-			    inet_ntoa4(ipn.ip_src),
+			    ip6_sprintf(ip6buf, &ip6n.ip6_src),
 			    ipsec_address(&saidx->proxy),
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
 
-			IPSEC_ISTATsproto, (V_espstat.esps_pdrops,
-			    V_ahstat.ahs_pdrops, V_ipcompstat.ipcomps_pdrops);
+			IPSEC_ISTAT(sproto, pdrops);
 			error = EACCES;
 			goto bad;
 		}
+#endif /* notyet */
 	}
-#endif /* INET */
-
-	/* IPv6-in-IP encapsulation */
-	if (prot == IPPROTO_IPV6) {
-		struct ip6_hdr ip6n;
-
-		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
-			IPSEC_ISTAT(sproto, V_espstat.esps_hdrops,
-			    V_ahstat.ahs_hdrops,
-			    V_ipcompstat.ipcomps_hdrops);
+#ifdef INET
+	/* IP-in-IP encapsulation */
+	else if (prot == IPPROTO_IPIP &&
+	    saidx->mode != IPSEC_MODE_TRANSPORT) {
+		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
+			IPSEC_ISTAT(sproto, hdrops);
 			error = EINVAL;
 			goto bad;
 		}
-		/* ip6n will now contain the inner IPv6 header. */
-		m_copydata(m, skip, sizeof(struct ip6_hdr),
-		    (caddr_t) &ip6n);
-
+		/* ipn will now contain the inner IPv4 header */
+	 	m_striphdr(m, 0, skip);
+		skip = 0;
+#ifdef notyet
 		/*
 		 * Check that the inner source address is the same as
 		 * the proxy address, if available.
 		 */
-		if ((saidx->proxy.sa.sa_family == AF_INET6 &&
-		    !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) &&
-		    !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
-			&saidx->proxy.sin6.sin6_addr)) ||
-		    (saidx->proxy.sa.sa_family != AF_INET6 &&
+		if ((saidx->proxy.sa.sa_family == AF_INET &&
+		    saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY &&
+		    ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) ||
+		    (saidx->proxy.sa.sa_family != AF_INET &&
 			saidx->proxy.sa.sa_family != 0)) {
 
 			DPRINTF(("%s: inner source address %s doesn't "
 			    "correspond to expected proxy source %s, "
 			    "SA %s/%08lx\n", __func__,
-			    ip6_sprintf(ip6buf, &ip6n.ip6_src),
+			    inet_ntoa4(ipn.ip_src),
 			    ipsec_address(&saidx->proxy),
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
 
-			IPSEC_ISTAT(sproto, V_espstat.esps_pdrops,
-			    V_ahstat.ahs_pdrops, V_ipcompstat.ipcomps_pdrops);
+			IPSEC_ISTAT(sproto, pdrops);
 			error = EACCES;
 			goto bad;
 		}
+#endif /* notyet */
 	}
-#endif /*XXX*/
+#endif /* INET */
+	else {
+		prot = IPPROTO_IPV6; /* for correct BPF processing */
+	}
 
 	/*
 	 * Record what we've done to the packet (under what SA it was
@@ -718,8 +750,7 @@
 		    sizeof(struct tdb_ident), M_NOWAIT);
 		if (mtag == NULL) {
 			DPRINTF(("%s: failed to get tag\n", __func__));
-			IPSEC_ISTAT(sproto, V_espstat.esps_hdrops,
-			    V_ahstat.ahs_hdrops, V_ipcompstat.ipcomps_hdrops);
+			IPSEC_ISTAT(sproto, hdrops);
 			error = ENOMEM;
 			goto bad;
 		}
@@ -742,24 +773,19 @@
 	key_sa_recordxfer(sav, m);
 
 #ifdef DEV_ENC
-	encif->if_ipackets++;
-	encif->if_ibytes += m->m_pkthdr.len;
-
 	/*
-	 * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
-	 * packet later after it has been decapsulated.
+	 * Pass the mbuf to enc0 for bpf and pfil.
 	 */
-	ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_BEFORE);
-
-	/* XXX-BZ does not make sense. */
-	if (prot != IPPROTO_IPIP)
-		if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
-			return (error);
+#ifdef INET
+	if (prot == IPPROTO_IPIP)
+		ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_AFTER);
 #endif
+	if (prot == IPPROTO_IPV6)
+		ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_AFTER);
 
-	/* Retrieve new protocol */
-	m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
-
+	if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER)) != 0)
+		return (error);
+#endif /* DEV_ENC */
 	/*
 	 * See the end of ip6_input for this logic.
 	 * IPPROTO_IPV[46] case will be processed just like other ones

Modified: trunk/sys/netipsec/ipsec_mbuf.c
===================================================================
--- trunk/sys/netipsec/ipsec_mbuf.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipsec_mbuf.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/netipsec/ipsec_mbuf.c 283901 2015-06-02 03:14:42Z ae $
  */
 
 /*
@@ -37,11 +38,8 @@
 #include <sys/mbuf.h>
 #include <sys/socket.h>
 
-#include <net/route.h>
 #include <net/vnet.h>
-
 #include <netinet/in.h>
-
 #include <netipsec/ipsec.h>
 
 /*
@@ -85,11 +83,11 @@
 		todo = remain;
 		while (todo > 0) {
 			if (todo > MHLEN) {
-				n = m_getcl(M_DONTWAIT, m->m_type, 0);
+				n = m_getcl(M_NOWAIT, m->m_type, 0);
 				len = MCLBYTES;
 			}
 			else {
-				n = m_get(M_DONTWAIT, m->m_type);
+				n = m_get(M_NOWAIT, m->m_type);
 				len = MHLEN;
 			}
 			if (n == NULL) {
@@ -115,7 +113,7 @@
 			}
 		}
 		else {
-			n = m_get(M_DONTWAIT, m->m_type);
+			n = m_get(M_NOWAIT, m->m_type);
 			if (n == NULL) {
 				m_freem(n0);
 				return NULL;
@@ -135,7 +133,7 @@
 			m = n;			/* header is at front ... */
 			*off = 0;		/* ... of new mbuf */
 		}
-		V_ipsec4stat.ips_mbinserted++;
+		IPSECSTAT_INC(ips_mbinserted);
 	} else {
 		/*
 		 * Copy the remainder to the back of the mbuf
@@ -203,7 +201,7 @@
 
 	if (pad > M_TRAILINGSPACE(m0)) {
 		/* Add an mbuf to the chain. */
-		MGET(m1, M_DONTWAIT, MT_DATA);
+		MGET(m1, M_NOWAIT, MT_DATA);
 		if (m1 == 0) {
 			m_freem(m0);
 			DPRINTF(("%s: unable to get extra mbuf\n", __func__));
@@ -241,7 +239,7 @@
 	/* Remove the header and associated data from the mbuf. */
 	if (roff == 0) {
 		/* The header was at the beginning of the mbuf */
-		V_ipsec4stat.ips_input_front++;
+		IPSECSTAT_INC(ips_input_front);
 		m_adj(m1, hlen);
 		if ((m1->m_flags & M_PKTHDR) == 0)
 			m->m_pkthdr.len -= hlen;
@@ -253,7 +251,7 @@
 		 * so first let's remove the remainder of the header from
 		 * the beginning of the remainder of the mbuf chain, if any.
 		 */
-		V_ipsec4stat.ips_input_end++;
+		IPSECSTAT_INC(ips_input_end);
 		if (roff + hlen > m1->m_len) {
 			/* Adjust the next mbuf by the remainder */
 			m_adj(m1->m_next, roff + hlen - m1->m_len);
@@ -278,7 +276,7 @@
 		 * The header lies in the "middle" of the mbuf; copy
 		 * the remainder of the mbuf down over the header.
 		 */
-		V_ipsec4stat.ips_input_middle++;
+		IPSECSTAT_INC(ips_input_middle);
 		bcopy(mtod(m1, u_char *) + roff + hlen,
 		      mtod(m1, u_char *) + roff,
 		      m1->m_len - (roff + hlen));

Modified: trunk/sys/netipsec/ipsec_output.c
===================================================================
--- trunk/sys/netipsec/ipsec_output.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/ipsec_output.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/netipsec/ipsec_output.c 283901 2015-06-02 03:14:42Z ae $
  */
 
 /*
@@ -45,7 +46,6 @@
 
 #include <net/if.h>
 #include <net/pfil.h>
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netinet/in.h>
@@ -164,11 +164,11 @@
 	 * doing further processing.
 	 */
 	if (isr->next) {
-		V_ipsec4stat.ips_out_bundlesa++;
 		/* XXX-BZ currently only support same AF bundles. */
 		switch (saidx->dst.sa.sa_family) {
 #ifdef INET
 		case AF_INET:
+			IPSECSTAT_INC(ips_out_bundlesa);
 			return ipsec4_process_packet(m, isr->next, 0, 0);
 			/* NOTREACHED */
 #endif
@@ -176,8 +176,8 @@
 #ifdef INET6
 		case AF_INET6:
 			/* XXX */
-			ipsec6_output_trans()
-			ipsec6_output_tunnel()
+			IPSEC6STAT_INC(ips_out_bundlesa);
+			return ipsec6_process_packet(m, isr->next);
 			/* NOTREACHED */
 #endif /* INET6 */
 #endif
@@ -190,8 +190,6 @@
 	}
 	key_sa_recordxfer(sav, m);		/* record data transfer */
 
-	m_addr_changed(m);
-
 	/*
 	 * We're done with IPsec processing, transmit the packet using the
 	 * appropriate network protocol (IP or IPv6). SPD lookup will be
@@ -199,12 +197,7 @@
 	 */
 	switch (saidx->dst.sa.sa_family) {
 #ifdef INET
-	struct ip *ip;
 	case AF_INET:
-		ip = mtod(m, struct ip *);
-		ip->ip_len = ntohs(ip->ip_len);
-		ip->ip_off = ntohs(ip->ip_off);
-
 #ifdef IPSEC_NAT_T
 		/*
 		 * If NAT-T is enabled, now that all IPsec processing is done
@@ -211,11 +204,8 @@
 		 * insert UDP encapsulation header after IP header.
 		 */
 		if (sav->natt_type) {
-#ifdef _IP_VHL
-			const int hlen = IP_VHL_HL(ip->ip_vhl);
-#else
+			struct ip *ip = mtod(m, struct ip *);
 			const int hlen = (ip->ip_hl << 2);
-#endif
 			int size, off;
 			struct mbuf *mi;
 			struct udphdr *udp;
@@ -248,7 +238,7 @@
 			udp->uh_dport = KEY_PORTFROMSADDR(&sav->sah->saidx.dst);
 			udp->uh_sum = 0;
 			udp->uh_ulen = htons(m->m_pkthdr.len - hlen);
-			ip->ip_len = m->m_pkthdr.len;
+			ip->ip_len = htons(m->m_pkthdr.len);
 			ip->ip_p = IPPROTO_UDP;
 
 			if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
@@ -282,8 +272,14 @@
 	int *error
 )
 {
-#define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \
-			    isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++)
+#define	IPSEC_OSTAT(name)	do {		\
+	if (isr->saidx.proto == IPPROTO_ESP)	\
+		ESPSTAT_INC(esps_##name);	\
+	else if (isr->saidx.proto == IPPROTO_AH)\
+		AHSTAT_INC(ahs_##name);		\
+	else					\
+		IPCOMPSTAT_INC(ipcomps_##name);	\
+} while (0)
 	struct secasvar *sav;
 
 	IPSECREQUEST_LOCK_ASSERT(isr);
@@ -362,7 +358,16 @@
 		 * this packet because it is responsibility for
 		 * upper layer to retransmit the packet.
 		 */
-		V_ipsec4stat.ips_out_nosa++;
+		switch(af) {
+		case AF_INET:
+			IPSECSTAT_INC(ips_out_nosa);
+			break;
+#ifdef INET6
+		case AF_INET6:
+			IPSEC6STAT_INC(ips_out_nosa);
+			break;
+#endif
+		}
 		goto bad;
 	}
 	sav = isr->sav;
@@ -391,8 +396,7 @@
 	    (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
 		DPRINTF(("%s: IPsec outbound packet dropped due"
 			" to policy (check your sysctls)\n", __func__));
-		IPSEC_OSTAT(V_espstat.esps_pdrops, V_ahstat.ahs_pdrops,
-		    V_ipcompstat.ipcomps_pdrops);
+		IPSEC_OSTAT(pdrops);
 		*error = EHOSTUNREACH;
 		goto bad;
 	}
@@ -403,8 +407,7 @@
 	 */
 	if (sav->tdb_xform == NULL) {
 		DPRINTF(("%s: no transform for SA\n", __func__));
-		IPSEC_OSTAT(V_espstat.esps_noxform, V_ahstat.ahs_noxform,
-		    V_ipcompstat.ipcomps_noxform);
+		IPSEC_OSTAT(noxform);
 		*error = EHOSTUNREACH;
 		goto bad;
 	}
@@ -504,17 +507,11 @@
 				goto bad;
 			}
 			ip = mtod(m, struct ip *);
-			ip->ip_len = htons(m->m_pkthdr.len);
-			ip->ip_sum = 0;
-#ifdef _IP_VHL
-			if (ip->ip_vhl == IP_VHL_BORING)
-				ip->ip_sum = in_cksum_hdr(ip);
-			else
-				ip->ip_sum = in_cksum(m,
-					_IP_VHL_HL(ip->ip_vhl) << 2);
-#else
-			ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
-#endif
+			if (ip->ip_v == IPVERSION) {
+				ip->ip_len = htons(m->m_pkthdr.len);
+				ip->ip_sum = 0;
+				ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+			}
 
 			/* Encapsulate the packet */
 			error = ipip_output(m, isr, &mp, 0, 0);
@@ -556,7 +553,7 @@
 
 #ifdef DEV_ENC
 	/* pass the mbuf to enc0 for bpf processing */
-	ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_AFTER);
+	ipsec_bpf(m, sav, sav->sah->saidx.dst.sa.sa_family, ENC_OUT|ENC_AFTER);
 	/* pass the mbuf to enc0 for packet filtering */
 	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
 		goto bad;
@@ -573,9 +570,26 @@
 	 *     for reclaiming their resources.
 	 */
 	if (sav->tdb_xform->xf_type != XF_IP4) {
-		ip = mtod(m, struct ip *);
-		i = ip->ip_hl << 2;
-		off = offsetof(struct ip, ip_p);
+		union sockaddr_union *dst = &sav->sah->saidx.dst;
+		switch(dst->sa.sa_family) {
+		case AF_INET:
+			ip = mtod(m, struct ip *);
+			i = ip->ip_hl << 2;
+			off = offsetof(struct ip, ip_p);
+			break;
+#ifdef INET6
+		case AF_INET6:
+			i = sizeof(struct ip6_hdr);
+			off = offsetof(struct ip6_hdr, ip6_nxt);
+			break;
+#endif /* INET6 */
+		default:
+		DPRINTF(("%s: unsupported protocol family %u\n",
+				 __func__, dst->sa.sa_family));
+			error = EPFNOSUPPORT;
+			IPSECSTAT_INC(ips_out_inval);
+			goto bad;
+		}
 		error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
 	} else {
 		error = ipsec_process_done(m, isr);
@@ -591,224 +605,52 @@
 }
 #endif
 
+
 #ifdef INET6
-/*
- * Chop IP6 header from the payload.
- */
-static struct mbuf *
-ipsec6_splithdr(struct mbuf *m)
+static int
+in6_sa_equal_addrwithscope(const struct sockaddr_in6 *sa, const struct in6_addr *ia)
 {
-	struct mbuf *mh;
-	struct ip6_hdr *ip6;
-	int hlen;
+	struct in6_addr ia2;
 
-	IPSEC_ASSERT(m->m_len >= sizeof (struct ip6_hdr),
-		("first mbuf too short, len %u", m->m_len));
-	ip6 = mtod(m, struct ip6_hdr *);
-	hlen = sizeof(struct ip6_hdr);
-	if (m->m_len > hlen) {
-		MGETHDR(mh, M_DONTWAIT, MT_DATA);
-		if (!mh) {
-			m_freem(m);
-			return NULL;
-		}
-		M_MOVE_PKTHDR(mh, m);
-		MH_ALIGN(mh, hlen);
-		m->m_len -= hlen;
-		m->m_data += hlen;
-		mh->m_next = m;
-		m = mh;
-		m->m_len = hlen;
-		bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen);
-	} else if (m->m_len < hlen) {
-		m = m_pullup(m, hlen);
-		if (!m)
-			return NULL;
-	}
-	return m;
+	memcpy(&ia2, &sa->sin6_addr, sizeof(ia2));
+	if (IN6_IS_SCOPE_LINKLOCAL(&sa->sin6_addr))
+		ia2.s6_addr16[1] = htons(sa->sin6_scope_id);
+
+	return IN6_ARE_ADDR_EQUAL(ia, &ia2);
 }
 
 /*
- * IPsec output logic for IPv6, transport mode.
+ * IPsec output logic for IPv6.
  */
 int
-ipsec6_output_trans(
-	struct ipsec_output_state *state,
-	u_char *nexthdrp,
-	struct mbuf *mprev,
-	struct secpolicy *sp,
-	int flags,
-	int *tun)
+ipsec6_process_packet(
+	struct mbuf *m,
+ 	struct ipsecrequest *isr
+    )
 {
-	struct ipsecrequest *isr;
 	struct secasindex saidx;
-	int error = 0;
-	struct mbuf *m;
+	struct secasvar *sav;
+	struct ip6_hdr *ip6;
+	int error, i, off;
+	union sockaddr_union *dst;
 
-	IPSEC_ASSERT(state != NULL, ("null state"));
-	IPSEC_ASSERT(state->m != NULL, ("null m"));
-	IPSEC_ASSERT(nexthdrp != NULL, ("null nexthdrp"));
-	IPSEC_ASSERT(mprev != NULL, ("null mprev"));
-	IPSEC_ASSERT(sp != NULL, ("null sp"));
-	IPSEC_ASSERT(tun != NULL, ("null tun"));
+	IPSEC_ASSERT(m != NULL, ("ipsec6_process_packet: null mbuf"));
+	IPSEC_ASSERT(isr != NULL, ("ipsec6_process_packet: null isr"));
 
-	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
-		printf("%s: applied SP\n", __func__);
-		kdebug_secpolicy(sp));
+	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
 
-	isr = sp->req;
-	if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
-		/* the rest will be handled by ipsec6_output_tunnel() */
-		*tun = 1;		/* need tunnel-mode processing */
-		return 0;
-	}
-
-	*tun = 0;
-	m = state->m;
-
-	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
 	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
 	if (isr == NULL) {
-		if (error != 0) {
-#ifdef notdef
-			/* XXX should notification be done for all errors ? */
-			/*
-			 * Notify the fact that the packet is discarded
-			 * to ourselves. I believe this is better than
-			 * just silently discarding. (jinmei at kame.net)
-			 * XXX: should we restrict the error to TCP packets?
-			 * XXX: should we directly notify sockets via
-			 *      pfctlinputs?
-			 */
-			icmp6_error(m, ICMP6_DST_UNREACH,
-				    ICMP6_DST_UNREACH_ADMIN, 0);
-			m = NULL;	/* NB: icmp6_error frees mbuf */
-#endif
+		if (error != 0)
 			goto bad;
-		}
 		return EJUSTRETURN;
 	}
 
-	error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
-						  sizeof (struct ip6_hdr),
-						  offsetof(struct ip6_hdr, 
-							   ip6_nxt));
-	IPSECREQUEST_UNLOCK(isr);
-	return error;
-bad:
-	if (isr)
-		IPSECREQUEST_UNLOCK(isr);
-	if (m)
-		m_freem(m);
-	state->m = NULL;
-	return error;
-}
+	sav = isr->sav;
+	dst = &sav->sah->saidx.dst;
 
-static int
-ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav)
-{
-	struct ip6_hdr *oip6;
-	struct ip6_hdr *ip6;
-	size_t plen;
-
-	/* can't tunnel between different AFs */
-	if (sav->sah->saidx.src.sa.sa_family != AF_INET6 ||
-	    sav->sah->saidx.dst.sa.sa_family != AF_INET6) {
-		m_freem(m);
-		return EINVAL;
-	}
-	IPSEC_ASSERT(m->m_len == sizeof (struct ip6_hdr),
-		("mbuf wrong size; len %u", m->m_len));
-
-
-	/*
-	 * grow the mbuf to accomodate the new IPv6 header.
-	 */
-	plen = m->m_pkthdr.len;
-	if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) {
-		struct mbuf *n;
-		MGET(n, M_DONTWAIT, MT_DATA);
-		if (!n) {
-			m_freem(m);
-			return ENOBUFS;
-		}
-		n->m_len = sizeof(struct ip6_hdr);
-		n->m_next = m->m_next;
-		m->m_next = n;
-		m->m_pkthdr.len += sizeof(struct ip6_hdr);
-		oip6 = mtod(n, struct ip6_hdr *);
-	} else {
-		m->m_next->m_len += sizeof(struct ip6_hdr);
-		m->m_next->m_data -= sizeof(struct ip6_hdr);
-		m->m_pkthdr.len += sizeof(struct ip6_hdr);
-		oip6 = mtod(m->m_next, struct ip6_hdr *);
-	}
 	ip6 = mtod(m, struct ip6_hdr *);
-	bcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr));
-
-	/* Fake link-local scope-class addresses */
-	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
-		oip6->ip6_src.s6_addr16[1] = 0;
-	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
-		oip6->ip6_dst.s6_addr16[1] = 0;
-
-	/* construct new IPv6 header. see RFC 2401 5.1.2.2 */
-	/* ECN consideration. */
-	ip6_ecn_ingress(V_ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
-	if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr))
-		ip6->ip6_plen = htons(plen);
-	else {
-		/* ip6->ip6_plen will be updated in ip6_output() */
-	}
-	ip6->ip6_nxt = IPPROTO_IPV6;
-	ip6->ip6_src = sav->sah->saidx.src.sin6.sin6_addr;
-	ip6->ip6_dst = sav->sah->saidx.dst.sin6.sin6_addr;
-	ip6->ip6_hlim = IPV6_DEFHLIM;
-
-	/* XXX Should ip6_src be updated later ? */
-
-	return 0;
-}
-
-/*
- * IPsec output logic for IPv6, tunnel mode.
- */
-int
-ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int flags)
-{
-	struct ip6_hdr *ip6;
-	struct ipsecrequest *isr;
-	struct secasindex saidx;
-	int error;
-	struct sockaddr_in6 *dst6;
-	struct mbuf *m;
-
-	IPSEC_ASSERT(state != NULL, ("null state"));
-	IPSEC_ASSERT(state->m != NULL, ("null m"));
-	IPSEC_ASSERT(sp != NULL, ("null sp"));
-
-	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
-		printf("%s: applied SP\n", __func__);
-		kdebug_secpolicy(sp));
-
-	m = state->m;
-	/*
-	 * transport mode ipsec (before the 1st tunnel mode) is already
-	 * processed by ipsec6_output_trans().
-	 */
-	for (isr = sp->req; isr; isr = isr->next) {
-		if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
-			break;
-	}
-
-	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
-	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
-	if (isr == NULL) {
-		if (error != 0)
-			goto bad;
-		return EJUSTRETURN; 
-	}
-
+	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
 #ifdef DEV_ENC
 	encif->if_opackets++;
 	encif->if_obytes += m->m_pkthdr.len;
@@ -818,95 +660,91 @@
 	/* pass the mbuf to enc0 for packet filtering */
 	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0)
 		goto bad;
-#endif
+#endif /* DEV_ENC */
 
-	/*
-	 * There may be the case that SA status will be changed when
-	 * we are refering to one. So calling splsoftnet().
-	 */
-	if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
-		/*
-		 * build IPsec tunnel.
-		 */
-		/* XXX should be processed with other familiy */
-		if (isr->sav->sah->saidx.src.sa.sa_family != AF_INET6) {
-			ipseclog((LOG_ERR, "%s: family mismatched between "
-			    "inner and outer, spi=%u\n", __func__,
-			    ntohl(isr->sav->spi)));
-			V_ipsec6stat.ips_out_inval++;
-			error = EAFNOSUPPORT;
+	/* Do the appropriate encapsulation, if necessary */
+	if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
+	    dst->sa.sa_family != AF_INET6 ||        /* PF mismatch */
+	    ((dst->sa.sa_family == AF_INET6) &&
+	     (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
+	     (!in6_sa_equal_addrwithscope(&dst->sin6,
+				  &ip6->ip6_dst)))) {
+		struct mbuf *mp;
+
+		/* Fix IPv6 header payload length. */
+		if (m->m_len < sizeof(struct ip6_hdr))
+			if ((m = m_pullup(m,sizeof(struct ip6_hdr))) == NULL) {
+				error = ENOBUFS;
+				goto bad;
+			}
+
+		if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
+			/* No jumbogram support. */
+			error = ENXIO;   /*XXX*/
 			goto bad;
 		}
 
-		m = ipsec6_splithdr(m);
-		if (!m) {
-			V_ipsec6stat.ips_out_nomem++;
-			error = ENOMEM;
+		/* Encapsulate the packet */
+		error = ipip_output(m, isr, &mp, 0, 0);
+		if (mp == NULL && !error) {
+			/* Should never happen. */
+			DPRINTF(("ipsec6_process_packet: ipip_output "
+				 "returns no mbuf and no error!"));
+			error = EFAULT;
 			goto bad;
 		}
-		error = ipsec6_encapsulate(m, isr->sav);
+
 		if (error) {
-			m = NULL;
+			if (mp) {
+				/* XXX: Should never happen! */
+				m_freem(mp);
+			}
+			m = NULL; /* ipip_output() already freed it */
 			goto bad;
 		}
-		ip6 = mtod(m, struct ip6_hdr *);
 
-		state->ro =
-		    (struct route *)&isr->sav->sah->route_cache.sin6_route;
-		state->dst = (struct sockaddr *)&state->ro->ro_dst;
-		dst6 = (struct sockaddr_in6 *)state->dst;
-		if (state->ro->ro_rt
-		 && ((state->ro->ro_rt->rt_flags & RTF_UP) == 0
-		  || !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_dst))) {
-			RTFREE(state->ro->ro_rt);
-			state->ro->ro_rt = NULL;
-		}
-		if (state->ro->ro_rt == NULL) {
-			bzero(dst6, sizeof(*dst6));
-			dst6->sin6_family = AF_INET6;
-			dst6->sin6_len = sizeof(*dst6);
-			dst6->sin6_addr = ip6->ip6_dst;
-			rtalloc_ign_fib(state->ro, 0UL, M_GETFIB(m));
-		}
-		if (state->ro->ro_rt == NULL) {
-			IP6STAT_INC(ip6s_noroute);
-			V_ipsec6stat.ips_out_noroute++;
-			error = EHOSTUNREACH;
-			goto bad;
-		}
-
-		/* adjust state->dst if tunnel endpoint is offlink */
-		if (state->ro->ro_rt->rt_flags & RTF_GATEWAY)
-			state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway;
+		m = mp;
+		mp = NULL;
 	}
 
-	m = ipsec6_splithdr(m);
-	if (!m) {
-		V_ipsec6stat.ips_out_nomem++;
-		error = ENOMEM;
-		goto bad;
-	}
-	ip6 = mtod(m, struct ip6_hdr *);
-
 #ifdef DEV_ENC
-	/* pass the mbuf to enc0 for bpf processing */
-	ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_AFTER);
+	ipsec_bpf(m, isr->sav, dst->sa.sa_family, ENC_OUT|ENC_AFTER);
 	/* pass the mbuf to enc0 for packet filtering */
 	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
 		goto bad;
-#endif
+#endif /* DEV_ENC */
 
-	error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
-		sizeof (struct ip6_hdr),
-		offsetof(struct ip6_hdr, ip6_nxt));
+	switch(dst->sa.sa_family) {
+#ifdef INET
+	case AF_INET:
+		{
+		struct ip *ip;
+		ip = mtod(m, struct ip *);
+		i = ip->ip_hl << 2;
+		off = offsetof(struct ip, ip_p);
+		}
+		break;
+#endif /* AF_INET */
+	case AF_INET6:
+		i = sizeof(struct ip6_hdr);
+		off = offsetof(struct ip6_hdr, ip6_nxt);
+		break;
+	default:
+		DPRINTF(("%s: unsupported protocol family %u\n",
+				 __func__, dst->sa.sa_family));
+		error = EPFNOSUPPORT;
+		IPSEC6STAT_INC(ips_out_inval);
+		goto bad;
+	}
+	error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
 	IPSECREQUEST_UNLOCK(isr);
 	return error;
 bad:
+
 	if (isr)
 		IPSECREQUEST_UNLOCK(isr);
 	if (m)
 		m_freem(m);
-	state->m = NULL;
 	return error;
 }
 #endif /*INET6*/

Modified: trunk/sys/netipsec/key.c
===================================================================
--- trunk/sys/netipsec/key.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/key.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/key.c 301780 2016-06-10 13:57:56Z ngie $	*/
 /*	$KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $	*/
 
 /*-
@@ -58,7 +59,6 @@
 #include <sys/syslog.h>
 
 #include <net/if.h>
-#include <net/route.h>
 #include <net/raw_cb.h>
 #include <net/vnet.h>
 
@@ -347,7 +347,7 @@
 	if ((head) != (sav)) {						\
 		ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \
 			(name), (head), (sav)));			\
-		continue;						\
+		break;							\
 	}								\
 } while (0)
 
@@ -409,54 +409,54 @@
 	int extlen[SADB_EXT_MAX + 1];
 };
 
-static struct secasvar *key_allocsa_policy __P((const struct secasindex *));
-static void key_freesp_so __P((struct secpolicy **));
-static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int));
-static void key_delsp __P((struct secpolicy *));
-static struct secpolicy *key_getsp __P((struct secpolicyindex *));
+static struct secasvar *key_allocsa_policy(const struct secasindex *);
+static void key_freesp_so(struct secpolicy **);
+static struct secasvar *key_do_allocsa_policy(struct secashead *, u_int);
+static void key_delsp(struct secpolicy *);
+static struct secpolicy *key_getsp(struct secpolicyindex *);
 static void _key_delsp(struct secpolicy *sp);
-static struct secpolicy *key_getspbyid __P((u_int32_t));
-static u_int32_t key_newreqid __P((void));
-static struct mbuf *key_gather_mbuf __P((struct mbuf *,
-	const struct sadb_msghdr *, int, int, ...));
-static int key_spdadd __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static u_int32_t key_getnewspid __P((void));
-static int key_spddelete __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_spddelete2 __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_spdget __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_spdflush __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_spddump __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static struct mbuf *key_setdumpsp __P((struct secpolicy *,
-	u_int8_t, u_int32_t, u_int32_t));
-static u_int key_getspreqmsglen __P((struct secpolicy *));
-static int key_spdexpire __P((struct secpolicy *));
-static struct secashead *key_newsah __P((struct secasindex *));
-static void key_delsah __P((struct secashead *));
-static struct secasvar *key_newsav __P((struct mbuf *,
+static struct secpolicy *key_getspbyid(u_int32_t);
+static u_int32_t key_newreqid(void);
+static struct mbuf *key_gather_mbuf(struct mbuf *,
+	const struct sadb_msghdr *, int, int, ...);
+static int key_spdadd(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static u_int32_t key_getnewspid(void);
+static int key_spddelete(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_spddelete2(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_spdget(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_spdflush(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_spddump(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static struct mbuf *key_setdumpsp(struct secpolicy *,
+	u_int8_t, u_int32_t, u_int32_t);
+static u_int key_getspreqmsglen(struct secpolicy *);
+static int key_spdexpire(struct secpolicy *);
+static struct secashead *key_newsah(struct secasindex *);
+static void key_delsah(struct secashead *);
+static struct secasvar *key_newsav(struct mbuf *,
 	const struct sadb_msghdr *, struct secashead *, int *,
-	const char*, int));
+	const char*, int);
 #define	KEY_NEWSAV(m, sadb, sah, e)				\
 	key_newsav(m, sadb, sah, e, __FILE__, __LINE__)
-static void key_delsav __P((struct secasvar *));
-static struct secashead *key_getsah __P((struct secasindex *));
-static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t));
-static struct secasvar *key_getsavbyspi __P((struct secashead *, u_int32_t));
-static int key_setsaval __P((struct secasvar *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_mature __P((struct secasvar *));
-static struct mbuf *key_setdumpsa __P((struct secasvar *, u_int8_t,
-	u_int8_t, u_int32_t, u_int32_t));
-static struct mbuf *key_setsadbmsg __P((u_int8_t, u_int16_t, u_int8_t,
-	u_int32_t, pid_t, u_int16_t));
-static struct mbuf *key_setsadbsa __P((struct secasvar *));
-static struct mbuf *key_setsadbaddr __P((u_int16_t,
-	const struct sockaddr *, u_int8_t, u_int16_t));
+static void key_delsav(struct secasvar *);
+static struct secashead *key_getsah(struct secasindex *);
+static struct secasvar *key_checkspidup(struct secasindex *, u_int32_t);
+static struct secasvar *key_getsavbyspi(struct secashead *, u_int32_t);
+static int key_setsaval(struct secasvar *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_mature(struct secasvar *);
+static struct mbuf *key_setdumpsa(struct secasvar *, u_int8_t,
+	u_int8_t, u_int32_t, u_int32_t);
+static struct mbuf *key_setsadbmsg(u_int8_t, u_int16_t, u_int8_t,
+	u_int32_t, pid_t, u_int16_t);
+static struct mbuf *key_setsadbsa(struct secasvar *);
+static struct mbuf *key_setsadbaddr(u_int16_t,
+	const struct sockaddr *, u_int8_t, u_int16_t);
 #ifdef IPSEC_NAT_T
 static struct mbuf *key_setsadbxport(u_int16_t, u_int16_t);
 static struct mbuf *key_setsadbxtype(u_int16_t);
@@ -464,15 +464,15 @@
 static void key_porttosaddr(struct sockaddr *, u_int16_t);
 #define	KEY_PORTTOSADDR(saddr, port)				\
 	key_porttosaddr((struct sockaddr *)(saddr), (port))
-static struct mbuf *key_setsadbxsa2 __P((u_int8_t, u_int32_t, u_int32_t));
-static struct mbuf *key_setsadbxpolicy __P((u_int16_t, u_int8_t,
-	u_int32_t));
+static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t, u_int32_t);
+static struct mbuf *key_setsadbxpolicy(u_int16_t, u_int8_t,
+	u_int32_t);
 static struct seckey *key_dup_keymsg(const struct sadb_key *, u_int, 
 				     struct malloc_type *);
 static struct seclifetime *key_dup_lifemsg(const struct sadb_lifetime *src,
 					    struct malloc_type *type);
 #ifdef INET6
-static int key_ismyaddr6 __P((struct sockaddr_in6 *));
+static int key_ismyaddr6(struct sockaddr_in6 *);
 #endif
 
 /* flags for key_cmpsaidx() */
@@ -480,74 +480,75 @@
 #define CMP_MODE_REQID	2	/* additionally HEAD, reqid, mode. */
 #define CMP_REQID	3	/* additionally HEAD, reaid. */
 #define CMP_EXACTLY	4	/* all elements. */
-static int key_cmpsaidx
-	__P((const struct secasindex *, const struct secasindex *, int));
+static int key_cmpsaidx(const struct secasindex *,
+    const struct secasindex *, int);
+static int key_cmpspidx_exactly(struct secpolicyindex *,
+    struct secpolicyindex *);
+static int key_cmpspidx_withmask(struct secpolicyindex *,
+    struct secpolicyindex *);
+static int key_sockaddrcmp(const struct sockaddr *,
+    const struct sockaddr *, int);
+static int key_bbcmp(const void *, const void *, u_int);
+static u_int16_t key_satype2proto(u_int8_t);
+static u_int8_t key_proto2satype(u_int16_t);
 
-static int key_cmpspidx_exactly
-	__P((struct secpolicyindex *, struct secpolicyindex *));
-static int key_cmpspidx_withmask
-	__P((struct secpolicyindex *, struct secpolicyindex *));
-static int key_sockaddrcmp __P((const struct sockaddr *, const struct sockaddr *, int));
-static int key_bbcmp __P((const void *, const void *, u_int));
-static u_int16_t key_satype2proto __P((u_int8_t));
-static u_int8_t key_proto2satype __P((u_int16_t));
-
-static int key_getspi __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static u_int32_t key_do_getnewspi __P((struct sadb_spirange *,
-					struct secasindex *));
-static int key_update __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
+static int key_getspi(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static u_int32_t key_do_getnewspi(struct sadb_spirange *,
+					struct secasindex *);
+static int key_update(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
 #ifdef IPSEC_DOSEQCHECK
-static struct secasvar *key_getsavbyseq __P((struct secashead *, u_int32_t));
+static struct secasvar *key_getsavbyseq(struct secashead *, u_int32_t);
 #endif
-static int key_add __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_setident __P((struct secashead *, struct mbuf *,
-	const struct sadb_msghdr *));
-static struct mbuf *key_getmsgbuf_x1 __P((struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_delete __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_get __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
+static int key_add(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_setident(struct secashead *, struct mbuf *,
+	const struct sadb_msghdr *);
+static struct mbuf *key_getmsgbuf_x1(struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_delete(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_delete_all(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *, u_int16_t);
+static int key_get(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
 
-static void key_getcomb_setlifetime __P((struct sadb_comb *));
-static struct mbuf *key_getcomb_esp __P((void));
-static struct mbuf *key_getcomb_ah __P((void));
-static struct mbuf *key_getcomb_ipcomp __P((void));
-static struct mbuf *key_getprop __P((const struct secasindex *));
+static void key_getcomb_setlifetime(struct sadb_comb *);
+static struct mbuf *key_getcomb_esp(void);
+static struct mbuf *key_getcomb_ah(void);
+static struct mbuf *key_getcomb_ipcomp(void);
+static struct mbuf *key_getprop(const struct secasindex *);
 
-static int key_acquire __P((const struct secasindex *, struct secpolicy *));
-static struct secacq *key_newacq __P((const struct secasindex *));
-static struct secacq *key_getacq __P((const struct secasindex *));
-static struct secacq *key_getacqbyseq __P((u_int32_t));
-static struct secspacq *key_newspacq __P((struct secpolicyindex *));
-static struct secspacq *key_getspacq __P((struct secpolicyindex *));
-static int key_acquire2 __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_register __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_expire __P((struct secasvar *));
-static int key_flush __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_dump __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_promisc __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *));
-static int key_senderror __P((struct socket *, struct mbuf *, int));
-static int key_validate_ext __P((const struct sadb_ext *, int));
-static int key_align __P((struct mbuf *, struct sadb_msghdr *));
+static int key_acquire(const struct secasindex *, struct secpolicy *);
+static struct secacq *key_newacq(const struct secasindex *);
+static struct secacq *key_getacq(const struct secasindex *);
+static struct secacq *key_getacqbyseq(u_int32_t);
+static struct secspacq *key_newspacq(struct secpolicyindex *);
+static struct secspacq *key_getspacq(struct secpolicyindex *);
+static int key_acquire2(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_register(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_expire(struct secasvar *, int);
+static int key_flush(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_dump(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_promisc(struct socket *, struct mbuf *,
+	const struct sadb_msghdr *);
+static int key_senderror(struct socket *, struct mbuf *, int);
+static int key_validate_ext(const struct sadb_ext *, int);
+static int key_align(struct mbuf *, struct sadb_msghdr *);
 static struct mbuf *key_setlifetime(struct seclifetime *src, 
 				     u_int16_t exttype);
 static struct mbuf *key_setkey(struct seckey *src, u_int16_t exttype);
 
 #if 0
-static const char *key_getfqdn __P((void));
-static const char *key_getuserfqdn __P((void));
+static const char *key_getfqdn(void);
+static const char *key_getuserfqdn(void);
 #endif
-static void key_sa_chgstate __P((struct secasvar *, u_int8_t));
-static struct mbuf *key_alloc_mbuf __P((int));
+static void key_sa_chgstate(struct secasvar *, u_int8_t);
 
 static __inline void
 sa_initref(struct secasvar *sav)
@@ -612,7 +613,8 @@
  *	others:	found and return the pointer.
  */
 struct secpolicy *
-key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag)
+key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where,
+    int tag)
 {
 	struct secpolicy *sp;
 
@@ -664,11 +666,8 @@
  *	others:	found and return the pointer.
  */
 struct secpolicy *
-key_allocsp2(u_int32_t spi,
-	     union sockaddr_union *dst,
-	     u_int8_t proto,
-	     u_int dir,
-	     const char* where, int tag)
+key_allocsp2(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto,
+    u_int dir, const char* where, int tag)
 {
 	struct secpolicy *sp;
 
@@ -1076,17 +1075,16 @@
  * keep source address in IPsec SA.  We see a tricky situation here.
  */
 struct secasvar *
-key_allocsa(
-	union sockaddr_union *dst,
-	u_int proto,
-	u_int32_t spi,
-	const char* where, int tag)
+key_allocsa(union sockaddr_union *dst, u_int proto, u_int32_t spi,
+    const char* where, int tag)
 {
 	struct secashead *sah;
 	struct secasvar *sav;
 	u_int stateidx, arraysize, state;
 	const u_int *saorder_state_valid;
-	int chkport;
+#ifdef IPSEC_NAT_T
+	int natt_chkport;
+#endif
 
 	IPSEC_ASSERT(dst != NULL, ("null dst address"));
 
@@ -1094,11 +1092,9 @@
 		printf("DP %s from %s:%u\n", __func__, where, tag));
 
 #ifdef IPSEC_NAT_T
-        chkport = (dst->sa.sa_family == AF_INET &&
+        natt_chkport = (dst->sa.sa_family == AF_INET &&
 	    dst->sa.sa_len == sizeof(struct sockaddr_in) &&
 	    dst->sin.sin_port != 0);
-#else
-	chkport = 0;
 #endif
 
 	/*
@@ -1116,6 +1112,8 @@
 		arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
 	}
 	LIST_FOREACH(sah, &V_sahtree, chain) {
+		int checkport;
+
 		/* search valid state */
 		for (stateidx = 0; stateidx < arraysize; stateidx++) {
 			state = saorder_state_valid[stateidx];
@@ -1130,13 +1128,25 @@
 					continue;
 				if (spi != sav->spi)
 					continue;
+				checkport = 0;
+#ifdef IPSEC_NAT_T
+				/*
+				 * Really only check ports when this is a NAT-T
+				 * SA.  Otherwise other lookups providing ports
+				 * might suffer.
+				 */
+				if (sav->natt_type && natt_chkport)
+					checkport = 1;
+#endif
 #if 0	/* don't check src */
 				/* check src address */
-				if (key_sockaddrcmp(&src->sa, &sav->sah->saidx.src.sa, chkport) != 0)
+				if (key_sockaddrcmp(&src->sa,	
+				    &sav->sah->saidx.src.sa, checkport) != 0)
 					continue;
 #endif
 				/* check dst address */
-				if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, chkport) != 0)
+				if (key_sockaddrcmp(&dst->sa,
+				    &sav->sah->saidx.dst.sa, checkport) != 0)
 					continue;
 				sa_addref(sav);
 				goto done;
@@ -1387,10 +1397,7 @@
  * so must be set properly later.
  */
 struct secpolicy *
-key_msg2sp(xpl0, len, error)
-	struct sadb_x_policy *xpl0;
-	size_t len;
-	int *error;
+key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
 {
 	struct secpolicy *newsp;
 
@@ -1622,8 +1629,7 @@
  * copy secpolicy struct to sadb_x_policy structure indicated.
  */
 struct mbuf *
-key_sp2msg(sp)
-	struct secpolicy *sp;
+key_sp2msg(struct secpolicy *sp)
 {
 	struct sadb_x_policy *xpl;
 	int tlen;
@@ -1634,15 +1640,11 @@
 
 	tlen = key_getspreqmsglen(sp);
 
-	m = key_alloc_mbuf(tlen);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
-
+	m = m_get2(tlen, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL)
+		return (NULL);
+	m_align(m, tlen);
 	m->m_len = tlen;
-	m->m_next = NULL;
 	xpl = mtod(m, struct sadb_x_policy *);
 	bzero(xpl, tlen);
 
@@ -1685,17 +1687,8 @@
 
 /* m will not be freed nor modified */
 static struct mbuf *
-#ifdef __STDC__
 key_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp,
-	int ndeep, int nitem, ...)
-#else
-key_gather_mbuf(m, mhp, ndeep, nitem, va_alist)
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
-	int ndeep;
-	int nitem;
-	va_dcl
-#endif
+    int ndeep, int nitem, ...)
 {
 	va_list ap;
 	int idx;
@@ -1723,7 +1716,7 @@
 
 			IPSEC_ASSERT(len <= MHLEN, ("header too big %u", len));
 
-			MGETHDR(n, M_DONTWAIT, MT_DATA);
+			MGETHDR(n, M_NOWAIT, MT_DATA);
 			if (!n)
 				goto fail;
 			n->m_len = len;
@@ -1732,17 +1725,16 @@
 			    mtod(n, caddr_t));
 		} else if (i < ndeep) {
 			len = mhp->extlen[idx];
-			n = key_alloc_mbuf(len);
-			if (!n || n->m_next) {	/*XXX*/
-				if (n)
-					m_freem(n);
+			n = m_get2(len, M_NOWAIT, MT_DATA, 0);
+			if (n == NULL)
 				goto fail;
-			}
+			m_align(n, len);
+			n->m_len = len;
 			m_copydata(m, mhp->extoff[idx], mhp->extlen[idx],
 			    mtod(n, caddr_t));
 		} else {
 			n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx],
-			    M_DONTWAIT);
+			    M_NOWAIT);
 		}
 		if (n == NULL)
 			goto fail;
@@ -1785,10 +1777,7 @@
  * m will always be freed.
  */
 static int
-key_spdadd(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_address *src0, *dst0;
 	struct sadb_x_policy *xpl0, *xpl;
@@ -2050,10 +2039,8 @@
  * m will always be freed.
  */
 static int
-key_spddelete(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_spddelete(struct socket *so, struct mbuf *m,
+    const struct sadb_msghdr *mhp)
 {
 	struct sadb_address *src0, *dst0;
 	struct sadb_x_policy *xpl0;
@@ -2160,10 +2147,8 @@
  * m will always be freed.
  */
 static int
-key_spddelete2(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_spddelete2(struct socket *so, struct mbuf *m,
+    const struct sadb_msghdr *mhp)
 {
 	u_int32_t id;
 	struct secpolicy *sp;
@@ -2200,9 +2185,9 @@
 	/* create new sadb_msg to reply. */
 	len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
 
-	MGETHDR(n, M_DONTWAIT, MT_DATA);
+	MGETHDR(n, M_NOWAIT, MT_DATA);
 	if (n && len > MHLEN) {
-		MCLGET(n, M_DONTWAIT);
+		MCLGET(n, M_NOWAIT);
 		if ((n->m_flags & M_EXT) == 0) {
 			m_freem(n);
 			n = NULL;
@@ -2222,7 +2207,7 @@
 		off, len));
 
 	n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY],
-	    mhp->extlen[SADB_X_EXT_POLICY], M_DONTWAIT);
+	    mhp->extlen[SADB_X_EXT_POLICY], M_NOWAIT);
 	if (!n->m_next) {
 		m_freem(n);
 		return key_senderror(so, m, ENOBUFS);
@@ -2242,7 +2227,7 @@
 }
 
 /*
- * SADB_X_GET processing
+ * SADB_X_SPDGET processing
  * receive
  *   <base, policy(*)>
  * from the user(?),
@@ -2254,10 +2239,7 @@
  * m will always be freed.
  */
 static int
-key_spdget(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_spdget(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	u_int32_t id;
 	struct secpolicy *sp;
@@ -2283,7 +2265,8 @@
 		return key_senderror(so, m, ENOENT);
 	}
 
-	n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
+	n = key_setdumpsp(sp, SADB_X_SPDGET, mhp->msg->sadb_msg_seq,
+	    mhp->msg->sadb_msg_pid);
 	KEY_FREESP(&sp);
 	if (n != NULL) {
 		m_freem(m);
@@ -2308,8 +2291,7 @@
  *    others: error number
  */
 int
-key_spdacquire(sp)
-	struct secpolicy *sp;
+key_spdacquire(struct secpolicy *sp)
 {
 	struct mbuf *result = NULL, *m;
 	struct secspacq *newspacq;
@@ -2328,7 +2310,8 @@
 		} else {
 			/* increment counter and do nothing. */
 			newspacq->count++;
-			return 0;
+			SPACQ_UNLOCK();
+			return (0);
 		}
 		SPACQ_UNLOCK();
 	} else {
@@ -2368,10 +2351,7 @@
  * m will always be freed.
  */
 static int
-key_spdflush(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_msg *newmsg;
 	struct secpolicy *sp;
@@ -2420,10 +2400,7 @@
  * m will always be freed.
  */
 static int
-key_spddump(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct secpolicy *sp;
 	int cnt;
@@ -2466,7 +2443,8 @@
 }
 
 static struct mbuf *
-key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq, u_int32_t pid)
+key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq,
+    u_int32_t pid)
 {
 	struct mbuf *result = NULL, *m;
 	struct seclifetime lt;
@@ -2542,8 +2520,7 @@
  * get PFKEY message length for security policy and request.
  */
 static u_int
-key_getspreqmsglen(sp)
-	struct secpolicy *sp;
+key_getspreqmsglen(struct secpolicy *sp)
 {
 	u_int tlen;
 
@@ -2580,8 +2557,7 @@
  *	others	: error number
  */
 static int
-key_spdexpire(sp)
-	struct secpolicy *sp;
+key_spdexpire(struct secpolicy *sp)
 {
 	struct mbuf *result = NULL, *m;
 	int len;
@@ -2602,13 +2578,13 @@
 
 	/* create lifetime extension (current and hard) */
 	len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL) {
 		error = ENOBUFS;
 		goto fail;
 	}
+	m_align(m, len);
+	m->m_len = len;
 	bzero(mtod(m, caddr_t), len);
 	lt = mtod(m, struct sadb_lifetime *);
 	lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
@@ -2694,8 +2670,7 @@
  *	others	: pointer to new SA head.
  */
 static struct secashead *
-key_newsah(saidx)
-	struct secasindex *saidx;
+key_newsah(struct secasindex *saidx)
 {
 	struct secashead *newsah;
 
@@ -2722,8 +2697,7 @@
  * delete SA index and all SA registerd.
  */
 static void
-key_delsah(sah)
-	struct secashead *sah;
+key_delsah(struct secashead *sah)
 {
 	struct secasvar *sav, *nextsav;
 	u_int stateidx;
@@ -2757,10 +2731,6 @@
 		/* remove from tree of SA index */
 		if (__LIST_CHAINED(sah))
 			LIST_REMOVE(sah, chain);
-		if (sah->route_cache.sa_route.ro_rt) {
-			RTFREE(sah->route_cache.sa_route.ro_rt);
-			sah->route_cache.sa_route.ro_rt = (struct rtentry *)NULL;
-		}
 		free(sah, M_IPSEC_SAH);
 	}
 }
@@ -2778,13 +2748,8 @@
  * does not modify mbuf.  does not free mbuf on error.
  */
 static struct secasvar *
-key_newsav(m, mhp, sah, errp, where, tag)
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
-	struct secashead *sah;
-	int *errp;
-	const char* where;
-	int tag;
+key_newsav(struct mbuf *m, const struct sadb_msghdr *mhp,
+    struct secashead *sah, int *errp, const char *where, int tag)
 {
 	struct secasvar *newsav;
 	const struct sadb_sa *xsa;
@@ -2929,8 +2894,7 @@
  * free() SA variable entry.
  */
 static void
-key_delsav(sav)
-	struct secasvar *sav;
+key_delsav(struct secasvar *sav)
 {
 	IPSEC_ASSERT(sav != NULL, ("null sav"));
 	IPSEC_ASSERT(sav->refcnt == 0, ("reference count %u > 0", sav->refcnt));
@@ -2950,8 +2914,7 @@
  *	others	: found, pointer to a SA.
  */
 static struct secashead *
-key_getsah(saidx)
-	struct secasindex *saidx;
+key_getsah(struct secasindex *saidx)
 {
 	struct secashead *sah;
 
@@ -2975,9 +2938,7 @@
  *	others	: found, pointer to a SA.
  */
 static struct secasvar *
-key_checkspidup(saidx, spi)
-	struct secasindex *saidx;
-	u_int32_t spi;
+key_checkspidup(struct secasindex *saidx, u_int32_t spi)
 {
 	struct secashead *sah;
 	struct secasvar *sav;
@@ -3011,9 +2972,7 @@
  *	others	: found, pointer to a SA.
  */
 static struct secasvar *
-key_getsavbyspi(sah, spi)
-	struct secashead *sah;
-	u_int32_t spi;
+key_getsavbyspi(struct secashead *sah, u_int32_t spi)
 {
 	struct secasvar *sav;
 	u_int stateidx, state;
@@ -3053,10 +3012,8 @@
  * does not modify mbuf.  does not free mbuf on error.
  */
 static int
-key_setsaval(sav, m, mhp)
-	struct secasvar *sav;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_setsaval(struct secasvar *sav, struct mbuf *m,
+    const struct sadb_msghdr *mhp)
 {
 	int error = 0;
 
@@ -3562,9 +3519,9 @@
 	len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
 	if (len > MCLBYTES)
 		return NULL;
-	MGETHDR(m, M_DONTWAIT, MT_DATA);
+	MGETHDR(m, M_NOWAIT, MT_DATA);
 	if (m && len > MHLEN) {
-		MCLGET(m, M_DONTWAIT);
+		MCLGET(m, M_NOWAIT);
 		if ((m->m_flags & M_EXT) == 0) {
 			m_freem(m);
 			m = NULL;
@@ -3594,8 +3551,7 @@
  * copy secasvar data into sadb_address.
  */
 static struct mbuf *
-key_setsadbsa(sav)
-	struct secasvar *sav;
+key_setsadbsa(struct secasvar *sav)
 {
 	struct mbuf *m;
 	struct sadb_sa *p;
@@ -3602,15 +3558,12 @@
 	int len;
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_sa));
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
-
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL)
+		return (NULL);
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_sa *);
-
 	bzero(p, len);
 	p->sadb_sa_len = PFKEY_UNIT64(len);
 	p->sadb_sa_exttype = SADB_EXT_SA;
@@ -3628,7 +3581,8 @@
  * set data into sadb_address.
  */
 static struct mbuf *
-key_setsadbaddr(u_int16_t exttype, const struct sockaddr *saddr, u_int8_t prefixlen, u_int16_t ul_proto)
+key_setsadbaddr(u_int16_t exttype, const struct sockaddr *saddr,
+    u_int8_t prefixlen, u_int16_t ul_proto)
 {
 	struct mbuf *m;
 	struct sadb_address *p;
@@ -3636,13 +3590,11 @@
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_address)) +
 	    PFKEY_ALIGN8(saddr->sa_len);
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
-
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL)
+		return (NULL);
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_address *);
 
 	bzero(p, len);
@@ -3682,13 +3634,11 @@
 	size_t len;
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2));
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
-
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL)
+		return (NULL);
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_x_sa2 *);
 
 	bzero(p, len);
@@ -3716,13 +3666,11 @@
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_type));
 
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL)
 		return (NULL);
-	}
-
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_x_nat_t_type *);
 
 	bzero(p, len);
@@ -3745,13 +3693,11 @@
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_port));
 
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL)
 		return (NULL);
-	}
-
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_x_nat_t_port *);
 
 	bzero(p, len);
@@ -3765,7 +3711,7 @@
 /* 
  * Get port from sockaddr. Port is in network byte order.
  */
-u_int16_t 
+u_int16_t
 key_portfromsaddr(struct sockaddr *sa)
 {
 
@@ -3822,13 +3768,11 @@
 	size_t len;
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy));
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
-		return NULL;
-	}
-
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL)
+		return (NULL);
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_x_policy *);
 
 	bzero(p, len);
@@ -3850,7 +3794,7 @@
  */
 struct seckey *
 key_dup_keymsg(const struct sadb_key *src, u_int len,
-	       struct malloc_type *type)
+    struct malloc_type *type)
 {
 	struct seckey *dst;
 	dst = (struct seckey *)malloc(sizeof(struct seckey), type, M_NOWAIT);
@@ -3882,8 +3826,7 @@
  */
 
 static struct seclifetime *
-key_dup_lifemsg(const struct sadb_lifetime *src,
-		 struct malloc_type *type)
+key_dup_lifemsg(const struct sadb_lifetime *src, struct malloc_type *type)
 {
 	struct seclifetime *dst = NULL;
 
@@ -3906,34 +3849,14 @@
  *	0: false
  */
 int
-key_ismyaddr(sa)
-	struct sockaddr *sa;
+key_ismyaddr(struct sockaddr *sa)
 {
-#ifdef INET
-	struct sockaddr_in *sin;
-	struct in_ifaddr *ia;
-#endif
 
 	IPSEC_ASSERT(sa != NULL, ("null sockaddr"));
-
 	switch (sa->sa_family) {
 #ifdef INET
 	case AF_INET:
-		sin = (struct sockaddr_in *)sa;
-		IN_IFADDR_RLOCK();
-		for (ia = V_in_ifaddrhead.tqh_first; ia;
-		     ia = ia->ia_link.tqe_next)
-		{
-			if (sin->sin_family == ia->ia_addr.sin_family &&
-			    sin->sin_len == ia->ia_addr.sin_len &&
-			    sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
-			{
-				IN_IFADDR_RUNLOCK();
-				return 1;
-			}
-		}
-		IN_IFADDR_RUNLOCK();
-		break;
+		return (in_localip(satosin(sa)->sin_addr));
 #endif
 #ifdef INET6
 	case AF_INET6:
@@ -3954,8 +3877,7 @@
 #include <netinet6/in6_var.h>
 
 static int
-key_ismyaddr6(sin6)
-	struct sockaddr_in6 *sin6;
+key_ismyaddr6(struct sockaddr_in6 *sin6)
 {
 	struct in6_ifaddr *ia;
 #if 0
@@ -3964,7 +3886,7 @@
 
 	IN6_IFADDR_RLOCK();
 	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
-		if (key_sockaddrcmp((struct sockaddr *)&sin6,
+		if (key_sockaddrcmp((struct sockaddr *)sin6,
 		    (struct sockaddr *)&ia->ia_addr, 0) == 0) {
 			IN6_IFADDR_RUNLOCK();
 			return 1;
@@ -4008,10 +3930,8 @@
  *      0 : not equal
  */
 static int
-key_cmpsaidx(
-	const struct secasindex *saidx0,
-	const struct secasindex *saidx1,
-	int flag)
+key_cmpsaidx(const struct secasindex *saidx0, const struct secasindex *saidx1,
+    int flag)
 {
 	int chkport = 0;
 
@@ -4056,10 +3976,12 @@
 		/*
 		 * If NAT-T is enabled, check ports for tunnel mode.
 		 * Do not check ports if they are set to zero in the SPD.
-		 * Also do not do it for transport mode, as there is no
-		 * port information available in the SP.
+		 * Also do not do it for native transport mode, as there
+		 * is no port information available in the SP.
 		 */
-		if (saidx1->mode == IPSEC_MODE_TUNNEL &&
+		if ((saidx1->mode == IPSEC_MODE_TUNNEL ||
+		     (saidx1->mode == IPSEC_MODE_TRANSPORT &&
+		      saidx1->proto == IPPROTO_ESP)) &&
 		    saidx1->src.sa.sa_family == AF_INET &&
 		    saidx1->dst.sa.sa_family == AF_INET &&
 		    ((const struct sockaddr_in *)(&saidx1->src))->sin_port &&
@@ -4088,9 +4010,8 @@
  *	0 : not equal
  */
 static int
-key_cmpspidx_exactly(
-	struct secpolicyindex *spidx0,
-	struct secpolicyindex *spidx1)
+key_cmpspidx_exactly(struct secpolicyindex *spidx0,
+    struct secpolicyindex *spidx1)
 {
 	/* sanity */
 	if (spidx0 == NULL && spidx1 == NULL)
@@ -4118,9 +4039,8 @@
  *	0 : not equal
  */
 static int
-key_cmpspidx_withmask(
-	struct secpolicyindex *spidx0,
-	struct secpolicyindex *spidx1)
+key_cmpspidx_withmask(struct secpolicyindex *spidx0,
+    struct secpolicyindex *spidx1)
 {
 	/* sanity */
 	if (spidx0 == NULL && spidx1 == NULL)
@@ -4211,10 +4131,8 @@
 
 /* returns 0 on match */
 static int
-key_sockaddrcmp(
-	const struct sockaddr *sa1,
-	const struct sockaddr *sa2,
-	int port)
+key_sockaddrcmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
+    int port)
 {
 #ifdef satosin
 #undef satosin
@@ -4386,41 +4304,29 @@
 					"time, why?\n", __func__));
 				continue;
 			}
-
-			/* check SOFT lifetime */
-			if (sav->lft_s->addtime != 0 &&
-			    now - sav->created > sav->lft_s->addtime) {
-				key_sa_chgstate(sav, SADB_SASTATE_DYING);
-				/* 
-				 * Actually, only send expire message if
-				 * SA has been used, as it was done before,
-				 * but should we always send such message,
-				 * and let IKE daemon decide if it should be
-				 * renegotiated or not ?
-				 * XXX expire message will actually NOT be
-				 * sent if SA is only used after soft
-				 * lifetime has been reached, see below
-				 * (DYING state)
-				 */
-				if (sav->lft_c->usetime != 0)
-					key_expire(sav);
-			}
-			/* check SOFT lifetime by bytes */
 			/*
-			 * XXX I don't know the way to delete this SA
-			 * when new SA is installed.  Caution when it's
-			 * installed too big lifetime by time.
+			 * RFC 2367:
+			 * HARD lifetimes MUST take precedence over SOFT
+			 * lifetimes, meaning if the HARD and SOFT lifetimes
+			 * are the same, the HARD lifetime will appear on the
+			 * EXPIRE message.
 			 */
-			else if (sav->lft_s->bytes != 0 &&
-			    sav->lft_s->bytes < sav->lft_c->bytes) {
-
+			/* check HARD lifetime */
+			if ((sav->lft_h->addtime != 0 &&
+			    now - sav->created > sav->lft_h->addtime) ||
+			    (sav->lft_h->bytes != 0 &&
+			    sav->lft_h->bytes < sav->lft_c->bytes)) {
+				key_sa_chgstate(sav, SADB_SASTATE_DEAD);
+				key_expire(sav, 1);
+				KEY_FREESAV(&sav);
+			}
+			/* check SOFT lifetime */
+			else if ((sav->lft_s->addtime != 0 &&
+			    now - sav->created > sav->lft_s->addtime) ||
+			    (sav->lft_s->bytes != 0 &&
+			    sav->lft_s->bytes < sav->lft_c->bytes)) {
 				key_sa_chgstate(sav, SADB_SASTATE_DYING);
-				/*
-				 * XXX If we keep to send expire
-				 * message in the status of
-				 * DYING. Do remove below code.
-				 */
-				key_expire(sav);
+				key_expire(sav, 0);
 			}
 		}
 
@@ -4440,6 +4346,7 @@
 			if (sav->lft_h->addtime != 0 &&
 			    now - sav->created > sav->lft_h->addtime) {
 				key_sa_chgstate(sav, SADB_SASTATE_DEAD);
+				key_expire(sav, 1);
 				KEY_FREESAV(&sav);
 			}
 #if 0	/* XXX Should we keep to send expire message until HARD lifetime ? */
@@ -4455,7 +4362,7 @@
 				 * If there is no SA then sending
 				 * expire message.
 				 */
-				key_expire(sav);
+				key_expire(sav, 0);
 			}
 #endif
 			/* check HARD lifetime by bytes */
@@ -4462,6 +4369,7 @@
 			else if (sav->lft_h->bytes != 0 &&
 			    sav->lft_h->bytes < sav->lft_c->bytes) {
 				key_sa_chgstate(sav, SADB_SASTATE_DEAD);
+				key_expire(sav, 1);
 				KEY_FREESAV(&sav);
 			}
 		}
@@ -4561,9 +4469,7 @@
 }
 
 void
-key_randomfill(p, l)
-	void *p;
-	size_t l;
+key_randomfill(void *p, size_t l)
 {
 	size_t n;
 	u_long v;
@@ -4649,10 +4555,7 @@
  *	other if success, return pointer to the message to send.
  */
 static int
-key_getspi(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_getspi(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_address *src0, *dst0;
 	struct secasindex saidx;
@@ -4822,9 +4725,9 @@
 	len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) +
 	    PFKEY_ALIGN8(sizeof(struct sadb_sa));
 
-	MGETHDR(n, M_DONTWAIT, MT_DATA);
+	MGETHDR(n, M_NOWAIT, MT_DATA);
 	if (len > MHLEN) {
-		MCLGET(n, M_DONTWAIT);
+		MCLGET(n, M_NOWAIT);
 		if ((n->m_flags & M_EXT) == 0) {
 			m_freem(n);
 			n = NULL;
@@ -4884,9 +4787,7 @@
  *	others: success.
  */
 static u_int32_t
-key_do_getnewspi(spirange, saidx)
-	struct sadb_spirange *spirange;
-	struct secasindex *saidx;
+key_do_getnewspi(struct sadb_spirange *spirange, struct secasindex *saidx)
 {
 	u_int32_t newspi;
 	u_int32_t min, max;
@@ -4964,10 +4865,7 @@
  * m will always be freed.
  */
 static int
-key_update(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_sa *sa0;
 	struct sadb_address *src0, *dst0;
@@ -5211,9 +5109,7 @@
  */
 #ifdef IPSEC_DOSEQCHECK
 static struct secasvar *
-key_getsavbyseq(sah, seq)
-	struct secashead *sah;
-	u_int32_t seq;
+key_getsavbyseq(struct secashead *sah, u_int32_t seq)
 {
 	struct secasvar *sav;
 	u_int state;
@@ -5254,10 +5150,7 @@
  * m will always be freed.
  */
 static int
-key_add(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_sa *sa0;
 	struct sadb_address *src0, *dst0;
@@ -5468,10 +5361,8 @@
 
 /* m is retained */
 static int
-key_setident(sah, m, mhp)
-	struct secashead *sah;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_setident(struct secashead *sah, struct mbuf *m,
+    const struct sadb_msghdr *mhp)
 {
 	const struct sadb_ident *idsrc, *iddst;
 	int idsrclen, iddstlen;
@@ -5544,9 +5435,7 @@
  * it is caller's responsibility to free the result. 
  */
 static struct mbuf *
-key_getmsgbuf_x1(m, mhp)
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_getmsgbuf_x1(struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct mbuf *n;
 
@@ -5575,9 +5464,6 @@
 	return n;
 }
 
-static int key_delete_all __P((struct socket *, struct mbuf *,
-	const struct sadb_msghdr *, u_int16_t));
-
 /*
  * SADB_DELETE processing
  * receive
@@ -5590,10 +5476,7 @@
  * m will always be freed.
  */
 static int
-key_delete(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_delete(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_sa *sa0;
 	struct sadb_address *src0, *dst0;
@@ -5737,8 +5620,8 @@
  * delete all SAs for src/dst.  Called from key_delete().
  */
 static int
-key_delete_all(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp,
-    u_int16_t proto)
+key_delete_all(struct socket *so, struct mbuf *m,
+    const struct sadb_msghdr *mhp, u_int16_t proto)
 {
 	struct sadb_address *src0, *dst0;
 	struct secasindex saidx;
@@ -5858,10 +5741,7 @@
  * m will always be freed.
  */
 static int
-key_get(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_get(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_sa *sa0;
 	struct sadb_address *src0, *dst0;
@@ -5984,8 +5864,7 @@
 
 /* XXX make it sysctl-configurable? */
 static void
-key_getcomb_setlifetime(comb)
-	struct sadb_comb *comb;
+key_getcomb_setlifetime(struct sadb_comb *comb)
 {
 
 	comb->sadb_comb_soft_allocations = 1;
@@ -6032,7 +5911,7 @@
 		else {
 			IPSEC_ASSERT(l <= MLEN,
 				("l=%u > MLEN=%lu", l, (u_long) MLEN));
-			MGET(m, M_DONTWAIT, MT_DATA);
+			MGET(m, M_NOWAIT, MT_DATA);
 			if (m) {
 				M_ALIGN(m, l);
 				m->m_len = l;
@@ -6077,11 +5956,8 @@
 }
 
 static void
-key_getsizes_ah(
-	const struct auth_hash *ah,
-	int alg,
-	u_int16_t* min,
-	u_int16_t* max)
+key_getsizes_ah(const struct auth_hash *ah, int alg, u_int16_t* min,
+    u_int16_t* max)
 {
 
 	*min = *max = ah->keysize;
@@ -6140,7 +6016,7 @@
 		if (!m) {
 			IPSEC_ASSERT(l <= MLEN,
 				("l=%u > MLEN=%lu", l, (u_long) MLEN));
-			MGET(m, M_DONTWAIT, MT_DATA);
+			MGET(m, M_NOWAIT, MT_DATA);
 			if (m) {
 				M_ALIGN(m, l);
 				m->m_len = l;
@@ -6147,7 +6023,7 @@
 				m->m_next = NULL;
 			}
 		} else
-			M_PREPEND(m, l, M_DONTWAIT);
+			M_PREPEND(m, l, M_NOWAIT);
 		if (!m)
 			return NULL;
 
@@ -6184,7 +6060,7 @@
 		if (!m) {
 			IPSEC_ASSERT(l <= MLEN,
 				("l=%u > MLEN=%lu", l, (u_long) MLEN));
-			MGET(m, M_DONTWAIT, MT_DATA);
+			MGET(m, M_NOWAIT, MT_DATA);
 			if (m) {
 				M_ALIGN(m, l);
 				m->m_len = l;
@@ -6191,7 +6067,7 @@
 				m->m_next = NULL;
 			}
 		} else
-			M_PREPEND(m, l, M_DONTWAIT);
+			M_PREPEND(m, l, M_NOWAIT);
 		if (!m)
 			return NULL;
 
@@ -6211,8 +6087,7 @@
  * XXX sysctl interface to ipsec_{ah,esp}_keymin
  */
 static struct mbuf *
-key_getprop(saidx)
-	const struct secasindex *saidx;
+key_getprop(const struct secasindex *saidx)
 {
 	struct sadb_prop *prop;
 	struct mbuf *m, *n;
@@ -6235,7 +6110,7 @@
 
 	if (!m)
 		return NULL;
-	M_PREPEND(m, l, M_DONTWAIT);
+	M_PREPEND(m, l, M_NOWAIT);
 	if (!m)
 		return NULL;
 
@@ -6275,16 +6150,21 @@
 static int
 key_acquire(const struct secasindex *saidx, struct secpolicy *sp)
 {
-	struct mbuf *result = NULL, *m;
+	union sockaddr_union addr;
+	struct mbuf *result, *m;
 	struct secacq *newacq;
-	u_int8_t satype;
-	int error = -1;
 	u_int32_t seq;
+	int error;
+	u_int16_t ul_proto;
+	u_int8_t mask, satype;
 
 	IPSEC_ASSERT(saidx != NULL, ("null saidx"));
 	satype = key_proto2satype(saidx->proto);
 	IPSEC_ASSERT(satype != 0, ("null satype, protocol %u", saidx->proto));
 
+	error = -1;
+	result = NULL;
+	ul_proto = IPSEC_ULPROTO_ANY;
 	/*
 	 * We never do anything about acquirng SA.  There is anather
 	 * solution that kernel blocks to send SADB_ACQUIRE message until
@@ -6321,9 +6201,37 @@
 	 * anything related to NAT-T at this time.
 	 */
 
-	/* set sadb_address for saidx's. */
-	m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
-	    &saidx->src.sa, FULLMASK, IPSEC_ULPROTO_ANY);
+	/*
+	 * set sadb_address for saidx's.
+	 *
+	 * Note that if sp is supplied, then we're being called from
+	 * key_checkrequest and should supply port and protocol information.
+	 */
+	if (sp != NULL && (sp->spidx.ul_proto == IPPROTO_TCP ||
+	    sp->spidx.ul_proto == IPPROTO_UDP))
+		ul_proto = sp->spidx.ul_proto;
+
+	addr = saidx->src;
+	mask = FULLMASK;
+	if (ul_proto != IPSEC_ULPROTO_ANY) {
+		switch (sp->spidx.src.sa.sa_family) {
+		case AF_INET:
+			if (sp->spidx.src.sin.sin_port != IPSEC_PORT_ANY) {
+				addr.sin.sin_port = sp->spidx.src.sin.sin_port;
+				mask = sp->spidx.prefs;
+			}
+			break;
+		case AF_INET6:
+			if (sp->spidx.src.sin6.sin6_port != IPSEC_PORT_ANY) {
+				addr.sin6.sin6_port = sp->spidx.src.sin6.sin6_port;
+				mask = sp->spidx.prefs;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, &addr.sa, mask, ul_proto);
 	if (!m) {
 		error = ENOBUFS;
 		goto fail;
@@ -6330,8 +6238,27 @@
 	}
 	m_cat(result, m);
 
-	m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
-	    &saidx->dst.sa, FULLMASK, IPSEC_ULPROTO_ANY);
+	addr = saidx->dst;
+	mask = FULLMASK;
+	if (ul_proto != IPSEC_ULPROTO_ANY) {
+		switch (sp->spidx.dst.sa.sa_family) {
+		case AF_INET:
+			if (sp->spidx.dst.sin.sin_port != IPSEC_PORT_ANY) {
+				addr.sin.sin_port = sp->spidx.dst.sin.sin_port;
+				mask = sp->spidx.prefd;
+			}
+			break;
+		case AF_INET6:
+			if (sp->spidx.dst.sin6.sin6_port != IPSEC_PORT_ANY) {
+				addr.sin6.sin6_port = sp->spidx.dst.sin6.sin6_port;
+				mask = sp->spidx.prefd;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, &addr.sa, mask, ul_proto);
 	if (!m) {
 		error = ENOBUFS;
 		goto fail;
@@ -6484,8 +6411,7 @@
 }
 
 static struct secacq *
-key_getacqbyseq(seq)
-	u_int32_t seq;
+key_getacqbyseq(u_int32_t seq)
 {
 	struct secacq *acq;
 
@@ -6500,8 +6426,7 @@
 }
 
 static struct secspacq *
-key_newspacq(spidx)
-	struct secpolicyindex *spidx;
+key_newspacq(struct secpolicyindex *spidx)
 {
 	struct secspacq *acq;
 
@@ -6526,8 +6451,7 @@
 }
 
 static struct secspacq *
-key_getspacq(spidx)
-	struct secpolicyindex *spidx;
+key_getspacq(struct secpolicyindex *spidx)
 {
 	struct secspacq *acq;
 
@@ -6558,10 +6482,7 @@
  * m will always be freed.
  */
 static int
-key_acquire2(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_acquire2(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	const struct sadb_address *src0, *dst0;
 	struct secasindex saidx;
@@ -6716,10 +6637,7 @@
  * m will always be freed.
  */
 static int
-key_register(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_register(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct secreg *reg, *newreg = 0;
 
@@ -6793,9 +6711,9 @@
 	if (len > MCLBYTES)
 		return key_senderror(so, m, ENOBUFS);
 
-	MGETHDR(n, M_DONTWAIT, MT_DATA);
+	MGETHDR(n, M_NOWAIT, MT_DATA);
 	if (len > MHLEN) {
-		MCLGET(n, M_DONTWAIT);
+		MCLGET(n, M_NOWAIT);
 		if ((n->m_flags & M_EXT) == 0) {
 			m_freem(n);
 			n = NULL;
@@ -6909,9 +6827,8 @@
  *	others	: error number
  */
 static int
-key_expire(struct secasvar *sav)
+key_expire(struct secasvar *sav, int hard)
 {
-	int s;
 	int satype;
 	struct mbuf *result = NULL, *m;
 	int len;
@@ -6918,9 +6835,6 @@
 	int error = -1;
 	struct sadb_lifetime *lt;
 
-	/* XXX: Why do we lock ? */
-	s = splnet();	/*called from softclock()*/
-
 	IPSEC_ASSERT (sav != NULL, ("null sav"));
 	IPSEC_ASSERT (sav->sah != NULL, ("null sa header"));
 
@@ -6954,13 +6868,13 @@
 
 	/* create lifetime extension (current and soft) */
 	len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
-	m = key_alloc_mbuf(len);
-	if (!m || m->m_next) {	/*XXX*/
-		if (m)
-			m_freem(m);
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+	if (m == NULL) {
 		error = ENOBUFS;
 		goto fail;
 	}
+	m_align(m, len);
+	m->m_len = len;
 	bzero(mtod(m, caddr_t), len);
 	lt = mtod(m, struct sadb_lifetime *);
 	lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
@@ -6971,11 +6885,19 @@
 	lt->sadb_lifetime_usetime = sav->lft_c->usetime;
 	lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2);
 	lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
-	lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
-	lt->sadb_lifetime_allocations = sav->lft_s->allocations;
-	lt->sadb_lifetime_bytes = sav->lft_s->bytes;
-	lt->sadb_lifetime_addtime = sav->lft_s->addtime;
-	lt->sadb_lifetime_usetime = sav->lft_s->usetime;
+	if (hard) {
+		lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+		lt->sadb_lifetime_allocations = sav->lft_h->allocations;
+		lt->sadb_lifetime_bytes = sav->lft_h->bytes;
+		lt->sadb_lifetime_addtime = sav->lft_h->addtime;
+		lt->sadb_lifetime_usetime = sav->lft_h->usetime;
+	} else {
+		lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+		lt->sadb_lifetime_allocations = sav->lft_s->allocations;
+		lt->sadb_lifetime_bytes = sav->lft_s->bytes;
+		lt->sadb_lifetime_addtime = sav->lft_s->addtime;
+		lt->sadb_lifetime_usetime = sav->lft_s->usetime;
+	}
 	m_cat(result, m);
 
 	/* set sadb_address for source */
@@ -7022,13 +6944,11 @@
 	mtod(result, struct sadb_msg *)->sadb_msg_len =
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
-	splx(s);
 	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
 
  fail:
 	if (result)
 		m_freem(result);
-	splx(s);
 	return error;
 }
 
@@ -7045,10 +6965,7 @@
  * m will always be freed.
  */
 static int
-key_flush(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_flush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct sadb_msg *newmsg;
 	struct secashead *sah, *nextsah;
@@ -7128,10 +7045,7 @@
  * m will always be freed.
  */
 static int
-key_dump(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	struct secashead *sah;
 	struct secasvar *sav;
@@ -7220,10 +7134,7 @@
  * m will always be freed.
  */
 static int
-key_promisc(so, m, mhp)
-	struct socket *so;
-	struct mbuf *m;
-	const struct sadb_msghdr *mhp;
+key_promisc(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
 {
 	int olen;
 
@@ -7270,8 +7181,8 @@
 	}
 }
 
-static int (*key_typesw[]) __P((struct socket *, struct mbuf *,
-		const struct sadb_msghdr *)) = {
+static int (*key_typesw[])(struct socket *, struct mbuf *,
+		const struct sadb_msghdr *) = {
 	NULL,		/* SADB_RESERVED */
 	key_getspi,	/* SADB_GETSPI */
 	key_update,	/* SADB_UPDATE */
@@ -7309,9 +7220,7 @@
  *    length for buffer to send to user process.
  */
 int
-key_parse(m, so)
-	struct mbuf *m;
-	struct socket *so;
+key_parse(struct mbuf *m, struct socket *so)
 {
 	struct sadb_msg *msg;
 	struct sadb_msghdr mh;
@@ -7337,10 +7246,9 @@
 	orglen = PFKEY_UNUNIT64(msg->sadb_msg_len);
 	target = KEY_SENDUP_ONE;
 
-	if ((m->m_flags & M_PKTHDR) == 0 ||
-	    m->m_pkthdr.len != m->m_pkthdr.len) {
+	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len != orglen) {
 		ipseclog((LOG_DEBUG, "%s: invalid message length.\n",__func__));
-		V_pfkeystat.out_invlen++;
+		PFKEYSTAT_INC(out_invlen);
 		error = EINVAL;
 		goto senderror;
 	}
@@ -7348,7 +7256,7 @@
 	if (msg->sadb_msg_version != PF_KEY_V2) {
 		ipseclog((LOG_DEBUG, "%s: PF_KEY version %u is mismatched.\n",
 		    __func__, msg->sadb_msg_version));
-		V_pfkeystat.out_invver++;
+		PFKEYSTAT_INC(out_invver);
 		error = EINVAL;
 		goto senderror;
 	}
@@ -7356,7 +7264,7 @@
 	if (msg->sadb_msg_type > SADB_MAX) {
 		ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n",
 		    __func__, msg->sadb_msg_type));
-		V_pfkeystat.out_invmsgtype++;
+		PFKEYSTAT_INC(out_invmsgtype);
 		error = EINVAL;
 		goto senderror;
 	}
@@ -7369,9 +7277,9 @@
 	if (m->m_next) {
 		struct mbuf *n;
 
-		MGETHDR(n, M_DONTWAIT, MT_DATA);
+		MGETHDR(n, M_NOWAIT, MT_DATA);
 		if (n && m->m_pkthdr.len > MHLEN) {
-			MCLGET(n, M_DONTWAIT);
+			MCLGET(n, M_NOWAIT);
 			if ((n->m_flags & M_EXT) == 0) {
 				m_free(n);
 				n = NULL;
@@ -7409,7 +7317,7 @@
 			ipseclog((LOG_DEBUG, "%s: must specify satype "
 			    "when msg type=%u.\n", __func__,
 			    msg->sadb_msg_type));
-			V_pfkeystat.out_invsatype++;
+			PFKEYSTAT_INC(out_invsatype);
 			error = EINVAL;
 			goto senderror;
 		}
@@ -7429,7 +7337,7 @@
 		case SADB_X_SPDDELETE2:
 			ipseclog((LOG_DEBUG, "%s: illegal satype=%u\n",
 				__func__, msg->sadb_msg_type));
-			V_pfkeystat.out_invsatype++;
+			PFKEYSTAT_INC(out_invsatype);
 			error = EINVAL;
 			goto senderror;
 		}
@@ -7440,7 +7348,7 @@
 	case SADB_SATYPE_MIP:
 		ipseclog((LOG_DEBUG, "%s: type %u isn't supported.\n",
 			__func__, msg->sadb_msg_satype));
-		V_pfkeystat.out_invsatype++;
+		PFKEYSTAT_INC(out_invsatype);
 		error = EOPNOTSUPP;
 		goto senderror;
 	case 1:	/* XXX: What does it do? */
@@ -7450,7 +7358,7 @@
 	default:
 		ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n",
 			__func__, msg->sadb_msg_satype));
-		V_pfkeystat.out_invsatype++;
+		PFKEYSTAT_INC(out_invsatype);
 		error = EINVAL;
 		goto senderror;
 	}
@@ -7468,7 +7376,7 @@
 		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
 			ipseclog((LOG_DEBUG, "%s: upper layer protocol "
 				"mismatched.\n", __func__));
-			V_pfkeystat.out_invaddr++;
+			PFKEYSTAT_INC(out_invaddr);
 			error = EINVAL;
 			goto senderror;
 		}
@@ -7478,7 +7386,7 @@
 		    PFKEY_ADDR_SADDR(dst0)->sa_family) {
 			ipseclog((LOG_DEBUG, "%s: address family mismatched.\n",
 				__func__));
-			V_pfkeystat.out_invaddr++;
+			PFKEYSTAT_INC(out_invaddr);
 			error = EINVAL;
 			goto senderror;
 		}
@@ -7486,7 +7394,7 @@
 		    PFKEY_ADDR_SADDR(dst0)->sa_len) {
 			ipseclog((LOG_DEBUG, "%s: address struct size "
 				"mismatched.\n", __func__));
-			V_pfkeystat.out_invaddr++;
+			PFKEYSTAT_INC(out_invaddr);
 			error = EINVAL;
 			goto senderror;
 		}
@@ -7495,7 +7403,7 @@
 		case AF_INET:
 			if (PFKEY_ADDR_SADDR(src0)->sa_len !=
 			    sizeof(struct sockaddr_in)) {
-				V_pfkeystat.out_invaddr++;
+				PFKEYSTAT_INC(out_invaddr);
 				error = EINVAL;
 				goto senderror;
 			}
@@ -7503,7 +7411,7 @@
 		case AF_INET6:
 			if (PFKEY_ADDR_SADDR(src0)->sa_len !=
 			    sizeof(struct sockaddr_in6)) {
-				V_pfkeystat.out_invaddr++;
+				PFKEYSTAT_INC(out_invaddr);
 				error = EINVAL;
 				goto senderror;
 			}
@@ -7511,7 +7419,7 @@
 		default:
 			ipseclog((LOG_DEBUG, "%s: unsupported address family\n",
 				__func__));
-			V_pfkeystat.out_invaddr++;
+			PFKEYSTAT_INC(out_invaddr);
 			error = EAFNOSUPPORT;
 			goto senderror;
 		}
@@ -7533,7 +7441,7 @@
 		    dst0->sadb_address_prefixlen > plen) {
 			ipseclog((LOG_DEBUG, "%s: illegal prefixlen.\n",
 				__func__));
-			V_pfkeystat.out_invaddr++;
+			PFKEYSTAT_INC(out_invaddr);
 			error = EINVAL;
 			goto senderror;
 		}
@@ -7546,7 +7454,7 @@
 
 	if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) ||
 	    key_typesw[msg->sadb_msg_type] == NULL) {
-		V_pfkeystat.out_invmsgtype++;
+		PFKEYSTAT_INC(out_invmsgtype);
 		error = EINVAL;
 		goto senderror;
 	}
@@ -7559,10 +7467,7 @@
 }
 
 static int
-key_senderror(so, m, code)
-	struct socket *so;
-	struct mbuf *m;
-	int code;
+key_senderror(struct socket *so, struct mbuf *m, int code)
 {
 	struct sadb_msg *msg;
 
@@ -7580,9 +7485,7 @@
  * XXX larger-than-MCLBYTES extension?
  */
 static int
-key_align(m, mhp)
-	struct mbuf *m;
-	struct sadb_msghdr *mhp;
+key_align(struct mbuf *m, struct sadb_msghdr *mhp)
 {
 	struct mbuf *n;
 	struct sadb_ext *ext;
@@ -7648,7 +7551,7 @@
 				ipseclog((LOG_DEBUG, "%s: duplicate ext_type "
 					"%u\n", __func__, ext->sadb_ext_type));
 				m_freem(m);
-				V_pfkeystat.out_dupext++;
+				PFKEYSTAT_INC(out_dupext);
 				return EINVAL;
 			}
 			break;
@@ -7656,7 +7559,7 @@
 			ipseclog((LOG_DEBUG, "%s: invalid ext_type %u\n",
 				__func__, ext->sadb_ext_type));
 			m_freem(m);
-			V_pfkeystat.out_invexttype++;
+			PFKEYSTAT_INC(out_invexttype);
 			return EINVAL;
 		}
 
@@ -7664,7 +7567,7 @@
 
 		if (key_validate_ext(ext, extlen)) {
 			m_freem(m);
-			V_pfkeystat.out_invlen++;
+			PFKEYSTAT_INC(out_invlen);
 			return EINVAL;
 		}
 
@@ -7682,7 +7585,7 @@
 
 	if (off != end) {
 		m_freem(m);
-		V_pfkeystat.out_invlen++;
+		PFKEYSTAT_INC(out_invlen);
 		return EINVAL;
 	}
 
@@ -7690,9 +7593,7 @@
 }
 
 static int
-key_validate_ext(ext, len)
-	const struct sadb_ext *ext;
-	int len;
+key_validate_ext(const struct sadb_ext *ext, int len)
 {
 	const struct sockaddr *sa;
 	enum { NONE, ADDR } checktype = NONE;
@@ -7865,11 +7766,8 @@
  * xxx more checks to be provided
  */
 int
-key_checktunnelsanity(sav, family, src, dst)
-	struct secasvar *sav;
-	u_int family;
-	caddr_t src;
-	caddr_t dst;
+key_checktunnelsanity(struct secasvar *sav, u_int family, caddr_t src,
+    caddr_t dst)
 {
 	IPSEC_ASSERT(sav->sah != NULL, ("null SA header"));
 
@@ -7880,9 +7778,7 @@
 
 /* record data transfer on SA, and update timestamps */
 void
-key_sa_recordxfer(sav, m)
-	struct secasvar *sav;
-	struct mbuf *m;
+key_sa_recordxfer(struct secasvar *sav, struct mbuf *m)
 {
 	IPSEC_ASSERT(sav != NULL, ("Null secasvar"));
 	IPSEC_ASSERT(m != NULL, ("Null mbuf"));
@@ -7921,26 +7817,6 @@
 	return;
 }
 
-/* dumb version */
-void
-key_sa_routechange(dst)
-	struct sockaddr *dst;
-{
-	struct secashead *sah;
-	struct route *ro;
-
-	SAHTREE_LOCK();
-	LIST_FOREACH(sah, &V_sahtree, chain) {
-		ro = &sah->route_cache.sa_route;
-		if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len
-		 && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) {
-			RTFREE(ro->ro_rt);
-			ro->ro_rt = (struct rtentry *)NULL;
-		}
-	}
-	SAHTREE_UNLOCK();
-}
-
 static void
 key_sa_chgstate(struct secasvar *sav, u_int8_t state)
 {
@@ -7956,8 +7832,7 @@
 }
 
 void
-key_sa_stir_iv(sav)
-	struct secasvar *sav;
+key_sa_stir_iv(struct secasvar *sav)
 {
 
 	IPSEC_ASSERT(sav->iv != NULL, ("null IV"));
@@ -7964,45 +7839,6 @@
 	key_randomfill(sav->iv, sav->ivlen);
 }
 
-/* XXX too much? */
-static struct mbuf *
-key_alloc_mbuf(l)
-	int l;
-{
-	struct mbuf *m = NULL, *n;
-	int len, t;
-
-	len = l;
-	while (len > 0) {
-		MGET(n, M_DONTWAIT, MT_DATA);
-		if (n && len > MLEN)
-			MCLGET(n, M_DONTWAIT);
-		if (!n) {
-			m_freem(m);
-			return NULL;
-		}
-
-		n->m_next = NULL;
-		n->m_len = 0;
-		n->m_len = M_TRAILINGSPACE(n);
-		/* use the bottom of mbuf, hoping we can prepend afterwards */
-		if (n->m_len > len) {
-			t = (n->m_len - len) & ~(sizeof(long) - 1);
-			n->m_data += t;
-			n->m_len = len;
-		}
-
-		len -= n->m_len;
-
-		if (m)
-			m_cat(m, n);
-		else
-			m = n;
-	}
-
-	return m;
-}
-
 /*
  * Take one of the kernel's security keys and convert it into a PF_KEY
  * structure within an mbuf, suitable for sending up to a waiting
@@ -8027,9 +7863,11 @@
 		return NULL;
 
 	len = PFKEY_ALIGN8(sizeof(struct sadb_key) + _KEYLEN(src));
-	m = key_alloc_mbuf(len);
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
 	if (m == NULL)
 		return NULL;
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_key *);
 	bzero(p, len);
 	p->sadb_key_len = PFKEY_UNIT64(len);
@@ -8064,9 +7902,11 @@
 	if (src == NULL)
 		return NULL;
 
-	m = key_alloc_mbuf(len);
+	m = m_get2(len, M_NOWAIT, MT_DATA, 0);
 	if (m == NULL)
 		return m;
+	m_align(m, len);
+	m->m_len = len;
 	p = mtod(m, struct sadb_lifetime *);
 
 	bzero(p, len);

Modified: trunk/sys/netipsec/key.h
===================================================================
--- trunk/sys/netipsec/key.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/key.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/key.h 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: key.h,v 1.21 2001/07/27 03:51:30 itojun Exp $	*/
 
 /*-
@@ -86,29 +87,27 @@
 #define	KEY_FREESAV(psav)					\
 	key_freesav(psav, __FILE__, __LINE__)
 
-extern void key_freeso __P((struct socket *));
-extern int key_checktunnelsanity __P((struct secasvar *, u_int,
-					caddr_t, caddr_t));
-extern int key_checkrequest
-	__P((struct ipsecrequest *isr, const struct secasindex *));
-
-extern struct secpolicy *key_msg2sp __P((struct sadb_x_policy *,
-	size_t, int *));
-extern struct mbuf *key_sp2msg __P((struct secpolicy *));
-extern int key_ismyaddr __P((struct sockaddr *));
-extern int key_spdacquire __P((struct secpolicy *));
-extern void key_timehandler __P((void));
-extern u_long key_random __P((void));
-extern void key_randomfill __P((void *, size_t));
-extern void key_freereg __P((struct socket *));
-extern int key_parse __P((struct mbuf *, struct socket *));
-extern void key_init __P((void));
+extern void key_freeso(struct socket *);
+extern int key_checktunnelsanity(struct secasvar *, u_int,
+    caddr_t, caddr_t);
+extern int key_checkrequest(struct ipsecrequest *isr,
+    const struct secasindex *);
+extern struct secpolicy *key_msg2sp(struct sadb_x_policy *,
+    size_t, int *);
+extern struct mbuf *key_sp2msg(struct secpolicy *);
+extern int key_ismyaddr(struct sockaddr *);
+extern int key_spdacquire(struct secpolicy *);
+extern void key_timehandler(void);
+extern u_long key_random(void);
+extern void key_randomfill(void *, size_t);
+extern void key_freereg(struct socket *);
+extern int key_parse(struct mbuf *, struct socket *);
+extern void key_init(void);
 #ifdef VIMAGE
 extern void key_destroy(void);
 #endif
-extern void key_sa_recordxfer __P((struct secasvar *, struct mbuf *));
-extern void key_sa_routechange __P((struct sockaddr *));
-extern void key_sa_stir_iv __P((struct secasvar *));
+extern void key_sa_recordxfer(struct secasvar *, struct mbuf *);
+extern void key_sa_stir_iv(struct secasvar *);
 #ifdef IPSEC_NAT_T
 u_int16_t key_portfromsaddr(struct sockaddr *);
 #define	KEY_PORTFROMSADDR(saddr)				\

Modified: trunk/sys/netipsec/key_debug.c
===================================================================
--- trunk/sys/netipsec/key_debug.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/key_debug.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/key_debug.c 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: key_debug.c,v 1.26 2001/06/27 10:46:50 sakane Exp $	*/
 
 /*-
@@ -45,7 +46,6 @@
 #endif
 #include <sys/socket.h>
 
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netipsec/key_var.h>
@@ -63,17 +63,17 @@
 #include <stdlib.h>
 #endif /* !_KERNEL */
 
-static void kdebug_sadb_prop __P((struct sadb_ext *));
-static void kdebug_sadb_identity __P((struct sadb_ext *));
-static void kdebug_sadb_supported __P((struct sadb_ext *));
-static void kdebug_sadb_lifetime __P((struct sadb_ext *));
-static void kdebug_sadb_sa __P((struct sadb_ext *));
-static void kdebug_sadb_address __P((struct sadb_ext *));
-static void kdebug_sadb_key __P((struct sadb_ext *));
-static void kdebug_sadb_x_sa2 __P((struct sadb_ext *));
+static void kdebug_sadb_prop(struct sadb_ext *);
+static void kdebug_sadb_identity(struct sadb_ext *);
+static void kdebug_sadb_supported(struct sadb_ext *);
+static void kdebug_sadb_lifetime(struct sadb_ext *);
+static void kdebug_sadb_sa(struct sadb_ext *);
+static void kdebug_sadb_address(struct sadb_ext *);
+static void kdebug_sadb_key(struct sadb_ext *);
+static void kdebug_sadb_x_sa2(struct sadb_ext *);
 
 #ifdef _KERNEL
-static void kdebug_secreplay __P((struct secreplay *));
+static void kdebug_secreplay(struct secreplay *);
 #endif
 
 #ifndef _KERNEL
@@ -84,8 +84,7 @@
 
 /* %%%: about struct sadb_msg */
 void
-kdebug_sadb(base)
-	struct sadb_msg *base;
+kdebug_sadb(struct sadb_msg *base)
 {
 	struct sadb_ext *ext;
 	int tlen, extlen;
@@ -173,8 +172,7 @@
 }
 
 static void
-kdebug_sadb_prop(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_prop(struct sadb_ext *ext)
 {
 	struct sadb_prop *prop = (struct sadb_prop *)ext;
 	struct sadb_comb *comb;
@@ -223,8 +221,7 @@
 }
 
 static void
-kdebug_sadb_identity(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_identity(struct sadb_ext *ext)
 {
 	struct sadb_ident *id = (struct sadb_ident *)ext;
 	int len;
@@ -266,8 +263,7 @@
 }
 
 static void
-kdebug_sadb_supported(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_supported(struct sadb_ext *ext)
 {
 	struct sadb_supported *sup = (struct sadb_supported *)ext;
 	struct sadb_alg *alg;
@@ -293,8 +289,7 @@
 }
 
 static void
-kdebug_sadb_lifetime(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_lifetime(struct sadb_ext *ext)
 {
 	struct sadb_lifetime *lft = (struct sadb_lifetime *)ext;
 
@@ -313,8 +308,7 @@
 }
 
 static void
-kdebug_sadb_sa(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_sa(struct sadb_ext *ext)
 {
 	struct sadb_sa *sa = (struct sadb_sa *)ext;
 
@@ -332,8 +326,7 @@
 }
 
 static void
-kdebug_sadb_address(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_address(struct sadb_ext *ext)
 {
 	struct sadb_address *addr = (struct sadb_address *)ext;
 
@@ -352,8 +345,7 @@
 }
 
 static void
-kdebug_sadb_key(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_key(struct sadb_ext *ext)
 {
 	struct sadb_key *key = (struct sadb_key *)ext;
 
@@ -381,8 +373,7 @@
 }
 
 static void
-kdebug_sadb_x_sa2(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_x_sa2(struct sadb_ext *ext)
 {
 	struct sadb_x_sa2 *sa2 = (struct sadb_x_sa2 *)ext;
 
@@ -400,8 +391,7 @@
 }
 
 void
-kdebug_sadb_x_policy(ext)
-	struct sadb_ext *ext;
+kdebug_sadb_x_policy(struct sadb_ext *ext)
 {
 	struct sadb_x_policy *xpl = (struct sadb_x_policy *)ext;
 	struct sockaddr *addr;
@@ -468,8 +458,7 @@
 #ifdef _KERNEL
 /* %%%: about SPD and SAD */
 void
-kdebug_secpolicy(sp)
-	struct secpolicy *sp;
+kdebug_secpolicy(struct secpolicy *sp)
 {
 	/* sanity check */
 	if (sp == NULL)
@@ -516,8 +505,7 @@
 }
 
 void
-kdebug_secpolicyindex(spidx)
-	struct secpolicyindex *spidx;
+kdebug_secpolicyindex(struct secpolicyindex *spidx)
 {
 	/* sanity check */
 	if (spidx == NULL)
@@ -537,8 +525,7 @@
 }
 
 void
-kdebug_secasindex(saidx)
-	struct secasindex *saidx;
+kdebug_secasindex(struct secasindex *saidx)
 {
 	/* sanity check */
 	if (saidx == NULL)
@@ -573,8 +560,7 @@
 }
 
 void
-kdebug_secasv(sav)
-	struct secasvar *sav;
+kdebug_secasv(struct secasvar *sav)
 {
 	/* sanity check */
 	if (sav == NULL)
@@ -615,8 +601,7 @@
 }
 
 static void
-kdebug_secreplay(rpl)
-	struct secreplay *rpl;
+kdebug_secreplay(struct secreplay *rpl)
 {
 	int len, l;
 
@@ -644,8 +629,7 @@
 }
 
 void
-kdebug_mbufhdr(m)
-	struct mbuf *m;
+kdebug_mbufhdr(struct mbuf *m)
 {
 	/* sanity check */
 	if (m == NULL)
@@ -672,8 +656,7 @@
 }
 
 void
-kdebug_mbuf(m0)
-	struct mbuf *m0;
+kdebug_mbuf(struct mbuf *m0)
 {
 	struct mbuf *m = m0;
 	int i, j;
@@ -697,8 +680,7 @@
 #endif /* _KERNEL */
 
 void
-kdebug_sockaddr(addr)
-	struct sockaddr *addr;
+kdebug_sockaddr(struct sockaddr *addr)
 {
 	struct sockaddr_in *sin4;
 #ifdef INET6
@@ -736,9 +718,7 @@
 }
 
 void
-ipsec_bindump(buf, len)
-	caddr_t buf;
-	int len;
+ipsec_bindump(caddr_t buf, int len)
 {
 	int i;
 
@@ -750,9 +730,7 @@
 
 
 void
-ipsec_hexdump(buf, len)
-	caddr_t buf;
-	int len;
+ipsec_hexdump(caddr_t buf, int len)
 {
 	int i;
 

Modified: trunk/sys/netipsec/key_debug.h
===================================================================
--- trunk/sys/netipsec/key_debug.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/key_debug.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/key_debug.h 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: key_debug.h,v 1.10 2001/08/05 08:37:52 itojun Exp $	*/
 
 /*-
@@ -62,8 +63,8 @@
 
 struct sadb_msg;
 struct sadb_ext;
-extern void kdebug_sadb __P((struct sadb_msg *));
-extern void kdebug_sadb_x_policy __P((struct sadb_ext *));
+extern void kdebug_sadb(struct sadb_msg *);
+extern void kdebug_sadb_x_policy(struct sadb_ext *);
 
 #ifdef _KERNEL
 struct secpolicy;
@@ -72,18 +73,18 @@
 struct secasvar;
 struct secreplay;
 struct mbuf;
-extern void kdebug_secpolicy __P((struct secpolicy *));
-extern void kdebug_secpolicyindex __P((struct secpolicyindex *));
-extern void kdebug_secasindex __P((struct secasindex *));
-extern void kdebug_secasv __P((struct secasvar *));
-extern void kdebug_mbufhdr __P((struct mbuf *));
-extern void kdebug_mbuf __P((struct mbuf *));
+extern void kdebug_secpolicy(struct secpolicy *);
+extern void kdebug_secpolicyindex(struct secpolicyindex *);
+extern void kdebug_secasindex(struct secasindex *);
+extern void kdebug_secasv(struct secasvar *);
+extern void kdebug_mbufhdr(struct mbuf *);
+extern void kdebug_mbuf(struct mbuf *);
 #endif /*_KERNEL*/
 
 struct sockaddr;
-extern void kdebug_sockaddr __P((struct sockaddr *));
+extern void kdebug_sockaddr(struct sockaddr *);
 
-extern void ipsec_hexdump __P((caddr_t, int));
-extern void ipsec_bindump __P((caddr_t, int));
+extern void ipsec_hexdump(caddr_t, int);
+extern void ipsec_bindump(caddr_t, int);
 
 #endif /* _NETIPSEC_KEY_DEBUG_H_ */

Modified: trunk/sys/netipsec/key_var.h
===================================================================
--- trunk/sys/netipsec/key_var.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/key_var.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/key_var.h 254925 2013-08-26 18:16:05Z jhb $	*/
 /*	$KAME: key_var.h,v 1.11 2001/09/12 23:05:07 sakane Exp $	*/
 
 /*-
@@ -48,22 +49,6 @@
 #define KEYCTL_PREFERED_OLDSA		12
 #define KEYCTL_MAXID			13
 
-#define KEYCTL_NAMES { \
-	{ 0, 0 }, \
-	{ "debug", CTLTYPE_INT }, \
-	{ "spi_try", CTLTYPE_INT }, \
-	{ "spi_min_value", CTLTYPE_INT }, \
-	{ "spi_max_value", CTLTYPE_INT }, \
-	{ "random_int", CTLTYPE_INT }, \
-	{ "larval_lifetime", CTLTYPE_INT }, \
-	{ "blockacq_count", CTLTYPE_INT }, \
-	{ "blockacq_lifetime", CTLTYPE_INT }, \
-	{ "esp_keymin", CTLTYPE_INT }, \
-	{ "esp_auth", CTLTYPE_INT }, \
-	{ "ah_keymin", CTLTYPE_INT }, \
-	{ "prefered_oldsa", CTLTYPE_INT }, \
-}
-
 #ifdef _KERNEL
 #define _ARRAYLEN(p) (sizeof(p)/sizeof(p[0]))
 #define _KEYLEN(key) ((u_int)((key)->bits >> 3))

Modified: trunk/sys/netipsec/keydb.h
===================================================================
--- trunk/sys/netipsec/keydb.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/keydb.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/keydb.h 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: keydb.h,v 1.14 2000/08/02 17:58:26 sakane Exp $	*/
 
 /*-
@@ -85,12 +86,6 @@
 	u_int64_t usetime;
 };
 
-union sa_route_union {
-	struct route		sa_route;
-	struct route		sin_route;	/* Duplicate for consistency. */
-	struct route_in6	sin6_route;
-};
-
 /* Security Association Data Base */
 struct secashead {
 	LIST_ENTRY(secashead) chain;
@@ -105,8 +100,6 @@
 	LIST_HEAD(_satree, secasvar) savtree[SADB_SASTATE_MAX+1];
 					/* SA chain */
 					/* The first of this list is newer SA */
-
-	union sa_route_union route_cache;
 };
 
 struct xformsw;
@@ -206,21 +199,21 @@
 #define SADB_KILL_INTERVAL	600	/* six seconds */
 
 /* secpolicy */
-extern struct secpolicy *keydb_newsecpolicy __P((void));
-extern void keydb_delsecpolicy __P((struct secpolicy *));
+extern struct secpolicy *keydb_newsecpolicy(void);
+extern void keydb_delsecpolicy(struct secpolicy *);
 /* secashead */
-extern struct secashead *keydb_newsecashead __P((void));
-extern void keydb_delsecashead __P((struct secashead *));
+extern struct secashead *keydb_newsecashead(void);
+extern void keydb_delsecashead(struct secashead *);
 /* secasvar */
-extern struct secasvar *keydb_newsecasvar __P((void));
-extern void keydb_refsecasvar __P((struct secasvar *));
-extern void keydb_freesecasvar __P((struct secasvar *));
+extern struct secasvar *keydb_newsecasvar(void);
+extern void keydb_refsecasvar(struct secasvar *);
+extern void keydb_freesecasvar(struct secasvar *);
 /* secreplay */
-extern struct secreplay *keydb_newsecreplay __P((size_t));
-extern void keydb_delsecreplay __P((struct secreplay *));
+extern struct secreplay *keydb_newsecreplay(size_t);
+extern void keydb_delsecreplay(struct secreplay *);
 /* secreg */
-extern struct secreg *keydb_newsecreg __P((void));
-extern void keydb_delsecreg __P((struct secreg *));
+extern struct secreg *keydb_newsecreg(void);
+extern void keydb_delsecreg(struct secreg *);
 
 #endif /* _KERNEL */
 

Modified: trunk/sys/netipsec/keysock.c
===================================================================
--- trunk/sys/netipsec/keysock.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/keysock.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/keysock.c 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $	*/
 
 /*-
@@ -53,7 +54,6 @@
 
 #include <net/if.h>
 #include <net/raw_cb.h>
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netinet/in.h>
@@ -75,10 +75,15 @@
 
 static struct sockaddr key_src = { 2, PF_KEY, };
 
-static int key_sendup0 __P((struct rawcb *, struct mbuf *, int));
+static int key_sendup0(struct rawcb *, struct mbuf *, int);
 
-VNET_DEFINE(struct pfkeystat, pfkeystat);
+VNET_PCPUSTAT_DEFINE(struct pfkeystat, pfkeystat);
+VNET_PCPUSTAT_SYSINIT(pfkeystat);
 
+#ifdef VIMAGE
+VNET_PCPUSTAT_SYSUNINIT(pfkeystat);
+#endif /* VIMAGE */
+
 /*
  * key_output()
  */
@@ -91,12 +96,12 @@
 	if (m == 0)
 		panic("%s: NULL pointer was passed.\n", __func__);
 
-	V_pfkeystat.out_total++;
-	V_pfkeystat.out_bytes += m->m_pkthdr.len;
+	PFKEYSTAT_INC(out_total);
+	PFKEYSTAT_ADD(out_bytes, m->m_pkthdr.len);
 
 	len = m->m_pkthdr.len;
 	if (len < sizeof(struct sadb_msg)) {
-		V_pfkeystat.out_tooshort++;
+		PFKEYSTAT_INC(out_tooshort);
 		error = EINVAL;
 		goto end;
 	}
@@ -103,7 +108,7 @@
 
 	if (m->m_len < sizeof(struct sadb_msg)) {
 		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
-			V_pfkeystat.out_nomem++;
+			PFKEYSTAT_INC(out_nomem);
 			error = ENOBUFS;
 			goto end;
 		}
@@ -114,9 +119,9 @@
 	KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
 
 	msg = mtod(m, struct sadb_msg *);
-	V_pfkeystat.out_msgtype[msg->sadb_msg_type]++;
+	PFKEYSTAT_INC(out_msgtype[msg->sadb_msg_type]);
 	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
-		V_pfkeystat.out_invlen++;
+		PFKEYSTAT_INC(out_invlen);
 		error = EINVAL;
 		goto end;
 	}
@@ -133,10 +138,7 @@
  * send message to the socket.
  */
 static int
-key_sendup0(rp, m, promisc)
-	struct rawcb *rp;
-	struct mbuf *m;
-	int promisc;
+key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc)
 {
 	int error;
 
@@ -143,16 +145,11 @@
 	if (promisc) {
 		struct sadb_msg *pmsg;
 
-		M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
-		if (m && m->m_len < sizeof(struct sadb_msg))
-			m = m_pullup(m, sizeof(struct sadb_msg));
-		if (!m) {
-			V_pfkeystat.in_nomem++;
-			m_freem(m);
-			return ENOBUFS;
+		M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT);
+		if (m == NULL) {
+			PFKEYSTAT_INC(in_nomem);
+			return (ENOBUFS);
 		}
-		m->m_pkthdr.len += sizeof(*pmsg);
-
 		pmsg = mtod(m, struct sadb_msg *);
 		bzero(pmsg, sizeof(*pmsg));
 		pmsg->sadb_msg_version = PF_KEY_V2;
@@ -160,12 +157,12 @@
 		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
 		/* pid and seq? */
 
-		V_pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
+		PFKEYSTAT_INC(in_msgtype[pmsg->sadb_msg_type]);
 	}
 
 	if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
 	    m, NULL)) {
-		V_pfkeystat.in_nomem++;
+		PFKEYSTAT_INC(in_nomem);
 		m_freem(m);
 		error = ENOBUFS;
 	} else
@@ -176,11 +173,7 @@
 
 /* XXX this interface should be obsoleted. */
 int
-key_sendup(so, msg, len, target)
-	struct socket *so;
-	struct sadb_msg *msg;
-	u_int len;
-	int target;	/*target of the resulting message*/
+key_sendup(struct socket *so, struct sadb_msg *msg, u_int len, int target)
 {
 	struct mbuf *m, *n, *mprev;
 	int tlen;
@@ -197,9 +190,9 @@
 	 * we increment statistics here, just in case we have ENOBUFS
 	 * in this function.
 	 */
-	V_pfkeystat.in_total++;
-	V_pfkeystat.in_bytes += len;
-	V_pfkeystat.in_msgtype[msg->sadb_msg_type]++;
+	PFKEYSTAT_INC(in_total);
+	PFKEYSTAT_ADD(in_bytes, len);
+	PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
 
 	/*
 	 * Get mbuf chain whenever possible (not clusters),
@@ -214,26 +207,26 @@
 	m = mprev = NULL;
 	while (tlen > 0) {
 		if (tlen == len) {
-			MGETHDR(n, M_DONTWAIT, MT_DATA);
+			MGETHDR(n, M_NOWAIT, MT_DATA);
 			if (n == NULL) {
-				V_pfkeystat.in_nomem++;
+				PFKEYSTAT_INC(in_nomem);
 				return ENOBUFS;
 			}
 			n->m_len = MHLEN;
 		} else {
-			MGET(n, M_DONTWAIT, MT_DATA);
+			MGET(n, M_NOWAIT, MT_DATA);
 			if (n == NULL) {
-				V_pfkeystat.in_nomem++;
+				PFKEYSTAT_INC(in_nomem);
 				return ENOBUFS;
 			}
 			n->m_len = MLEN;
 		}
 		if (tlen >= MCLBYTES) {	/*XXX better threshold? */
-			MCLGET(n, M_DONTWAIT);
+			MCLGET(n, M_NOWAIT);
 			if ((n->m_flags & M_EXT) == 0) {
 				m_free(n);
 				m_freem(m);
-				V_pfkeystat.in_nomem++;
+				PFKEYSTAT_INC(in_nomem);
 				return ENOBUFS;
 			}
 			n->m_len = MCLBYTES;
@@ -256,9 +249,9 @@
 	m_copyback(m, 0, len, (caddr_t)msg);
 
 	/* avoid duplicated statistics */
-	V_pfkeystat.in_total--;
-	V_pfkeystat.in_bytes -= len;
-	V_pfkeystat.in_msgtype[msg->sadb_msg_type]--;
+	PFKEYSTAT_ADD(in_total, -1);
+	PFKEYSTAT_ADD(in_bytes, -len);
+	PFKEYSTAT_ADD(in_msgtype[msg->sadb_msg_type], -1);
 
 	return key_sendup_mbuf(so, m, target);
 }
@@ -265,10 +258,7 @@
 
 /* so can be NULL if target != KEY_SENDUP_ONE */
 int
-key_sendup_mbuf(so, m, target)
-	struct socket *so;
-	struct mbuf *m;
-	int target;
+key_sendup_mbuf(struct socket *so, struct mbuf *m, int target)
 {
 	struct mbuf *n;
 	struct keycb *kp;
@@ -281,12 +271,12 @@
 	if (so == NULL && target == KEY_SENDUP_ONE)
 		panic("%s: NULL pointer was passed.\n", __func__);
 
-	V_pfkeystat.in_total++;
-	V_pfkeystat.in_bytes += m->m_pkthdr.len;
+	PFKEYSTAT_INC(in_total);
+	PFKEYSTAT_ADD(in_bytes, m->m_pkthdr.len);
 	if (m->m_len < sizeof(struct sadb_msg)) {
 		m = m_pullup(m, sizeof(struct sadb_msg));
 		if (m == NULL) {
-			V_pfkeystat.in_nomem++;
+			PFKEYSTAT_INC(in_nomem);
 			return ENOBUFS;
 		}
 	}
@@ -293,7 +283,7 @@
 	if (m->m_len >= sizeof(struct sadb_msg)) {
 		struct sadb_msg *msg;
 		msg = mtod(m, struct sadb_msg *);
-		V_pfkeystat.in_msgtype[msg->sadb_msg_type]++;
+		PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
 	}
 	mtx_lock(&rawcb_mtx);
 	LIST_FOREACH(rp, &V_rawcb_list, list)
@@ -338,7 +328,7 @@
 				sendup++;
 			break;
 		}
-		V_pfkeystat.in_msgtarget[target]++;
+		PFKEYSTAT_INC(in_msgtarget[target]);
 
 		if (!sendup)
 			continue;
@@ -345,7 +335,7 @@
 
 		if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
 			m_freem(m);
-			V_pfkeystat.in_nomem++;
+			PFKEYSTAT_INC(in_nomem);
 			mtx_unlock(&rawcb_mtx);
 			return ENOBUFS;
 		}

Modified: trunk/sys/netipsec/keysock.h
===================================================================
--- trunk/sys/netipsec/keysock.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/keysock.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/keysock.h 283902 2015-06-02 03:43:36Z ae $	*/
 /*	$KAME: keysock.h,v 1.8 2000/03/27 05:11:06 sumikawa Exp $	*/
 
 /*-
@@ -36,26 +37,26 @@
 /* statistics for pfkey socket */
 struct pfkeystat {
 	/* kernel -> userland */
-	u_quad_t out_total;		/* # of total calls */
-	u_quad_t out_bytes;		/* total bytecount */
-	u_quad_t out_msgtype[256];	/* message type histogram */
-	u_quad_t out_invlen;		/* invalid length field */
-	u_quad_t out_invver;		/* invalid version field */
-	u_quad_t out_invmsgtype;	/* invalid message type field */
-	u_quad_t out_tooshort;		/* msg too short */
-	u_quad_t out_nomem;		/* memory allocation failure */
-	u_quad_t out_dupext;		/* duplicate extension */
-	u_quad_t out_invexttype;	/* invalid extension type */
-	u_quad_t out_invsatype;		/* invalid sa type */
-	u_quad_t out_invaddr;		/* invalid address extension */
+	uint64_t out_total;		/* # of total calls */
+	uint64_t out_bytes;		/* total bytecount */
+	uint64_t out_msgtype[256];	/* message type histogram */
+	uint64_t out_invlen;		/* invalid length field */
+	uint64_t out_invver;		/* invalid version field */
+	uint64_t out_invmsgtype;	/* invalid message type field */
+	uint64_t out_tooshort;		/* msg too short */
+	uint64_t out_nomem;		/* memory allocation failure */
+	uint64_t out_dupext;		/* duplicate extension */
+	uint64_t out_invexttype;	/* invalid extension type */
+	uint64_t out_invsatype;		/* invalid sa type */
+	uint64_t out_invaddr;		/* invalid address extension */
 	/* userland -> kernel */
-	u_quad_t in_total;		/* # of total calls */
-	u_quad_t in_bytes;		/* total bytecount */
-	u_quad_t in_msgtype[256];	/* message type histogram */
-	u_quad_t in_msgtarget[3];	/* one/all/registered */
-	u_quad_t in_nomem;		/* memory allocation failure */
+	uint64_t in_total;		/* # of total calls */
+	uint64_t in_bytes;		/* total bytecount */
+	uint64_t in_msgtype[256];	/* message type histogram */
+	uint64_t in_msgtarget[3];	/* one/all/registered */
+	uint64_t in_nomem;		/* memory allocation failure */
 	/* others */
-	u_quad_t sockerr;		/* # of socket related errors */
+	uint64_t sockerr;		/* # of socket related errors */
 };
 
 #define KEY_SENDUP_ONE		0
@@ -63,6 +64,8 @@
 #define KEY_SENDUP_REGISTERED	2
 
 #ifdef _KERNEL
+#include <sys/counter.h>
+
 struct keycb {
 	struct rawcb kp_raw;	/* rawcb */
 	int kp_promisc;		/* promiscuous mode */
@@ -69,15 +72,17 @@
 	int kp_registered;	/* registered socket */
 };
 
-VNET_DECLARE(struct pfkeystat, pfkeystat);
-#define	V_pfkeystat		VNET(pfkeystat)
+VNET_PCPUSTAT_DECLARE(struct pfkeystat, pfkeystat);
+#define	PFKEYSTAT_ADD(name, val)	\
+    VNET_PCPUSTAT_ADD(struct pfkeystat, pfkeystat, name, (val))
+#define	PFKEYSTAT_INC(name)		PFKEYSTAT_ADD(name, 1)
 
 extern int key_output(struct mbuf *m, struct socket *so);
-extern int key_usrreq __P((struct socket *,
-	int, struct mbuf *, struct mbuf *, struct mbuf *));
+extern int key_usrreq(struct socket *, int, struct mbuf *,
+    struct mbuf *, struct mbuf *);
 
-extern int key_sendup __P((struct socket *, struct sadb_msg *, u_int, int));
-extern int key_sendup_mbuf __P((struct socket *, struct mbuf *, int));
+extern int key_sendup(struct socket *, struct sadb_msg *, u_int, int);
+extern int key_sendup_mbuf(struct socket *, struct mbuf *, int);
 #endif /* _KERNEL */
 
 #endif /*_NETIPSEC_KEYSOCK_H_*/

Modified: trunk/sys/netipsec/xform.h
===================================================================
--- trunk/sys/netipsec/xform.h	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/xform.h	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/xform.h 220206 2011-03-31 15:23:32Z fabient $	*/
 /*	$OpenBSD: ip_ipsp.h,v 1.119 2002/03/14 01:27:11 millert Exp $	*/
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),

Modified: trunk/sys/netipsec/xform_ah.c
===================================================================
--- trunk/sys/netipsec/xform_ah.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/xform_ah.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/xform_ah.c 330609 2018-03-07 16:55:15Z gordon $	*/
 /*	$OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),
@@ -56,7 +57,6 @@
 #include <netinet/ip_ecn.h>
 #include <netinet/ip6.h>
 
-#include <net/route.h>
 #include <netipsec/ipsec.h>
 #include <netipsec/ah.h>
 #include <netipsec/ah_var.h>
@@ -89,8 +89,13 @@
 
 VNET_DEFINE(int, ah_enable) = 1;	/* control flow of packets with AH */
 VNET_DEFINE(int, ah_cleartos) = 1;	/* clear ip_tos when doing AH calc */
-VNET_DEFINE(struct ahstat, ahstat);
+VNET_PCPUSTAT_DEFINE(struct ahstat, ahstat);
+VNET_PCPUSTAT_SYSINIT(ahstat);
 
+#ifdef VIMAGE
+VNET_PCPUSTAT_SYSUNINIT(ahstat);
+#endif /* VIMAGE */
+
 #ifdef INET
 SYSCTL_DECL(_net_inet_ah);
 SYSCTL_VNET_INT(_net_inet_ah, OID_AUTO,
@@ -97,8 +102,8 @@
 	ah_enable,	CTLFLAG_RW,	&VNET_NAME(ah_enable),	0, "");
 SYSCTL_VNET_INT(_net_inet_ah, OID_AUTO,
 	ah_cleartos,	CTLFLAG_RW,	&VNET_NAME(ah_cleartos), 0, "");
-SYSCTL_VNET_STRUCT(_net_inet_ah, IPSECCTL_STATS,
-	stats,		CTLFLAG_RD,	&VNET_NAME(ahstat), ahstat, "");
+SYSCTL_VNET_PCPUSTAT(_net_inet_ah, IPSECCTL_STATS, stats, struct ahstat,
+    ahstat, "AH statistics (struct ahstat, netipsec/ah_var.h)");
 #endif
 
 static unsigned char ipseczeroes[256];	/* larger than an ip6 extension hdr */
@@ -305,24 +310,11 @@
 		ip->ip_ttl = 0;
 		ip->ip_sum = 0;
 
-		/*
-		 * On input, fix ip_len which has been byte-swapped
-		 * at ip_input().
-		 */
-		if (!out) {
-			ip->ip_len = htons(ip->ip_len + skip);
+		if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK)
+			ip->ip_off &= htons(IP_DF);
+		else
+			ip->ip_off = htons(0);
 
-			if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK)
-				ip->ip_off = htons(ip->ip_off & IP_DF);
-			else
-				ip->ip_off = 0;
-		} else {
-			if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK)
-				ip->ip_off = htons(ntohs(ip->ip_off) & IP_DF);
-			else
-				ip->ip_off = 0;
-		}
-
 		ptr = mtod(m, unsigned char *);
 
 		/* IPv4 option processing */
@@ -580,7 +572,7 @@
 	IP6_EXTHDR_GET(ah, struct newah *, m, skip, rplen);
 	if (ah == NULL) {
 		DPRINTF(("ah_input: cannot pullup header\n"));
-		V_ahstat.ahs_hdrops++;		/*XXX*/
+		AHSTAT_INC(ahs_hdrops);		/*XXX*/
 		m_freem(m);
 		return ENOBUFS;
 	}
@@ -587,7 +579,7 @@
 
 	/* Check replay window, if applicable. */
 	if (sav->replay && !ipsec_chkreplay(ntohl(ah->ah_seq), sav)) {
-		V_ahstat.ahs_replay++;
+		AHSTAT_INC(ahs_replay);
 		DPRINTF(("%s: packet replay failure: %s\n", __func__,
 			  ipsec_logsastr(sav)));
 		m_freem(m);
@@ -604,17 +596,27 @@
 			hl, (u_long) (authsize + rplen - sizeof (struct ah)),
 			ipsec_address(&sav->sah->saidx.dst),
 			(u_long) ntohl(sav->spi)));
-		V_ahstat.ahs_badauthl++;
+		AHSTAT_INC(ahs_badauthl);
 		m_freem(m);
 		return EACCES;
 	}
-	V_ahstat.ahs_ibytes += m->m_pkthdr.len - skip - hl;
+	if (skip + authsize + rplen > m->m_pkthdr.len) {
+		DPRINTF(("%s: bad mbuf length %u (expecting %lu)"
+		    " for packet in SA %s/%08lx\n", __func__,
+		    m->m_pkthdr.len, (u_long) (skip + authsize + rplen),
+		    ipsec_address(&sav->sah->saidx.dst),
+		    (u_long) ntohl(sav->spi)));
+		AHSTAT_INC(ahs_badauthl);
+		m_freem(m);
+		return EACCES;
+	}
+	AHSTAT_ADD(ahs_ibytes, m->m_pkthdr.len - skip - hl);
 
 	/* Get crypto descriptors. */
 	crp = crypto_getreq(1);
 	if (crp == NULL) {
 		DPRINTF(("%s: failed to acquire crypto descriptor\n",__func__));
-		V_ahstat.ahs_crypto++;
+		AHSTAT_INC(ahs_crypto);
 		m_freem(m);
 		return ENOBUFS;
 	}
@@ -654,7 +656,7 @@
 	}
 	if (tc == NULL) {
 		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
-		V_ahstat.ahs_crypto++;
+		AHSTAT_INC(ahs_crypto);
 		crypto_freereq(crp);
 		m_freem(m);
 		return ENOBUFS;
@@ -673,12 +675,15 @@
 		/* Zeroize the authenticator on the packet. */
 		m_copyback(m, skip + rplen, authsize, ipseczeroes);
 
+		/* Save ah_nxt, since ah pointer can become invalid after "massage" */
+		hl = ah->ah_nxt;
+
 		/* "Massage" the packet headers for crypto processing. */
 		error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family,
 		    skip, ahx->type, 0);
 		if (error != 0) {
 			/* NB: mbuf is free'd by ah_massage_headers */
-			V_ahstat.ahs_hdrops++;
+			AHSTAT_INC(ahs_hdrops);
 			free(tc, M_XDATA);
 			crypto_freereq(crp);
 			return error;
@@ -697,7 +702,7 @@
 	tc->tc_spi = sav->spi;
 	tc->tc_dst = sav->sah->saidx.dst;
 	tc->tc_proto = sav->sah->saidx.proto;
-	tc->tc_nxt = ah->ah_nxt;
+	tc->tc_nxt = hl;
 	tc->tc_protoff = protoff;
 	tc->tc_skip = skip;
 	tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified. */
@@ -754,17 +759,15 @@
 		if (sav->tdb_cryptoid != 0)
 			sav->tdb_cryptoid = crp->crp_sid;
 
-		if (crp->crp_etype == EAGAIN) {
-			error = crypto_dispatch(crp);
-			return error;
-		}
+		if (crp->crp_etype == EAGAIN)
+			return (crypto_dispatch(crp));
 
-		V_ahstat.ahs_noxform++;
+		AHSTAT_INC(ahs_noxform);
 		DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
 		error = crp->crp_etype;
 		goto bad;
 	} else {
-		V_ahstat.ahs_hist[sav->alg_auth]++;
+		AHSTAT_INC(ahs_hist[sav->alg_auth]);
 		crypto_freereq(crp);		/* No longer needed. */
 		crp = NULL;
 	}
@@ -771,7 +774,7 @@
 
 	/* Shouldn't happen... */
 	if (m == NULL) {
-		V_ahstat.ahs_crypto++;
+		AHSTAT_INC(ahs_crypto);
 		DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
 		error = EINVAL;
 		goto bad;
@@ -797,7 +800,7 @@
 			    "in SA %s/%08lx\n", __func__,
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
-			V_ahstat.ahs_badauth++;
+			AHSTAT_INC(ahs_badauth);
 			error = EACCES;
 			goto bad;
 		}
@@ -828,7 +831,7 @@
 		m_copydata(m, skip + offsetof(struct newah, ah_seq),
 			   sizeof (seq), (caddr_t) &seq);
 		if (ipsec_updatereplay(ntohl(seq), sav)) {
-			V_ahstat.ahs_replay++;
+			AHSTAT_INC(ahs_replay);
 			error = ENOBUFS;			/*XXX as above*/
 			goto bad;
 		}
@@ -842,7 +845,7 @@
 		DPRINTF(("%s: mangled mbuf chain for SA %s/%08lx\n", __func__,
 		    ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi)));
 
-		V_ahstat.ahs_hdrops++;
+		AHSTAT_INC(ahs_hdrops);
 		goto bad;
 	}
 
@@ -903,7 +906,7 @@
 	ahx = sav->tdb_authalgxform;
 	IPSEC_ASSERT(ahx != NULL, ("null authentication xform"));
 
-	V_ahstat.ahs_output++;
+	AHSTAT_INC(ahs_output);
 
 	/* Figure out header size. */
 	rplen = HDRSIZE(sav);
@@ -926,7 +929,7 @@
 		    sav->sah->saidx.dst.sa.sa_family,
 		    ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi)));
-		V_ahstat.ahs_nopf++;
+		AHSTAT_INC(ahs_nopf);
 		error = EPFNOSUPPORT;
 		goto bad;
 	}
@@ -937,13 +940,13 @@
 		    ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi),
 		    rplen + authsize + m->m_pkthdr.len, maxpacketsize));
-		V_ahstat.ahs_toobig++;
+		AHSTAT_INC(ahs_toobig);
 		error = EMSGSIZE;
 		goto bad;
 	}
 
 	/* Update the counters. */
-	V_ahstat.ahs_obytes += m->m_pkthdr.len - skip;
+	AHSTAT_ADD(ahs_obytes, m->m_pkthdr.len - skip);
 
 	m = m_unshare(m, M_NOWAIT);
 	if (m == NULL) {
@@ -950,7 +953,7 @@
 		DPRINTF(("%s: cannot clone mbuf chain, SA %s/%08lx\n", __func__,
 		    ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi)));
-		V_ahstat.ahs_hdrops++;
+		AHSTAT_INC(ahs_hdrops);
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -963,7 +966,7 @@
 		    rplen + authsize,
 		    ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi)));
-		V_ahstat.ahs_hdrops++;		/*XXX differs from openbsd */
+		AHSTAT_INC(ahs_hdrops);		/*XXX differs from openbsd */
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -991,7 +994,7 @@
 				__func__,
 				ipsec_address(&sav->sah->saidx.dst),
 				(u_long) ntohl(sav->spi)));
-			V_ahstat.ahs_wrap++;
+			AHSTAT_INC(ahs_wrap);
 			error = EINVAL;
 			goto bad;
 		}
@@ -1008,7 +1011,7 @@
 	if (crp == NULL) {
 		DPRINTF(("%s: failed to acquire crypto descriptors\n",
 			__func__));
-		V_ahstat.ahs_crypto++;
+		AHSTAT_INC(ahs_crypto);
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -1030,7 +1033,7 @@
 	if (tc == NULL) {
 		crypto_freereq(crp);
 		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
-		V_ahstat.ahs_crypto++;
+		AHSTAT_INC(ahs_crypto);
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -1121,7 +1124,6 @@
 	struct secasvar *sav;
 	struct mbuf *m;
 	caddr_t ptr;
-	int err;
 
 	tc = (struct tdb_crypto *) crp->crp_opaque;
 	IPSEC_ASSERT(tc != NULL, ("null opaque data area!"));
@@ -1135,7 +1137,7 @@
 	sav = tc->tc_sav;
 	/* With the isr lock released SA pointer can be updated. */
 	if (sav != isr->sav) {
-		V_ahstat.ahs_notdb++;
+		AHSTAT_INC(ahs_notdb);
 		DPRINTF(("%s: SA expired while in crypto\n", __func__));
 		error = ENOBUFS;		/*XXX*/
 		goto bad;
@@ -1148,11 +1150,10 @@
 
 		if (crp->crp_etype == EAGAIN) {
 			IPSECREQUEST_UNLOCK(isr);
-			error = crypto_dispatch(crp);
-			return error;
+			return (crypto_dispatch(crp));
 		}
 
-		V_ahstat.ahs_noxform++;
+		AHSTAT_INC(ahs_noxform);
 		DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
 		error = crp->crp_etype;
 		goto bad;
@@ -1160,12 +1161,12 @@
 
 	/* Shouldn't happen... */
 	if (m == NULL) {
-		V_ahstat.ahs_crypto++;
+		AHSTAT_INC(ahs_crypto);
 		DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
 		error = EINVAL;
 		goto bad;
 	}
-	V_ahstat.ahs_hist[sav->alg_auth]++;
+	AHSTAT_INC(ahs_hist[sav->alg_auth]);
 
 	/*
 	 * Copy original headers (with the new protocol number) back
@@ -1192,10 +1193,10 @@
 #endif
 
 	/* NB: m is reclaimed by ipsec_process_done. */
-	err = ipsec_process_done(m, isr);
+	error = ipsec_process_done(m, isr);
 	KEY_FREESAV(&sav);
 	IPSECREQUEST_UNLOCK(isr);
-	return err;
+	return error;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);

Modified: trunk/sys/netipsec/xform_esp.c
===================================================================
--- trunk/sys/netipsec/xform_esp.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/xform_esp.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/xform_esp.c 283901 2015-06-02 03:14:42Z ae $	*/
 /*	$OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),
@@ -56,7 +57,6 @@
 #include <netinet/ip_ecn.h>
 #include <netinet/ip6.h>
 
-#include <net/route.h>
 #include <netipsec/ipsec.h>
 #include <netipsec/ah.h>
 #include <netipsec/ah_var.h>
@@ -77,17 +77,20 @@
 #include <opencrypto/xform.h>
 
 VNET_DEFINE(int, esp_enable) = 1;
-VNET_DEFINE(struct espstat, espstat);
+VNET_PCPUSTAT_DEFINE(struct espstat, espstat);
+VNET_PCPUSTAT_SYSINIT(espstat);
 
+#ifdef VIMAGE
+VNET_PCPUSTAT_SYSUNINIT(espstat);
+#endif /* VIMAGE */
+
 SYSCTL_DECL(_net_inet_esp);
 SYSCTL_VNET_INT(_net_inet_esp, OID_AUTO,
 	esp_enable,	CTLFLAG_RW,	&VNET_NAME(esp_enable),	0, "");
-SYSCTL_VNET_STRUCT(_net_inet_esp, IPSECCTL_STATS,
-	stats,		CTLFLAG_RD,	&VNET_NAME(espstat),	espstat, "");
+SYSCTL_VNET_PCPUSTAT(_net_inet_esp, IPSECCTL_STATS, stats,
+    struct espstat, espstat,
+    "ESP statistics (struct espstat, netipsec/esp_var.h");
 
-static VNET_DEFINE(int, esp_max_ivlen);	/* max iv length over all algorithms */
-#define	V_esp_max_ivlen	VNET(esp_max_ivlen)
-
 static int esp_input_cb(struct cryptop *op);
 static int esp_output_cb(struct cryptop *crp);
 
@@ -147,7 +150,7 @@
 		 * + sizeof (next header field)
 		 * + max icv supported.
 		 */
-		size = sizeof (struct newesp) + V_esp_max_ivlen + 9 + 16;
+		size = sizeof (struct newesp) + EALG_MAX_BLOCK_LEN + 9 + 16;
 	}
 	return size;
 }
@@ -196,10 +199,6 @@
 	 */
 	sav->ivlen = (txform == &enc_xform_null ? 0 : txform->blocksize);
 	sav->iv = (caddr_t) malloc(sav->ivlen, M_XDATA, M_WAITOK);
-	if (sav->iv == NULL) {
-		DPRINTF(("%s: no memory for IV\n", __func__));
-		return EINVAL;
-	}
 	key_randomfill(sav->iv, sav->ivlen);	/*XXX*/
 
 	/*
@@ -286,7 +285,7 @@
 	if ( (skip&3) || (m->m_pkthdr.len&3) ){
 		DPRINTF(("%s: misaligned packet, skip %u pkt len %u",
 				__func__, skip, m->m_pkthdr.len));
-		V_espstat.esps_badilen++;
+		ESPSTAT_INC(esps_badilen);
 		m_freem(m);
 		return EINVAL;
 	}
@@ -332,7 +331,7 @@
 		    plen, espx->blocksize,
 		    ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi)));
-		V_espstat.esps_badilen++;
+		ESPSTAT_INC(esps_badilen);
 		m_freem(m);
 		return EINVAL;
 	}
@@ -343,13 +342,13 @@
 	if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) {
 		DPRINTF(("%s: packet replay check for %s\n", __func__,
 		    ipsec_logsastr(sav)));	/*XXX*/
-		V_espstat.esps_replay++;
+		ESPSTAT_INC(esps_replay);
 		m_freem(m);
 		return ENOBUFS;		/*XXX*/
 	}
 
 	/* Update the counters */
-	V_espstat.esps_ibytes += m->m_pkthdr.len - (skip + hlen + alen);
+	ESPSTAT_ADD(esps_ibytes, m->m_pkthdr.len - (skip + hlen + alen));
 
 	/* Find out if we've already done crypto */
 	for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
@@ -368,7 +367,7 @@
 	if (crp == NULL) {
 		DPRINTF(("%s: failed to acquire crypto descriptors\n",
 			__func__));
-		V_espstat.esps_crypto++;
+		ESPSTAT_INC(esps_crypto);
 		m_freem(m);
 		return ENOBUFS;
 	}
@@ -383,7 +382,7 @@
 	if (tc == NULL) {
 		crypto_freereq(crp);
 		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
-		V_espstat.esps_crypto++;
+		ESPSTAT_INC(esps_crypto);
 		m_freem(m);
 		return ENOBUFS;
 	}
@@ -496,12 +495,10 @@
 		if (sav->tdb_cryptoid != 0)
 			sav->tdb_cryptoid = crp->crp_sid;
 
-		if (crp->crp_etype == EAGAIN) {
-			error = crypto_dispatch(crp);
-			return error;
-		}
+		if (crp->crp_etype == EAGAIN)
+			return (crypto_dispatch(crp));
 
-		V_espstat.esps_noxform++;
+		ESPSTAT_INC(esps_noxform);
 		DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
 		error = crp->crp_etype;
 		goto bad;
@@ -509,12 +506,12 @@
 
 	/* Shouldn't happen... */
 	if (m == NULL) {
-		V_espstat.esps_crypto++;
+		ESPSTAT_INC(esps_crypto);
 		DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
 		error = EINVAL;
 		goto bad;
 	}
-	V_espstat.esps_hist[sav->alg_enc]++;
+	ESPSTAT_INC(esps_hist[sav->alg_enc]);
 
 	/* If authentication was performed, check now. */
 	if (esph != NULL) {
@@ -533,7 +530,7 @@
 		 * the verification for us.  Otherwise we need to
 		 * check the authentication calculation.
 		 */
-		V_ahstat.ahs_hist[sav->alg_auth]++;
+		AHSTAT_INC(ahs_hist[sav->alg_auth]);
 		if (mtag == NULL) {
 			/* Copy the authenticator from the packet */
 			m_copydata(m, m->m_pkthdr.len - alen,
@@ -548,7 +545,7 @@
 				    __func__,
 				    ipsec_address(&saidx->dst),
 				    (u_long) ntohl(sav->spi)));
-				V_espstat.esps_badauth++;
+				ESPSTAT_INC(esps_badauth);
 				error = EACCES;
 				goto bad;
 			}
@@ -578,7 +575,7 @@
 		if (ipsec_updatereplay(ntohl(seq), sav)) {
 			DPRINTF(("%s: packet replay check for %s\n", __func__,
 			    ipsec_logsastr(sav)));
-			V_espstat.esps_replay++;
+			ESPSTAT_INC(esps_replay);
 			error = ENOBUFS;
 			goto bad;
 		}
@@ -593,7 +590,7 @@
 	/* Remove the ESP header and IV from the mbuf. */
 	error = m_striphdr(m, skip, hlen);
 	if (error) {
-		V_espstat.esps_hdrops++;
+		ESPSTAT_INC(esps_hdrops);
 		DPRINTF(("%s: bad mbuf chain, SA %s/%08lx\n", __func__,
 		    ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi)));
@@ -605,7 +602,7 @@
 
 	/* Verify pad length */
 	if (lastthree[1] + 2 > m->m_pkthdr.len - skip) {
-		V_espstat.esps_badilen++;
+		ESPSTAT_INC(esps_badilen);
 		DPRINTF(("%s: invalid padding length %d for %u byte packet "
 			"in SA %s/%08lx\n", __func__,
 			 lastthree[1], m->m_pkthdr.len - skip,
@@ -618,7 +615,7 @@
 	/* Verify correct decryption by checking the last padding bytes */
 	if ((sav->flags & SADB_X_EXT_PMASK) != SADB_X_EXT_PRAND) {
 		if (lastthree[1] != lastthree[0] && lastthree[1] != 0) {
-			V_espstat.esps_badenc++;
+			ESPSTAT_INC(esps_badenc);
 			DPRINTF(("%s: decryption failed for packet in "
 				"SA %s/%08lx\n", __func__,
 				ipsec_address(&sav->sah->saidx.dst),
@@ -678,7 +675,7 @@
 {
 	struct enc_xform *espx;
 	struct auth_hash *esph;
-	int hlen, rlen, plen, padding, blks, alen, i, roff;
+	int hlen, rlen, padding, blks, alen, i, roff;
 	struct mbuf *mo = (struct mbuf *) NULL;
 	struct tdb_crypto *tc;
 	struct secasvar *sav;
@@ -710,7 +707,6 @@
 
 	/* XXX clamp padding length a la KAME??? */
 	padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
-	plen = rlen + padding;		/* Padded payload length. */
 
 	if (esph)
 		switch (esph->type) {
@@ -726,7 +722,7 @@
 	else
 		alen = 0;
 
-	V_espstat.esps_output++;
+	ESPSTAT_INC(esps_output);
 
 	saidx = &sav->sah->saidx;
 	/* Check for maximum packet size violations. */
@@ -746,7 +742,7 @@
 		    "family %d, SA %s/%08lx\n", __func__,
 		    saidx->dst.sa.sa_family, ipsec_address(&saidx->dst),
 		    (u_long) ntohl(sav->spi)));
-		V_espstat.esps_nopf++;
+		ESPSTAT_INC(esps_nopf);
 		error = EPFNOSUPPORT;
 		goto bad;
 	}
@@ -755,19 +751,19 @@
 		    "(len %u, max len %u)\n", __func__,
 		    ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi),
 		    skip + hlen + rlen + padding + alen, maxpacketsize));
-		V_espstat.esps_toobig++;
+		ESPSTAT_INC(esps_toobig);
 		error = EMSGSIZE;
 		goto bad;
 	}
 
 	/* Update the counters. */
-	V_espstat.esps_obytes += m->m_pkthdr.len - skip;
+	ESPSTAT_ADD(esps_obytes, m->m_pkthdr.len - skip);
 
 	m = m_unshare(m, M_NOWAIT);
 	if (m == NULL) {
 		DPRINTF(("%s: cannot clone mbuf chain, SA %s/%08lx\n", __func__,
 		    ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi)));
-		V_espstat.esps_hdrops++;
+		ESPSTAT_INC(esps_hdrops);
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -778,7 +774,7 @@
 		DPRINTF(("%s: %u byte ESP hdr inject failed for SA %s/%08lx\n",
 		    __func__, hlen, ipsec_address(&saidx->dst),
 		    (u_long) ntohl(sav->spi)));
-		V_espstat.esps_hdrops++;		/* XXX diffs from openbsd */
+		ESPSTAT_INC(esps_hdrops);		/* XXX diffs from openbsd */
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -842,7 +838,7 @@
 	if (crp == NULL) {
 		DPRINTF(("%s: failed to acquire crypto descriptors\n",
 			__func__));
-		V_espstat.esps_crypto++;
+		ESPSTAT_INC(esps_crypto);
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -871,7 +867,7 @@
 	if (tc == NULL) {
 		crypto_freereq(crp);
 		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
-		V_espstat.esps_crypto++;
+		ESPSTAT_INC(esps_crypto);
 		error = ENOBUFS;
 		goto bad;
 	}
@@ -921,7 +917,7 @@
 	struct ipsecrequest *isr;
 	struct secasvar *sav;
 	struct mbuf *m;
-	int err, error;
+	int error;
 
 	tc = (struct tdb_crypto *) crp->crp_opaque;
 	IPSEC_ASSERT(tc != NULL, ("null opaque data area!"));
@@ -932,7 +928,7 @@
 	sav = tc->tc_sav;
 	/* With the isr lock released SA pointer can be updated. */
 	if (sav != isr->sav) {
-		V_espstat.esps_notdb++;
+		ESPSTAT_INC(esps_notdb);
 		DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
 		    __func__, ipsec_address(&tc->tc_dst),
 		    (u_long) ntohl(tc->tc_spi), tc->tc_proto));
@@ -948,11 +944,10 @@
 
 		if (crp->crp_etype == EAGAIN) {
 			IPSECREQUEST_UNLOCK(isr);
-			error = crypto_dispatch(crp);
-			return error;
+			return (crypto_dispatch(crp));
 		}
 
-		V_espstat.esps_noxform++;
+		ESPSTAT_INC(esps_noxform);
 		DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
 		error = crp->crp_etype;
 		goto bad;
@@ -960,14 +955,14 @@
 
 	/* Shouldn't happen... */
 	if (m == NULL) {
-		V_espstat.esps_crypto++;
+		ESPSTAT_INC(esps_crypto);
 		DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
 		error = EINVAL;
 		goto bad;
 	}
-	V_espstat.esps_hist[sav->alg_enc]++;
+	ESPSTAT_INC(esps_hist[sav->alg_enc]);
 	if (sav->tdb_authalgxform != NULL)
-		V_ahstat.ahs_hist[sav->alg_auth]++;
+		AHSTAT_INC(ahs_hist[sav->alg_auth]);
 
 	/* Release crypto descriptors. */
 	free(tc, M_XDATA);
@@ -1004,10 +999,10 @@
 #endif
 
 	/* NB: m is reclaimed by ipsec_process_done. */
-	err = ipsec_process_done(m, isr);
+	error = ipsec_process_done(m, isr);
 	KEY_FREESAV(&sav);
 	IPSECREQUEST_UNLOCK(isr);
-	return err;
+	return error;
 bad:
 	if (sav)
 		KEY_FREESAV(&sav);
@@ -1028,20 +1023,7 @@
 static void
 esp_attach(void)
 {
-#define	MAXIV(xform)					\
-	if (xform.blocksize > V_esp_max_ivlen)		\
-		V_esp_max_ivlen = xform.blocksize	\
 
-	MAXIV(enc_xform_des);		/* SADB_EALG_DESCBC */
-	MAXIV(enc_xform_3des);		/* SADB_EALG_3DESCBC */
-	MAXIV(enc_xform_rijndael128);	/* SADB_X_EALG_AES */
-	MAXIV(enc_xform_blf);		/* SADB_X_EALG_BLOWFISHCBC */
-	MAXIV(enc_xform_cast5);		/* SADB_X_EALG_CAST128CBC */
-	MAXIV(enc_xform_skipjack);	/* SADB_X_EALG_SKIPJACK */
-	MAXIV(enc_xform_null);		/* SADB_EALG_NULL */
-	MAXIV(enc_xform_camellia);	/* SADB_X_EALG_CAMELLIACBC */
-
 	xform_register(&esp_xformsw);
-#undef MAXIV
 }
 SYSINIT(esp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, esp_attach, NULL);

Modified: trunk/sys/netipsec/xform_ipcomp.c
===================================================================
--- trunk/sys/netipsec/xform_ipcomp.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/xform_ipcomp.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/xform_ipcomp.c 283901 2015-06-02 03:14:42Z ae $	*/
 /* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */
 
 /*-
@@ -48,7 +49,6 @@
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netipsec/ipsec.h>
@@ -70,13 +70,19 @@
 #include <opencrypto/xform.h>
 
 VNET_DEFINE(int, ipcomp_enable) = 1;
-VNET_DEFINE(struct ipcompstat, ipcompstat);
+VNET_PCPUSTAT_DEFINE(struct ipcompstat, ipcompstat);
+VNET_PCPUSTAT_SYSINIT(ipcompstat);
 
+#ifdef VIMAGE
+VNET_PCPUSTAT_SYSUNINIT(ipcompstat);
+#endif /* VIMAGE */
+
 SYSCTL_DECL(_net_inet_ipcomp);
 SYSCTL_VNET_INT(_net_inet_ipcomp, OID_AUTO,
 	ipcomp_enable,	CTLFLAG_RW,	&VNET_NAME(ipcomp_enable),	0, "");
-SYSCTL_VNET_STRUCT(_net_inet_ipcomp, IPSECCTL_STATS,
-	stats,		CTLFLAG_RD,	&VNET_NAME(ipcompstat),	ipcompstat, "");
+SYSCTL_VNET_PCPUSTAT(_net_inet_ipcomp, IPSECCTL_STATS, stats,
+    struct ipcompstat, ipcompstat,
+    "IPCOMP statistics (struct ipcompstat, netipsec/ipcomp_var.h");
 
 static int ipcomp_input_cb(struct cryptop *crp);
 static int ipcomp_output_cb(struct cryptop *crp);
@@ -152,7 +158,7 @@
 	 * compression it means someone is playing tricks on us.
 	 */
 	if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) {
-		V_ipcompstat.ipcomps_hdrops++;		/*XXX*/
+		IPCOMPSTAT_INC(ipcomps_hdrops);		/*XXX*/
 		DPRINTF(("%s: m_pullup failed\n", __func__));
 		return (ENOBUFS);
 	}
@@ -160,7 +166,7 @@
 	ipcomp = (struct ipcomp *)addr;
 	if (ipcomp->comp_nxt == IPPROTO_IPCOMP) {
 		m_freem(m);
-		V_ipcompstat.ipcomps_pdrops++;	/* XXX have our own stats? */
+		IPCOMPSTAT_INC(ipcomps_pdrops);	/* XXX have our own stats? */
 		DPRINTF(("%s: recursive compression detected\n", __func__));
 		return (EINVAL);
 	}
@@ -170,7 +176,7 @@
 	if (crp == NULL) {
 		m_freem(m);
 		DPRINTF(("%s: no crypto descriptors\n", __func__));
-		V_ipcompstat.ipcomps_crypto++;
+		IPCOMPSTAT_INC(ipcomps_crypto);
 		return ENOBUFS;
 	}
 	/* Get IPsec-specific opaque pointer */
@@ -179,7 +185,7 @@
 		m_freem(m);
 		crypto_freereq(crp);
 		DPRINTF(("%s: cannot allocate tdb_crypto\n", __func__));
-		V_ipcompstat.ipcomps_crypto++;
+		IPCOMPSTAT_INC(ipcomps_crypto);
 		return ENOBUFS;
 	}
 	crdc = crp->crp_desc;
@@ -256,7 +262,7 @@
 		if (crp->crp_etype == EAGAIN) {
 			return crypto_dispatch(crp);
 		}
-		V_ipcompstat.ipcomps_noxform++;
+		IPCOMPSTAT_INC(ipcomps_noxform);
 		DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
 		error = crp->crp_etype;
 		goto bad;
@@ -263,12 +269,12 @@
 	}
 	/* Shouldn't happen... */
 	if (m == NULL) {
-		V_ipcompstat.ipcomps_crypto++;
+		IPCOMPSTAT_INC(ipcomps_crypto);
 		DPRINTF(("%s: null mbuf returned from crypto\n", __func__));
 		error = EINVAL;
 		goto bad;
 	}
-	V_ipcompstat.ipcomps_hist[sav->alg_comp]++;
+	IPCOMPSTAT_INC(ipcomps_hist[sav->alg_comp]);
 
 	clen = crp->crp_olen;		/* Length of data after processing */
 
@@ -280,7 +286,7 @@
 	m->m_pkthdr.len = clen + hlen + skip;
 
 	if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == 0) {
-		V_ipcompstat.ipcomps_hdrops++;		/*XXX*/
+		IPCOMPSTAT_INC(ipcomps_hdrops);		/*XXX*/
 		DPRINTF(("%s: m_pullup failed\n", __func__));
 		error = EINVAL;				/*XXX*/
 		goto bad;
@@ -293,7 +299,7 @@
 	/* Remove the IPCOMP header */
 	error = m_striphdr(m, skip, hlen);
 	if (error) {
-		V_ipcompstat.ipcomps_hdrops++;
+		IPCOMPSTAT_INC(ipcomps_hdrops);
 		DPRINTF(("%s: bad mbuf chain, IPCA %s/%08lx\n", __func__,
 			 ipsec_address(&sav->sah->saidx.dst),
 			 (u_long) ntohl(sav->spi)));
@@ -364,12 +370,12 @@
 	 * See RFC 3173, 2.2. Non-Expansion Policy.
 	 */
 	if (m->m_pkthdr.len <= ipcompx->minlen) {
-		V_ipcompstat.ipcomps_threshold++;
+		IPCOMPSTAT_INC(ipcomps_threshold);
 		return ipsec_process_done(m, isr);
 	}
 
 	ralen = m->m_pkthdr.len - skip;	/* Raw payload length before comp. */
-	V_ipcompstat.ipcomps_output++;
+	IPCOMPSTAT_INC(ipcomps_output);
 
 	/* Check for maximum packet size violations. */
 	switch (sav->sah->saidx.dst.sa.sa_family) {
@@ -384,7 +390,7 @@
 		break;
 #endif /* INET6 */
 	default:
-		V_ipcompstat.ipcomps_nopf++;
+		IPCOMPSTAT_INC(ipcomps_nopf);
 		DPRINTF(("%s: unknown/unsupported protocol family %d, "
 		    "IPCA %s/%08lx\n", __func__,
 		    sav->sah->saidx.dst.sa.sa_family,
@@ -394,7 +400,7 @@
 		goto bad;
 	}
 	if (ralen + skip + IPCOMP_HLENGTH > maxpacketsize) {
-		V_ipcompstat.ipcomps_toobig++;
+		IPCOMPSTAT_INC(ipcomps_toobig);
 		DPRINTF(("%s: packet in IPCA %s/%08lx got too big "
 		    "(len %u, max len %u)\n", __func__,
 		    ipsec_address(&sav->sah->saidx.dst),
@@ -405,11 +411,11 @@
 	}
 
 	/* Update the counters */
-	V_ipcompstat.ipcomps_obytes += m->m_pkthdr.len - skip;
+	IPCOMPSTAT_ADD(ipcomps_obytes, m->m_pkthdr.len - skip);
 
 	m = m_unshare(m, M_NOWAIT);
 	if (m == NULL) {
-		V_ipcompstat.ipcomps_hdrops++;
+		IPCOMPSTAT_INC(ipcomps_hdrops);
 		DPRINTF(("%s: cannot clone mbuf chain, IPCA %s/%08lx\n",
 		    __func__, ipsec_address(&sav->sah->saidx.dst),
 		    (u_long) ntohl(sav->spi)));
@@ -422,7 +428,7 @@
 	/* Get crypto descriptors */
 	crp = crypto_getreq(1);
 	if (crp == NULL) {
-		V_ipcompstat.ipcomps_crypto++;
+		IPCOMPSTAT_INC(ipcomps_crypto);
 		DPRINTF(("%s: failed to acquire crypto descriptor\n",__func__));
 		error = ENOBUFS;
 		goto bad;
@@ -442,7 +448,7 @@
 	tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto),
 		M_XDATA, M_NOWAIT|M_ZERO);
 	if (tc == NULL) {
-		V_ipcompstat.ipcomps_crypto++;
+		IPCOMPSTAT_INC(ipcomps_crypto);
 		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
 		crypto_freereq(crp);
 		error = ENOBUFS;
@@ -495,7 +501,7 @@
 	sav = tc->tc_sav;
 	/* With the isr lock released SA pointer can be updated. */
 	if (sav != isr->sav) {
-		V_ipcompstat.ipcomps_notdb++;
+		IPCOMPSTAT_INC(ipcomps_notdb);
 		DPRINTF(("%s: SA expired while in crypto\n", __func__));
 		error = ENOBUFS;		/*XXX*/
 		goto bad;
@@ -511,7 +517,7 @@
 			IPSECREQUEST_UNLOCK(isr);
 			return crypto_dispatch(crp);
 		}
-		V_ipcompstat.ipcomps_noxform++;
+		IPCOMPSTAT_INC(ipcomps_noxform);
 		DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
 		error = crp->crp_etype;
 		goto bad;
@@ -518,12 +524,12 @@
 	}
 	/* Shouldn't happen... */
 	if (m == NULL) {
-		V_ipcompstat.ipcomps_crypto++;
+		IPCOMPSTAT_INC(ipcomps_crypto);
 		DPRINTF(("%s: bogus return buffer from crypto\n", __func__));
 		error = EINVAL;
 		goto bad;
 	}
-	V_ipcompstat.ipcomps_hist[sav->alg_comp]++;
+	IPCOMPSTAT_INC(ipcomps_hist[sav->alg_comp]);
 
 	if (crp->crp_ilen - skip > crp->crp_olen) {
 		struct mbuf *mo;
@@ -534,7 +540,7 @@
 		/* Compression helped, inject IPCOMP header. */
 		mo = m_makespace(m, skip, IPCOMP_HLENGTH, &roff);
 		if (mo == NULL) {
-			V_ipcompstat.ipcomps_wrap++;
+			IPCOMPSTAT_INC(ipcomps_wrap);
 			DPRINTF(("%s: IPCOMP header inject failed for IPCA %s/%08lx\n",
 			    __func__, ipsec_address(&sav->sah->saidx.dst),
 			    (u_long) ntohl(sav->spi)));
@@ -579,7 +585,7 @@
 			break;
 #endif /* INET6 */
 		default:
-			V_ipcompstat.ipcomps_nopf++;
+			IPCOMPSTAT_INC(ipcomps_nopf);
 			DPRINTF(("%s: unknown/unsupported protocol "
 			    "family %d, IPCA %s/%08lx\n", __func__,
 			    sav->sah->saidx.dst.sa.sa_family,
@@ -590,7 +596,7 @@
 		}
 	} else {
 		/* Compression was useless, we have lost time. */
-		V_ipcompstat.ipcomps_uncompr++;
+		IPCOMPSTAT_INC(ipcomps_uncompr);
 		DPRINTF(("%s: compressions was useless %d - %d <= %d\n",
 		    __func__, crp->crp_ilen, skip, crp->crp_olen));
 		/* XXX remember state to not compress the next couple
@@ -631,13 +637,3 @@
 }
 
 SYSINIT(ipcomp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipcomp_attach, NULL);
-
-static void
-vnet_ipcomp_attach(const void *unused __unused)
-{
-
-	V_ipcompstat.version = IPCOMPSTAT_VERSION;
-}
-
-VNET_SYSINIT(vnet_ipcomp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
-    vnet_ipcomp_attach, NULL);

Modified: trunk/sys/netipsec/xform_ipip.c
===================================================================
--- trunk/sys/netipsec/xform_ipip.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/xform_ipip.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$	*/
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/xform_ipip.c 283901 2015-06-02 03:14:42Z ae $	*/
 /*	$OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
 /*-
  * The authors of this code are John Ioannidis (ji at tla.org),
@@ -53,7 +54,6 @@
 
 #include <net/if.h>
 #include <net/pfil.h>
-#include <net/route.h>
 #include <net/netisr.h>
 #include <net/vnet.h>
 
@@ -64,9 +64,6 @@
 #include <netinet/ip_ecn.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_encap.h>
-#ifdef MROUTING
-#include <netinet/ip_mroute.h>
-#endif
 
 #include <netipsec/ipsec.h>
 #include <netipsec/xform.h>
@@ -91,13 +88,19 @@
  * net.inet.ipip.allow value.  Zero means drop them, all else is acceptance.
  */
 VNET_DEFINE(int, ipip_allow) = 0;
-VNET_DEFINE(struct ipipstat, ipipstat);
+VNET_PCPUSTAT_DEFINE(struct ipipstat, ipipstat);
+VNET_PCPUSTAT_SYSINIT(ipipstat);
 
+#ifdef VIMAGE
+VNET_PCPUSTAT_SYSUNINIT(ipipstat);
+#endif /* VIMAGE */
+
 SYSCTL_DECL(_net_inet_ipip);
 SYSCTL_VNET_INT(_net_inet_ipip, OID_AUTO,
 	ipip_allow,	CTLFLAG_RW,	&VNET_NAME(ipip_allow),	0, "");
-SYSCTL_VNET_STRUCT(_net_inet_ipip, IPSECCTL_STATS,
-	stats,		CTLFLAG_RD,	&VNET_NAME(ipipstat),	ipipstat, "");
+SYSCTL_VNET_PCPUSTAT(_net_inet_ipip, IPSECCTL_STATS, stats,
+    struct ipipstat, ipipstat,
+    "IPIP statistics (struct ipipstat, netipsec/ipip_var.h)");
 
 /* XXX IPCOMP */
 #define	M_IPSEC	(M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED)
@@ -115,7 +118,7 @@
 	/* If we do not accept IP-in-IP explicitly, drop.  */
 	if (!V_ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) {
 		DPRINTF(("%s: dropped due to policy\n", __func__));
-		V_ipipstat.ipips_pdrops++;
+		IPIPSTAT_INC(ipips_pdrops);
 		m_freem(*m);
 		return IPPROTO_DONE;
 	}
@@ -136,7 +139,7 @@
 	/* If we do not accept IP-in-IP explicitly, drop.  */
 	if (!V_ipip_allow && (m->m_flags & M_IPSEC) == 0) {
 		DPRINTF(("%s: dropped due to policy\n", __func__));
-		V_ipipstat.ipips_pdrops++;
+		IPIPSTAT_INC(ipips_pdrops);
 		m_freem(m);
 		return;
 	}
@@ -155,24 +158,17 @@
 static void
 _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
 {
-#ifdef INET
-	register struct sockaddr_in *sin;
-#endif
-	register struct ifnet *ifp;
-	register struct ifaddr *ifa;
 	struct ip *ipo;
 #ifdef INET6
-	register struct sockaddr_in6 *sin6;
 	struct ip6_hdr *ip6 = NULL;
 	u_int8_t itos;
 #endif
-	u_int8_t nxt;
 	int isr;
 	u_int8_t otos;
 	u_int8_t v;
 	int hlen;
 
-	V_ipipstat.ipips_ipackets++;
+	IPIPSTAT_INC(ipips_ipackets);
 
 	m_copydata(m, 0, 1, &v);
 
@@ -188,7 +184,7 @@
 		break;
 #endif
         default:
-		V_ipipstat.ipips_family++;
+		IPIPSTAT_INC(ipips_family);
 		m_freem(m);
 		return /* EAFNOSUPPORT */;
 	}
@@ -197,22 +193,12 @@
 	if (m->m_len < hlen) {
 		if ((m = m_pullup(m, hlen)) == NULL) {
 			DPRINTF(("%s: m_pullup (1) failed\n", __func__));
-			V_ipipstat.ipips_hdrops++;
+			IPIPSTAT_INC(ipips_hdrops);
 			return;
 		}
 	}
-
 	ipo = mtod(m, struct ip *);
 
-#ifdef MROUTING
-	if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) {
-		if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) {
-			ipip_mroute_input (m, iphlen);
-			return;
-		}
-	}
-#endif /* MROUTING */
-
 	/* Keep outer ecn field. */
 	switch (v >> 4) {
 #ifdef INET
@@ -234,7 +220,7 @@
 
 	/* Sanity check */
 	if (m->m_pkthdr.len < sizeof(struct ip))  {
-		V_ipipstat.ipips_hdrops++;
+		IPIPSTAT_INC(ipips_hdrops);
 		m_freem(m);
 		return;
 	}
@@ -254,7 +240,7 @@
 		break;
 #endif
 	default:
-		V_ipipstat.ipips_family++;
+		IPIPSTAT_INC(ipips_family);
 		m_freem(m);
 		return; /* EAFNOSUPPORT */
 	}
@@ -265,7 +251,7 @@
 	if (m->m_len < hlen) {
 		if ((m = m_pullup(m, hlen)) == NULL) {
 			DPRINTF(("%s: m_pullup (2) failed\n", __func__));
-			V_ipipstat.ipips_hdrops++;
+			IPIPSTAT_INC(ipips_hdrops);
 			return;
 		}
 	}
@@ -281,7 +267,6 @@
 #ifdef INET
     	case 4:
                 ipo = mtod(m, struct ip *);
-                nxt = ipo->ip_p;
 		ip_ecn_egress(V_ip4_ipsec_ecn, &otos, &ipo->ip_tos);
                 break;
 #endif /* INET */
@@ -288,7 +273,6 @@
 #ifdef INET6
     	case 6:
                 ip6 = (struct ip6_hdr *) ipo;
-                nxt = ip6->ip6_nxt;
 		itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
 		ip_ecn_egress(V_ip6_ipsec_ecn, &otos, &itos);
 		ip6->ip6_flow &= ~htonl(0xff << 20);
@@ -303,72 +287,27 @@
 	if ((m->m_pkthdr.rcvif == NULL ||
 	    !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) &&
 	    V_ipip_allow != 2) {
-	    	IFNET_RLOCK_NOSLEEP();
-		TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
-			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 #ifdef INET
-				if (ipo) {
-					if (ifa->ifa_addr->sa_family !=
-					    AF_INET)
-						continue;
-
-					sin = (struct sockaddr_in *) ifa->ifa_addr;
-
-					if (sin->sin_addr.s_addr ==
-					    ipo->ip_src.s_addr)	{
-						V_ipipstat.ipips_spoof++;
-						m_freem(m);
-						IFNET_RUNLOCK_NOSLEEP();
-						return;
-					}
-				}
-#endif /* INET */
-
+		if ((v >> 4) == IPVERSION &&
+		    in_localip(ipo->ip_src) != 0) {
+			IPIPSTAT_INC(ipips_spoof);
+			m_freem(m);
+			return;
+		}
+#endif
 #ifdef INET6
-				if (ip6) {
-					if (ifa->ifa_addr->sa_family !=
-					    AF_INET6)
-						continue;
-
-					sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
-
-					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
-						V_ipipstat.ipips_spoof++;
-						m_freem(m);
-						IFNET_RUNLOCK_NOSLEEP();
-						return;
-					}
-
-				}
-#endif /* INET6 */
-			}
+		if ((v & IPV6_VERSION_MASK) == IPV6_VERSION &&
+		    in6_localip(&ip6->ip6_src) != 0) {
+			IPIPSTAT_INC(ipips_spoof);
+			m_freem(m);
+			return;
 		}
-		IFNET_RUNLOCK_NOSLEEP();
+#endif
 	}
 
 	/* Statistics */
-	V_ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
+	IPIPSTAT_ADD(ipips_ibytes, m->m_pkthdr.len - iphlen);
 
-#ifdef DEV_ENC
-	switch (v >> 4) {
-#ifdef INET
-	case 4:
-		ipsec_bpf(m, NULL, AF_INET, ENC_IN|ENC_AFTER);
-		break;
-#endif
-#ifdef INET6
-	case 6:
-		ipsec_bpf(m, NULL, AF_INET6, ENC_IN|ENC_AFTER);
-		break;
-#endif
-	default:
-		panic("%s: bogus ip version %u", __func__, v>>4);
-	}
-	/* pass the mbuf to enc0 for packet filtering */
-	if (ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER) != 0)
-		return;
-#endif
-
 	/*
 	 * Interface pointer stays the same; if no IPsec processing has
 	 * been done (or will be done), this will point to a normal
@@ -392,10 +331,8 @@
 		panic("%s: bogus ip version %u", __func__, v>>4);
 	}
 
-	m_addr_changed(m);
-
 	if (netisr_queue(isr, m)) {	/* (0) on success. */
-		V_ipipstat.ipips_qfull++;
+		IPIPSTAT_INC(ipips_qfull);
 		DPRINTF(("%s: packet dropped because of full queue\n",
 			__func__));
 	}
@@ -444,15 +381,15 @@
 			    "address in SA %s/%08lx\n", __func__,
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
-			V_ipipstat.ipips_unspec++;
+			IPIPSTAT_INC(ipips_unspec);
 			error = EINVAL;
 			goto bad;
 		}
 
-		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
+		M_PREPEND(m, sizeof(struct ip), M_NOWAIT);
 		if (m == 0) {
 			DPRINTF(("%s: M_PREPEND failed\n", __func__));
-			V_ipipstat.ipips_hdrops++;
+			IPIPSTAT_INC(ipips_hdrops);
 			error = ENOBUFS;
 			goto bad;
 		}
@@ -524,7 +461,7 @@
 			    "address in SA %s/%08lx\n", __func__,
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
-			V_ipipstat.ipips_unspec++;
+			IPIPSTAT_INC(ipips_unspec);
 			error = ENOBUFS;
 			goto bad;
 		}
@@ -536,10 +473,10 @@
 		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
 			ip6->ip6_dst.s6_addr16[1] = 0;
 
-		M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
+		M_PREPEND(m, sizeof(struct ip6_hdr), M_NOWAIT);
 		if (m == 0) {
 			DPRINTF(("%s: M_PREPEND failed\n", __func__));
-			V_ipipstat.ipips_hdrops++;
+			IPIPSTAT_INC(ipips_hdrops);
 			error = ENOBUFS;
 			goto bad;
 		}
@@ -549,10 +486,10 @@
 		ip6o->ip6_flow = 0;
 		ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
 		ip6o->ip6_vfc |= IPV6_VERSION;
-		ip6o->ip6_plen = htons(m->m_pkthdr.len);
-		ip6o->ip6_hlim = V_ip_defttl;
+		ip6o->ip6_hlim = IPV6_DEFHLIM;
 		ip6o->ip6_dst = saidx->dst.sin6.sin6_addr;
 		ip6o->ip6_src = saidx->src.sin6.sin6_addr;
+		ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
 
 		switch (tp) {
 #ifdef INET
@@ -584,7 +521,7 @@
 		}
 
 		otos = 0;
-		ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
+		ip_ecn_ingress(V_ip6_ipsec_ecn, &otos, &itos);
 		ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
 		break;
 #endif /* INET6 */
@@ -593,12 +530,12 @@
 nofamily:
 		DPRINTF(("%s: unsupported protocol family %u\n", __func__,
 		    saidx->dst.sa.sa_family));
-		V_ipipstat.ipips_family++;
+		IPIPSTAT_INC(ipips_family);
 		error = EAFNOSUPPORT;		/* XXX diffs from openbsd */
 		goto bad;
 	}
 
-	V_ipipstat.ipips_opackets++;
+	IPIPSTAT_INC(ipips_opackets);
 	*mp = m;
 
 #ifdef INET
@@ -608,7 +545,8 @@
 			tdb->tdb_cur_bytes +=
 			    m->m_pkthdr.len - sizeof(struct ip);
 #endif
-		V_ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip);
+		IPIPSTAT_ADD(ipips_obytes,
+		    m->m_pkthdr.len - sizeof(struct ip));
 	}
 #endif /* INET */
 
@@ -619,8 +557,8 @@
 			tdb->tdb_cur_bytes +=
 			    m->m_pkthdr.len - sizeof(struct ip6_hdr);
 #endif
-		V_ipipstat.ipips_obytes +=
-		    m->m_pkthdr.len - sizeof(struct ip6_hdr);
+		IPIPSTAT_ADD(ipips_obytes,
+		    m->m_pkthdr.len - sizeof(struct ip6_hdr));
 	}
 #endif /* INET6 */
 
@@ -688,7 +626,7 @@
 };
 #endif /* INET6 && INET */
 
-#if defined(INET)
+#ifdef INET
 /*
  * Check the encapsulated packet to see if we want it
  */

Modified: trunk/sys/netipsec/xform_tcp.c
===================================================================
--- trunk/sys/netipsec/xform_tcp.c	2018-05-25 13:07:02 UTC (rev 9925)
+++ trunk/sys/netipsec/xform_tcp.c	2018-05-25 13:07:22 UTC (rev 9926)
@@ -1,4 +1,5 @@
-/*	$MidnightBSD$ */
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/netipsec/xform_tcp.c 283901 2015-06-02 03:14:42Z ae $ */
 
 /*-
  * Copyright (c) 2003 Bruce M. Simpson <bms at spc.org>
@@ -47,7 +48,6 @@
 #include <netinet/tcp.h>
 #include <netinet/tcp_var.h>
 
-#include <net/route.h>
 #include <net/vnet.h>
 
 #include <netipsec/ipsec.h>



More information about the Midnightbsd-cvs mailing list