]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netkey/key.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / bsd / netkey / key.c
index 6d6e92fd12a0caa6a86db2a206d933a046d39e16..2c635da4c53ba3d723e5c78728054bf34a6982d3 100644 (file)
@@ -1,5 +1,5 @@
-/*     $FreeBSD: src/sys/netkey/key.c,v 1.16.2.5 2001/07/03 11:01:58 ume Exp $ */
-/*     $KAME: key.c,v 1.187 2001/05/24 07:41:22 itojun Exp $   */
+/*     $FreeBSD: src/sys/netkey/key.c,v 1.16.2.13 2002/07/24 18:17:40 ume Exp $        */
+/*     $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $   */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -48,6 +48,9 @@
 #include <sys/errno.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
+#include <sys/syslog.h>
+
+#include <kern/locks.h>
 
 #include <net/if.h>
 #include <net/route.h>
 #define satosin(s) ((struct sockaddr_in *)s)
 #endif
 
+#define FULLMASK       0xff
+
+lck_grp_t         *sadb_mutex_grp;
+lck_grp_attr_t    *sadb_mutex_grp_attr;
+lck_attr_t        *sadb_mutex_attr;
+lck_mtx_t         *sadb_mutex;
+extern lck_mtx_t  *nd6_mutex;
+
 /*
  * Note on SA reference counting:
  * - SAs that are not in DEAD state will have (total external reference + 1)
@@ -128,14 +139,22 @@ static u_int key_int_random = 60; /*interval to initialize randseed,1(m)*/
 static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/
 static int key_blockacq_count = 10;    /* counter for blocking SADB_ACQUIRE.*/
 static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/
+static int key_preferred_oldsa = 0;    /* preferred old sa rather than new sa.*/
+static int natt_keepalive_interval = 20;       /* interval between natt keepalives.*/
 
 static u_int32_t acq_seq = 0;
 static int key_tick_init_random = 0;
+__private_extern__ u_int32_t natt_now = 0;
 
 static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX];    /* SPD */
 static LIST_HEAD(_sahtree, secashead) sahtree;                 /* SAD */
 static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1];
                                                        /* registed list */
+                                                       
+#define SPIHASHSIZE    128
+#define        SPIHASH(x)      (((x) ^ ((x) >> 16)) % SPIHASHSIZE)
+static LIST_HEAD(_spihash, secasvar) spihash[SPIHASHSIZE];
+
 #ifndef IPSEC_NONBLOCK_ACQUIRE
 static LIST_HEAD(_acqtree, secacq) acqtree;            /* acquiring list */
 #endif
@@ -144,18 +163,17 @@ static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */
 struct key_cb key_cb;
 
 /* search order for SAs */
-static u_int saorder_state_valid[] = {
+static const u_int saorder_state_valid_prefer_old[] = {
        SADB_SASTATE_DYING, SADB_SASTATE_MATURE,
-       /*
-        * This order is important because we must select a oldest SA
-        * for outbound processing.  For inbound, This is not important.
-        */
 };
-static u_int saorder_state_alive[] = {
+static const u_int saorder_state_valid_prefer_new[] = {
+       SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
+};
+static const u_int saorder_state_alive[] = {
        /* except DEAD */
        SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL
 };
-static u_int saorder_state_any[] = {
+static const u_int saorder_state_any[] = {
        SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
        SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD
 };
@@ -184,7 +202,7 @@ static const int minsize[] = {
 };
 static const int maxsize[] = {
        sizeof(struct sadb_msg),        /* SADB_EXT_RESERVED */
-       sizeof(struct sadb_sa),         /* SADB_EXT_SA */
+       sizeof(struct sadb_sa_2),               /* SADB_EXT_SA */
        sizeof(struct sadb_lifetime),   /* SADB_EXT_LIFETIME_CURRENT */
        sizeof(struct sadb_lifetime),   /* SADB_EXT_LIFETIME_HARD */
        sizeof(struct sadb_lifetime),   /* SADB_EXT_LIFETIME_SOFT */
@@ -243,6 +261,10 @@ SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT,        blockacq_count, CTLFLAG_RW, \
 SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \
        &key_blockacq_lifetime, 0,      "");
 
+/* ESP auth */
+SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH,  esp_auth, CTLFLAG_RW, \
+       &ipsec_esp_auth,        0,      "");
+
 /* minimum ESP key length */
 SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN,        esp_keymin, CTLFLAG_RW, \
        &ipsec_esp_keymin,      0,      "");
@@ -251,6 +273,18 @@ SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN,    esp_keymin, CTLFLAG_RW, \
 SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \
        &ipsec_ah_keymin,       0,      "");
 
+/* perfered old SA rather than new SA */
+SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA,    prefered_oldsa, CTLFLAG_RW,\
+       &key_preferred_oldsa,   0,      "");
+
+/* time between NATT keepalives in seconds, 0 disabled  */
+SYSCTL_INT(_net_key, KEYCTL_NATT_KEEPALIVE_INTERVAL, natt_keepalive_interval, CTLFLAG_RW,\
+       &natt_keepalive_interval,       0,      "");
+
+/* PF_KEY statistics */
+SYSCTL_STRUCT(_net_key, KEYCTL_PFKEYSTAT, pfkeystat, CTLFLAG_RD,\
+       &pfkeystat, pfkeystat, "");
+
 #ifndef LIST_FOREACH
 #define LIST_FOREACH(elm, head, field)                                     \
        for (elm = LIST_FIRST(head); elm; elm = LIST_NEXT(elm, field))
@@ -271,20 +305,20 @@ do {\
 
 #define KEY_CHKSASTATE(head, sav, name) \
 do { \
-       if ((head) != (sav)) {                                               \
-               printf("%s: state mismatched (TREE=%d SA=%d)\n",             \
-                       (name), (head), (sav));                              \
-               continue;                                                    \
-       }                                                                    \
+       if ((head) != (sav)) {                                          \
+               ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \
+                       (name), (head), (sav)));                        \
+               continue;                                               \
+       }                                                               \
 } while (0)
 
 #define KEY_CHKSPDIR(head, sp, name) \
 do { \
-       if ((head) != (sp)) {                                                \
-               printf("%s: direction mismatched (TREE=%d SP=%d), "          \
-                       "anyway continue.\n",                                \
-                       (name), (head), (sp));                               \
-       }                                                                    \
+       if ((head) != (sp)) {                                           \
+               ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \
+                       "anyway continue.\n",                           \
+                       (name), (head), (sp)));                         \
+       }                                                               \
 } while (0)
 
 #if 1
@@ -348,137 +382,163 @@ struct sadb_msghdr {
        int extlen[SADB_EXT_MAX + 1];
 };
 
-static struct secasvar *key_allocsa_policy __P((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 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, 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 *,
-       const struct sadb_msghdr *, struct secashead *, int *));
-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,
-       struct sockaddr *, u_int8_t, u_int16_t));
+static struct secasvar *key_allocsa_policy(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 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, 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 *);
+static void key_delsav(struct secasvar *);
+static struct secashead *key_getsah(struct secasindex *);
+static struct secasvar *key_checkspidup(struct secasindex *, u_int32_t);
+static void key_setspi __P((struct secasvar *, 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,
+       struct sockaddr *, u_int8_t, u_int16_t);
 #if 0
-static struct mbuf *key_setsadbident __P((u_int16_t, u_int16_t, caddr_t,
-       int, u_int64_t));
+static struct mbuf *key_setsadbident(u_int16_t, u_int16_t, caddr_t,
+       int, u_int64_t);
 #endif
-static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t);
-static struct mbuf *key_setsadbxpolicy __P((u_int16_t, u_int8_t,
-       u_int32_t));
-static void *key_newbuf __P((const void *, u_int));
+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 void *key_newbuf(const void *, u_int);
 #if INET6
-static int key_ismyaddr6 __P((struct sockaddr_in6 *));
-#endif
-static int key_cmpsaidx_exactly
-       __P((struct secasindex *, struct secasindex *));
-static int key_cmpsaidx_withmode
-       __P((struct secasindex *, struct secasindex *));
-static int key_cmpsaidx_withoutmode2
-       __P((struct secasindex *, struct secasindex *));
-static int key_cmpsaidx_withoutmode
-       __P((struct secasindex *, struct secasindex *));
-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((struct sockaddr *, struct sockaddr *, int));
-static int key_bbcmp __P((caddr_t, caddr_t, u_int));
-static void key_srandom __P((void));
-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_ismyaddr6(struct sockaddr_in6 *);
+#endif
+
+/* flags for key_cmpsaidx() */
+#define CMP_HEAD       1       /* protocol, addresses. */
+#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(struct secasindex *, 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(struct sockaddr *, struct sockaddr *, int);
+static int key_bbcmp(caddr_t, caddr_t, u_int);
+static void key_srandom(void);
+static u_int16_t key_satype2proto(u_int8_t);
+static u_int8_t key_proto2satype(u_int16_t);
+
+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 *);
 #if 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 void key_getcomb_setlifetime __P((struct sadb_comb *));
+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_get(struct socket *, struct mbuf *, const struct sadb_msghdr *);
+
+static void key_getcomb_setlifetime(struct sadb_comb *);
 #if IPSEC_ESP
-static struct mbuf *key_getcomb_esp __P((void));
+static struct mbuf *key_getcomb_esp(void);
 #endif
-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 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((struct secasindex *, struct secpolicy *));
+static int key_acquire(struct secasindex *, struct secpolicy *);
 #ifndef IPSEC_NONBLOCK_ACQUIRE
-static struct secacq *key_newacq __P((struct secasindex *));
-static struct secacq *key_getacq __P((struct secasindex *));
-static struct secacq *key_getacqbyseq __P((u_int32_t));
-#endif
-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 struct secacq *key_newacq(struct secasindex *);
+static struct secacq *key_getacq(struct secasindex *);
+static struct secacq *key_getacqbyseq(u_int32_t);
+#endif
+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 *);
+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 *);
 #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 struct mbuf *key_alloc_mbuf(int);
 
 extern int ipsec_bypass;
+void ipsec_send_natt_keepalive(struct secasvar *sav);
+
+
+/*
+ * PF_KEY init
+ * setup locks and call raw_init()
+ *
+ */
+void
+key_init(void)
+{
+
+       int i;
+       
+       sadb_mutex_grp_attr = lck_grp_attr_alloc_init();
+       sadb_mutex_grp = lck_grp_alloc_init("sadb", sadb_mutex_grp_attr);
+       sadb_mutex_attr = lck_attr_alloc_init();
+       lck_attr_setdefault(sadb_mutex_attr);
+
+       if ((sadb_mutex = lck_mtx_alloc_init(sadb_mutex_grp, sadb_mutex_attr)) == NULL) {
+               printf("key_init: can't alloc sadb_mutex\n");
+               return;
+       }
+
+       for (i = 0; i < SPIHASHSIZE; i++)
+               LIST_INIT(&spihash[i]);
+
+       raw_init();
+}
+
 
 /* %%% IPsec policy management */
 /*
@@ -496,6 +556,7 @@ key_allocsp(spidx, dir)
        struct timeval tv;
        int s;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
        /* sanity check */
        if (spidx == NULL)
                panic("key_allocsp: NULL pointer is passed.\n");
@@ -510,7 +571,6 @@ key_allocsp(spidx, dir)
        }
 
        /* get a SP entry */
-       s = splnet();   /*called from softclock()*/
        KEYDEBUG(KEYDEBUG_IPSEC_DATA,
                printf("*** objects\n");
                kdebug_secpolicyindex(spidx));
@@ -526,7 +586,6 @@ key_allocsp(spidx, dir)
                        goto found;
        }
 
-       splx(s);
        return NULL;
 
 found:
@@ -537,7 +596,6 @@ found:
        microtime(&tv);
        sp->lastused = tv.tv_sec;
        sp->refcnt++;
-       splx(s);
        KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                printf("DP key_allocsp cause refcnt++:%d SP:%p\n",
                        sp->refcnt, sp));
@@ -561,7 +619,14 @@ key_gettunnel(osrc, odst, isrc, idst)
        struct sockaddr *os, *od, *is, *id;
        struct secpolicyindex spidx;
 
-       s = splnet();   /*called from softclock()*/
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
+       if (isrc->sa_family != idst->sa_family) {
+               ipseclog((LOG_ERR, "protocol family mismatched %d != %d\n.",
+                       isrc->sa_family, idst->sa_family));
+               return NULL;
+       }
+
        LIST_FOREACH(sp, &sptree[dir], chain) {
                if (sp->state == IPSEC_SPSTATE_DEAD)
                        continue;
@@ -601,14 +666,13 @@ key_gettunnel(osrc, odst, isrc, idst)
                        goto found;
                }
        }
-       splx(s);
+
        return NULL;
 
 found:
        microtime(&tv);
        sp->lastused = tv.tv_sec;
        sp->refcnt++;
-       splx(s);
        return sp;
 }
 
@@ -626,6 +690,8 @@ key_checkrequest(isr, saidx)
        u_int level;
        int error;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (isr == NULL || saidx == NULL)
                panic("key_checkrequest: NULL pointer is passed.\n");
@@ -692,11 +758,9 @@ key_checkrequest(isr, saidx)
 
        /* there is no SA */
        if ((error = key_acquire(saidx, isr->sp)) != 0) {
-               /* XXX What I do ? */
-#if IPSEC_DEBUG
-               printf("key_checkrequest: error %d returned "
-                       "from key_acquire.\n", error);
-#endif
+               /* XXX What should I do ? */
+               ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned "
+                       "from key_acquire.\n", error));
                return error;
        }
 
@@ -716,11 +780,15 @@ key_allocsa_policy(saidx)
        struct secashead *sah;
        struct secasvar *sav;
        u_int stateidx, state;
+       const u_int *saorder_state_valid;
+       int arraysize;
+
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
 
        LIST_FOREACH(sah, &sahtree, chain) {
                if (sah->state == SADB_SASTATE_DEAD)
                        continue;
-               if (key_cmpsaidx_withmode(&sah->saidx, saidx))
+               if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID))
                        goto found;
        }
 
@@ -728,10 +796,19 @@ key_allocsa_policy(saidx)
 
     found:
 
-       /* search valid state */
-       for (stateidx = 0;
-            stateidx < _ARRAYLEN(saorder_state_valid);
-            stateidx++) {
+       /*
+        * search a valid state list for outbound packet.
+        * This search order is important.
+        */
+       if (key_preferred_oldsa) {
+               saorder_state_valid = saorder_state_valid_prefer_old;
+               arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
+       } else {
+               saorder_state_valid = saorder_state_valid_prefer_new;
+               arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
+       }
+
+       for (stateidx = 0; stateidx < arraysize; stateidx++) {
 
                state = saorder_state_valid[stateidx];
 
@@ -755,12 +832,18 @@ key_do_allocsa_policy(sah, state)
        struct secashead *sah;
        u_int state;
 {
-       struct secasvar *sav, *candidate;
+       struct secasvar *sav, *nextsav, *candidate, *d;
+
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
 
        /* initilize */
        candidate = NULL;
 
-       LIST_FOREACH(sav, &sah->savtree[state], chain) {
+       for (sav = LIST_FIRST(&sah->savtree[state]);
+            sav != NULL;
+            sav = nextsav) {
+
+               nextsav = LIST_NEXT(sav, chain);
 
                /* sanity check */
                KEY_CHKSASTATE(sav->state, state, "key_do_allocsa_policy");
@@ -778,11 +861,82 @@ key_do_allocsa_policy(sah, state)
                        panic("key_do_allocsa_policy: "
                                "lifetime_current is NULL.\n");
 
-               /* XXX What the best method is to compare ? */
-               if (candidate->lft_c->sadb_lifetime_addtime >
+               /* What the best method is to compare ? */
+               if (key_preferred_oldsa) {
+                       if (candidate->lft_c->sadb_lifetime_addtime >
+                                       sav->lft_c->sadb_lifetime_addtime) {
+                               candidate = sav;
+                       }
+                       continue;
+                       /*NOTREACHED*/
+               }
+
+               /* prefered new sa rather than old sa */
+               if (candidate->lft_c->sadb_lifetime_addtime <
                                sav->lft_c->sadb_lifetime_addtime) {
+                       d = candidate;
                        candidate = sav;
-                       continue;
+               } else
+                       d = sav;
+
+               /*
+                * prepared to delete the SA when there is more
+                * suitable candidate and the lifetime of the SA is not
+                * permanent.
+                */
+               if (d->lft_c->sadb_lifetime_addtime != 0) {
+                       struct mbuf *m, *result;
+
+                       key_sa_chgstate(d, SADB_SASTATE_DEAD);
+
+                       m = key_setsadbmsg(SADB_DELETE, 0,
+                           d->sah->saidx.proto, 0, 0, d->refcnt - 1);
+                       if (!m)
+                               goto msgfail;
+                       result = m;
+
+                       /* set sadb_address for saidx's. */
+                       m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
+                               (struct sockaddr *)&d->sah->saidx.src,
+                               d->sah->saidx.src.ss_len << 3,
+                               IPSEC_ULPROTO_ANY);
+                       if (!m)
+                               goto msgfail;
+                       m_cat(result, m);
+
+                       /* set sadb_address for saidx's. */
+                       m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
+                               (struct sockaddr *)&d->sah->saidx.src,
+                               d->sah->saidx.src.ss_len << 3,
+                               IPSEC_ULPROTO_ANY);
+                       if (!m)
+                               goto msgfail;
+                       m_cat(result, m);
+
+                       /* create SA extension */
+                       m = key_setsadbsa(d);
+                       if (!m)
+                               goto msgfail;
+                       m_cat(result, m);
+
+                       if (result->m_len < sizeof(struct sadb_msg)) {
+                               result = m_pullup(result,
+                                               sizeof(struct sadb_msg));
+                               if (result == NULL)
+                                       goto msgfail;
+                       }
+
+                       result->m_pkthdr.len = 0;
+                       for (m = result; m; m = m->m_next)
+                               result->m_pkthdr.len += m->m_len;
+                       mtod(result, struct sadb_msg *)->sadb_msg_len =
+                               PFKEY_UNIT64(result->m_pkthdr.len);
+
+                       if (key_sendup_mbuf(NULL, result,
+                                       KEY_SENDUP_REGISTERED))
+                               goto msgfail;
+                msgfail:
+                       key_freesav(d);
                }
        }
 
@@ -800,7 +954,7 @@ key_do_allocsa_policy(sah, state)
  * allocating a SA entry for a *INBOUND* packet.
  * Must call key_freesav() later.
  * OUT: positive:      pointer to a sav.
- *     NULL:           not found, or error occured.
+ *     NULL:           not found, or error occurred.
  *
  * In the comparison, source address will be ignored for RFC2401 conformance.
  * To quote, from section 4.1:
@@ -817,129 +971,150 @@ key_allocsa(family, src, dst, proto, spi)
        caddr_t src, dst;
        u_int32_t spi;
 {
-       struct secashead *sah;
-       struct secasvar *sav;
-       u_int stateidx, state;
+       struct secasvar *sav, *match;
+       u_int stateidx, state, tmpidx, matchidx;
        struct sockaddr_in sin;
        struct sockaddr_in6 sin6;
        int s;
+       const u_int *saorder_state_valid;
+       int arraysize;
+
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
 
        /* sanity check */
        if (src == NULL || dst == NULL)
                panic("key_allocsa: NULL pointer is passed.\n");
 
+       /*
+        * when both systems employ similar strategy to use a SA.
+        * the search order is important even in the inbound case.
+        */
+       if (key_preferred_oldsa) {
+               saorder_state_valid = saorder_state_valid_prefer_old;
+               arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
+       } else {
+               saorder_state_valid = saorder_state_valid_prefer_new;
+               arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
+       }
+
        /*
         * searching SAD.
         * XXX: to be checked internal IP header somewhere.  Also when
         * IPsec tunnel packet is received.  But ESP tunnel mode is
         * encrypted so we can't check internal IP header.
         */
-       s = splnet();   /*called from softclock()*/
-       LIST_FOREACH(sah, &sahtree, chain) {
-               /* search valid state */
-               for (stateidx = 0;
-                    stateidx < _ARRAYLEN(saorder_state_valid);
-                    stateidx++) {
+       /*
+        * search a valid state list for inbound packet.
+        * the search order is not important.
+        */
+       match = NULL;
+       matchidx = arraysize;
+       LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
+               if (sav->spi != spi)
+                       continue;
+               if (proto != sav->sah->saidx.proto)
+                       continue;
+               if (family != sav->sah->saidx.src.ss_family ||
+                   family != sav->sah->saidx.dst.ss_family)
+                       continue;
+               tmpidx = arraysize;
+               for (stateidx = 0; stateidx < matchidx; stateidx++) {
                        state = saorder_state_valid[stateidx];
-                       LIST_FOREACH(sav, &sah->savtree[state], chain) {
-                               /* sanity check */
-                               KEY_CHKSASTATE(sav->state, state, "key_allocsav");
-                               if (proto != sav->sah->saidx.proto)
-                                       continue;
-                               if (spi != sav->spi)
-                                       continue;
-                               if (family != sav->sah->saidx.src.ss_family ||
-                                   family != sav->sah->saidx.dst.ss_family)
-                                       continue;
+                       if (sav->state == state) {
+                               tmpidx = stateidx;
+                               break;
+                       }
+               }
+               if (tmpidx >= matchidx)
+                       continue;
 
 #if 0  /* don't check src */
-                               /* check src address */
-                               switch (family) {
-                               case AF_INET:
-                                       bzero(&sin, sizeof(sin));
-                                       sin.sin_family = AF_INET;
-                                       sin.sin_len = sizeof(sin);
-                                       bcopy(src, &sin.sin_addr,
-                                           sizeof(sin.sin_addr));
-                                       if (key_sockaddrcmp((struct sockaddr*)&sin,
-                                           (struct sockaddr *)&sav->sah->saidx.src, 0) != 0)
-                                               continue;
-
-                                       break;
-                               case AF_INET6:
-                                       bzero(&sin6, sizeof(sin6));
-                                       sin6.sin6_family = AF_INET6;
-                                       sin6.sin6_len = sizeof(sin6);
-                                       bcopy(src, &sin6.sin6_addr,
-                                           sizeof(sin6.sin6_addr));
-                                       if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
-                                               /* kame fake scopeid */
-                                               sin6.sin6_scope_id =
-                                                   ntohs(sin6.sin6_addr.s6_addr16[1]);
-                                               sin6.sin6_addr.s6_addr16[1] = 0;
-                                       }
-                                       if (key_sockaddrcmp((struct sockaddr*)&sin6,
-                                           (struct sockaddr *)&sav->sah->saidx.src, 0) != 0)
-                                               continue;
-                                       break;
-                               default:
-                                       printf("key_allocsa: unknown address family=%d.\n",
-                                               family);
-                                       continue;
-                               }
+               /* check src address */
+               switch (family) {
+               case AF_INET:
+                       bzero(&sin, sizeof(sin));
+                       sin.sin_family = AF_INET;
+                       sin.sin_len = sizeof(sin);
+                       bcopy(src, &sin.sin_addr,
+                           sizeof(sin.sin_addr));
+                       if (key_sockaddrcmp((struct sockaddr*)&sin,
+                           (struct sockaddr *)&sav->sah->saidx.src, 0) != 0)
+                               continue;
+                       break;
+               case AF_INET6:
+                  bzero(&sin6, sizeof(sin6));
+                  sin6.sin6_family = AF_INET6;
+                  sin6.sin6_len = sizeof(sin6);
+                  bcopy(src, &sin6.sin6_addr,
+                          sizeof(sin6.sin6_addr));
+                  if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
+                                  /* kame fake scopeid */
+                                  sin6.sin6_scope_id =
+                                          ntohs(sin6.sin6_addr.s6_addr16[1]);
+                                  sin6.sin6_addr.s6_addr16[1] = 0;
+                  }
+                  if (key_sockaddrcmp((struct sockaddr*)&sin6,
+                           (struct sockaddr *)&sav->sah->saidx.src, 0) != 0)
+                               continue;
+                       break;
+               default:
+                       ipseclog((LOG_DEBUG, "key_allocsa: "
+                           "unknown address family=%d.\n",
+                           family));
+                       continue;
+               }
 
 #endif
-                               /* check dst address */
-                               switch (family) {
-                               case AF_INET:
-                                       bzero(&sin, sizeof(sin));
-                                       sin.sin_family = AF_INET;
-                                       sin.sin_len = sizeof(sin);
-                                       bcopy(dst, &sin.sin_addr,
-                                           sizeof(sin.sin_addr));
-                                       if (key_sockaddrcmp((struct sockaddr*)&sin,
-                                           (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0)
-                                               continue;
-
-                                       break;
-                               case AF_INET6:
-                                       bzero(&sin6, sizeof(sin6));
-                                       sin6.sin6_family = AF_INET6;
-                                       sin6.sin6_len = sizeof(sin6);
-                                       bcopy(dst, &sin6.sin6_addr,
-                                           sizeof(sin6.sin6_addr));
-                                       if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
-                                               /* kame fake scopeid */
-                                               sin6.sin6_scope_id =
-                                                   ntohs(sin6.sin6_addr.s6_addr16[1]);
-                                               sin6.sin6_addr.s6_addr16[1] = 0;
-                                       }
-                                       if (key_sockaddrcmp((struct sockaddr*)&sin6,
-                                           (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0)
-                                               continue;
-                                       break;
-                               default:
-                                       printf("key_allocsa: unknown address family=%d.\n",
-                                               family);
-                                       continue;
-                               }
+               /* check dst address */
+               switch (family) {
+               case AF_INET:
+                       bzero(&sin, sizeof(sin));
+                       sin.sin_family = AF_INET;
+                       sin.sin_len = sizeof(sin);
+                       bcopy(dst, &sin.sin_addr,
+                           sizeof(sin.sin_addr));
+                       if (key_sockaddrcmp((struct sockaddr*)&sin,
+                           (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0)
+                               continue;
 
-                               goto found;
-                       }
+                       break;
+               case AF_INET6:
+                  bzero(&sin6, sizeof(sin6));
+                  sin6.sin6_family = AF_INET6;
+                  sin6.sin6_len = sizeof(sin6);
+                  bcopy(dst, &sin6.sin6_addr,
+                          sizeof(sin6.sin6_addr));
+                  if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
+                                  /* kame fake scopeid */
+                                  sin6.sin6_scope_id =
+                                          ntohs(sin6.sin6_addr.s6_addr16[1]);
+                                  sin6.sin6_addr.s6_addr16[1] = 0;
+                  }
+                  if (key_sockaddrcmp((struct sockaddr*)&sin6,
+                           (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0)
+                               continue;
+                       break;
+               default:
+                       ipseclog((LOG_DEBUG, "key_allocsa: "
+                           "unknown address family=%d.\n", family));
+                       continue;
                }
+
+               match = sav;
+               matchidx = tmpidx;
        }
+       if (match)
+               goto found;
 
        /* not found */
-       splx(s);
        return NULL;
 
 found:
-       sav->refcnt++;
-       splx(s);
+       match->refcnt++;        
        KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                printf("DP allocsa cause refcnt++:%d SA:%p\n",
-                       sav->refcnt, sav));
-       return sav;
+                       match->refcnt, match));
+       return match;
 }
 
 /*
@@ -950,6 +1125,8 @@ void
 key_freesp(sp)
        struct secpolicy *sp;
 {
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sp == NULL)
                panic("key_freesp: NULL pointer is passed.\n");
@@ -965,6 +1142,7 @@ key_freesp(sp)
        return;
 }
 
+#if 0
 /*
  * Must be called after calling key_allocsp().
  * For the packet with socket.
@@ -973,6 +1151,8 @@ void
 key_freeso(so)
        struct socket *so;
 {
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL)
                panic("key_freeso: NULL pointer is passed.\n");
@@ -1015,20 +1195,22 @@ key_freeso(so)
                break;
 #endif /* INET6 */
        default:
-#if IPSEC_DEBUG
-               printf("key_freeso: unknown address family=%d.\n",
-                       so->so_proto->pr_domain->dom_family);
-#endif
+               ipseclog((LOG_DEBUG, "key_freeso: unknown address family=%d.\n",
+                   so->so_proto->pr_domain->dom_family));
                return;
        }
 
        return;
 }
+#endif
 
 static void
 key_freesp_so(sp)
        struct secpolicy **sp;
 {
+
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sp == NULL || *sp == NULL)
                panic("key_freesp_so: sp == NULL\n");
@@ -1059,6 +1241,8 @@ void
 key_freesav(sav)
        struct secasvar *sav;
 {
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sav == NULL)
                panic("key_freesav: NULL pointer is passed.\n");
@@ -1084,6 +1268,8 @@ key_delsp(sp)
 {
        int s;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sp == NULL)
                panic("key_delsp: NULL pointer is passed.\n");
@@ -1134,6 +1320,8 @@ key_getsp(spidx)
 {
        struct secpolicy *sp;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (spidx == NULL)
                panic("key_getsp: NULL pointer is passed.\n");
@@ -1161,6 +1349,8 @@ key_getspbyid(id)
 {
        struct secpolicy *sp;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) {
                if (sp->state == IPSEC_SPSTATE_DEAD)
                        continue;
@@ -1210,15 +1400,15 @@ key_msg2sp(xpl0, len, error)
 {
        struct secpolicy *newsp;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (xpl0 == NULL)
                panic("key_msg2sp: NULL pointer was passed.\n");
        if (len < sizeof(*xpl0))
                panic("key_msg2sp: invalid length.\n");
        if (len != PFKEY_EXTLEN(xpl0)) {
-#if IPSEC_DEBUG
-               printf("key_msg2sp: Invalid msg length.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_msg2sp: Invalid msg length.\n"));
                *error = EINVAL;
                return NULL;
        }
@@ -1248,9 +1438,8 @@ key_msg2sp(xpl0, len, error)
 
                /* validity check */
                if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) {
-#if IPSEC_DEBUG
-                       printf("key_msg2sp: Invalid msg length.\n");
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_msg2sp: Invalid msg length.\n"));
                        key_freesp(newsp);
                        *error = EINVAL;
                        return NULL;
@@ -1263,10 +1452,8 @@ key_msg2sp(xpl0, len, error)
 
                        /* length check */
                        if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
-#if IPSEC_DEBUG
-                               printf("key_msg2sp: "
-                                       "invalid ipsecrequest length.\n");
-#endif
+                               ipseclog((LOG_DEBUG, "key_msg2sp: "
+                                       "invalid ipsecrequest length.\n"));
                                key_freesp(newsp);
                                *error = EINVAL;
                                return NULL;
@@ -1275,9 +1462,8 @@ key_msg2sp(xpl0, len, error)
                        /* allocate request buffer */
                        KMALLOC(*p_isr, struct ipsecrequest *, sizeof(**p_isr));
                        if ((*p_isr) == NULL) {
-#if IPSEC_DEBUG
-                               printf("key_msg2sp: No more memory.\n");
-#endif
+                               ipseclog((LOG_DEBUG,
+                                   "key_msg2sp: No more memory.\n"));
                                key_freesp(newsp);
                                *error = ENOBUFS;
                                return NULL;
@@ -1293,10 +1479,9 @@ key_msg2sp(xpl0, len, error)
                        case IPPROTO_IPCOMP:
                                break;
                        default:
-#if IPSEC_DEBUG
-                               printf("key_msg2sp: invalid proto type=%u\n",
-                                       xisr->sadb_x_ipsecrequest_proto);
-#endif
+                               ipseclog((LOG_DEBUG,
+                                   "key_msg2sp: invalid proto type=%u\n",
+                                   xisr->sadb_x_ipsecrequest_proto));
                                key_freesp(newsp);
                                *error = EPROTONOSUPPORT;
                                return NULL;
@@ -1309,10 +1494,9 @@ key_msg2sp(xpl0, len, error)
                                break;
                        case IPSEC_MODE_ANY:
                        default:
-#if IPSEC_DEBUG
-                               printf("key_msg2sp: invalid mode=%u\n",
-                                       xisr->sadb_x_ipsecrequest_mode);
-#endif
+                               ipseclog((LOG_DEBUG,
+                                   "key_msg2sp: invalid mode=%u\n",
+                                   xisr->sadb_x_ipsecrequest_mode));
                                key_freesp(newsp);
                                *error = EINVAL;
                                return NULL;
@@ -1332,12 +1516,10 @@ key_msg2sp(xpl0, len, error)
                                 */
                                if (xisr->sadb_x_ipsecrequest_reqid
                                                > IPSEC_MANUAL_REQID_MAX) {
-#if IPSEC_DEBUG
-                                       printf("key_msg2sp: reqid=%d "
-                                               "range violation, "
-                                               "updated by kernel.\n",
-                                               xisr->sadb_x_ipsecrequest_reqid);
-#endif
+                                       ipseclog((LOG_DEBUG,
+                                           "key_msg2sp: reqid=%d range "
+                                           "violation, updated by kernel.\n",
+                                           xisr->sadb_x_ipsecrequest_reqid));
                                        xisr->sadb_x_ipsecrequest_reqid = 0;
                                }
 
@@ -1359,10 +1541,8 @@ key_msg2sp(xpl0, len, error)
                                break;
 
                        default:
-#if IPSEC_DEBUG
-                               printf("key_msg2sp: invalid level=%u\n",
-                                       xisr->sadb_x_ipsecrequest_level);
-#endif
+                               ipseclog((LOG_DEBUG, "key_msg2sp: invalid level=%u\n",
+                                       xisr->sadb_x_ipsecrequest_level));
                                key_freesp(newsp);
                                *error = EINVAL;
                                return NULL;
@@ -1378,10 +1558,8 @@ key_msg2sp(xpl0, len, error)
                                /* validity check */
                                if (paddr->sa_len
                                    > sizeof((*p_isr)->saidx.src)) {
-#if IPSEC_DEBUG
-                                       printf("key_msg2sp: invalid request "
-                                               "address length.\n");
-#endif
+                                       ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
+                                               "address length.\n"));
                                        key_freesp(newsp);
                                        *error = EINVAL;
                                        return NULL;
@@ -1395,10 +1573,8 @@ key_msg2sp(xpl0, len, error)
                                /* validity check */
                                if (paddr->sa_len
                                    > sizeof((*p_isr)->saidx.dst)) {
-#if IPSEC_DEBUG
-                                       printf("key_msg2sp: invalid request "
-                                               "address length.\n");
-#endif
+                                       ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
+                                               "address length.\n"));
                                        key_freesp(newsp);
                                        *error = EINVAL;
                                        return NULL;
@@ -1416,9 +1592,7 @@ key_msg2sp(xpl0, len, error)
 
                        /* validity check */
                        if (tlen < 0) {
-#if IPSEC_DEBUG
-                               printf("key_msg2sp: becoming tlen < 0.\n");
-#endif
+                               ipseclog((LOG_DEBUG, "key_msg2sp: becoming tlen < 0.\n"));
                                key_freesp(newsp);
                                *error = EINVAL;
                                return NULL;
@@ -1430,9 +1604,7 @@ key_msg2sp(xpl0, len, error)
            }
                break;
        default:
-#if IPSEC_DEBUG
-               printf("key_msg2sp: invalid policy type.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_msg2sp: invalid policy type.\n"));
                key_freesp(newsp);
                *error = EINVAL;
                return NULL;
@@ -1447,6 +1619,8 @@ key_newreqid()
 {
        static u_int32_t auto_reqid = IPSEC_MANUAL_REQID_MAX + 1;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        auto_reqid = (auto_reqid == ~0
                        ? IPSEC_MANUAL_REQID_MAX + 1 : auto_reqid + 1);
 
@@ -1467,6 +1641,8 @@ key_sp2msg(sp)
        caddr_t p;
        struct mbuf *m;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check. */
        if (sp == NULL)
                panic("key_sp2msg: NULL pointer was passed.\n");
@@ -1625,6 +1801,8 @@ key_spdadd(so, m, mhp)
        struct timeval tv;
        int error;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_spdadd: NULL pointer is passed.\n");
@@ -1632,25 +1810,19 @@ key_spdadd(so, m, mhp)
        if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
            mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
            mhp->ext[SADB_X_EXT_POLICY] == NULL) {
-#if IPSEC_DEBUG
-               printf("key_spdadd: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
-#if IPSEC_DEBUG
-               printf("key_spdadd: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL) {
                if (mhp->extlen[SADB_EXT_LIFETIME_HARD]
                        < sizeof(struct sadb_lifetime)) {
-#if IPSEC_DEBUG
-                       printf("key_spdadd: invalid message is passed.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
                        return key_senderror(so, m, EINVAL);
                }
                lft = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD];
@@ -1676,9 +1848,7 @@ key_spdadd(so, m, mhp)
        case IPSEC_DIR_OUTBOUND:
                break;
        default:
-#if IPSEC_DEBUG
-               printf("key_spdadd: Invalid SP direction.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spdadd: Invalid SP direction.\n"));
                mhp->msg->sadb_msg_errno = EINVAL;
                return 0;
        }
@@ -1687,9 +1857,7 @@ key_spdadd(so, m, mhp)
        /* key_spdadd() accepts DISCARD, NONE and IPSEC. */
        if (xpl0->sadb_x_policy_type == IPSEC_POLICY_ENTRUST
         || xpl0->sadb_x_policy_type == IPSEC_POLICY_BYPASS) {
-#if IPSEC_DEBUG
-               printf("key_spdadd: Invalid policy type.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spdadd: Invalid policy type.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -1697,34 +1865,26 @@ key_spdadd(so, m, mhp)
         if (mhp->msg->sadb_msg_type != SADB_X_SPDSETIDX
         && xpl0->sadb_x_policy_type == IPSEC_POLICY_IPSEC
         && mhp->extlen[SADB_X_EXT_POLICY] <= sizeof(*xpl0)) {
-#if IPSEC_DEBUG
-               printf("key_spdadd: some policy requests part required.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spdadd: some policy requests part required.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
        /*
         * checking there is SP already or not.
-        * If type is SPDUPDATE and no SP found, then error.
-        * If type is either SPDADD or SPDSETIDX and SP found, then error.
+        * SPDUPDATE doesn't depend on whether there is a SP or not.
+        * If the type is either SPDADD or SPDSETIDX AND a SP is found,
+        * then error.
         */
        newsp = key_getsp(&spidx);
        if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
-               if (newsp == NULL) {
-#if IPSEC_DEBUG
-                       printf("key_spdadd: no SP found.\n");
-#endif
-                       return key_senderror(so, m, ENOENT);
+               if (newsp) {
+                       newsp->state = IPSEC_SPSTATE_DEAD;
+                       key_freesp(newsp);
                }
-
-               newsp->state = IPSEC_SPSTATE_DEAD;
-               key_freesp(newsp);
        } else {
                if (newsp != NULL) {
                        key_freesp(newsp);
-#if IPSEC_DEBUG
-                       printf("key_spdadd: a SP entry exists already.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_spdadd: a SP entry exists already.\n"));
                        return key_senderror(so, m, EEXIST);
                }
        }
@@ -1863,9 +2023,11 @@ key_getnewspid()
        int count = key_spi_trycnt;     /* XXX */
        struct secpolicy *sp;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* when requesting to allocate spi ranged */
        while (count--) {
-               newid = (policy_id = (policy_id == ~0 ? 1 : ++policy_id));
+               newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1));
 
                if ((sp = key_getspbyid(newid)) == NULL)
                        break;
@@ -1874,9 +2036,7 @@ key_getnewspid()
        }
 
        if (count == 0 || newid == 0) {
-#if IPSEC_DEBUG
-               printf("key_getnewspid: to allocate policy id is failed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_getnewspid: to allocate policy id is failed.\n"));
                return 0;
        }
 
@@ -1906,6 +2066,8 @@ key_spddelete(so, m, mhp)
        struct secpolicyindex spidx;
        struct secpolicy *sp;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_spddelete: NULL pointer is passed.\n");
@@ -1913,17 +2075,13 @@ key_spddelete(so, m, mhp)
        if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
            mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
            mhp->ext[SADB_X_EXT_POLICY] == NULL) {
-#if IPSEC_DEBUG
-               printf("key_spddelete: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
-#if IPSEC_DEBUG
-               printf("key_spddelete: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -1947,17 +2105,13 @@ key_spddelete(so, m, mhp)
        case IPSEC_DIR_OUTBOUND:
                break;
        default:
-#if IPSEC_DEBUG
-               printf("key_spddelete: Invalid SP direction.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spddelete: Invalid SP direction.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
        /* Is there SP in SPD ? */
        if ((sp = key_getsp(&spidx)) == NULL) {
-#if IPSEC_DEBUG
-               printf("key_spddelete: no SP found.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -2008,15 +2162,15 @@ key_spddelete2(so, m, mhp)
        u_int32_t id;
        struct secpolicy *sp;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_spddelete2: NULL pointer is passed.\n");
 
        if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
            mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
-#if IPSEC_DEBUG
-               printf("key_spddelete2: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spddelete2: invalid message is passed.\n"));
                key_senderror(so, m, EINVAL);
                return 0;
        }
@@ -2025,9 +2179,7 @@ key_spddelete2(so, m, mhp)
 
        /* Is there SP in SPD ? */
        if ((sp = key_getspbyid(id)) == NULL) {
-#if IPSEC_DEBUG
-               printf("key_spddelete2: no SP found id:%u.\n", id);
-#endif
+               ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n", id));
                key_senderror(so, m, EINVAL);
        }
 
@@ -2109,15 +2261,15 @@ key_spdget(so, m, mhp)
        struct secpolicy *sp;
        struct mbuf *n;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_spdget: NULL pointer is passed.\n");
 
        if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
            mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
-#if IPSEC_DEBUG
-               printf("key_spdget: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spdget: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -2125,9 +2277,7 @@ key_spdget(so, m, mhp)
 
        /* Is there SP in SPD ? */
        if ((sp = key_getspbyid(id)) == NULL) {
-#if IPSEC_DEBUG
-               printf("key_spdget: no SP found id:%u.\n", id);
-#endif
+               ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n", id));
                return key_senderror(so, m, ENOENT);
        }
 
@@ -2145,7 +2295,7 @@ key_spdget(so, m, mhp)
  * send
  *   <base, policy(*)>
  * to KMD, and expect to receive
- *   <base> with SADB_X_SPDACQUIRE if error occured,
+ *   <base> with SADB_X_SPDACQUIRE if error occurred,
  * or
  *   <base, policy>
  * with SADB_X_SPDUPDATE from KMD by PF_KEY.
@@ -2162,6 +2312,8 @@ key_spdacquire(sp)
        struct secspacq *newspacq;
        int error;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sp == NULL)
                panic("key_spdacquire: NULL pointer is passed.\n");
@@ -2234,6 +2386,8 @@ key_spdflush(so, m, mhp)
        struct secpolicy *sp;
        u_int dir;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_spdflush: NULL pointer is passed.\n");
@@ -2248,9 +2402,7 @@ key_spdflush(so, m, mhp)
        }
 
        if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) {
-#if IPSEC_DEBUG
-               printf("key_spdflush: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_spdflush: No more memory.\n"));
                return key_senderror(so, m, ENOBUFS);
        }
 
@@ -2287,6 +2439,8 @@ key_spddump(so, m, mhp)
        u_int dir;
        struct mbuf *n;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_spddump: NULL pointer is passed.\n");
@@ -2325,6 +2479,8 @@ key_setdumpsp(sp, type, seq, pid)
 {
        struct mbuf *result = NULL, *m;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt);
        if (!m)
                goto fail;
@@ -2381,6 +2537,8 @@ key_getspreqmsglen(sp)
 {
        u_int tlen;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        tlen = sizeof(struct sadb_x_policy);
 
        /* if is the policy for ipsec ? */
@@ -2423,8 +2581,7 @@ key_spdexpire(sp)
        int error = -1;
        struct sadb_lifetime *lt;
 
-       /* XXX: Why do we lock ? */
-       s = splnet();   /*called from softclock()*/
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
 
        /* sanity check */
        if (sp == NULL)
@@ -2517,7 +2674,6 @@ key_spdexpire(sp)
  fail:
        if (result)
                m_freem(result);
-       splx(s);
        return error;
 }
 
@@ -2533,6 +2689,8 @@ key_newsah(saidx)
 {
        struct secashead *newsah;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (saidx == NULL)
                panic("key_newsaidx: NULL pointer is passed.\n");
@@ -2562,6 +2720,8 @@ key_delsah(sah)
        int s;
        int zombie = 0;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sah == NULL)
                panic("key_delsah: NULL pointer is passed.\n");
@@ -2640,15 +2800,15 @@ key_newsav(m, mhp, sah, errp)
        struct secasvar *newsav;
        const struct sadb_sa *xsa;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (m == NULL || mhp == NULL || mhp->msg == NULL || sah == NULL)
                panic("key_newsa: NULL pointer is passed.\n");
 
        KMALLOC(newsav, struct secasvar *, sizeof(struct secasvar));
        if (newsav == NULL) {
-#if IPSEC_DEBUG
-               printf("key_newsa: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n"));
                *errp = ENOBUFS;
                return NULL;
        }
@@ -2656,7 +2816,7 @@ key_newsav(m, mhp, sah, errp)
 
        switch (mhp->msg->sadb_msg_type) {
        case SADB_GETSPI:
-               newsav->spi = 0;
+               key_setspi(newsav, 0);
 
 #if IPSEC_DOSEQCHECK
                /* sync sequence number */
@@ -2672,14 +2832,12 @@ key_newsav(m, mhp, sah, errp)
                /* sanity check */
                if (mhp->ext[SADB_EXT_SA] == NULL) {
                        KFREE(newsav);
-#if IPSEC_DEBUG
-                       printf("key_newsa: invalid message is passed.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_newsa: invalid message is passed.\n"));
                        *errp = EINVAL;
                        return NULL;
                }
                xsa = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA];
-               newsav->spi = xsa->sadb_sa_spi;
+               key_setspi(newsav, xsa->sadb_sa_spi);
                newsav->seq = mhp->msg->sadb_msg_seq;
                break;
        default:
@@ -2692,6 +2850,8 @@ key_newsav(m, mhp, sah, errp)
        if (mhp->msg->sadb_msg_type != SADB_GETSPI) {
                *errp = key_setsaval(newsav, m, mhp);
                if (*errp) {
+                       if (newsav->spihash.le_prev || newsav->spihash.le_next)
+                               LIST_REMOVE(newsav, spihash);
                        KFREE(newsav);
                        return NULL;
                }
@@ -2723,6 +2883,8 @@ static void
 key_delsav(sav)
        struct secasvar *sav;
 {
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sav == NULL)
                panic("key_delsav: NULL pointer is passed.\n");
@@ -2733,6 +2895,9 @@ key_delsav(sav)
        /* remove from SA header */
        if (__LIST_CHAINED(sav))
                LIST_REMOVE(sav, chain);
+               
+       if (sav->spihash.le_prev || sav->spihash.le_next)
+               LIST_REMOVE(sav, spihash);
 
        if (sav->key_auth != NULL) {
                bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
@@ -2787,10 +2952,12 @@ key_getsah(saidx)
 {
        struct secashead *sah;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        LIST_FOREACH(sah, &sahtree, chain) {
                if (sah->state == SADB_SASTATE_DEAD)
                        continue;
-               if (key_cmpsaidx_withoutmode2(&sah->saidx, saidx))
+               if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID))
                        return sah;
        }
 
@@ -2809,29 +2976,47 @@ key_checkspidup(saidx, spi)
        struct secasindex *saidx;
        u_int32_t spi;
 {
-       struct secashead *sah;
        struct secasvar *sav;
+       u_int stateidx, state;
+       
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
 
        /* check address family */
        if (saidx->src.ss_family != saidx->dst.ss_family) {
-#if IPSEC_DEBUG
-               printf("key_checkspidup: address family mismatched.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n"));
                return NULL;
        }
 
        /* check all SAD */
-       LIST_FOREACH(sah, &sahtree, chain) {
-               if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst))
+       LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
+               if (sav->spi != spi)
                        continue;
-               sav = key_getsavbyspi(sah, spi);
-               if (sav != NULL)
-                       return sav;
+               for (stateidx = 0;
+                    stateidx < _ARRAYLEN(saorder_state_alive);
+                    stateidx++) {
+                       state = saorder_state_alive[stateidx];
+                       if (sav->state == state &&
+                           key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst))
+                               return sav;
+               }
        }
 
        return NULL;
 }
 
+static void
+key_setspi(sav, spi)
+       struct secasvar *sav;
+       u_int32_t spi;
+{
+
+       sav->spi = spi;
+       if (sav->spihash.le_prev || sav->spihash.le_next)
+               LIST_REMOVE(sav, spihash);
+       LIST_INSERT_HEAD(&spihash[SPIHASH(spi)], sav, spihash);
+}
+
+
 /*
  * search SAD litmited alive SA, protocol, SPI.
  * OUT:
@@ -2843,34 +3028,27 @@ key_getsavbyspi(sah, spi)
        struct secashead *sah;
        u_int32_t spi;
 {
-       struct secasvar *sav;
-       u_int stateidx, state;
-
-       /* search all status */
-       for (stateidx = 0;
-            stateidx < _ARRAYLEN(saorder_state_alive);
-            stateidx++) {
-
-               state = saorder_state_alive[stateidx];
-               LIST_FOREACH(sav, &sah->savtree[state], chain) {
-
-                       /* sanity check */
-                       if (sav->state != state) {
-#if IPSEC_DEBUG
-                               printf("key_getsavbyspi: "
-                                       "invalid sav->state "
-                                       "(queue: %d SA: %d)\n",
-                                       state, sav->state);
-#endif
-                               continue;
+       struct secasvar *sav, *match;
+       u_int stateidx, state, matchidx;
+                       
+       match = NULL;
+       matchidx = _ARRAYLEN(saorder_state_alive);
+       LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
+               if (sav->spi != spi)
+                       continue;
+               if (sav->sah != sah)
+                       continue;
+               for (stateidx = 0; stateidx < matchidx; stateidx++) {
+                       state = saorder_state_alive[stateidx];
+                       if (sav->state == state) {
+                               match = sav;
+                               matchidx = stateidx;
+                               break;
                        }
-
-                       if (sav->spi == spi)
-                               return sav;
                }
        }
 
-       return NULL;
+       return match;
 }
 
 /*
@@ -2893,6 +3071,8 @@ key_setsaval(sav, m, mhp)
        int error = 0;
        struct timeval tv;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_setsaval: NULL pointer is passed.\n");
@@ -2907,6 +3087,8 @@ key_setsaval(sav, m, mhp)
        sav->lft_c = NULL;
        sav->lft_h = NULL;
        sav->lft_s = NULL;
+       sav->remote_ike_port = 0;
+       sav->natt_last_activity = natt_now;
 
        /* SA */
        if (mhp->ext[SADB_EXT_SA] != NULL) {
@@ -2914,6 +3096,7 @@ key_setsaval(sav, m, mhp)
 
                sa0 = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA];
                if (mhp->extlen[SADB_EXT_SA] < sizeof(*sa0)) {
+                       ipseclog((LOG_DEBUG, "key_setsaval: invalid message size.\n"));
                        error = EINVAL;
                        goto fail;
                }
@@ -2921,14 +3104,26 @@ key_setsaval(sav, m, mhp)
                sav->alg_auth = sa0->sadb_sa_auth;
                sav->alg_enc = sa0->sadb_sa_encrypt;
                sav->flags = sa0->sadb_sa_flags;
+               
+               /*
+                * Verify that a nat-traversal port was specified if
+                * the nat-traversal flag is set.
+                */
+               if ((sav->flags & SADB_X_EXT_NATT) != 0) {
+                       if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa_2) ||
+                                ((struct sadb_sa_2*)(sa0))->sadb_sa_natt_port == 0) {
+                               ipseclog((LOG_DEBUG, "key_setsaval: natt port not set.\n"));
+                               error = EINVAL;
+                               goto fail;
+                       }
+                       sav->remote_ike_port = ((struct sadb_sa_2*)(sa0))->sadb_sa_natt_port;
+               }
 
                /* replay window */
                if ((sa0->sadb_sa_flags & SADB_X_EXT_OLD) == 0) {
                        sav->replay = keydb_newsecreplay(sa0->sadb_sa_replay);
                        if (sav->replay == NULL) {
-#if IPSEC_DEBUG
-                               printf("key_setsaval: No more memory.\n");
-#endif
+                               ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
                                error = ENOBUFS;
                                goto fail;
                        }
@@ -2945,6 +3140,7 @@ key_setsaval(sav, m, mhp)
 
                error = 0;
                if (len < sizeof(*key0)) {
+                       ipseclog((LOG_DEBUG, "key_setsaval: invalid auth key ext len. len = %d\n", len));
                        error = EINVAL;
                        goto fail;
                }
@@ -2961,17 +3157,13 @@ key_setsaval(sav, m, mhp)
                        break;
                }
                if (error) {
-#if IPSEC_DEBUG
-                       printf("key_setsaval: invalid key_auth values.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_setsaval: invalid key_auth values.\n"));
                        goto fail;
                }
 
                sav->key_auth = (struct sadb_key *)key_newbuf(key0, len);
                if (sav->key_auth == NULL) {
-#if IPSEC_DEBUG
-                       printf("key_setsaval: No more memory.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
                        error = ENOBUFS;
                        goto fail;
                }
@@ -2987,6 +3179,7 @@ key_setsaval(sav, m, mhp)
 
                error = 0;
                if (len < sizeof(*key0)) {
+                       ipseclog((LOG_DEBUG, "key_setsaval: invalid encryption key ext len. len = %d\n", len));
                        error = EINVAL;
                        goto fail;
                }
@@ -2994,14 +3187,13 @@ key_setsaval(sav, m, mhp)
                case SADB_SATYPE_ESP:
                        if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) &&
                            sav->alg_enc != SADB_EALG_NULL) {
+                           ipseclog((LOG_DEBUG, "key_setsaval: invalid ESP algorithm.\n"));
                                error = EINVAL;
                                break;
                        }
                        sav->key_enc = (struct sadb_key *)key_newbuf(key0, len);
                        if (sav->key_enc == NULL) {
-#if IPSEC_DEBUG
-                               printf("key_setsaval: No more memory.\n");
-#endif
+                               ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
                                error = ENOBUFS;
                                goto fail;
                        }
@@ -3017,9 +3209,7 @@ key_setsaval(sav, m, mhp)
                        break;
                }
                if (error) {
-#if IPSEC_DEBUG
-                       printf("key_setsatval: invalid key_enc value.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_setsaval: invalid key_enc value.\n"));
                        goto fail;
                }
        }
@@ -3037,9 +3227,7 @@ key_setsaval(sav, m, mhp)
                        break;
                KMALLOC(sav->iv, caddr_t, sav->ivlen);
                if (sav->iv == 0) {
-#if IPSEC_DEBUG
-                       printf("key_setsaval: No more memory.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
                        error = ENOBUFS;
                        goto fail;
                }
@@ -3052,9 +3240,7 @@ key_setsaval(sav, m, mhp)
        case SADB_X_SATYPE_IPCOMP:
                break;
        default:
-#if IPSEC_DEBUG
-               printf("key_setsaval: invalid SA type.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_setsaval: invalid SA type.\n"));
                error = EINVAL;
                goto fail;
        }
@@ -3067,9 +3253,7 @@ key_setsaval(sav, m, mhp)
        KMALLOC(sav->lft_c, struct sadb_lifetime *,
            sizeof(struct sadb_lifetime));
        if (sav->lft_c == NULL) {
-#if IPSEC_DEBUG
-               printf("key_setsaval: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
                error = ENOBUFS;
                goto fail;
        }
@@ -3091,15 +3275,14 @@ key_setsaval(sav, m, mhp)
        lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD];
        if (lft0 != NULL) {
                if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) {
+                       ipseclog((LOG_DEBUG, "key_setsaval: invalid hard lifetime ext len.\n"));
                        error = EINVAL;
                        goto fail;
                }
                sav->lft_h = (struct sadb_lifetime *)key_newbuf(lft0,
                    sizeof(*lft0));
                if (sav->lft_h == NULL) {
-#if IPSEC_DEBUG
-                       printf("key_setsaval: No more memory.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
                        error = ENOBUFS;
                        goto fail;
                }
@@ -3109,15 +3292,14 @@ key_setsaval(sav, m, mhp)
        lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_SOFT];
        if (lft0 != NULL) {
                if (mhp->extlen[SADB_EXT_LIFETIME_SOFT] < sizeof(*lft0)) {
+                       ipseclog((LOG_DEBUG, "key_setsaval: invalid soft lifetime ext len.\n"));
                        error = EINVAL;
                        goto fail;
                }
                sav->lft_s = (struct sadb_lifetime *)key_newbuf(lft0,
                    sizeof(*lft0));
                if (sav->lft_s == NULL) {
-#if IPSEC_DEBUG
-                       printf("key_setsaval: No more memory.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
                        error = ENOBUFS;
                        goto fail;
                }
@@ -3134,14 +3316,17 @@ key_setsaval(sav, m, mhp)
                sav->replay = NULL;
        }
        if (sav->key_auth != NULL) {
+               bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
                KFREE(sav->key_auth);
                sav->key_auth = NULL;
        }
        if (sav->key_enc != NULL) {
+               bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc));
                KFREE(sav->key_enc);
                sav->key_enc = NULL;
        }
        if (sav->sched) {
+               bzero(sav->sched, sav->schedlen);
                KFREE(sav->sched);
                sav->sched = NULL;
        }
@@ -3180,15 +3365,16 @@ key_mature(sav)
 
        mature = 0;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* check SPI value */
        switch (sav->sah->saidx.proto) {
        case IPPROTO_ESP:
        case IPPROTO_AH:
                if (ntohl(sav->spi) >= 0 && ntohl(sav->spi) <= 255) {
-#if IPSEC_DEBUG
-                       printf("key_mature: illegal range of SPI %u.\n",
-                           (u_int32_t)ntohl(sav->spi));
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_mature: illegal range of SPI %u.\n",
+                           (u_int32_t)ntohl(sav->spi)));
                        return EINVAL;
                }
                break;
@@ -3200,10 +3386,8 @@ key_mature(sav)
                /* check flags */
                if ((sav->flags & SADB_X_EXT_OLD)
                 && (sav->flags & SADB_X_EXT_DERIV)) {
-#if IPSEC_DEBUG
-                       printf("key_mature: "
-                               "invalid flag (derived) given to old-esp.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: "
+                           "invalid flag (derived) given to old-esp.\n"));
                        return EINVAL;
                }
                if (sav->alg_auth == SADB_AALG_NONE)
@@ -3215,17 +3399,13 @@ key_mature(sav)
        case IPPROTO_AH:
                /* check flags */
                if (sav->flags & SADB_X_EXT_DERIV) {
-#if IPSEC_DEBUG
-                       printf("key_mature: "
-                               "invalid flag (derived) given to AH SA.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: "
+                           "invalid flag (derived) given to AH SA.\n"));
                        return EINVAL;
                }
                if (sav->alg_enc != SADB_EALG_NONE) {
-#if IPSEC_DEBUG
-                       printf("key_mature: "
-                               "protocol and algorithm mismated.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: "
+                           "protocol and algorithm mismated.\n"));
                        return(EINVAL);
                }
                checkmask = 2;
@@ -3233,26 +3413,20 @@ key_mature(sav)
                break;
        case IPPROTO_IPCOMP:
                if (sav->alg_auth != SADB_AALG_NONE) {
-#if IPSEC_DEBUG
-                       printf("key_mature: "
-                               "protocol and algorithm mismated.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: "
+                               "protocol and algorithm mismated.\n"));
                        return(EINVAL);
                }
                if ((sav->flags & SADB_X_EXT_RAWCPI) == 0
                 && ntohl(sav->spi) >= 0x10000) {
-#if IPSEC_DEBUG
-                       printf("key_mature: invalid cpi for IPComp.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: invalid cpi for IPComp.\n"));
                        return(EINVAL);
                }
                checkmask = 4;
                mustmask = 4;
                break;
        default:
-#if IPSEC_DEBUG
-               printf("key_mature: Invalid satype.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_mature: Invalid satype.\n"));
                return EPROTONOSUPPORT;
        }
 
@@ -3263,10 +3437,8 @@ key_mature(sav)
 
                algo = ah_algorithm_lookup(sav->alg_auth);
                if (!algo) {
-#if IPSEC_DEBUG
-                       printf("key_mature: "
-                               "unknown authentication algorithm.\n");
-#endif
+                       ipseclog((LOG_DEBUG,"key_mature: "
+                           "unknown authentication algorithm.\n"));
                        return EINVAL;
                }
 
@@ -3276,11 +3448,10 @@ key_mature(sav)
                else
                        keylen = 0;
                if (keylen < algo->keymin || algo->keymax < keylen) {
-#if IPSEC_DEBUG
-                       printf("key_mature: invalid AH key length %d "
-                               "(%d-%d allowed)\n", keylen,
-                               algo->keymin, algo->keymax);
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_mature: invalid AH key length %d "
+                           "(%d-%d allowed)\n",
+                           keylen, algo->keymin, algo->keymax));
                        return EINVAL;
                }
 
@@ -3293,9 +3464,7 @@ key_mature(sav)
                }
 
                if ((mustmask & 2) != 0 &&  mature != SADB_SATYPE_AH) {
-#if IPSEC_DEBUG
-                       printf("key_mature: no satisfy algorithm for AH\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for AH\n"));
                        return EINVAL;
                }
        }
@@ -3308,9 +3477,7 @@ key_mature(sav)
 
                algo = esp_algorithm_lookup(sav->alg_enc);
                if (!algo) {
-#if IPSEC_DEBUG
-                       printf("key_mature: unknown encryption algorithm.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: unknown encryption algorithm.\n"));
                        return EINVAL;
                }
 
@@ -3320,11 +3487,10 @@ key_mature(sav)
                else
                        keylen = 0;
                if (keylen < algo->keymin || algo->keymax < keylen) {
-#if IPSEC_DEBUG
-                       printf("key_mature: invalid ESP key length %d "
-                               "(%d-%d allowed)\n", keylen,
-                               algo->keymin, algo->keymax);
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_mature: invalid ESP key length %d "
+                           "(%d-%d allowed)\n",
+                           keylen, algo->keymin, algo->keymax));
                        return EINVAL;
                }
 
@@ -3337,15 +3503,11 @@ key_mature(sav)
                }
 
                if ((mustmask & 1) != 0 &&  mature != SADB_SATYPE_ESP) {
-#if IPSEC_DEBUG
-                       printf("key_mature: no satisfy algorithm for ESP\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for ESP\n"));
                        return EINVAL;
                }
 #else /*IPSEC_ESP*/
-#if IPSEC_DEBUG
-               printf("key_mature: ESP not supported in this configuration\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_mature: ESP not supported in this configuration\n"));
                return EINVAL;
 #endif
        }
@@ -3357,9 +3519,7 @@ key_mature(sav)
                /* algorithm-dependent check */
                algo = ipcomp_algorithm_lookup(sav->alg_enc);
                if (!algo) {
-#if IPSEC_DEBUG
-                       printf("key_mature: unknown compression algorithm.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_mature: unknown compression algorithm.\n"));
                        return EINVAL;
                }
        }
@@ -3391,6 +3551,8 @@ key_setdumpsa(sav, type, satype, seq, pid)
                SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY,
        };
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt);
        if (m == NULL)
                goto fail;
@@ -3408,6 +3570,7 @@ key_setdumpsa(sav, type, satype, seq, pid)
 
                case SADB_X_EXT_SA2:
                        m = key_setsadbxsa2(sav->sah->saidx.mode,
+                                       sav->replay ? sav->replay->count : 0,
                                        sav->sah->saidx.reqid);
                        if (!m)
                                goto fail;
@@ -3416,7 +3579,7 @@ key_setdumpsa(sav, type, satype, seq, pid)
                case SADB_EXT_ADDRESS_SRC:
                        m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
                            (struct sockaddr *)&sav->sah->saidx.src,
-                           sav->sah->saidx.src.ss_len << 3, IPSEC_ULPROTO_ANY);
+                           FULLMASK, IPSEC_ULPROTO_ANY);
                        if (!m)
                                goto fail;
                        break;
@@ -3424,7 +3587,7 @@ key_setdumpsa(sav, type, satype, seq, pid)
                case SADB_EXT_ADDRESS_DST:
                        m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
                            (struct sockaddr *)&sav->sah->saidx.dst,
-                           sav->sah->saidx.dst.ss_len << 3, IPSEC_ULPROTO_ANY);
+                           FULLMASK, IPSEC_ULPROTO_ANY);
                        if (!m)
                                goto fail;
                        break;
@@ -3626,6 +3789,18 @@ key_setsadbaddr(exttype, saddr, prefixlen, ul_proto)
        p->sadb_address_len = PFKEY_UNIT64(len);
        p->sadb_address_exttype = exttype;
        p->sadb_address_proto = ul_proto;
+       if (prefixlen == FULLMASK) {
+               switch (saddr->sa_family) {
+               case AF_INET:
+                       prefixlen = sizeof(struct in_addr) << 3;
+                       break;
+               case AF_INET6:
+                       prefixlen = sizeof(struct in6_addr) << 3;
+                       break;
+               default:
+                       ; /*XXX*/
+               }
+       }
        p->sadb_address_prefixlen = prefixlen;
        p->sadb_address_reserved = 0;
 
@@ -3680,9 +3855,9 @@ key_setsadbident(exttype, idtype, string, stringlen, id)
  * set data into sadb_x_sa2.
  */
 static struct mbuf *
-key_setsadbxsa2(mode, reqid)
+key_setsadbxsa2(mode, seq, reqid)
        u_int8_t mode;
-       u_int32_t reqid;
+       u_int32_t seq, reqid;
 {
        struct mbuf *m;
        struct sadb_x_sa2 *p;
@@ -3704,7 +3879,7 @@ key_setsadbxsa2(mode, reqid)
        p->sadb_x_sa2_mode = mode;
        p->sadb_x_sa2_reserved1 = 0;
        p->sadb_x_sa2_reserved2 = 0;
-       p->sadb_x_sa2_reserved3 = 0;
+       p->sadb_x_sa2_sequence = seq;
        p->sadb_x_sa2_reqid = reqid;
 
        return m;
@@ -3756,9 +3931,7 @@ key_newbuf(src, len)
 
        KMALLOC(new, caddr_t, len);
        if (new == NULL) {
-#if IPSEC_DEBUG
-               printf("key_newbuf: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_newbuf: No more memory.\n"));
                return NULL;
        }
        bcopy(src, new, len);
@@ -3786,6 +3959,7 @@ key_ismyaddr(sa)
        switch (sa->sa_family) {
 #if INET
        case AF_INET:
+               lck_mtx_lock(rt_mtx);
                sin = (struct sockaddr_in *)sa;
                for (ia = in_ifaddrhead.tqh_first; ia;
                     ia = ia->ia_link.tqe_next)
@@ -3794,9 +3968,11 @@ key_ismyaddr(sa)
                            sin->sin_len == ia->ia_addr.sin_len &&
                            sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
                        {
+                               lck_mtx_unlock(rt_mtx);
                                return 1;
                        }
                }
+               lck_mtx_unlock(rt_mtx);
                break;
 #endif
 #if INET6
@@ -3824,10 +4000,13 @@ key_ismyaddr6(sin6)
        struct in6_ifaddr *ia;
        struct in6_multi *in6m;
 
-       for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
+       lck_mtx_lock(nd6_mutex);
+       for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
                if (key_sockaddrcmp((struct sockaddr *)&sin6,
-                   (struct sockaddr *)&ia->ia_addr, 0) == 0)
+                   (struct sockaddr *)&ia->ia_addr, 0) == 0) {
+                       lck_mtx_unlock(nd6_mutex);
                        return 1;
+               }
 
                /*
                 * XXX Multicast
@@ -3837,9 +4016,12 @@ key_ismyaddr6(sin6)
                 */
                in6m = NULL;
                IN6_LOOKUP_MULTI(sin6->sin6_addr, ia->ia_ifp, in6m);
-               if (in6m)
+               if (in6m) {
+                       lck_mtx_unlock(nd6_mutex);
                        return 1;
+               }
        }
+       lck_mtx_unlock(nd6_mutex);
 
        /* loopback, just for safety */
        if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
@@ -3850,96 +4032,21 @@ key_ismyaddr6(sin6)
 #endif /*INET6*/
 
 /*
- * compare two secasindex structure exactly.
- * IN:
- *     saidx0: source, it can be in SAD.
- *     saidx1: object.
- * OUT:
- *     1 : equal
- *     0 : not equal
- */
-static int
-key_cmpsaidx_exactly(saidx0, saidx1)
-       struct secasindex *saidx0, *saidx1;
-{
-       /* sanity */
-       if (saidx0 == NULL && saidx1 == NULL)
-               return 1;
-
-       if (saidx0 == NULL || saidx1 == NULL)
-               return 0;
-
-       if (saidx0->proto != saidx1->proto
-        || saidx0->mode != saidx1->mode
-        || saidx0->reqid != saidx1->reqid)
-               return 0;
-
-       if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.ss_len) != 0 ||
-           bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.ss_len) != 0)
-               return 0;
-
-       return 1;
-}
-
-/*
- * compare two secasindex structure with consideration mode.
- * don't compare port.
- * IN:
- *     saidx0: source, it is often in SAD.
- *     saidx1: object, it is often from SPD.
- * OUT:
- *     1 : equal
- *     0 : not equal
- */
-static int
-key_cmpsaidx_withmode(saidx0, saidx1)
-       struct secasindex *saidx0, *saidx1;
-{
-       /* sanity */
-       if (saidx0 == NULL && saidx1 == NULL)
-               return 1;
-
-       if (saidx0 == NULL || saidx1 == NULL)
-               return 0;
-
-       if (saidx0->proto != saidx1->proto)
-               return 0;
-
-       /*
-        * If reqid of SPD is non-zero, unique SA is required.
-        * The result must be of same reqid in this case.
-        */
-       if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid)
-               return 0;
-
-       if (saidx0->mode != IPSEC_MODE_ANY && saidx0->mode != saidx1->mode)
-               return 0;
-
-       if (key_sockaddrcmp((struct sockaddr *)&saidx0->src,
-           (struct sockaddr *)&saidx1->src, 0) != 0) {
-               return 0;
-       }
-       if (key_sockaddrcmp((struct sockaddr *)&saidx0->dst,
-           (struct sockaddr *)&saidx1->dst, 0) != 0) {
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * compare two secasindex structure without mode, but think reqid.
+ * compare two secasindex structure.
+ * flag can specify to compare 2 saidxes.
+ * compare two secasindex structure without both mode and reqid.
  * don't compare port.
- * IN:
- *     saidx0: source, it is often in SAD.
- *     saidx1: object, it is often from user.
- * OUT:
- *     1 : equal
- *     0 : not equal
+ * IN:  
+ *      saidx0: source, it can be in SAD.
+ *      saidx1: object.
+ * OUT: 
+ *      1 : equal
+ *      0 : not equal
  */
 static int
-key_cmpsaidx_withoutmode2(saidx0, saidx1)
+key_cmpsaidx(saidx0, saidx1, flag)
        struct secasindex *saidx0, *saidx1;
+       int flag;
 {
        /* sanity */
        if (saidx0 == NULL && saidx1 == NULL)
@@ -3951,56 +4058,41 @@ key_cmpsaidx_withoutmode2(saidx0, saidx1)
        if (saidx0->proto != saidx1->proto)
                return 0;
 
-       /*
-        * If reqid of SPD is non-zero, unique SA is required.
-        * The result must be of same reqid in this case.
-        */
-       if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid)
-               return 0;
-
-       if (key_sockaddrcmp((struct sockaddr *)&saidx0->src,
-           (struct sockaddr *)&saidx1->src, 0) != 0) {
-               return 0;
-       }
-       if (key_sockaddrcmp((struct sockaddr *)&saidx0->dst,
-           (struct sockaddr *)&saidx1->dst, 0) != 0) {
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- * compare two secasindex structure without both mode and reqid.
- * don't compare port.
- * IN:
- *     saidx0: source, it is often in SAD.
- *     saidx1: object, it is often from user.
- * OUT:
- *     1 : equal
- *     0 : not equal
- */
-static int
-key_cmpsaidx_withoutmode(saidx0, saidx1)
-       struct secasindex *saidx0, *saidx1;
-{
-       /* sanity */
-       if (saidx0 == NULL && saidx1 == NULL)
-               return 1;
+       if (flag == CMP_EXACTLY) {
+               if (saidx0->mode != saidx1->mode)
+                       return 0;
+               if (saidx0->reqid != saidx1->reqid)
+                       return 0;
+               if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.ss_len) != 0 ||
+                   bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.ss_len) != 0)
+                       return 0;
+       } else {
 
-       if (saidx0 == NULL || saidx1 == NULL)
-               return 0;
+               /* CMP_MODE_REQID, CMP_REQID, CMP_HEAD */
+               if (flag == CMP_MODE_REQID
+                 ||flag == CMP_REQID) {
+                       /*
+                        * If reqid of SPD is non-zero, unique SA is required.
+                        * The result must be of same reqid in this case.
+                        */
+                       if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid)
+                               return 0;
+               }
 
-       if (saidx0->proto != saidx1->proto)
-               return 0;
+               if (flag == CMP_MODE_REQID) {
+                       if (saidx0->mode != IPSEC_MODE_ANY
+                        && saidx0->mode != saidx1->mode)
+                               return 0;
+               }
 
-       if (key_sockaddrcmp((struct sockaddr *)&saidx0->src,
-           (struct sockaddr *)&saidx1->src, 0) != 0) {
-               return 0;
-       }
-       if (key_sockaddrcmp((struct sockaddr *)&saidx0->dst,
-           (struct sockaddr *)&saidx1->dst, 0) != 0) {
-               return 0;
+               if (key_sockaddrcmp((struct sockaddr *)&saidx0->src,
+                               (struct sockaddr *)&saidx1->src, 0) != 0) {
+                       return 0;
+               }
+               if (key_sockaddrcmp((struct sockaddr *)&saidx0->dst,
+                               (struct sockaddr *)&saidx1->dst, 0) != 0) {
+                       return 0;
+               }
        }
 
        return 1;
@@ -4238,18 +4330,6 @@ key_bbcmp(p1, p2, bits)
  * and do to remove or to expire.
  * XXX: year 2038 problem may remain.
  */
-void
-key_timehandler_funnel(void)
-{
-#ifdef __APPLE__
-       boolean_t   funnel_state;
-       funnel_state = thread_funnel_set(network_flock, TRUE);
-#endif
-       key_timehandler();
-#ifdef __APPLE__
-        (void) thread_funnel_set(network_flock, FALSE);
-#endif
-}
 
 void
 key_timehandler(void)
@@ -4260,8 +4340,7 @@ key_timehandler(void)
 
        microtime(&tv);
 
-       s = splnet();   /*called from softclock()*/
-
+       lck_mtx_lock(sadb_mutex);
        /* SPD */
     {
        struct secpolicy *sp, *nextsp;
@@ -4322,7 +4401,23 @@ key_timehandler(void)
                                key_freesav(sav);
                        }
                }
-
+               
+               /*
+                * If this is a NAT traversal SA with no activity,
+                * we need to send a keep alive.
+                *
+                * Performed outside of the loop before so we will
+                * only ever send one keepalive. The first SA on
+                * the list is the one that will be used for sending
+                * traffic, so this is the one we use for determining
+                * when to send the keepalive.
+                */
+               sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_MATURE]);
+               if (natt_keepalive_interval && sav && (sav->flags & SADB_X_EXT_NATT_KEEPALIVE) != 0 &&
+                       (natt_now - sav->natt_last_activity) >= natt_keepalive_interval) {
+                       ipsec_send_natt_keepalive(sav);
+               }
+               
                /*
                 * check MATURE entry to start to send expire message
                 * whether or not.
@@ -4339,10 +4434,8 @@ key_timehandler(void)
 
                        /* sanity check */
                        if (sav->lft_c == NULL) {
-#if IPSEC_DEBUG
-                               printf("key_timehandler: "
-                                       "There is no CURRENT time, why?\n");
-#endif
+                               ipseclog((LOG_DEBUG,"key_timehandler: "
+                                       "There is no CURRENT time, why?\n"));
                                continue;
                        }
 
@@ -4350,8 +4443,9 @@ key_timehandler(void)
                        if (sav->lft_s->sadb_lifetime_addtime != 0
                         && tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) {
                                /*
-                                * check SA to be used whether or not.
-                                * when SA hasn't been used, delete it.
+                                * check the SA if it has been used.
+                                * when it hasn't been used, delete it.
+                                * i don't think such SA will be used.
                                 */
                                if (sav->lft_c->sadb_lifetime_usetime == 0) {
                                        key_sa_chgstate(sav, SADB_SASTATE_DEAD);
@@ -4367,6 +4461,7 @@ key_timehandler(void)
                                        key_expire(sav);
                                }
                        }
+
                        /* check SOFT lifetime by bytes */
                        /*
                         * XXX I don't know the way to delete this SA
@@ -4399,10 +4494,8 @@ key_timehandler(void)
 
                        /* sanity check */
                        if (sav->lft_c == NULL) {
-#if IPSEC_DEBUG
-                               printf("key_timehandler: "
-                                       "There is no CURRENT time, why?\n");
-#endif
+                               ipseclog((LOG_DEBUG, "key_timehandler: "
+                                       "There is no CURRENT time, why?\n"));
                                continue;
                        }
 
@@ -4446,13 +4539,11 @@ key_timehandler(void)
 
                        /* sanity check */
                        if (sav->state != SADB_SASTATE_DEAD) {
-#if IPSEC_DEBUG
-                               printf("key_timehandler: "
+                               ipseclog((LOG_DEBUG, "key_timehandler: "
                                        "invalid sav->state "
                                        "(queue: %d SA: %d): "
                                        "kill it anyway\n",
-                                       SADB_SASTATE_DEAD, sav->state);
-#endif
+                                       SADB_SASTATE_DEAD, sav->state));
                        }
 
                        /*
@@ -4508,13 +4599,15 @@ key_timehandler(void)
                key_tick_init_random = 0;
                key_srandom();
        }
+       
+       natt_now++;
 
+       lck_mtx_unlock(sadb_mutex);
 #ifndef IPSEC_DEBUG2
        /* do exchange to tick time !! */
-       (void)timeout((void *)key_timehandler_funnel, (void *)0, hz);
+       (void)timeout((void *)key_timehandler, (void *)0, hz);
 #endif /* IPSEC_DEBUG2 */
 
-       splx(s);
        return;
 }
 
@@ -4655,22 +4748,20 @@ key_getspi(so, m, mhp)
        u_int32_t reqid;
        int error;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_getspi: NULL pointer is passed.\n");
 
        if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
            mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
-#if IPSEC_DEBUG
-               printf("key_getspi: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
-#if IPSEC_DEBUG
-               printf("key_getspi: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
@@ -4686,9 +4777,7 @@ key_getspi(so, m, mhp)
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_getspi: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_getspi: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -4739,9 +4828,7 @@ key_getspi(so, m, mhp)
        if ((newsah = key_getsah(&saidx)) == NULL) {
                /* create a new SA index */
                if ((newsah = key_newsah(&saidx)) == NULL) {
-#if IPSEC_DEBUG
-                       printf("key_getspi: No more memory.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n"));
                        return key_senderror(so, m, ENOBUFS);
                }
        }
@@ -4755,7 +4842,7 @@ key_getspi(so, m, mhp)
        }
 
        /* set spi */
-       newsav->spi = htonl(spi);
+       key_setspi(newsav, htonl(spi));
 
 #ifndef IPSEC_NONBLOCK_ACQUIRE
        /* delete the entry in acqtree */
@@ -4856,6 +4943,8 @@ key_do_getnewspi(spirange, saidx)
        u_int32_t min, max;
        int count = key_spi_trycnt;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* set spi range to allocate */
        if (spirange != NULL) {
                min = spirange->sadb_spirange_min;
@@ -4878,9 +4967,7 @@ key_do_getnewspi(spirange, saidx)
 
        if (min == max) {
                if (key_checkspidup(saidx, min) != NULL) {
-#if IPSEC_DEBUG
-                       printf("key_do_getnewspi: SPI %u exists already.\n", min);
-#endif
+                       ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n", min));
                        return 0;
                }
 
@@ -4902,9 +4989,7 @@ key_do_getnewspi(spirange, saidx)
                }
 
                if (count == 0 || newspi == 0) {
-#if IPSEC_DEBUG
-                       printf("key_do_getnewspi: to allocate spi is failed.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_do_getnewspi: to allocate spi is failed.\n"));
                        return 0;
                }
        }
@@ -4945,15 +5030,15 @@ key_update(so, m, mhp)
        u_int32_t reqid;
        int error;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_update: NULL pointer is passed.\n");
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_update: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_update: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -4968,17 +5053,13 @@ key_update(so, m, mhp)
             mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) ||
            (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL &&
             mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) {
-#if IPSEC_DEBUG
-               printf("key_update: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
            mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
-#if IPSEC_DEBUG
-               printf("key_update: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
@@ -4999,9 +5080,7 @@ key_update(so, m, mhp)
 
        /* get a SA header */
        if ((sah = key_getsah(&saidx)) == NULL) {
-#if IPSEC_DEBUG
-               printf("key_update: no SA index found.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_update: no SA index found.\n"));
                return key_senderror(so, m, ENOENT);
        }
 
@@ -5015,45 +5094,40 @@ key_update(so, m, mhp)
 #if IPSEC_DOSEQCHECK
        if (mhp->msg->sadb_msg_seq != 0
         && (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) {
-#if IPSEC_DEBUG
-               printf("key_update: no larval SA with sequence %u exists.\n",
-                       mhp->msg->sadb_msg_seq);
-#endif
+               ipseclog((LOG_DEBUG,
+                   "key_update: no larval SA with sequence %u exists.\n",
+                   mhp->msg->sadb_msg_seq));
                return key_senderror(so, m, ENOENT);
        }
 #else
        if ((sav = key_getsavbyspi(sah, sa0->sadb_sa_spi)) == NULL) {
-#if IPSEC_DEBUG
-               printf("key_update: no such a SA found (spi:%u)\n",
-                       (u_int32_t)ntohl(sa0->sadb_sa_spi));
-#endif
+               ipseclog((LOG_DEBUG,
+                   "key_update: no such a SA found (spi:%u)\n",
+                   (u_int32_t)ntohl(sa0->sadb_sa_spi)));
                return key_senderror(so, m, EINVAL);
        }
 #endif
 
        /* validity check */
        if (sav->sah->saidx.proto != proto) {
-#if IPSEC_DEBUG
-               printf("key_update: protocol mismatched (DB=%u param=%u)\n",
-                       sav->sah->saidx.proto, proto);
-#endif
+               ipseclog((LOG_DEBUG,
+                   "key_update: protocol mismatched (DB=%u param=%u)\n",
+                   sav->sah->saidx.proto, proto));
                return key_senderror(so, m, EINVAL);
        }
 #if IPSEC_DOSEQCHECK
        if (sav->spi != sa0->sadb_sa_spi) {
-#if IPSEC_DEBUG
-               printf("key_update: SPI mismatched (DB:%u param:%u)\n",
-                       (u_int32_t)ntohl(sav->spi),
-                       (u_int32_t)ntohl(sa0->sadb_sa_spi));
-#endif
+               ipseclog((LOG_DEBUG,
+                   "key_update: SPI mismatched (DB:%u param:%u)\n",
+                   (u_int32_t)ntohl(sav->spi),
+                   (u_int32_t)ntohl(sa0->sadb_sa_spi)));
                return key_senderror(so, m, EINVAL);
        }
 #endif
        if (sav->pid != mhp->msg->sadb_msg_pid) {
-#if IPSEC_DEBUG
-               printf("key_update: pid mismatched (DB:%u param:%u)\n",
-                       sav->pid, mhp->msg->sadb_msg_pid);
-#endif
+               ipseclog((LOG_DEBUG,
+                   "key_update: pid mismatched (DB:%u param:%u)\n",
+                   sav->pid, mhp->msg->sadb_msg_pid));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -5065,9 +5139,9 @@ key_update(so, m, mhp)
        }
 
        /* check SA values to be mature. */
-       if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) {
+       if ((error = key_mature(sav)) != 0) {
                key_freesav(sav);
-               return key_senderror(so, m, 0);
+               return key_senderror(so, m, error);
        }
 
     {
@@ -5076,9 +5150,7 @@ key_update(so, m, mhp)
        /* set msg buf from mhp */
        n = key_getmsgbuf_x1(m, mhp);
        if (n == NULL) {
-#if IPSEC_DEBUG
-               printf("key_update: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_update: No more memory.\n"));
                return key_senderror(so, m, ENOBUFS);
        }
 
@@ -5103,6 +5175,8 @@ key_getsavbyseq(sah, seq)
        struct secasvar *sav;
        u_int state;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        state = SADB_SASTATE_LARVAL;
 
        /* search SAD with sequence number ? */
@@ -5155,15 +5229,15 @@ key_add(so, m, mhp)
        u_int32_t reqid;
        int error;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_add: NULL pointer is passed.\n");
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_add: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_add: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -5178,18 +5252,14 @@ key_add(so, m, mhp)
             mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) ||
            (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL &&
             mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) {
-#if IPSEC_DEBUG
-               printf("key_add: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
            mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
                /* XXX need more */
-#if IPSEC_DEBUG
-               printf("key_add: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
@@ -5211,9 +5281,7 @@ key_add(so, m, mhp)
        if ((newsah = key_getsah(&saidx)) == NULL) {
                /* create a new SA header */
                if ((newsah = key_newsah(&saidx)) == NULL) {
-#if IPSEC_DEBUG
-                       printf("key_add: No more memory.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_add: No more memory.\n"));
                        return key_senderror(so, m, ENOBUFS);
                }
        }
@@ -5228,9 +5296,7 @@ key_add(so, m, mhp)
        /* create new SA entry. */
        /* We can create new SA only if SPI is differenct. */
        if (key_getsavbyspi(newsah, sa0->sadb_sa_spi)) {
-#if IPSEC_DEBUG
-               printf("key_add: SA already exists.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_add: SA already exists.\n"));
                return key_senderror(so, m, EEXIST);
        }
        newsav = key_newsav(m, mhp, newsah, &error);
@@ -5255,9 +5321,7 @@ key_add(so, m, mhp)
        /* set msg buf from mhp */
        n = key_getmsgbuf_x1(m, mhp);
        if (n == NULL) {
-#if IPSEC_DEBUG
-               printf("key_update: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_update: No more memory.\n"));
                return key_senderror(so, m, ENOBUFS);
        }
 
@@ -5276,6 +5340,8 @@ key_setident(sah, m, mhp)
        const struct sadb_ident *idsrc, *iddst;
        int idsrclen, iddstlen;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sah == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_setident: NULL pointer is passed.\n");
@@ -5290,9 +5356,7 @@ key_setident(sah, m, mhp)
        
        if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL ||
            mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) {
-#if IPSEC_DEBUG
-               printf("key_setident: invalid identity.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_setident: invalid identity.\n"));
                return EINVAL;
        }
 
@@ -5303,9 +5367,7 @@ key_setident(sah, m, mhp)
 
        /* validity check */
        if (idsrc->sadb_ident_type != iddst->sadb_ident_type) {
-#if IPSEC_DEBUG
-               printf("key_setident: ident type mismatch.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_setident: ident type mismatch.\n"));
                return EINVAL;
        }
 
@@ -5323,18 +5385,14 @@ key_setident(sah, m, mhp)
        /* make structure */
        KMALLOC(sah->idents, struct sadb_ident *, idsrclen);
        if (sah->idents == NULL) {
-#if IPSEC_DEBUG
-               printf("key_setident: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_setident: No more memory.\n"));
                return ENOBUFS;
        }
        KMALLOC(sah->identd, struct sadb_ident *, iddstlen);
        if (sah->identd == NULL) {
                KFREE(sah->idents);
                sah->idents = NULL;
-#if IPSEC_DEBUG
-               printf("key_setident: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_setident: No more memory.\n"));
                return ENOBUFS;
        }
        bcopy(idsrc, sah->idents, idsrclen);
@@ -5380,8 +5438,8 @@ key_getmsgbuf_x1(m, mhp)
        return n;
 }
 
-static int key_delete_all __P((struct socket *, struct mbuf *,
-       const struct sadb_msghdr *, u_int16_t));
+static int key_delete_all(struct socket *, struct mbuf *,
+       const struct sadb_msghdr *, u_int16_t);
 
 /*
  * SADB_DELETE processing
@@ -5407,31 +5465,27 @@ key_delete(so, m, mhp)
        struct secasvar *sav = NULL;
        u_int16_t proto;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_delete: NULL pointer is passed.\n");
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_delete: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_delete: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
        if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
            mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
-#if IPSEC_DEBUG
-               printf("key_delete: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
        if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
-#if IPSEC_DEBUG
-               printf("key_delete: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -5441,14 +5495,10 @@ key_delete(so, m, mhp)
                 * that match the src/dst.  This is used during
                 * IKE INITIAL-CONTACT.
                 */
-#if IPSEC_DEBUG
-               printf("key_delete: doing delete all.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_delete: doing delete all.\n"));
                return key_delete_all(so, m, mhp, proto);
        } else if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa)) {
-#if IPSEC_DEBUG
-               printf("key_delete: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -5463,7 +5513,7 @@ key_delete(so, m, mhp)
        LIST_FOREACH(sah, &sahtree, chain) {
                if (sah->state == SADB_SASTATE_DEAD)
                        continue;
-               if (key_cmpsaidx_withoutmode(&sah->saidx, &saidx) == 0)
+               if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
                        continue;
 
                /* get a SA with SPI. */
@@ -5472,9 +5522,7 @@ key_delete(so, m, mhp)
                        break;
        }
        if (sah == NULL) {
-#if IPSEC_DEBUG
-               printf("key_delete: no SA found.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_delete: no SA found.\n"));
                return key_senderror(so, m, ENOENT);
        }
 
@@ -5523,6 +5571,8 @@ key_delete_all(so, m, mhp, proto)
        struct secasvar *sav, *nextsav;
        u_int stateidx, state;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
        dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
 
@@ -5532,7 +5582,7 @@ key_delete_all(so, m, mhp, proto)
        LIST_FOREACH(sah, &sahtree, chain) {
                if (sah->state == SADB_SASTATE_DEAD)
                        continue;
-               if (key_cmpsaidx_withoutmode(&sah->saidx, &saidx) == 0)
+               if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
                        continue;
 
                /* Delete all non-LARVAL SAs. */
@@ -5547,12 +5597,10 @@ key_delete_all(so, m, mhp, proto)
                                nextsav = LIST_NEXT(sav, chain);
                                /* sanity check */
                                if (sav->state != state) {
-#if IPSEC_DEBUG
-                                       printf("key_delete_all: "
+                                       ipseclog((LOG_DEBUG, "key_delete_all: "
                                               "invalid sav->state "
                                               "(queue: %d SA: %d)\n",
-                                              state, sav->state);
-#endif
+                                              state, sav->state));
                                        continue;
                                }
                                
@@ -5611,32 +5659,28 @@ key_get(so, m, mhp)
        struct secasvar *sav = NULL;
        u_int16_t proto;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_get: NULL pointer is passed.\n");
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_get: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_get: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
        if (mhp->ext[SADB_EXT_SA] == NULL ||
            mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
            mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
-#if IPSEC_DEBUG
-               printf("key_get: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
            mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
-#if IPSEC_DEBUG
-               printf("key_get: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -5651,7 +5695,7 @@ key_get(so, m, mhp)
        LIST_FOREACH(sah, &sahtree, chain) {
                if (sah->state == SADB_SASTATE_DEAD)
                        continue;
-               if (key_cmpsaidx_withoutmode(&sah->saidx, &saidx) == 0)
+               if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
                        continue;
 
                /* get a SA with SPI. */
@@ -5660,9 +5704,7 @@ key_get(so, m, mhp)
                        break;
        }
        if (sah == NULL) {
-#if IPSEC_DEBUG
-               printf("key_get: no SA found.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_get: no SA found.\n"));
                return key_senderror(so, m, ENOENT);
        }
 
@@ -5672,9 +5714,7 @@ key_get(so, m, mhp)
 
        /* map proto to satype */
        if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_get: there was invalid proto in SAD.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_get: there was invalid proto in SAD.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -5947,7 +5987,7 @@ key_getprop(saidx)
  *   <base, SA, address(SD), (address(P)), x_policy,
  *       (identity(SD),) (sensitivity,) proposal>
  * to KMD, and expect to receive
- *   <base> with SADB_ACQUIRE if error occured,
+ *   <base> with SADB_ACQUIRE if error occurred,
  * or
  *   <base, src address, dst address, (SPI range)> with SADB_GETSPI
  * from KMD by PF_KEY.
@@ -5974,6 +6014,8 @@ key_acquire(saidx, sp)
        int error = -1;
        u_int32_t seq;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (saidx == NULL)
                panic("key_acquire: NULL pointer is passed.\n");
@@ -6022,8 +6064,7 @@ key_acquire(saidx, sp)
 
        /* set sadb_address for saidx's. */
        m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
-           (struct sockaddr *)&saidx->src, saidx->src.ss_len << 3,
-           IPSEC_ULPROTO_ANY);
+           (struct sockaddr *)&saidx->src, FULLMASK, IPSEC_ULPROTO_ANY);
        if (!m) {
                error = ENOBUFS;
                goto fail;
@@ -6031,8 +6072,7 @@ key_acquire(saidx, sp)
        m_cat(result, m);
 
        m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
-           (struct sockaddr *)&saidx->dst, saidx->dst.ss_len << 3,
-           IPSEC_ULPROTO_ANY);
+           (struct sockaddr *)&saidx->dst, FULLMASK, IPSEC_ULPROTO_ANY);
        if (!m) {
                error = ENOBUFS;
                goto fail;
@@ -6154,9 +6194,7 @@ key_newacq(saidx)
        /* get new entry */
        KMALLOC(newacq, struct secacq *, sizeof(struct secacq));
        if (newacq == NULL) {
-#if IPSEC_DEBUG
-               printf("key_newacq: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_newacq: No more memory.\n"));
                return NULL;
        }
        bzero(newacq, sizeof(*newacq));
@@ -6177,8 +6215,10 @@ key_getacq(saidx)
 {
        struct secacq *acq;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        LIST_FOREACH(acq, &acqtree, chain) {
-               if (key_cmpsaidx_exactly(saidx, &acq->saidx))
+               if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY))
                        return acq;
        }
 
@@ -6191,6 +6231,8 @@ key_getacqbyseq(seq)
 {
        struct secacq *acq;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        LIST_FOREACH(acq, &acqtree, chain) {
                if (acq->seq == seq)
                        return acq;
@@ -6210,9 +6252,7 @@ key_newspacq(spidx)
        /* get new entry */
        KMALLOC(acq, struct secspacq *, sizeof(struct secspacq));
        if (acq == NULL) {
-#if IPSEC_DEBUG
-               printf("key_newspacq: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_newspacq: No more memory.\n"));
                return NULL;
        }
        bzero(acq, sizeof(*acq));
@@ -6232,6 +6272,8 @@ key_getspacq(spidx)
 {
        struct secspacq *acq;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        LIST_FOREACH(acq, &spacqtree, chain) {
                if (key_cmpspidx_exactly(spidx, &acq->spidx))
                        return acq;
@@ -6266,15 +6308,17 @@ key_acquire2(so, m, mhp)
        u_int16_t proto;
        int error;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_acquire2: NULL pointer is passed.\n");
 
        /*
         * Error message from KMd.
-        * We assume that if error was occured in IKEd, the length of PFKEY
+        * We assume that if error was occurred in IKEd, the length of PFKEY
         * message is equal to the size of sadb_msg structure.
-        * We do not raise error even if error occured in this function.
+        * We do not raise error even if error occurred in this function.
         */
        if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) {
 #ifndef IPSEC_NONBLOCK_ACQUIRE
@@ -6283,9 +6327,7 @@ key_acquire2(so, m, mhp)
 
                /* check sequence number */
                if (mhp->msg->sadb_msg_seq == 0) {
-#if IPSEC_DEBUG
-                       printf("key_acquire2: must specify sequence number.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_acquire2: must specify sequence number.\n"));
                        m_freem(m);
                        return 0;
                }
@@ -6314,9 +6356,7 @@ key_acquire2(so, m, mhp)
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_acquire2: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_acquire2: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -6324,18 +6364,14 @@ key_acquire2(so, m, mhp)
            mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
            mhp->ext[SADB_EXT_PROPOSAL] == NULL) {
                /* error */
-#if IPSEC_DEBUG
-               printf("key_acquire2: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
        if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
            mhp->extlen[SADB_EXT_PROPOSAL] < sizeof(struct sadb_prop)) {
                /* error */
-#if IPSEC_DEBUG
-               printf("key_acquire2: invalid message is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -6349,22 +6385,18 @@ key_acquire2(so, m, mhp)
        LIST_FOREACH(sah, &sahtree, chain) {
                if (sah->state == SADB_SASTATE_DEAD)
                        continue;
-               if (key_cmpsaidx_withmode(&sah->saidx, &saidx))
+               if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID))
                        break;
        }
        if (sah != NULL) {
-#if IPSEC_DEBUG
-               printf("key_acquire2: a SA exists already.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_acquire2: a SA exists already.\n"));
                return key_senderror(so, m, EEXIST);
        }
 
        error = key_acquire(&saidx, NULL);
        if (error != 0) {
-#if IPSEC_DEBUG
-               printf("key_acquire2: error %d returned "
-                       "from key_acquire.\n", mhp->msg->sadb_msg_errno);
-#endif
+               ipseclog((LOG_DEBUG, "key_acquire2: error %d returned "
+                       "from key_acquire.\n", mhp->msg->sadb_msg_errno));
                return key_senderror(so, m, error);
        }
 
@@ -6392,6 +6424,8 @@ key_register(so, m, mhp)
 {
        struct secreg *reg, *newreg = 0;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_register: NULL pointer is passed.\n");
@@ -6407,9 +6441,7 @@ key_register(so, m, mhp)
        /* check whether existing or not */
        LIST_FOREACH(reg, &regtree[mhp->msg->sadb_msg_satype], chain) {
                if (reg->so == so) {
-#if IPSEC_DEBUG
-                       printf("key_register: socket exists already.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_register: socket exists already.\n"));
                        return key_senderror(so, m, EEXIST);
                }
        }
@@ -6417,15 +6449,15 @@ key_register(so, m, mhp)
        /* create regnode */
        KMALLOC(newreg, struct secreg *, sizeof(*newreg));
        if (newreg == NULL) {
-#if IPSEC_DEBUG
-               printf("key_register: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_register: No more memory.\n"));
                return key_senderror(so, m, ENOBUFS);
        }
        bzero((caddr_t)newreg, sizeof(*newreg));
 
+       socket_lock(so, 1);
        newreg->so = so;
        ((struct keycb *)sotorawcb(so))->kp_registered++;
+       socket_unlock(so, 1);
 
        /* add regnode to regtree. */
        LIST_INSERT_HEAD(&regtree[mhp->msg->sadb_msg_satype], newreg, chain);
@@ -6559,6 +6591,8 @@ key_freereg(so)
        struct secreg *reg;
        int i;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL)
                panic("key_freereg: NULL pointer is passed.\n");
@@ -6603,8 +6637,7 @@ key_expire(sav)
        int error = -1;
        struct sadb_lifetime *lt;
 
-       /* XXX: Why do we lock ? */
-       s = splnet();   /*called from softclock()*/
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
 
        /* sanity check */
        if (sav == NULL)
@@ -6631,7 +6664,9 @@ key_expire(sav)
        m_cat(result, m);
 
        /* create SA extension */
-       m = key_setsadbxsa2(sav->sah->saidx.mode, sav->sah->saidx.reqid);
+       m = key_setsadbxsa2(sav->sah->saidx.mode,
+                       sav->replay ? sav->replay->count : 0,
+                       sav->sah->saidx.reqid);
        if (!m) {
                error = ENOBUFS;
                goto fail;
@@ -6662,7 +6697,7 @@ key_expire(sav)
        /* set sadb_address for source */
        m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
            (struct sockaddr *)&sav->sah->saidx.src,
-           sav->sah->saidx.src.ss_len << 3, IPSEC_ULPROTO_ANY);
+           FULLMASK, IPSEC_ULPROTO_ANY);
        if (!m) {
                error = ENOBUFS;
                goto fail;
@@ -6672,7 +6707,7 @@ key_expire(sav)
        /* set sadb_address for destination */
        m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
            (struct sockaddr *)&sav->sah->saidx.dst,
-           sav->sah->saidx.dst.ss_len << 3, IPSEC_ULPROTO_ANY);
+           FULLMASK, IPSEC_ULPROTO_ANY);
        if (!m) {
                error = ENOBUFS;
                goto fail;
@@ -6699,6 +6734,7 @@ key_expire(sav)
        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:
@@ -6733,15 +6769,15 @@ key_flush(so, m, mhp)
        u_int8_t state;
        u_int stateidx;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_flush: NULL pointer is passed.\n");
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_flush: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_flush: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -6775,9 +6811,7 @@ key_flush(so, m, mhp)
 
        if (m->m_len < sizeof(struct sadb_msg) ||
            sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) {
-#if IPSEC_DEBUG
-               printf("key_flush: No more memory.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_flush: No more memory.\n"));
                return key_senderror(so, m, ENOBUFS);
        }
 
@@ -6820,15 +6854,15 @@ key_dump(so, m, mhp)
        struct sadb_msg *newmsg;
        struct mbuf *n;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_dump: NULL pointer is passed.\n");
 
        /* map satype to proto */
        if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
-#if IPSEC_DEBUG
-               printf("key_dump: invalid satype is passed.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_dump: invalid satype is passed.\n"));
                return key_senderror(so, m, EINVAL);
        }
 
@@ -6861,9 +6895,7 @@ key_dump(so, m, mhp)
 
                /* map proto to satype */
                if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
-#if IPSEC_DEBUG
-                       printf("key_dump: there was invalid proto in SAD.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_dump: there was invalid proto in SAD.\n"));
                        return key_senderror(so, m, EINVAL);
                }
 
@@ -6899,6 +6931,8 @@ key_promisc(so, m, mhp)
 {
        int olen;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
                panic("key_promisc: NULL pointer is passed.\n");
@@ -6915,7 +6949,8 @@ key_promisc(so, m, mhp)
        } else if (olen == sizeof(struct sadb_msg)) {
                /* enable/disable promisc mode */
                struct keycb *kp;
-
+               
+               socket_lock(so, 1);
                if ((kp = (struct keycb *)sotorawcb(so)) == NULL)
                        return key_senderror(so, m, EINVAL);
                mhp->msg->sadb_msg_errno = 0;
@@ -6925,8 +6960,10 @@ key_promisc(so, m, mhp)
                        kp->kp_promisc = mhp->msg->sadb_msg_satype;
                        break;
                default:
+                       socket_unlock(so, 1);
                        return key_senderror(so, m, EINVAL);
                }
+               socket_unlock(so, 1);
 
                /* send the original message back to everyone */
                mhp->msg->sadb_msg_errno = 0;
@@ -6941,8 +6978,8 @@ key_promisc(so, m, mhp)
        }
 }
 
-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 */
@@ -6990,13 +7027,15 @@ key_parse(m, so)
        int error;
        int target;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (m == NULL || so == NULL)
                panic("key_parse: NULL pointer is passed.\n");
 
 #if 0  /*kdebug_sadb assumes msg in linear buffer*/
        KEYDEBUG(KEYDEBUG_KEY_DUMP,
-               printf("key_parse: passed sadb_msg\n");
+               ipseclog((LOG_DEBUG, "key_parse: passed sadb_msg\n"));
                kdebug_sadb(msg));
 #endif
 
@@ -7011,29 +7050,24 @@ key_parse(m, so)
 
        if ((m->m_flags & M_PKTHDR) == 0 ||
            m->m_pkthdr.len != m->m_pkthdr.len) {
-#if IPSEC_DEBUG
-               printf("key_parse: invalid message length.\n");
-#endif
+               ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n"));
                pfkeystat.out_invlen++;
                error = EINVAL;
                goto senderror;
        }
 
        if (msg->sadb_msg_version != PF_KEY_V2) {
-#if IPSEC_DEBUG
-               printf("key_parse: PF_KEY version %u is mismatched.\n",
-                   msg->sadb_msg_version);
-#endif
+               ipseclog((LOG_DEBUG,
+                   "key_parse: PF_KEY version %u is mismatched.\n",
+                   msg->sadb_msg_version));
                pfkeystat.out_invver++;
                error = EINVAL;
                goto senderror;
        }
 
        if (msg->sadb_msg_type > SADB_MAX) {
-#if IPSEC_DEBUG
-               printf("key_parse: invalid type %u is passed.\n",
-                   msg->sadb_msg_type);
-#endif
+               ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n",
+                   msg->sadb_msg_type));
                pfkeystat.out_invmsgtype++;
                error = EINVAL;
                goto senderror;
@@ -7089,11 +7123,8 @@ key_parse(m, so)
                case SADB_GET:
                case SADB_ACQUIRE:
                case SADB_EXPIRE:
-#if IPSEC_DEBUG
-                       printf("key_parse: must specify satype "
-                               "when msg type=%u.\n",
-                               msg->sadb_msg_type);
-#endif
+                       ipseclog((LOG_DEBUG, "key_parse: must specify satype "
+                           "when msg type=%u.\n", msg->sadb_msg_type));
                        pfkeystat.out_invsatype++;
                        error = EINVAL;
                        goto senderror;
@@ -7111,10 +7142,8 @@ key_parse(m, so)
                case SADB_X_SPDSETIDX:
                case SADB_X_SPDUPDATE:
                case SADB_X_SPDDELETE2:
-#if IPSEC_DEBUG
-                       printf("key_parse: illegal satype=%u\n",
-                           msg->sadb_msg_type);
-#endif
+                       ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n",
+                           msg->sadb_msg_type));
                        pfkeystat.out_invsatype++;
                        error = EINVAL;
                        goto senderror;
@@ -7124,10 +7153,8 @@ key_parse(m, so)
        case SADB_SATYPE_OSPFV2:
        case SADB_SATYPE_RIPV2:
        case SADB_SATYPE_MIP:
-#if IPSEC_DEBUG
-               printf("key_parse: type %u isn't supported.\n",
-                   msg->sadb_msg_satype);
-#endif
+               ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n",
+                   msg->sadb_msg_satype));
                pfkeystat.out_invsatype++;
                error = EOPNOTSUPP;
                goto senderror;
@@ -7136,10 +7163,8 @@ key_parse(m, so)
                        break;
                /*FALLTHROUGH*/
        default:
-#if IPSEC_DEBUG
-               printf("key_parse: invalid type %u is passed.\n",
-                   msg->sadb_msg_satype);
-#endif
+               ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n",
+                   msg->sadb_msg_satype));
                pfkeystat.out_invsatype++;
                error = EINVAL;
                goto senderror;
@@ -7156,9 +7181,7 @@ key_parse(m, so)
 
                /* check upper layer protocol */
                if (src0->sadb_address_proto != dst0->sadb_address_proto) {
-#if IPSEC_DEBUG
-                       printf("key_parse: upper layer protocol mismatched.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n"));
                        pfkeystat.out_invaddr++;
                        error = EINVAL;
                        goto senderror;
@@ -7167,18 +7190,15 @@ key_parse(m, so)
                /* check family */
                if (PFKEY_ADDR_SADDR(src0)->sa_family !=
                    PFKEY_ADDR_SADDR(dst0)->sa_family) {
-#if IPSEC_DEBUG
-                       printf("key_parse: address family mismatched.\n");
-#endif
+                       ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n"));
                        pfkeystat.out_invaddr++;
                        error = EINVAL;
                        goto senderror;
                }
                if (PFKEY_ADDR_SADDR(src0)->sa_len !=
                    PFKEY_ADDR_SADDR(dst0)->sa_len) {
-#if IPSEC_DEBUG
-                       printf("key_parse: address struct size mismatched.\n");
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_parse: address struct size mismatched.\n"));
                        pfkeystat.out_invaddr++;
                        error = EINVAL;
                        goto senderror;
@@ -7202,9 +7222,8 @@ key_parse(m, so)
                        }
                        break;
                default:
-#if IPSEC_DEBUG
-                       printf("key_parse: unsupported address family.\n");
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_parse: unsupported address family.\n"));
                        pfkeystat.out_invaddr++;
                        error = EAFNOSUPPORT;
                        goto senderror;
@@ -7225,9 +7244,8 @@ key_parse(m, so)
                /* check max prefix length */
                if (src0->sadb_address_prefixlen > plen ||
                    dst0->sadb_address_prefixlen > plen) {
-#if IPSEC_DEBUG
-                       printf("key_parse: illegal prefixlen.\n");
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_parse: illegal prefixlen.\n"));
                        pfkeystat.out_invaddr++;
                        error = EINVAL;
                        goto senderror;
@@ -7261,6 +7279,8 @@ key_senderror(so, m, code)
 {
        struct sadb_msg *msg;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        if (m->m_len < sizeof(struct sadb_msg))
                panic("invalid mbuf passed to key_senderror");
 
@@ -7333,21 +7353,18 @@ key_align(m, mhp)
                         * KEY_AUTH or KEY_ENCRYPT ?
                         */
                        if (mhp->ext[ext->sadb_ext_type] != NULL) {
-#if IPSEC_DEBUG
-                               printf("key_align: duplicate ext_type %u "
-                                       "is passed.\n",
-                                       ext->sadb_ext_type);
-#endif
+                               ipseclog((LOG_DEBUG,
+                                   "key_align: duplicate ext_type %u "
+                                   "is passed.\n", ext->sadb_ext_type));
                                m_freem(m);
                                pfkeystat.out_dupext++;
                                return EINVAL;
                        }
                        break;
                default:
-#if IPSEC_DEBUG
-                       printf("key_align: invalid ext_type %u is passed.\n",
-                               ext->sadb_ext_type);
-#endif
+                       ipseclog((LOG_DEBUG,
+                           "key_align: invalid ext_type %u is passed.\n",
+                           ext->sadb_ext_type));
                        m_freem(m);
                        pfkeystat.out_invexttype++;
                        return EINVAL;
@@ -7442,7 +7459,7 @@ key_validate_ext(ext, len)
 }
 
 void
-key_init()
+key_domain_init()
 {
        int i;
 
@@ -7474,7 +7491,7 @@ key_init()
 #endif
 
 #ifndef IPSEC_DEBUG2
-       timeout((void *)key_timehandler_funnel, (void *)0, hz);
+       timeout((void *)key_timehandler, (void *)0, hz);
 #endif /*IPSEC_DEBUG2*/
 
        /* initialize key statistics */
@@ -7502,6 +7519,8 @@ key_checktunnelsanity(sav, family, src, dst)
        caddr_t src;
        caddr_t dst;
 {
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        /* sanity check */
        if (sav->sah == NULL)
                panic("sav->sah == NULL at key_checktunnelsanity");
@@ -7581,6 +7600,8 @@ key_sa_recordxfer(sav, m)
        struct secasvar *sav;
        struct mbuf *m;
 {
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        if (!sav)
                panic("key_sa_recordxfer called with sav == NULL");
        if (!m)
@@ -7632,6 +7653,7 @@ key_sa_routechange(dst)
        struct secashead *sah;
        struct route *ro;
 
+       lck_mtx_lock(sadb_mutex);
        LIST_FOREACH(sah, &sahtree, chain) {
                ro = &sah->sa_route;
                if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len
@@ -7640,6 +7662,7 @@ key_sa_routechange(dst)
                        ro->ro_rt = (struct rtentry *)NULL;
                }
        }
+       lck_mtx_unlock(sadb_mutex);
 
        return;
 }
@@ -7649,6 +7672,8 @@ key_sa_chgstate(sav, state)
        struct secasvar *sav;
        u_int8_t state;
 {
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        if (sav == NULL)
                panic("key_sa_chgstate called with sav == NULL");
 
@@ -7667,6 +7692,8 @@ key_sa_stir_iv(sav)
        struct secasvar *sav;
 {
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+
        if (!sav->iv)
                panic("key_sa_stir_iv called with sav == NULL");
        key_randomfill(sav->iv, sav->ivlen);