]> git.saurik.com Git - apple/ipsec.git/blobdiff - ipsec-tools/racoon/pfkey_racoon.c
ipsec-292.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / pfkey_racoon.c
index 76ecbc387c5d69fab8c6072b5045ae8127023656..63c61dd94dc897e203f7745e19378bf780dfa4e0 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include "config.h"
+#include "racoon_types.h"
 
 #include <stdlib.h>
 #include <string.h>
 #include <arpa/inet.h>
 
 #ifdef ENABLE_NATT
-# ifdef __linux__
-#  include <linux/udp.h>
-# endif
-# if defined(__NetBSD__) || defined(__FreeBSD__)
-#  include <netinet/udp.h>
-# endif
+#include <netinet/udp.h>
 #endif
 
 #include <sys/types.h>
 #include <sys/sysctl.h>
 
 #include <net/route.h>
-#ifdef __APPLE__
-#include <System/net/pfkeyv2.h>
-#else
 #include <net/pfkeyv2.h>
-#endif
 
 #include <netinet/in.h>
 #ifndef HAVE_NETINET6_IPSEC
@@ -80,6 +72,8 @@
 #include "plog.h"
 #include "sockmisc.h"
 #include "debug.h"
+#include "fsm.h"
+#include "ike_session.h"
 
 #include "schedule.h"
 #include "localconf.h"
 #include "algorithm.h"
 #include "sainfo.h"
 #include "proposal.h"
-#include "admin.h"
-#include "privsep.h"
 #include "strnames.h"
-#include "backupsa.h"
 #include "gcmalloc.h"
 #include "nattraversal.h"
 #include "crypto_openssl.h"
 #include "grabmyaddr.h"
 #include "vpn_control.h"
 #include "vpn_control_var.h"
+#include "ike_session.h"
+#include "ipsecSessionTracer.h"
+#include "ipsecMessageTracer.h"
+#include "power_mgmt.h"
+#include "session.h"
 
 #if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC)
 #define SADB_X_EALG_AESCBC  SADB_X_EALG_RIJNDAELCBC
 #endif
 
 /* prototype */
-static u_int ipsecdoi2pfkey_aalg __P((u_int));
-static u_int ipsecdoi2pfkey_ealg __P((u_int));
-static u_int ipsecdoi2pfkey_calg __P((u_int));
-static u_int ipsecdoi2pfkey_alg __P((u_int, u_int));
-static u_int keylen_aalg __P((u_int));
-static u_int keylen_ealg __P((u_int, int));
-
-static int pk_recvgetspi __P((caddr_t *));
-static int pk_recvupdate __P((caddr_t *));
-static int pk_recvadd __P((caddr_t *));
-static int pk_recvdelete __P((caddr_t *));
-static int pk_recvacquire __P((caddr_t *));
-static int pk_recvexpire __P((caddr_t *));
-static int pk_recvflush __P((caddr_t *));
-static int getsadbpolicy __P((caddr_t *, int *, int, struct ph2handle *));
-static int pk_recvspdupdate __P((caddr_t *));
-static int pk_recvspdadd __P((caddr_t *));
-static int pk_recvspddelete __P((caddr_t *));
-static int pk_recvspdexpire __P((caddr_t *));
-static int pk_recvspdget __P((caddr_t *));
-static int pk_recvspddump __P((caddr_t *));
-static int pk_recvspdflush __P((caddr_t *));
-static struct sadb_msg *pk_recv __P((int, int *));
-
-static int (*pkrecvf[]) __P((caddr_t *)) = {
+static u_int ipsecdoi2pfkey_aalg (u_int);
+static u_int ipsecdoi2pfkey_ealg (u_int);
+static u_int ipsecdoi2pfkey_calg (u_int);
+static u_int ipsecdoi2pfkey_alg (u_int, u_int);
+static u_int keylen_aalg (u_int);
+static u_int keylen_ealg (u_int, int);
+
+static int pk_recvgetspi (caddr_t *);
+static int pk_recvupdate (caddr_t *);
+static int pk_recvadd (caddr_t *);
+static int pk_recvdelete (caddr_t *);
+static int pk_recvacquire (caddr_t *);
+static int pk_recvexpire (caddr_t *);
+static int pk_recvflush (caddr_t *);
+static int getsadbpolicy (caddr_t *, int *, int, phase2_handle_t *);
+static int pk_recvspdupdate (caddr_t *);
+static int pk_recvspdadd (caddr_t *);
+static int pk_recvspddelete (caddr_t *);
+static int pk_recvspdexpire (caddr_t *);
+static int pk_recvspdget (caddr_t *);
+static int pk_recvspddump (caddr_t *);
+static int pk_recvspdflush (caddr_t *);
+static int pk_recvgetsastat (caddr_t *);
+static struct sadb_msg *pk_recv (int, ssize_t *);
+
+static int (*pkrecvf[]) (caddr_t *) = {
 NULL,
 pk_recvgetspi,
 pk_recvupdate,
@@ -159,14 +156,16 @@ pk_recvspdflush,
 NULL,  /* SADB_X_SPDSETIDX */
 pk_recvspdexpire,
 NULL,  /* SADB_X_SPDDELETE2 */
-NULL,  /* SADB_X_NAT_T_NEW_MAPPING */
-NULL, /* SADB_X_MIGRATE */
-#if (SADB_MAX > 24)
-#error "SADB extra message?"
+pk_recvgetsastat, /* SADB_GETSASTAT */
+NULL,  /* SADB_X_SPDENABLE */
+NULL, /* SADB_X_SPDDISNABLE */
+NULL, /* SADB_MIGRATE */
+#if (SADB_MAX > 26)
+#warning "SADB extra message?"
 #endif
 };
 
-static int addnewsp __P((caddr_t *));
+static int addnewsp (caddr_t *);
 
 /* cope with old kame headers - ugly */
 #ifndef SADB_X_AALG_MD5
@@ -191,82 +190,60 @@ static int addnewsp __P((caddr_t *));
 #endif
 #endif
 
-/*
- * PF_KEY packet handler
- *     0: success
- *     -1: fail
- */
 int
-pfkey_handler()
-{
+pfkey_process(msg)
        struct sadb_msg *msg;
-       int len;
+{
        caddr_t mhp[SADB_EXT_MAX + 1];
        int error = -1;
-
-       /* receive pfkey message. */
-       len = 0;
-       msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len);
-       if (msg == NULL) {
-               if (len < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "failed to recv from pfkey (%s)\n",
-                               strerror(errno));
-                       goto end;
-               } else {
-                       /* short message - msg not ready */
-                       return 0;
-               }
-       }
-
-       plog(LLV_DEBUG, LOCATION, NULL, "get pfkey %s message\n",
-               s_pfkey_type(msg->sadb_msg_type));
-       plogdump(LLV_DEBUG2, msg, msg->sadb_msg_len << 3);
+       
+    // Special debug use only - creates large logs
+       // plogdump(ASL_LEVEL_DEBUG, msg, msg->sadb_msg_len << 3, "get pfkey %s message\n",
+       //               s_pfkey_type(msg->sadb_msg_type));
 
        /* validity check */
+    /* check pfkey message. */
+       if (pfkey_align(msg, mhp)) {
+               plog(ASL_LEVEL_ERR,
+             "libipsec failed pfkey align (%s)\n",
+             ipsec_strerror());
+               goto end;
+       }
+       if (pfkey_check(mhp)) {
+               plog(ASL_LEVEL_ERR,
+             "libipsec failed pfkey check (%s)\n",
+             ipsec_strerror());
+               goto end;
+       }
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];             // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+    
        if (msg->sadb_msg_errno) {
                int pri;
 
                /* when SPD is empty, treat the state as no error. */
                if (msg->sadb_msg_type == SADB_X_SPDDUMP &&
                    msg->sadb_msg_errno == ENOENT)
-                       pri = LLV_DEBUG;
+                       pri = ASL_LEVEL_DEBUG;
                else
-                       pri = LLV_ERROR;
+                       pri = ASL_LEVEL_ERR;
 
-               plog(pri, LOCATION, NULL,
+               plog(pri, 
                        "pfkey %s failed: %s\n",
                        s_pfkey_type(msg->sadb_msg_type),
                        strerror(msg->sadb_msg_errno));
-
                goto end;
        }
-
-       /* check pfkey message. */
-       if (pfkey_align(msg, mhp)) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "libipsec failed pfkey align (%s)\n",
-                       ipsec_strerror());
-               goto end;
-       }
-       if (pfkey_check(mhp)) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "libipsec failed pfkey check (%s)\n",
-                       ipsec_strerror());
-               goto end;
-       }
-       msg = (struct sadb_msg *)mhp[0];
-
+    
        /* safety check */
        if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "unknown PF_KEY message type=%u\n",
                        msg->sadb_msg_type);
                goto end;
        }
 
        if (pkrecvf[msg->sadb_msg_type] == NULL) {
-               plog(LLV_INFO, LOCATION, NULL,
+               plog(ASL_LEVEL_INFO, 
                        "unsupported PF_KEY message %s\n",
                        s_pfkey_type(msg->sadb_msg_type));
                goto end;
@@ -282,6 +259,78 @@ end:
        return(error);
 }
 
+/*
+ * PF_KEY packet handler
+ *     0: success
+ *     -1: fail
+ */
+
+//%%%%%%%%%%%%%%%%%% need to handle errors encountered here - this no longer returns a result
+void
+pfkey_handler(void *unused)
+{
+       struct sadb_msg *msg;
+       ssize_t len;
+
+       if (slept_at || woke_at) {
+               plog(ASL_LEVEL_DEBUG, 
+                        "ignoring pfkey port until power-mgmt event is handled.\n");
+               return;
+       }
+       
+       /* receive pfkey message. */
+       len = 0;
+       msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len);
+
+       if (msg == NULL) {
+               if (len < 0) {
+                       plog(ASL_LEVEL_ERR, 
+                                "failed to recv from pfkey (%s)\n",
+                                strerror(errno));
+                       return;                 
+               } else {
+                       /* short message - msg not ready */
+                       plog(ASL_LEVEL_DEBUG, "recv short message from pfkey\n");
+                       return;
+               }
+       }
+       pfkey_process(msg);
+}
+
+void
+pfkey_post_handler()
+{
+       struct saved_msg_elem *elem;
+       struct saved_msg_elem *elem_tmp = NULL;
+
+       if (slept_at || woke_at) {
+               plog(ASL_LEVEL_DEBUG, 
+                        "ignoring (saved) pfkey messages until power-mgmt event is handled.\n");
+               return;
+       }
+
+       TAILQ_FOREACH_SAFE(elem, &lcconf->saved_msg_queue, chain, elem_tmp) {
+               pfkey_process((struct sadb_msg *)elem->msg);
+               TAILQ_REMOVE(&lcconf->saved_msg_queue, elem, chain);
+               racoon_free(elem);
+
+       }
+}
+
+int
+pfkey_save_msg(msg)
+       struct sadb_msg *msg;
+{
+       struct saved_msg_elem *elem;
+       
+       elem = (struct saved_msg_elem *)racoon_calloc(sizeof(struct saved_msg_elem), 1);
+       if (elem == NULL)
+               return -1;
+       elem->msg = msg;
+       TAILQ_INSERT_TAIL(&lcconf->saved_msg_queue, elem, chain);
+       return 0;
+}
+
 /*
  * dump SADB
  */
@@ -294,18 +343,18 @@ pfkey_dump_sadb(satype)
        pid_t pid = getpid();
        struct sadb_msg *msg = NULL;
        size_t bl, ml;
-       int len;
+       ssize_t len;
 
-       if ((s = privsep_pfkey_open()) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+       if ((s = pfkey_open()) < 0) {
+               plog(ASL_LEVEL_ERR, 
                        "libipsec failed pfkey open: %s\n",
                        ipsec_strerror());
                return NULL;
        }
 
-       plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_dump\n");
+       plog(ASL_LEVEL_DEBUG, "call pfkey_send_dump\n");
        if (pfkey_send_dump(s, satype) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "libipsec failed dump: %s\n", ipsec_strerror());
                goto fail;
        }
@@ -321,14 +370,25 @@ pfkey_dump_sadb(satype)
                                continue;
                }
 
-               if (msg->sadb_msg_type != SADB_DUMP || msg->sadb_msg_pid != pid)
+               /*
+                * for multi-processor system this had to be added because the messages can
+                * be interleaved - they won't all be dump messages
+                */
+               if (msg->sadb_msg_type != SADB_DUMP) {  /* save for later processing */
+                       pfkey_save_msg(msg);
+                       msg = NULL;
+                       continue;
+               }
+
+               // ignore dump messages that aren't racoon's
+               if (msg->sadb_msg_pid != pid)
                        continue;
 
                ml = msg->sadb_msg_len << 3;
                bl = buf ? buf->l : 0;
                buf = vrealloc(buf, bl + ml);
                if (buf == NULL) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "failed to reallocate buffer to dump.\n");
                        goto fail;
                }
@@ -347,34 +407,10 @@ done:
        if (msg)
                racoon_free(msg);
        if (s >= 0)
-               privsep_pfkey_close(s);
+               pfkey_close_sock(s);
        return buf;
 }
 
-#ifdef ENABLE_ADMINPORT
-/*
- * flush SADB
- */
-void
-pfkey_flush_sadb(proto)
-       u_int proto;
-{
-       int satype;
-
-       /* convert to SADB_SATYPE */
-       if ((satype = admin2pfkey_proto(proto)) < 0)
-               return;
-
-       plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_flush\n");
-       if (pfkey_send_flush(lcconf->sock_pfkey, satype) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "libipsec failed send flush (%s)\n", ipsec_strerror());
-               return;
-       }
-
-       return;
-}
-#endif
 
 /*
  * These are the SATYPEs that we manage.  We register to get
@@ -394,24 +430,24 @@ const int pfkey_nsatypes =
  * PF_KEY initialization
  */
 int
-pfkey_init()
+pfkey_init(void)
 {
-       int i, reg_fail;
+       int i, reg_fail, sock;
 
-       if ((lcconf->sock_pfkey = privsep_pfkey_open()) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+       if ((lcconf->sock_pfkey = pfkey_open()) < 0) {
+               plog(ASL_LEVEL_ERR, 
                        "libipsec failed pfkey open (%s)\n", ipsec_strerror());
                return -1;
        }
 
        for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                    "call pfkey_send_register for %s\n",
                    pfkey_satypes[i].ps_name);
                if (pfkey_send_register(lcconf->sock_pfkey,
                                        pfkey_satypes[i].ps_satype) < 0 ||
                    pfkey_recv_register(lcconf->sock_pfkey) < 0) {
-                       plog(LLV_WARNING, LOCATION, NULL,
+                       plog(ASL_LEVEL_WARNING, 
                            "failed to register %s (%s)\n",
                            pfkey_satypes[i].ps_name,
                            ipsec_strerror());
@@ -420,30 +456,50 @@ pfkey_init()
        }
 
        if (reg_fail == pfkey_nsatypes) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "failed to regist any protocol.\n");
-               pfkey_close(lcconf->sock_pfkey);
+        close(lcconf->sock_pfkey);
                return -1;
        }
-
-       initsp();
+    initsp();
+    
+    lcconf->pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_pfkey, 0, dispatch_get_main_queue());
+    if (lcconf->pfkey_source == NULL) {
+        plog(ASL_LEVEL_ERR, "could not create pfkey socket source.");
+        return -1;
+    }
+    dispatch_source_set_event_handler_f(lcconf->pfkey_source, pfkey_handler);
+    sock = lcconf->sock_pfkey;
+    dispatch_source_set_cancel_handler(lcconf->pfkey_source, 
+                                       ^{ 
+                                           pfkey_close_sock(sock);
+                                       });
+    dispatch_resume(lcconf->pfkey_source);
 
        if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "libipsec sending spddump failed: %s\n",
                        ipsec_strerror());
-               pfkey_close(lcconf->sock_pfkey);
+               pfkey_close();
                return -1;
        }
 #if 0
        if (pfkey_promisc_toggle(1) < 0) {
-               pfkey_close(lcconf->sock_pfkey);
+               pfkey_close();
                return -1;
        }
 #endif
+    
        return 0;
 }
 
+void
+pfkey_close(void) 
+{
+    dispatch_source_cancel(lcconf->pfkey_source);
+    lcconf->pfkey_source = NULL;
+}
+
 /* %%% for conversion */
 /* IPSECDOI_ATTR_AUTH -> SADB_AALG */
 static u_int
@@ -451,44 +507,46 @@ ipsecdoi2pfkey_aalg(hashtype)
        u_int hashtype;
 {
        switch (hashtype) {
-       case IPSECDOI_ATTR_AUTH_HMAC_MD5:
-               return SADB_AALG_MD5HMAC;
-       case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
-               return SADB_AALG_SHA1HMAC;
-       case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
+        case IPSECDOI_ATTR_AUTH_HMAC_MD5:
+        case IPSECDOI_ATTR_AUTH_HMAC_MD5_96:
+            return SADB_AALG_MD5HMAC;
+        case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
+        case IPSECDOI_ATTR_AUTH_HMAC_SHA1_96:
+            return SADB_AALG_SHA1HMAC;
+        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
 #if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC)
-               return SADB_X_AALG_SHA2_256;
+            return SADB_X_AALG_SHA2_256;
 #else
-               return SADB_X_AALG_SHA2_256HMAC;
+            return SADB_X_AALG_SHA2_256HMAC;
 #endif
-       case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
+        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
 #if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC)
-               return SADB_X_AALG_SHA2_384;
+            return SADB_X_AALG_SHA2_384;
 #else
-               return SADB_X_AALG_SHA2_384HMAC;
+            return SADB_X_AALG_SHA2_384HMAC;
 #endif
-       case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
+        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
 #if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC)
-               return SADB_X_AALG_SHA2_512;
+            return SADB_X_AALG_SHA2_512;
 #else
-               return SADB_X_AALG_SHA2_512HMAC;
+            return SADB_X_AALG_SHA2_512HMAC;
 #endif
-       case IPSECDOI_ATTR_AUTH_KPDK:           /* need special care */
-               return SADB_AALG_NONE;
-
-       /* not supported */
-       case IPSECDOI_ATTR_AUTH_DES_MAC:
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "Not supported hash type: %u\n", hashtype);
-               return ~0;
-
-       case 0: /* reserved */
-       default:
-               return SADB_AALG_NONE;
-
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "Invalid hash type: %u\n", hashtype);
-               return ~0;
+        case IPSECDOI_ATTR_AUTH_KPDK:          /* need special care */
+            return SADB_AALG_NONE;
+            
+            /* not supported */
+        case IPSECDOI_ATTR_AUTH_DES_MAC:
+            plog(ASL_LEVEL_ERR,
+                 "Not supported hash type: %u\n", hashtype);
+            return ~0;
+            
+        case 0: /* reserved */
+        default:
+            return SADB_AALG_NONE;
+            
+            plog(ASL_LEVEL_ERR, 
+                 "Invalid hash type: %u\n", hashtype);
+            return ~0;
        }
        /*NOTREACHED*/
 }
@@ -531,13 +589,13 @@ ipsecdoi2pfkey_ealg(t_id)
        case IPSECDOI_ESP_3IDEA:
        case IPSECDOI_ESP_IDEA:
        case IPSECDOI_ESP_RC4:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "Not supported transform: %u\n", t_id);
                return ~0;
 
        case 0: /* reserved */
        default:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "Invalid transform id: %u\n", t_id);
                return ~0;
        }
@@ -559,7 +617,7 @@ ipsecdoi2pfkey_calg(t_id)
 
        case 0: /* reserved */
        default:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "Invalid transform id: %u\n", t_id);
                return ~0;
        }
@@ -580,7 +638,7 @@ ipsecdoi2pfkey_proto(proto)
                return SADB_X_SATYPE_IPCOMP;
 
        default:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "Invalid ipsec_doi proto: %u\n", proto);
                return ~0;
        }
@@ -599,7 +657,7 @@ ipsecdoi2pfkey_alg(algclass, type)
        case IPSECDOI_PROTO_IPCOMP:
                return ipsecdoi2pfkey_calg(type);
        default:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "Invalid ipsec_doi algclass: %u\n", algclass);
                return ~0;
        }
@@ -620,7 +678,7 @@ pfkey2ipsecdoi_proto(satype)
                return IPSECDOI_PROTO_IPCOMP;
 
        default:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "Invalid pfkey proto: %u\n", satype);
                return ~0;
        }
@@ -646,7 +704,7 @@ ipsecdoi2pfkey_mode(mode)
 #endif
                return IPSEC_MODE_TRANSPORT;
        default:
-               plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
+               plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode);
                return ~0;
        }
        /*NOTREACHED*/
@@ -665,7 +723,7 @@ pfkey2ipsecdoi_mode(mode)
        case IPSEC_MODE_ANY:
                return IPSECDOI_ATTR_ENC_MODE_ANY;
        default:
-               plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
+               plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode);
                return ~0;
        }
        /*NOTREACHED*/
@@ -683,7 +741,7 @@ keylen_aalg(hashtype)
 
        res = alg_ipsec_hmacdef_hashlen(hashtype);
        if (res == -1) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "invalid hmac algorithm %u.\n", hashtype);
                return ~0;
        }
@@ -700,7 +758,7 @@ keylen_ealg(enctype, encklen)
 
        res = alg_ipsec_encdef_keylen(enctype, encklen);
        if (res == -1) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "invalid encryption algorithm %u.\n", enctype);
                return ~0;
        }
@@ -708,8 +766,9 @@ keylen_ealg(enctype, encklen)
 }
 
 int
-pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
+pfkey_convertfromipsecdoi(iph2, proto_id, t_id, hashtype,
                e_type, e_keylen, a_type, a_keylen, flags)
+    phase2_handle_t *iph2;
        u_int proto_id;
        u_int t_id;
        u_int hashtype;
@@ -733,9 +792,9 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
                if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
                        goto bad;
                *a_keylen >>= 3;
-
+                       
                if (*e_type == SADB_EALG_NONE) {
-                       plog(LLV_ERROR, LOCATION, NULL, "no ESP algorithm.\n");
+                       plog(ASL_LEVEL_ERR, "no ESP algorithm.\n");
                        goto bad;
                }
                break;
@@ -756,7 +815,7 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
                *e_type = SADB_EALG_NONE;
                *e_keylen = 0;
                if (*a_type == SADB_AALG_NONE) {
-                       plog(LLV_ERROR, LOCATION, NULL, "no AH algorithm.\n");
+                       plog(ASL_LEVEL_ERR, "no AH algorithm.\n");
                        goto bad;
                }
                break;
@@ -771,13 +830,13 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
                *a_type = SADB_AALG_NONE;
                *a_keylen = 0;
                if (*e_type == SADB_X_CALG_NONE) {
-                       plog(LLV_ERROR, LOCATION, NULL, "no IPCOMP algorithm.\n");
+                       plog(ASL_LEVEL_ERR, "no IPCOMP algorithm.\n");
                        goto bad;
                }
                break;
 
        default:
-               plog(LLV_ERROR, LOCATION, NULL, "unknown IPsec protocol.\n");
+               plog(ASL_LEVEL_ERR, "unknown IPsec protocol.\n");
                goto bad;
        }
 
@@ -794,25 +853,23 @@ pfkey_timeover_stub(p)
        void *p;
 {
 
-       pfkey_timeover((struct ph2handle *)p);
+       pfkey_timeover((phase2_handle_t *)p);
 }
 
 void
 pfkey_timeover(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
-       plog(LLV_ERROR, LOCATION, NULL,
+       plog(ASL_LEVEL_ERR, 
                "%s give up to get IPsec-SA due to time up to wait.\n",
-               saddrwop2str(iph2->dst));
+               saddrwop2str((struct sockaddr *)iph2->dst));
        SCHED_KILL(iph2->sce);
 
        /* If initiator side, send error to kernel by SADB_ACQUIRE. */
        if (iph2->side == INITIATOR)
                pk_sendeacquire(iph2);
 
-       unbindph12(iph2);
-       remph2(iph2);
-       delph2(iph2);
+       ike_session_unlink_phase2(iph2);
 
        return;
 }
@@ -826,9 +883,9 @@ pfkey_timeover(iph2)
  */
 int
 pk_sendgetspi(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
-       struct sockaddr *src = NULL, *dst = NULL;
+       struct sockaddr_storage *src = NULL, *dst = NULL;
        u_int satype, mode;
        struct saprop *pp;
        struct saproto *pr;
@@ -859,7 +916,7 @@ pk_sendgetspi(iph2)
                /* validity check */
                satype = ipsecdoi2pfkey_proto(pr->proto_id);
                if (satype == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid proto_id %d\n", pr->proto_id);
                        return -1;
                }
@@ -875,12 +932,12 @@ pk_sendgetspi(iph2)
                }
                mode = ipsecdoi2pfkey_mode(pr->encmode);
                if (mode == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid encmode %d\n", pr->encmode);
                        return -1;
                }
 
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
+               plog(ASL_LEVEL_DEBUG, "call pfkey_send_getspi\n");
                if (pfkey_send_getspi(
                                lcconf->sock_pfkey,
                                satype,
@@ -888,13 +945,14 @@ pk_sendgetspi(iph2)
                                dst,                    /* src of SA */
                                src,                    /* dst of SA */
                                minspi, maxspi,
-                               pr->reqid_in, iph2->seq) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                               pr->reqid_in, 0, 0, iph2->seq, 0) < 0) {
+                       plog(ASL_LEVEL_ERR, 
                                "ipseclib failed send getspi (%s)\n",
                                ipsec_strerror());
                        return -1;
                }
-               plog(LLV_DEBUG, LOCATION, NULL,
+
+               plog(ASL_LEVEL_DEBUG, 
                        "pfkey GETSPI sent: %s\n",
                        sadbsecas2str(dst, src, satype, 0, mode));
        }
@@ -911,8 +969,8 @@ pk_recvgetspi(mhp)
 {
        struct sadb_msg *msg;
        struct sadb_sa *sa;
-       struct ph2handle *iph2;
-       struct sockaddr *dst;
+       phase2_handle_t *iph2;
+       struct sockaddr_storage *dst;
        int proto_id;
        int allspiok, notfound;
        struct saprop *pp;
@@ -921,17 +979,17 @@ pk_recvgetspi(mhp)
        /* validity check */
        if (mhp[SADB_EXT_SA] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "inappropriate sadb getspi message passed.\n");
+               plog(ASL_LEVEL_ERR, 
+                       "Inappropriate sadb getspi message passed.\n");
                return -1;
        }
-       msg = (struct sadb_msg *)mhp[0];
-       sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
-       dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                     // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
+       dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */   
 
        /* the message has to be processed or not ? */
        if (msg->sadb_msg_pid != getpid()) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "%s message is not interesting "
                        "because pid %d is not mine.\n",
                        s_pfkey_type(msg->sadb_msg_type),
@@ -939,21 +997,44 @@ pk_recvgetspi(mhp)
                return -1;
        }
 
-       iph2 = getph2byseq(msg->sadb_msg_seq);
+       iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
        if (iph2 == NULL) {
-               plog(LLV_DEBUG, LOCATION, NULL,
-                       "seq %d of %s message not interesting.\n",
+               plog(ASL_LEVEL_DEBUG, 
+                       "Seq %d of %s message not interesting.\n",
                        msg->sadb_msg_seq,
                        s_pfkey_type(msg->sadb_msg_type));
                return -1;
        }
 
-       if (iph2->status != PHASE2ST_GETSPISENT) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "status mismatch (db:%d msg:%d)\n",
-                       iph2->status, PHASE2ST_GETSPISENT);
+       if (iph2->is_dying) {
+               plog(ASL_LEVEL_ERR,
+                        "Status mismatch Phase 2 dying (db:%d)\n",
+                        iph2->status);
                return -1;
        }
+    
+       switch (iph2->version) {
+        case ISAKMP_VERSION_NUMBER_IKEV1:
+            if (iph2->status != IKEV1_STATE_QUICK_I_GETSPISENT &&
+                iph2->status != IKEV1_STATE_QUICK_R_GETSPISENT) {
+                plog(ASL_LEVEL_ERR, "Status mismatch (db:%d)\n", iph2->status);
+                return -1;
+            }
+            // check the underlying iph2->ph1
+            if (!iph2->ph1) {
+                if (!ike_session_update_ph2_ph1bind(iph2)) {
+                    plog(ASL_LEVEL_ERR, 
+                         "Can't proceed with getspi for  %s. no suitable ISAKMP-SA found \n",
+                         saddrwop2str((struct sockaddr *)iph2->dst));
+                    ike_session_unlink_phase2(iph2);
+                    return -1;
+                }
+            }
+            break;
+        default:
+            plog(ASL_LEVEL_ERR, "Internal error: invalid IKE major version %d\n", iph2->version);
+            return -1;
+    }
 
        /* set SPI, and check to get all spi whether or not */
        allspiok = 1;
@@ -965,7 +1046,7 @@ pk_recvgetspi(mhp)
                if (pr->proto_id == proto_id && pr->spi == 0) {
                        pr->spi = sa->sadb_sa_spi;
                        notfound = 0;
-                       plog(LLV_DEBUG, LOCATION, NULL,
+                       plog(ASL_LEVEL_DEBUG, 
                                "pfkey GETSPI succeeded: %s\n",
                                sadbsecas2str(iph2->dst, iph2->src,
                                    msg->sadb_msg_satype,
@@ -977,26 +1058,25 @@ pk_recvgetspi(mhp)
        }
 
        if (notfound) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "get spi for unknown address %s\n",
-                       saddrwop2str(iph2->dst));
+               plog(ASL_LEVEL_ERR, 
+                       "Get spi for unknown address %s\n",
+                       saddrwop2str((struct sockaddr *)iph2->dst));
+        ike_session_unlink_phase2(iph2);
                return -1;
        }
 
        if (allspiok) {
-               /* update status */
-               iph2->status = PHASE2ST_GETSPIDONE;
-               if (isakmp_post_getspi(iph2) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "failed to start post getspi.\n");
-                       unbindph12(iph2);
-                       remph2(iph2);
-                       delph2(iph2);
-                       iph2 = NULL;
-                       return -1;
-               }
-       }
-
+        switch (iph2->version) {
+            case ISAKMP_VERSION_NUMBER_IKEV1:
+                if (isakmp_post_getspi(iph2) < 0) {
+                    plog(ASL_LEVEL_ERR, "IKEv1 post getspi failed.\n");
+                    ike_session_unlink_phase2(iph2);
+                    iph2 = NULL;
+                    return -1;
+                }
+                break;
+        }
+       }       
        return 0;
 }
 
@@ -1005,21 +1085,22 @@ pk_recvgetspi(mhp)
  */
 int
 pk_sendupdate(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
        struct saproto *pr;
-       struct sockaddr *src = NULL, *dst = NULL;
+       struct sockaddr_storage *src = NULL, *dst = NULL;
        u_int e_type, e_keylen, a_type, a_keylen, flags;
        u_int satype, mode;
        u_int64_t lifebyte = 0;
        u_int wsize = 4;  /* XXX static size of window */ 
        int proxy = 0;
        struct ph2natt natt;
+    int authtype;
 
        /* sanity check */
        if (iph2->approval == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "no approvaled SAs found.\n");
+               plog(ASL_LEVEL_ERR, 
+                       "No approved SAs found.\n");
        }
 
        if (iph2->side == INITIATOR)
@@ -1041,8 +1122,8 @@ pk_sendupdate(iph2)
                /* validity check */
                satype = ipsecdoi2pfkey_proto(pr->proto_id);
                if (satype == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "invalid proto_id %d\n", pr->proto_id);
+                       plog(ASL_LEVEL_ERR, 
+                               "Invalid proto_id %d\n", pr->proto_id);
                        return -1;
                }
                else if (satype == SADB_X_SATYPE_IPCOMP) {
@@ -1054,18 +1135,21 @@ pk_sendupdate(iph2)
 #else
                mode = ipsecdoi2pfkey_mode(pr->encmode);
                if (mode == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "invalid encmode %d\n", pr->encmode);
+                       plog(ASL_LEVEL_ERR, 
+                               "Invalid encmode %d\n", pr->encmode);
                        return -1;
                }
 #endif
 
                /* set algorithm type and key length */
                e_keylen = pr->head->encklen;
+        authtype = pr->head->authtype;
+        a_keylen = 0;
                if (pfkey_convertfromipsecdoi(
+                iph2,
                                pr->proto_id,
                                pr->head->trns_id,
-                               pr->head->authtype,
+                authtype,
                                &e_type, &e_keylen,
                                &a_type, &a_keylen, &flags) < 0)
                        return -1;
@@ -1076,19 +1160,31 @@ pk_sendupdate(iph2)
                lifebyte = 0;
 #endif
 
-#ifdef __APPLE__
 #ifdef ENABLE_NATT
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n");
+               //plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n");
+        plog(ASL_LEVEL_DEBUG, "call pfkey_send_update: e_type %d, e_klen %d, a_type %d, a_klen %d\n",
+             e_type, e_keylen, a_type, a_keylen);
                if (pr->udp_encap) {
                        memset (&natt, 0, sizeof (natt));
                        natt.sport = extract_port (iph2->ph1->remote);
                        flags |= SADB_X_EXT_NATT;
-                       if (iph2->ph1->natt_flags & NAT_DETECTED_ME)
-                               flags |= SADB_X_EXT_NATT_KEEPALIVE;
-                       else if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
+                       if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
                                mode == IPSEC_MODE_TRANSPORT &&
-                               src->sa_family == AF_INET)
-                                       flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
+                               src->ss_family == AF_INET) {
+                               flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
+                               if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
+                                       // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
+                                       flags |= SADB_X_EXT_NATT_DETECTED_PEER;
+                               }
+                       } else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
+                               if (iph2->ph1->rmconf->natt_keepalive == TRUE)
+                                       flags |= SADB_X_EXT_NATT_KEEPALIVE;
+                       } else {
+                               if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
+                                       // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
+                                       flags |= SADB_X_EXT_NATT_DETECTED_PEER;
+                               }
+                       }
                } else {
                        memset (&natt, 0, sizeof (natt));
                }
@@ -1105,14 +1201,14 @@ pk_sendupdate(iph2)
                                pr->keymat->v,
                                e_type, e_keylen, a_type, a_keylen, flags,
                                0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq, natt.sport) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                               iph2->seq, natt.sport, 0) < 0) {
+                       plog(ASL_LEVEL_ERR, 
                                "libipsec failed send update (%s)\n",
                                ipsec_strerror());
                        return -1;
                }
 #else
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n");
+               plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n");
                if (pfkey_send_update(
                                lcconf->sock_pfkey,
                                satype,
@@ -1125,95 +1221,15 @@ pk_sendupdate(iph2)
                                pr->keymat->v,
                                e_type, e_keylen, a_type, a_keylen, flags,
                                0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq, 0) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                               iph2->seq, 0, 0) < 0) {
+                       plog(ASL_LEVEL_ERR, 
                                "libipsec failed send update (%s)\n",
                                ipsec_strerror());
                        return -1;
                }
 #endif /* ENABLE_NATT */
-#else
-#ifdef ENABLE_NATT
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update_nat\n");
-               if (pr->udp_encap) {
-                       memset (&natt, 0, sizeof (natt));
-                       natt.type = iph2->ph1->natt_options->encaps_type;
-                       natt.sport = extract_port (iph2->ph1->remote);
-                       natt.dport = extract_port (iph2->ph1->local);
-                       natt.oa = NULL;         // FIXME: Here comes OA!!!
-                       natt.frag = iph2->ph1->rmconf->esp_frag;
-               } else {
-                       memset (&natt, 0, sizeof (natt));
-               }
 
-               if (pfkey_send_update_nat(
-                               lcconf->sock_pfkey,
-                               satype,
-                               mode,
-                               dst,
-                               src,
-                               pr->spi,
-                               pr->reqid_in,
-                               wsize,  
-                               pr->keymat->v,
-                               e_type, e_keylen, a_type, a_keylen, flags,
-                               0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq,
-                               natt.type, natt.sport, natt.dport, natt.oa,
-                               natt.frag) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "libipsec failed send update_nat (%s)\n",
-                               ipsec_strerror());
-                       return -1;
-               }
-#else
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n");
-               if (pfkey_send_update(
-                               lcconf->sock_pfkey,
-                               satype,
-                               mode,
-                               dst,
-                               src,
-                               pr->spi,
-                               pr->reqid_in,
-                               wsize,  
-                               pr->keymat->v,
-                               e_type, e_keylen, a_type, a_keylen, flags,
-                               0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "libipsec failed send update (%s)\n",
-                               ipsec_strerror());
-                       return -1;
-               }
-#endif /* ENABLE_NATT */
-#endif /* __APPLE__ */
 
-               if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
-                       continue;
-
-               /*
-                * It maybe good idea to call backupsa_to_file() after
-                * racoon will receive the sadb_update messages.
-                * But it is impossible because there is not key in the
-                * information from the kernel.
-                */
-               if (backupsa_to_file(satype, mode, dst, src,
-                               pr->spi, pr->reqid_in, 4,
-                               pr->keymat->v,
-                               e_type, e_keylen, a_type, a_keylen, flags,
-                               0, iph2->approval->lifebyte * 1024,
-                               iph2->approval->lifetime, 0,
-                               iph2->seq) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "backuped SA failed: %s\n",
-                               sadbsecas2str(dst, src,
-                               satype, pr->spi, mode));
-               }
-               plog(LLV_DEBUG, LOCATION, NULL,
-                       "backuped SA: %s\n",
-                       sadbsecas2str(dst, src,
-                       satype, pr->spi, mode));
        }
 
        return 0;
@@ -1225,8 +1241,8 @@ pk_recvupdate(mhp)
 {
        struct sadb_msg *msg;
        struct sadb_sa *sa;
-       struct sockaddr *src, *dst;
-       struct ph2handle *iph2;
+       struct sockaddr_storage *src, *dst;
+       phase2_handle_t *iph2;
        u_int proto_id, encmode, sa_mode;
        int incomplete = 0;
        struct saproto *pr;
@@ -1240,22 +1256,22 @@ pk_recvupdate(mhp)
         || mhp[SADB_EXT_SA] == NULL
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb update message passed.\n");
                return -1;
        }
-       msg = (struct sadb_msg *)mhp[0];
-       src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
-       dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
-       sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                 // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+       dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+       sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
 
        sa_mode = mhp[SADB_X_EXT_SA2] == NULL
                ? IPSEC_MODE_ANY
-               : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
+               : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
 
        /* the message has to be processed or not ? */
        if (msg->sadb_msg_pid != getpid()) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "%s message is not interesting "
                        "because pid %d is not mine.\n",
                        s_pfkey_type(msg->sadb_msg_type),
@@ -1263,19 +1279,26 @@ pk_recvupdate(mhp)
                return -1;
        }
 
-       iph2 = getph2byseq(msg->sadb_msg_seq);
+       iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
        if (iph2 == NULL) {
-               plog(LLV_DEBUG, LOCATION, NULL,
-                       "seq %d of %s message not interesting.\n",
+               plog(ASL_LEVEL_DEBUG, 
+                       "Seq %d of %s message not interesting.\n",
                        msg->sadb_msg_seq,
                        s_pfkey_type(msg->sadb_msg_type));
                return -1;
        }
 
-       if (iph2->status != PHASE2ST_ADDSA) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "status mismatch (db:%d msg:%d)\n",
-                       iph2->status, PHASE2ST_ADDSA);
+       if (iph2->is_dying) {
+               plog(ASL_LEVEL_ERR,
+                        "Status mismatch Phase 2 dying (db:%d)\n",
+                        iph2->status);
+               return -1;
+       }
+       if (iph2->status != IKEV1_STATE_QUICK_I_ADDSA &&
+        iph2->status != IKEV1_STATE_QUICK_R_ADDSA) {
+               plog(ASL_LEVEL_ERR,
+                       "Status mismatch (db:%d)\n",
+                       iph2->status);
                return -1;
        }
 
@@ -1283,13 +1306,13 @@ pk_recvupdate(mhp)
        for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
                proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
                if (proto_id == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid proto_id %d\n", msg->sadb_msg_satype);
                        return -1;
                }
                encmode = pfkey2ipsecdoi_mode(sa_mode);
                if (encmode == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid encmode %d\n", sa_mode);
                        return -1;
                }
@@ -1297,14 +1320,14 @@ pk_recvupdate(mhp)
                if (pr->proto_id == proto_id
                 && pr->spi == sa->sadb_sa_spi) {
                        pr->ok = 1;
-                       plog(LLV_DEBUG, LOCATION, NULL,
+                       plog(ASL_LEVEL_DEBUG, 
                                "pfkey UPDATE succeeded: %s\n",
                                sadbsecas2str(iph2->dst, iph2->src,
                                    msg->sadb_msg_satype,
                                    sa->sadb_sa_spi,
                                    sa_mode));
 
-                       plog(LLV_INFO, LOCATION, NULL,
+                       plog(ASL_LEVEL_INFO, 
                                "IPsec-SA established: %s\n",
                                sadbsecas2str(iph2->dst, iph2->src,
                                        msg->sadb_msg_satype, sa->sadb_sa_spi,
@@ -1322,16 +1345,34 @@ pk_recvupdate(mhp)
        SCHED_KILL(iph2->sce);
        
        /* update status */
-       iph2->status = PHASE2ST_ESTABLISHED;
+       fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_ESTABLISHED);
+
+       if (iph2->side == INITIATOR) {
+               IPSECSESSIONTRACEREVENT(iph2->parent_session,
+                                                               IPSECSESSIONEVENTCODE_IKEV1_PH2_INIT_SUCC,
+                                                               CONSTSTR("Initiator, Quick-Mode"),
+                                                               CONSTSTR(NULL));
+       } else {
+               IPSECSESSIONTRACEREVENT(iph2->parent_session,
+                                                               IPSECSESSIONEVENTCODE_IKEV1_PH2_RESP_SUCC,
+                                                               CONSTSTR("Responder, Quick-Mode"),
+                                                               CONSTSTR(NULL));
+       }
+
+       ike_session_ph2_established(iph2);
 
+       IPSECLOGASLMSG("IPSec Phase 2 established (Initiated by %s).\n",
+                                  (iph2->side == INITIATOR)? "me" : "peer");
+       
 #ifdef ENABLE_STATS
        gettimeofday(&iph2->end, NULL);
-       syslog(LOG_NOTICE, "%s(%s): %8.6f",
-               "phase2", "quick", timedelta(&iph2->start, &iph2->end));
+       plog(ASL_LEVEL_NOTICE, "%s(%s): %8.6f",
+               "Phase 2", "quick", timedelta(&iph2->start, &iph2->end));
 #endif
 
        /* count up */
-       iph2->ph1->ph2cnt++;
+       if (iph2->ph1)
+               iph2->ph1->ph2cnt++;
 
        /* turn off schedule */
        if (iph2->scr)
@@ -1341,12 +1382,12 @@ pk_recvupdate(mhp)
         * since we are going to reuse the phase2 handler, we need to
         * remain it and refresh all the references between ph1 and ph2 to use.
         */
-       unbindph12(iph2);
+       ike_session_unbindph12(iph2);   //%%%%% fix this
 
        iph2->sce = sched_new(iph2->approval->lifetime,
            isakmp_ph2expire_stub, iph2);
 
-       plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+       plog(ASL_LEVEL_DEBUG, "===\n");
        return 0;
 }
 
@@ -1355,20 +1396,21 @@ pk_recvupdate(mhp)
  */
 int
 pk_sendadd(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
        struct saproto *pr;
-       struct sockaddr *src = NULL, *dst = NULL;
+       struct sockaddr_storage *src = NULL, *dst = NULL;
        u_int e_type, e_keylen, a_type, a_keylen, flags;
        u_int satype, mode;
        u_int64_t lifebyte = 0;
        u_int wsize = 4; /* XXX static size of window */ 
        int proxy = 0;
        struct ph2natt natt;
+    int authtype;
 
        /* sanity check */
        if (iph2->approval == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "no approvaled SAs found.\n");
        }
 
@@ -1391,7 +1433,7 @@ pk_sendadd(iph2)
                /* validity check */
                satype = ipsecdoi2pfkey_proto(pr->proto_id);
                if (satype == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid proto_id %d\n", pr->proto_id);
                        return -1;
                }
@@ -1404,7 +1446,7 @@ pk_sendadd(iph2)
 #else
                mode = ipsecdoi2pfkey_mode(pr->encmode);
                if (mode == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid encmode %d\n", pr->encmode);
                        return -1;
                }
@@ -1412,10 +1454,13 @@ pk_sendadd(iph2)
 
                /* set algorithm type and key length */
                e_keylen = pr->head->encklen;
+        authtype = pr->head->authtype;
+        a_keylen = 0;
                if (pfkey_convertfromipsecdoi(
+                iph2,
                                pr->proto_id,
                                pr->head->trns_id,
-                               pr->head->authtype,
+                authtype,
                                &e_type, &e_keylen,
                                &a_type, &a_keylen, &flags) < 0)
                        return -1;
@@ -1426,20 +1471,32 @@ pk_sendadd(iph2)
                lifebyte = 0;
 #endif
 
-#ifdef __APPLE__
 #ifdef ENABLE_NATT
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n");
+               //plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n");
+        plog(ASL_LEVEL_DEBUG, "call pfkey_send_add: e_type %d, e_klen %d, a_type %d, a_klen %d\n",
+             e_type, e_keylen, a_type, a_keylen);
 
                if (pr->udp_encap) {
                        memset (&natt, 0, sizeof (natt));
                        natt.dport = extract_port (iph2->ph1->remote);
                        flags |= SADB_X_EXT_NATT;
-                       if (iph2->ph1->natt_flags & NAT_DETECTED_ME)
-                               flags |= SADB_X_EXT_NATT_KEEPALIVE;
-                       else if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
+                       if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
                                mode == IPSEC_MODE_TRANSPORT &&
-                               dst->sa_family == AF_INET)
-                                       flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
+                               src->ss_family == AF_INET) {
+                               flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
+                               if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
+                                       // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
+                                       flags |= SADB_X_EXT_NATT_DETECTED_PEER;
+                               }
+                       } else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
+                               if (iph2->ph1->rmconf->natt_keepalive == TRUE)
+                                       flags |= SADB_X_EXT_NATT_KEEPALIVE;
+                       } else {
+                               if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
+                                       // is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
+                                       flags |= SADB_X_EXT_NATT_DETECTED_PEER;
+                               }
+                       }               
                } else {
                        memset (&natt, 0, sizeof (natt));
 
@@ -1460,14 +1517,14 @@ pk_sendadd(iph2)
                                pr->keymat_p->v,
                                e_type, e_keylen, a_type, a_keylen, flags,
                                0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq,natt.dport) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                               iph2->seq,natt.dport, 0) < 0) {
+                       plog(ASL_LEVEL_ERR, 
                                "libipsec failed send add (%s)\n",
                                ipsec_strerror());
                        return -1;
                }
 #else
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n");
+               plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n");
 
                /* Remove port information, it is not used without NAT-T */
                //set_port(src, 0);
@@ -1485,105 +1542,13 @@ pk_sendadd(iph2)
                                pr->keymat_p->v,
                                e_type, e_keylen, a_type, a_keylen, flags,
                                0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq, 0) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "libipsec failed send add (%s)\n",
-                               ipsec_strerror());
-                       return -1;
-               }
-#endif /* ENABLE_NATT */
-#else /* __APPLE__ */
-#ifdef ENABLE_NATT
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add_nat\n");
-
-               if (pr->udp_encap) {
-                       memset (&natt, 0, sizeof (natt));
-                       natt.type = UDP_ENCAP_ESPINUDP;
-                       natt.sport = extract_port (iph2->ph1->local);
-                       natt.dport = extract_port (iph2->ph1->remote);
-                       natt.oa = NULL;         // FIXME: Here comes OA!!!
-                       natt.frag = iph2->ph1->rmconf->esp_frag;
-               } else {
-                       memset (&natt, 0, sizeof (natt));
-
-                       /* Remove port information, that SA doesn't use it */
-                       set_port(src, 0);
-                       set_port(dst, 0);
-               }
-
-               if (pfkey_send_add_nat(
-                               lcconf->sock_pfkey,
-                               satype,
-                               mode,
-                               src,
-                               dst,
-                               pr->spi_p,
-                               pr->reqid_out,
-                               wsize,  
-                               pr->keymat_p->v,
-                               e_type, e_keylen, a_type, a_keylen, flags,
-                               0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq,
-                               natt.type, natt.sport, natt.dport, natt.oa,
-                               natt.frag) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "libipsec failed send add_nat (%s)\n",
-                               ipsec_strerror());
-                       return -1;
-               }
-#else
-               plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n");
-
-               /* Remove port information, it is not used without NAT-T */
-               set_port(src, 0);
-               set_port(dst, 0);
-
-               if (pfkey_send_add(
-                               lcconf->sock_pfkey,
-                               satype,
-                               mode,
-                               src,
-                               dst,
-                               pr->spi_p,
-                               pr->reqid_out,
-                               wsize,
-                               pr->keymat_p->v,
-                               e_type, e_keylen, a_type, a_keylen, flags,
-                               0, lifebyte, iph2->approval->lifetime, 0,
-                               iph2->seq) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                               iph2->seq, 0, 0) < 0) {
+                       plog(ASL_LEVEL_ERR, 
                                "libipsec failed send add (%s)\n",
                                ipsec_strerror());
                        return -1;
                }
 #endif /* ENABLE_NATT */
-#endif /* __APPLE__ */
-
-               if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
-                       continue;
-
-               /*
-                * It maybe good idea to call backupsa_to_file() after
-                * racoon will receive the sadb_update messages.
-                * But it is impossible because there is not key in the
-                * information from the kernel.
-                */
-               if (backupsa_to_file(satype, mode, src, dst,
-                               pr->spi_p, pr->reqid_out, 4,
-                               pr->keymat_p->v,
-                               e_type, e_keylen, a_type, a_keylen, flags,
-                               0, iph2->approval->lifebyte * 1024,
-                               iph2->approval->lifetime, 0,
-                               iph2->seq) < 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "backuped SA failed: %s\n",
-                               sadbsecas2str(src, dst,
-                               satype, pr->spi_p, mode));
-               }
-               plog(LLV_DEBUG, LOCATION, NULL,
-                       "backuped SA: %s\n",
-                       sadbsecas2str(src, dst,
-                       satype, pr->spi_p, mode));
        }
 
        return 0;
@@ -1595,8 +1560,8 @@ pk_recvadd(mhp)
 {
        struct sadb_msg *msg;
        struct sadb_sa *sa;
-       struct sockaddr *src, *dst;
-       struct ph2handle *iph2;
+       struct sockaddr_storage *src, *dst;
+       phase2_handle_t *iph2;
        u_int sa_mode;
 
        /* ignore this message because of local test mode. */
@@ -1608,22 +1573,22 @@ pk_recvadd(mhp)
         || mhp[SADB_EXT_SA] == NULL
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb add message passed.\n");
                return -1;
        }
-       msg = (struct sadb_msg *)mhp[0];
-       src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
-       dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
-       sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                     // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+       dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+       sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
 
        sa_mode = mhp[SADB_X_EXT_SA2] == NULL
                ? IPSEC_MODE_ANY
-               : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
+               : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
 
        /* the message has to be processed or not ? */
        if (msg->sadb_msg_pid != getpid()) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "%s message is not interesting "
                        "because pid %d is not mine.\n",
                        s_pfkey_type(msg->sadb_msg_type),
@@ -1631,30 +1596,31 @@ pk_recvadd(mhp)
                return -1;
        }
 
-       iph2 = getph2byseq(msg->sadb_msg_seq);
+       iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
        if (iph2 == NULL) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "seq %d of %s message not interesting.\n",
                        msg->sadb_msg_seq,
                        s_pfkey_type(msg->sadb_msg_type));
                return -1;
        }
-
        /*
         * NOTE don't update any status of phase2 handle
         * because they must be updated by SADB_UPDATE message
         */
 
-       plog(LLV_INFO, LOCATION, NULL,
+       plog(ASL_LEVEL_INFO, 
                "IPsec-SA established: %s\n",
                sadbsecas2str(iph2->src, iph2->dst,
                        msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
                        
+       ike_session_cleanup_other_established_ph2s(iph2->parent_session, iph2);
+       
 #ifdef ENABLE_VPNCONTROL_PORT
                {
                        u_int32_t address;
                        
-                       if (iph2->dst->sa_family == AF_INET)
+                       if (iph2->dst->ss_family == AF_INET)
                                address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
                        else
                                address = 0;
@@ -1662,7 +1628,7 @@ pk_recvadd(mhp)
                }       
 #endif
 
-       plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+       plog(ASL_LEVEL_DEBUG, "===\n");
        return 0;
 }
 
@@ -1672,8 +1638,8 @@ pk_recvexpire(mhp)
 {
        struct sadb_msg *msg;
        struct sadb_sa *sa;
-       struct sockaddr *src, *dst;
-       struct ph2handle *iph2;
+       struct sockaddr_storage *src, *dst;
+       phase2_handle_t *iph2;
        u_int proto_id, sa_mode;
 
        /* sanity check */
@@ -1683,46 +1649,46 @@ pk_recvexpire(mhp)
         || mhp[SADB_EXT_ADDRESS_DST] == NULL
         || (mhp[SADB_EXT_LIFETIME_HARD] != NULL
          && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb expire message passed.\n");
                return -1;
        }
-       msg = (struct sadb_msg *)mhp[0];
-       sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
-       src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
-       dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                 // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
+       src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+       dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
 
        sa_mode = mhp[SADB_X_EXT_SA2] == NULL
                ? IPSEC_MODE_ANY
-               : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
+               : (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
 
        proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
        if (proto_id == ~0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "invalid proto_id %d\n", msg->sadb_msg_satype);
                return -1;
        }
 
-       plog(LLV_INFO, LOCATION, NULL,
+       plog(ASL_LEVEL_INFO, 
                "IPsec-SA expired: %s\n",
                sadbsecas2str(src, dst,
                        msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
 
-       iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
+       iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
        if (iph2 == NULL) {
                /*
                 * Ignore it because two expire messages are come up.
                 * phase2 handler has been deleted already when 2nd message
                 * is received.
                 */
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "no such a SA found: %s\n",
                        sadbsecas2str(src, dst,
                            msg->sadb_msg_satype, sa->sadb_sa_spi,
                            sa_mode));
                return 0;
        }
-       if (iph2->status != PHASE2ST_ESTABLISHED) {
+       if (iph2->is_dying || !FSM_STATE_IS_ESTABLISHED(iph2->status)) {
                /*
                 * If the status is not equal to PHASE2ST_ESTABLISHED,
                 * racoon ignores this expire message.  There are two reason.
@@ -1731,34 +1697,31 @@ pk_recvexpire(mhp)
                 * without receiving a expire message.  Another is that racoon
                 * may receive the multiple expire messages from the kernel.
                 */
-               plog(LLV_WARNING, LOCATION, NULL,
-                       "the expire message is received "
-                       "but the handler has not been established.\n");
+               plog(ASL_LEVEL_WARNING,
+             "The expire message is received but the handler %s (status = 0x%x).\n",
+             iph2->is_dying ? "is dying" : "has not been established", iph2->status);
                return 0;
        }
 
        /* turn off the timer for calling isakmp_ph2expire() */ 
        SCHED_KILL(iph2->sce);
-
-       iph2->status = PHASE2ST_EXPIRED;
-
-       /* INITIATOR, begin phase 2 exchange. */
+       
+       fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_EXPIRED);
+       
+       /* INITIATOR, begin phase 2 exchange only if there's no other established ph2. */
        /* allocate buffer for status management of pfkey message */
-       if (iph2->side == INITIATOR) {
+       if (iph2->side == INITIATOR &&
+               !ike_session_has_other_established_ph2(iph2->parent_session, iph2) &&
+               !ike_session_drop_rekey(iph2->parent_session, IKE_SESSION_REKEY_TYPE_PH2)) {
 
-               initph2(iph2);
-
-               /* update status for re-use */
-               iph2->status = PHASE2ST_STATUS2;
+               ike_session_initph2(iph2);
 
                /* start isakmp initiation by using ident exchange */
                if (isakmp_post_acquire(iph2) < 0) {
-                       plog(LLV_ERROR, LOCATION, iph2->dst,
+                       plog(ASL_LEVEL_ERR,
                                "failed to begin ipsec sa "
-                               "re-negotication.\n");
-                       unbindph12(iph2);
-                       remph2(iph2);
-                       delph2(iph2);
+                               "re-negotiation.\n");
+                       ike_session_unlink_phase2(iph2);
                        return -1;
                }
 
@@ -1766,12 +1729,11 @@ pk_recvexpire(mhp)
                /*NOTREACHED*/
        }
 
+
        /* If not received SADB_EXPIRE, INITIATOR delete ph2handle. */
        /* RESPONDER always delete ph2handle, keep silent.  RESPONDER doesn't
         * manage IPsec SA, so delete the list */
-       unbindph12(iph2);
-       remph2(iph2);
-       delph2(iph2);
+       ike_session_unlink_phase2(iph2);
 
        return 0;
 }
@@ -1783,10 +1745,10 @@ pk_recvacquire(mhp)
        struct sadb_msg *msg;
        struct sadb_x_policy *xpl;
        struct secpolicy *sp_out = NULL, *sp_in = NULL;
-#define MAXNESTEDSA    5       /* XXX */
-       struct ph2handle *iph2[MAXNESTEDSA];
-       struct sockaddr *src, *dst;
-       int n;  /* # of phase 2 handler */
+       phase2_handle_t *iph2;
+       struct sockaddr_storage *src, *dst;
+    ike_session_t *session = NULL;
+    struct remoteconf *rmconf;
 
        /* ignore this message because of local test mode. */
        if (f_local)
@@ -1797,36 +1759,36 @@ pk_recvacquire(mhp)
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL
         || mhp[SADB_X_EXT_POLICY] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb acquire message passed.\n");
                return -1;
        }
-       msg = (struct sadb_msg *)mhp[0];
-       xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
-       src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
-       dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                         // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+       src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+       dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
 
        /* ignore if type is not IPSEC_POLICY_IPSEC */
        if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "ignore ACQUIRE message. type is not IPsec.\n");
                return 0;
        }
 
        /* ignore it if src is multicast address */
     {
-       struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+       struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
 
-       if ((sa->sa_family == AF_INET
+       if ((sa->ss_family == AF_INET
          && IN_MULTICAST(ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr)))
 #ifdef INET6
-        || (sa->sa_family == AF_INET6
+        || (sa->ss_family == AF_INET6
          && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sa)->sin6_addr))
 #endif
        ) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "ignore due to multicast address: %s.\n",
-                       saddrwop2str(sa));
+                       saddrwop2str((struct sockaddr *)sa));
                return 0;
        }
     }
@@ -1841,10 +1803,16 @@ pk_recvacquire(mhp)
                 *   than one in the policy, so kernel will drop them;
                 * => therefore this acquire is not for us! --Aidas
                 */
-               struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+                                                                    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+               struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);    
                struct myaddrs *p;
                int do_listen = 0;
+        char * str;
                for (p = lcconf->myaddrs; p; p = p->next) {
+            str = saddr2str((struct sockaddr *)p->addr);
+            plog(ASL_LEVEL_DEBUG, 
+                 "checking listen addrs: %s", str);
+            
                        if (!cmpsaddrwop(p->addr, sa)) {
                                do_listen = 1;
                                break;
@@ -1852,9 +1820,9 @@ pk_recvacquire(mhp)
                }
 
                if (!do_listen) {
-                       plog(LLV_DEBUG, LOCATION, NULL,
+                       plog(ASL_LEVEL_DEBUG, 
                                "ignore because do not listen on source address : %s.\n",
-                               saddrwop2str(sa));
+                               saddrwop2str((struct sockaddr *)sa));
                        return 0;
                }
        }
@@ -1866,147 +1834,168 @@ pk_recvacquire(mhp)
         *       should ignore such a acquire message because the phase 2
         *       is just negotiating.
         *    2. its state is equal to PHASE2ST_ESTABLISHED, then racoon
-        *       has to prcesss such a acquire message because racoon may
-        *       lost the expire message.
+        *       has to process such a acquire message because racoon may
+        *       have lost the expire message.
         */
-       iph2[0] = getph2byid(src, dst, xpl->sadb_x_policy_id);
-       if (iph2[0] != NULL) {
-               if (iph2[0]->status < PHASE2ST_ESTABLISHED) {
-                       plog(LLV_DEBUG, LOCATION, NULL,
+       iph2 = ike_session_getph2byid(src, dst, xpl->sadb_x_policy_id);
+       if (iph2 != NULL) {
+        session = iph2->parent_session;
+               if (!FSM_STATE_IS_ESTABLISHED(iph2->status)) {
+                       plog(ASL_LEVEL_DEBUG,
                                "ignore the acquire because ph2 found\n");
                        return -1;
                }
-               if (iph2[0]->status == PHASE2ST_EXPIRED)
-                       iph2[0] = NULL;
+               if (FSM_STATE_IS_EXPIRED(iph2->status))
+                       iph2 = NULL;
                /*FALLTHROUGH*/
        }
 
        /* search for proper policyindex */
        sp_out = getspbyspid(xpl->sadb_x_policy_id);
        if (sp_out == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n",
+               plog(ASL_LEVEL_ERR, "no policy found: id:%d.\n",
                        xpl->sadb_x_policy_id);
                return -1;
        }
-       plog(LLV_DEBUG, LOCATION, NULL,
+       plog(ASL_LEVEL_DEBUG, 
                "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
 
        /* get inbound policy */
     {
-       struct policyindex spidx;
-
-       spidx.dir = IPSEC_DIR_INBOUND;
-       memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
-       memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
-       spidx.prefs = sp_out->spidx.prefd;
-       spidx.prefd = sp_out->spidx.prefs;
-       spidx.ul_proto = sp_out->spidx.ul_proto;
-
-       sp_in = getsp(&spidx);
-       if (sp_in) {
-               plog(LLV_DEBUG, LOCATION, NULL,
-                       "suitable inbound SP found: %s.\n",
-                       spidx2str(&sp_in->spidx));
-       } else {
-               plog(LLV_NOTIFY, LOCATION, NULL,
-                       "no in-bound policy found: %s\n",
-                       spidx2str(&spidx));
-       }
+        struct policyindex spidx;
+
+        spidx.dir = IPSEC_DIR_INBOUND;
+        memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
+        memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
+        spidx.prefs = sp_out->spidx.prefd;
+        spidx.prefd = sp_out->spidx.prefs;
+        spidx.ul_proto = sp_out->spidx.ul_proto;
+
+        sp_in = getsp(&spidx);
+        if (sp_in) {
+            plog(ASL_LEVEL_DEBUG,
+                "Suitable inbound SP found: %s.\n",
+                spidx2str(&sp_in->spidx));
+        } else {
+            plog(ASL_LEVEL_NOTICE,
+                "No in-bound policy found: %s\n",
+                spidx2str(&spidx));
+        }
     }
-
-       memset(iph2, 0, MAXNESTEDSA);
-
-       n = 0;
-
+    
        /* allocate a phase 2 */
-       iph2[n] = newph2();
-       if (iph2[n] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "failed to allocate phase2 entry.\n");
+    rmconf = getrmconf(dst);
+       if (rmconf == NULL) {
+               plog(ASL_LEVEL_ERR, "No configuration found for %s.\n",
+             saddrwop2str((struct sockaddr *)dst));
                return -1;
        }
-       iph2[n]->side = INITIATOR;
-       iph2[n]->spid = xpl->sadb_x_policy_id;
-       iph2[n]->satype = msg->sadb_msg_satype;
-       iph2[n]->seq = msg->sadb_msg_seq;
-       iph2[n]->status = PHASE2ST_STATUS2;
 
+       iph2 = ike_session_newph2(rmconf->ike_version, PHASE2_TYPE_SA);
+       if (iph2 == NULL) {
+               plog(ASL_LEVEL_ERR,
+                       "Failed to allocate Phase 2 entry.\n");
+               return -1;
+       }
+       plog(ASL_LEVEL_DEBUG, "Got new Phase 2 version %d\n", iph2->version);
+    iph2->version = rmconf->ike_version;
+       iph2->side = INITIATOR;
+       iph2->spid = xpl->sadb_x_policy_id;
+
+       iph2->satype = msg->sadb_msg_satype;
+       iph2->seq = msg->sadb_msg_seq;
        /* set end addresses of SA */
-       iph2[n]->dst = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]));
-       if (iph2[n]->dst == NULL) {
-               delph2(iph2[n]);
+                                                // Wcast_align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       iph2->src = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]));
+       if (iph2->src == NULL) {
+               ike_session_delph2(iph2);
                return -1;
        }
-       iph2[n]->src = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]));
-       if (iph2[n]->src == NULL) {
-               delph2(iph2[n]);
+    iph2->dst = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]));
+       if (iph2->dst == NULL) {
+        ike_session_delph2(iph2);
                return -1;
+    }
+    
+       if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) {
+               fsm_set_state(&iph2->status, IKEV1_STATE_QUICK_I_START);
        }
 
-       plog(LLV_DEBUG, LOCATION, NULL,
+       plog(ASL_LEVEL_DEBUG,
                "new acquire %s\n", spidx2str(&sp_out->spidx));
 
        /* get sainfo */
     {
-       vchar_t *idsrc, *iddst;
-
-       idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src,
-                               sp_out->spidx.prefs, sp_out->spidx.ul_proto);
-       if (idsrc == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "failed to get ID for %s\n",
-                       spidx2str(&sp_out->spidx));
-               delph2(iph2[n]);
-               return -1;
-       }
-       iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst,
-                               sp_out->spidx.prefd, sp_out->spidx.ul_proto);
-       if (iddst == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "failed to get ID for %s\n",
-                       spidx2str(&sp_out->spidx));
-               vfree(idsrc);
-               delph2(iph2[n]);
-               return -1;
-       }
-       iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL, 0);
-       vfree(idsrc);
-       vfree(iddst);
-       if (iph2[n]->sainfo == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "failed to get sainfo.\n");
-               delph2(iph2[n]);
-               return -1;
-               /* XXX should use the algorithm list from register message */
-       }
+        vchar_t *idsrc, *iddst;
+
+        idsrc = ipsecdoi_sockaddr2id(&sp_out->spidx.src,
+                    sp_out->spidx.prefs, sp_out->spidx.ul_proto);
+        if (idsrc == NULL) {
+            plog(ASL_LEVEL_ERR, 
+                "failed to get ID for %s\n",
+                spidx2str(&sp_out->spidx));
+            ike_session_delph2(iph2);
+            return -1;
+        }
+        iddst = ipsecdoi_sockaddr2id(&sp_out->spidx.dst,
+                    sp_out->spidx.prefd, sp_out->spidx.ul_proto);
+        if (iddst == NULL) {
+            plog(ASL_LEVEL_ERR, 
+                "failed to get ID for %s\n",
+                spidx2str(&sp_out->spidx));
+            vfree(idsrc);
+            ike_session_delph2(iph2);
+            return -1;
+        }
+        iph2->sainfo = getsainfo(idsrc, iddst, NULL, 0);
+        vfree(idsrc);
+        vfree(iddst);
+        if (iph2->sainfo == NULL) {
+            plog(ASL_LEVEL_ERR,
+                "failed to get sainfo.\n");
+            ike_session_delph2(iph2);
+            return -1;
+            /* XXX should use the algorithm list from register message */
+        }
     }
+    retain_sainfo(iph2->sainfo);
 
-       if (set_proposal_from_policy(iph2[n], sp_out, sp_in) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "failed to create saprop.\n");
-               delph2(iph2[n]);
+       if (set_proposal_from_policy(iph2, sp_out, sp_in) < 0) {
+               plog(ASL_LEVEL_ERR,
+                        "failed to create saprop.\n");
+                       ike_session_delph2(iph2);
                return -1;
        }
-       insph2(iph2[n]);
+
+    if (session == NULL)
+        session = ike_session_get_session(iph2->src, iph2->dst, 1, NULL);
+    if (session == NULL)
+        fatal_error(-1);
+
+    if (ike_session_link_phase2(session, iph2))
+        fatal_error(-1);    //????? fix ???
 
        /* start isakmp initiation by using ident exchange */
        /* XXX should be looped if there are multiple phase 2 handler. */
-       if (isakmp_post_acquire(iph2[n]) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "failed to begin ipsec sa negotication.\n");
+       if (isakmp_post_acquire(iph2) < 0) {
+               plog(ASL_LEVEL_ERR,
+                       "failed to begin ipsec sa negotiation.\n");
                goto err;
        }
+       
+#if !TARGET_OS_EMBEDDED
+       if ( lcconf->vt == NULL){
+               if (!(lcconf->vt = vproc_transaction_begin(NULL)))
+                       plog(ASL_LEVEL_ERR, 
+                               "vproc_transaction_begin returns NULL.\n");
+       }
+#endif                         
 
+       
        return 0;
 
 err:
-       while (n >= 0) {
-               unbindph12(iph2[n]);
-               remph2(iph2[n]);
-               delph2(iph2[n]);
-               iph2[n] = NULL;
-               n--;
-       }
+    ike_session_unlink_phase2(iph2);
        return -1;
 }
 
@@ -2016,8 +2005,8 @@ pk_recvdelete(mhp)
 {
        struct sadb_msg *msg;
        struct sadb_sa *sa;
-       struct sockaddr *src, *dst;
-       struct ph2handle *iph2 = NULL;
+       struct sockaddr_storage *src, *dst;
+       phase2_handle_t *iph2 = NULL;
        u_int proto_id;
 
        /* ignore this message because of local test mode. */
@@ -2026,21 +2015,20 @@ pk_recvdelete(mhp)
 
        /* sanity check */
        if (mhp[0] == NULL
-        || mhp[SADB_EXT_SA] == NULL
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb delete message passed.\n");
                return -1;
        }
-       msg = (struct sadb_msg *)mhp[0];
-       sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
-       src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
-       dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                 // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
+       src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+       dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
 
        /* the message has to be processed or not ? */
        if (msg->sadb_msg_pid == getpid()) {
-               plog(LLV_DEBUG, LOCATION, NULL,
+               plog(ASL_LEVEL_DEBUG, 
                        "%s message is not interesting "
                        "because the message was originated by me.\n",
                        s_pfkey_type(msg->sadb_msg_type));
@@ -2049,33 +2037,44 @@ pk_recvdelete(mhp)
 
        proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
        if (proto_id == ~0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "invalid proto_id %d\n", msg->sadb_msg_satype);
                return -1;
        }
 
-       iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
+    plog(ASL_LEVEL_DEBUG, "SADB delete message: proto-id %d\n", proto_id);
+    plog(ASL_LEVEL_DEBUG, "src: %s\n", saddr2str((struct sockaddr *)src));
+    plog(ASL_LEVEL_DEBUG, "dst: %s\n", saddr2str((struct sockaddr *)dst));
+    
+    if (!sa) {
+        ike_session_deleteallph2(src, dst, proto_id);
+        ike_session_deleteallph1(src, dst);
+        return 0;
+    }
+
+       iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
        if (iph2 == NULL) {
                /* ignore */
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "no iph2 found: %s\n",
                        sadbsecas2str(src, dst, msg->sadb_msg_satype,
                                sa->sadb_sa_spi, IPSEC_MODE_ANY));
                return 0;
        }
 
-       plog(LLV_ERROR, LOCATION, NULL,
+       plog(ASL_LEVEL_ERR, 
                "pfkey DELETE received: %s\n",
                sadbsecas2str(iph2->src, iph2->dst,
                        msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
 
        /* send delete information */
-       if (iph2->status == PHASE2ST_ESTABLISHED)
+    
+    /* TODO: Look into handling this properly. Currently, if we get here, we can end up sending delete messages to the server for their own SAs, which is rejected. */
+       /*if (FSM_STATE_IS_ESTABLISHED(iph2->status))
                isakmp_info_send_d2(iph2);
 
-       unbindph12(iph2);
-       remph2(iph2);
-       delph2(iph2);
+       ike_session_cleanup_ph1s_by_ph2(iph2);
+       ike_session_unlink_phase2(iph2);*/
 
        return 0;
 }
@@ -2084,18 +2083,15 @@ static int
 pk_recvflush(mhp)
        caddr_t *mhp;
 {
-       /* ignore this message because of local test mode. */
-       if (f_local)
-               return 0;
-
        /* sanity check */
        if (mhp[0] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb flush message passed.\n");
                return -1;
        }
 
-       flushph2();
+       ike_session_flush_all_phase2(false);
+       ike_session_flush_all_phase1(false);
 
        return 0;
 }
@@ -2104,9 +2100,9 @@ static int
 getsadbpolicy(policy0, policylen0, type, iph2)
        caddr_t *policy0;
        int *policylen0, type;
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
-       struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+       struct policyindex *spidx = iph2->spidx_gen;
        struct sadb_x_policy *xpl;
        struct sadb_x_ipsecrequest *xisr;
        struct saproto *pr;
@@ -2121,8 +2117,8 @@ getsadbpolicy(policy0, policylen0, type, iph2)
                for (pr = iph2->approval->head; pr; pr = pr->next) {
                        xisrlen = sizeof(*xisr);
                        if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
-                               xisrlen += (sysdep_sa_len(iph2->src)
-                                         + sysdep_sa_len(iph2->dst));
+                               xisrlen += (sysdep_sa_len((struct sockaddr *)iph2->src)
+                                         + sysdep_sa_len((struct sockaddr *)iph2->dst));
                        }
 
                        policylen += PFKEY_ALIGN8(xisrlen);
@@ -2132,12 +2128,12 @@ getsadbpolicy(policy0, policylen0, type, iph2)
        /* make policy structure */
        policy = racoon_malloc(policylen);
        if (!policy) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "buffer allocation failed.\n");
                return -1;
        }
 
-       xpl = (struct sadb_x_policy *)policy;
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)policy;
        xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen);
        xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
        xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
@@ -2157,13 +2153,13 @@ getsadbpolicy(policy0, policylen0, type, iph2)
 
                satype = doi2ipproto(pr->proto_id);
                if (satype == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid proto_id %d\n", pr->proto_id);
                        goto err;
                }
                mode = ipsecdoi2pfkey_mode(pr->encmode);
                if (mode == ~0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid encmode %d\n", pr->encmode);
                        goto err;
                }
@@ -2183,8 +2179,8 @@ getsadbpolicy(policy0, policylen0, type, iph2)
                if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
                        int src_len, dst_len;
 
-                       src_len = sysdep_sa_len(iph2->src);
-                       dst_len = sysdep_sa_len(iph2->dst);
+                       src_len = sysdep_sa_len((struct sockaddr *)iph2->src);
+                       dst_len = sysdep_sa_len((struct sockaddr *)iph2->dst);
                        xisrlen += src_len + dst_len;
 
                        memcpy(p, iph2->src, src_len);
@@ -2212,9 +2208,9 @@ err:
 
 int
 pk_sendspdupdate2(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
-       struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+       struct policyindex *spidx = iph2->spidx_gen;
        caddr_t policy = NULL;
        int policylen = 0;
        u_int64_t ltime, vtime;
@@ -2223,26 +2219,26 @@ pk_sendspdupdate2(iph2)
        vtime = 0;
 
        if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "getting sadb policy failed.\n");
                return -1;
        }
 
        if (pfkey_send_spdupdate2(
                        lcconf->sock_pfkey,
-                       (struct sockaddr *)&spidx->src,
+                       &spidx->src,
                        spidx->prefs,
-                       (struct sockaddr *)&spidx->dst,
+                       &spidx->dst,
                        spidx->prefd,
                        spidx->ul_proto,
                        ltime, vtime,
                        policy, policylen, 0) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "libipsec failed send spdupdate2 (%s)\n",
                        ipsec_strerror());
                goto end;
        }
-       plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdupdate2\n");
+       plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdupdate2\n");
 
 end:
        if (policy)
@@ -2265,13 +2261,13 @@ pk_recvspdupdate(mhp)
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL
         || mhp[SADB_X_EXT_POLICY] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spdupdate message passed.\n");
                return -1;
        }
-       saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
-       daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
-       xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+       saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];        // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
 
 #ifdef HAVE_PFKEY_POLICY_PRIORITY
        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
@@ -2294,7 +2290,7 @@ pk_recvspdupdate(mhp)
 
        sp = getsp(&spidx);
        if (sp == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "such policy does not already exist: \"%s\"\n",
                        spidx2str(&spidx));
        } else {
@@ -2313,9 +2309,9 @@ pk_recvspdupdate(mhp)
  */
 int
 pk_sendspdadd2(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
-       struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+       struct policyindex *spidx = iph2->spidx_gen;
        caddr_t policy = NULL;
        int policylen = 0;
        u_int64_t ltime, vtime;
@@ -2324,26 +2320,26 @@ pk_sendspdadd2(iph2)
        vtime = 0;
 
        if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "getting sadb policy failed.\n");
                return -1;
        }
 
        if (pfkey_send_spdadd2(
                        lcconf->sock_pfkey,
-                       (struct sockaddr *)&spidx->src,
+                       &spidx->src,
                        spidx->prefs,
-                       (struct sockaddr *)&spidx->dst,
+                       &spidx->dst,
                        spidx->prefd,
                        spidx->ul_proto,
                        ltime, vtime,
                        policy, policylen, 0) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "libipsec failed send spdadd2 (%s)\n",
                        ipsec_strerror());
                goto end;
        }
-       plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdadd2\n");
+       plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdadd2\n");
 
 end:
        if (policy)
@@ -2366,13 +2362,13 @@ pk_recvspdadd(mhp)
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL
         || mhp[SADB_X_EXT_POLICY] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spdadd message passed.\n");
                return -1;
        }
-       saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
-       daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
-       xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+       saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
 
 #ifdef HAVE_PFKEY_POLICY_PRIORITY
        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
@@ -2395,7 +2391,7 @@ pk_recvspdadd(mhp)
 
        sp = getsp(&spidx);
        if (sp != NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "such policy already exists. "
                        "anyway replace it: %s\n",
                        spidx2str(&spidx));
@@ -2414,32 +2410,32 @@ pk_recvspdadd(mhp)
  */
 int
 pk_sendspddelete(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
-       struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+       struct policyindex *spidx = iph2->spidx_gen;
        caddr_t policy = NULL;
        int policylen;
 
        if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "getting sadb policy failed.\n");
                return -1;
        }
 
        if (pfkey_send_spddelete(
                        lcconf->sock_pfkey,
-                       (struct sockaddr *)&spidx->src,
+                       &spidx->src,
                        spidx->prefs,
-                       (struct sockaddr *)&spidx->dst,
+                       &spidx->dst,
                        spidx->prefd,
                        spidx->ul_proto,
                        policy, policylen, 0) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "libipsec failed send spddelete (%s)\n",
                        ipsec_strerror());
                goto end;
        }
-       plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spddelete\n");
+       plog(ASL_LEVEL_DEBUG, "call pfkey_send_spddelete\n");
 
 end:
        if (policy)
@@ -2462,13 +2458,13 @@ pk_recvspddelete(mhp)
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL
         || mhp[SADB_X_EXT_POLICY] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spddelete message passed.\n");
                return -1;
        }
-       saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
-       daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
-       xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+       saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
 
 #ifdef HAVE_PFKEY_POLICY_PRIORITY
        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
@@ -2491,12 +2487,14 @@ pk_recvspddelete(mhp)
 
        sp = getsp(&spidx);
        if (sp == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "no policy found: %s\n",
                        spidx2str(&spidx));
                return -1;
        }
 
+    ike_session_purgephXbyspid(xpl->sadb_x_policy_id, true);
+
        remsp(sp);
        delsp(sp);
 
@@ -2517,13 +2515,13 @@ pk_recvspdexpire(mhp)
         || mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL
         || mhp[SADB_X_EXT_POLICY] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spdexpire message passed.\n");
                return -1;
        }
-       saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
-       daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
-       xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+       saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
 
 #ifdef HAVE_PFKEY_POLICY_PRIORITY
        KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
@@ -2546,12 +2544,14 @@ pk_recvspdexpire(mhp)
 
        sp = getsp(&spidx);
        if (sp == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "no policy found: %s\n",
                        spidx2str(&spidx));
                return -1;
        }
 
+    ike_session_purgephXbyspid(xpl->sadb_x_policy_id, false);
+
        remsp(sp);
        delsp(sp);
 
@@ -2564,7 +2564,7 @@ pk_recvspdget(mhp)
 {
        /* sanity check */
        if (mhp[0] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spdget message passed.\n");
                return -1;
        }
@@ -2584,18 +2584,18 @@ pk_recvspddump(mhp)
 
        /* sanity check */
        if (mhp[0] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spddump message passed.\n");
                return -1;
        }
-       msg = (struct sadb_msg *)mhp[0];
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];         // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
 
-       saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
-       daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
-       xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+       saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+       daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
 
        if (saddr == NULL || daddr == NULL || xpl == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spddump message passed.\n");
                return -1;
        }
@@ -2621,7 +2621,7 @@ pk_recvspddump(mhp)
 
        sp = getsp(&spidx);
        if (sp != NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "such policy already exists. "
                        "anyway replace it: %s\n",
                        spidx2str(&spidx));
@@ -2641,11 +2641,13 @@ pk_recvspdflush(mhp)
 {
        /* sanity check */
        if (mhp[0] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spdflush message passed.\n");
                return -1;
        }
 
+    ike_session_flush_all_phase2(false);
+    ike_session_flush_all_phase1(false);
        flushsp();
 
        return 0;
@@ -2656,7 +2658,7 @@ pk_recvspdflush(mhp)
  */
 int
 pk_sendeacquire(iph2)
-       struct ph2handle *iph2;
+       phase2_handle_t *iph2;
 {
        struct sadb_msg *newmsg;
        int len;
@@ -2664,7 +2666,7 @@ pk_sendeacquire(iph2)
        len = sizeof(struct sadb_msg);
        newmsg = racoon_calloc(1, len);
        if (newmsg == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "failed to get buffer to send acquire.\n");
                return -1;
        }
@@ -2687,6 +2689,145 @@ pk_sendeacquire(iph2)
        return 0;
 }
 
+int
+pk_sendget_inbound_sastats(ike_session_t *session)
+{
+    u_int32_t max_stats;
+    u_int32_t seq;
+
+    if (!session) {
+        plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
+        return -1;
+    }
+
+    session->traffic_monitor.num_in_curr_req = 0;
+    bzero(session->traffic_monitor.in_curr_req, sizeof(session->traffic_monitor.in_curr_req));
+    max_stats = (sizeof(session->traffic_monitor.in_curr_req) / sizeof(session->traffic_monitor.in_curr_req[0]));
+
+    // get list of SAs
+    if ((session->traffic_monitor.num_in_curr_req = ike_session_get_sas_for_stats(session,
+                                                                                  IPSEC_DIR_INBOUND,
+                                                                                  &seq,
+                                                                                  session->traffic_monitor.in_curr_req,
+                                                                                  max_stats))) {
+        u_int64_t session_ids[] = {(u_int64_t)session, 0};
+
+        //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
+
+        if (pfkey_send_getsastats(lcconf->sock_pfkey,
+                                  seq,
+                                  session_ids,
+                                  1,
+                                  IPSEC_DIR_INBOUND,
+                                  session->traffic_monitor.in_curr_req,
+                                  session->traffic_monitor.num_in_curr_req) < 0) {
+            return -1;
+        }
+        //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
+
+        return session->traffic_monitor.num_in_curr_req;
+    }
+    return 0;
+}
+
+int
+pk_sendget_outbound_sastats(ike_session_t *session)
+{
+    u_int32_t max_stats;
+    u_int32_t seq;
+    
+    if (!session) {
+        plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
+        return -1;
+    }
+    
+    session->traffic_monitor.num_out_curr_req = 0;
+    bzero(session->traffic_monitor.out_curr_req, sizeof(session->traffic_monitor.out_curr_req));
+    max_stats = (sizeof(session->traffic_monitor.out_curr_req) / sizeof(session->traffic_monitor.out_curr_req[0]));
+
+    // get list of SAs
+    if ((session->traffic_monitor.num_out_curr_req = ike_session_get_sas_for_stats(session,
+                                                                                   IPSEC_DIR_OUTBOUND,
+                                                                                   &seq,
+                                                                                   session->traffic_monitor.out_curr_req,
+                                                                                   max_stats))) {
+        u_int64_t session_ids[] = {(u_int64_t)session, 0};
+        
+        //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
+        
+        if (pfkey_send_getsastats(lcconf->sock_pfkey,
+                                  seq,
+                                  session_ids,
+                                  1,
+                                  IPSEC_DIR_OUTBOUND,
+                                  session->traffic_monitor.out_curr_req,
+                                  session->traffic_monitor.num_out_curr_req) < 0) {
+            return -1;
+        }
+        //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
+        
+        return session->traffic_monitor.num_out_curr_req;
+    }
+    return 0;
+}
+
+/*
+ * receive GETSPDSTAT from kernel.
+ */
+static int
+pk_recvgetsastat(mhp) 
+caddr_t *mhp;
+{
+       struct sadb_msg        *msg;
+    struct sadb_session_id *session_id;
+    struct sadb_sastat     *stat_resp;
+       ike_session_t          *session;
+
+       /* validity check */
+       if (mhp[0] == NULL ||
+        mhp[SADB_EXT_SESSION_ID] == NULL ||
+        mhp[SADB_EXT_SASTAT] == NULL) {
+               plog(ASL_LEVEL_ERR, 
+             "inappropriate sadb getsastat response.\n");
+               return -1;
+       }
+       msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                         // Wcast-align fix (void*) - mhp contains pointers to structs in an aligned buffer
+    session_id = ALIGNED_CAST(struct sadb_session_id *)mhp[SADB_EXT_SESSION_ID];
+       stat_resp = ALIGNED_CAST(struct sadb_sastat *)mhp[SADB_EXT_SASTAT];
+
+       /* the message has to be processed or not ? */
+       if (msg->sadb_msg_pid != getpid()) {
+               plog(ASL_LEVEL_DEBUG, 
+             "%s message is not interesting "
+             "because pid %d is not mine.\n",
+             s_pfkey_type(msg->sadb_msg_type),
+             msg->sadb_msg_pid);
+               return -1;
+       }
+    if (!session_id->sadb_session_id_v[0]) {
+               plog(ASL_LEVEL_DEBUG, 
+             "%s message is bad "
+             "because session-id[0] is invalid.\n",
+             s_pfkey_type(msg->sadb_msg_type));
+        return -1;
+    }
+    session = ALIGNED_CAST(__typeof__(session))session_id->sadb_session_id_v[0];
+
+    if (!stat_resp->sadb_sastat_list_len) {
+               plog(ASL_LEVEL_DEBUG, 
+             "%s message is bad "
+             "because it has no sastats.\n",
+             s_pfkey_type(msg->sadb_msg_type));
+        return -1;
+    }
+
+    ike_session_update_traffic_idle_status(session,
+                                           stat_resp->sadb_sastat_dir,
+                                           (struct sastat *)(stat_resp + 1),
+                                           stat_resp->sadb_sastat_list_len);
+       return 0;
+}
+
 /*
  * check if the algorithm is supported or not.
  * OUT  0: ok
@@ -2708,12 +2849,9 @@ pk_checkalg(class, calg, keylen)
                sup = SADB_EXT_SUPPORTED_AUTH;
                break;
        case IPSECDOI_PROTO_IPCOMP:
-               plog(LLV_DEBUG, LOCATION, NULL,
-                       "compression algorithm can not be checked "
-                       "because sadb message doesn't support it.\n");
                return 0;
        default:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "invalid algorithm class.\n");
                return -1;
        }
@@ -2723,7 +2861,7 @@ pk_checkalg(class, calg, keylen)
 
        if (keylen == 0) {
                if (ipsec_get_keylen(sup, alg, &alg0)) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "%s.\n", ipsec_strerror());
                        return -1;
                }
@@ -2732,7 +2870,7 @@ pk_checkalg(class, calg, keylen)
 
        error = ipsec_check_keylen(sup, alg, keylen);
        if (error)
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "%s.\n", ipsec_strerror());
 
        return error;
@@ -2747,8 +2885,8 @@ pk_checkalg(class, calg, keylen)
  */
 static struct sadb_msg *
 pk_recv(so, lenp)
-int so;
-int *lenp;
+       int so;
+       ssize_t *lenp;
 {
        struct sadb_msg *newmsg;
        int reallen = 0; 
@@ -2759,11 +2897,16 @@ int *lenp;
        
        if (reallen == 0)
                return NULL;
-       
+
        if ((newmsg = racoon_calloc(1, reallen)) == NULL)
                return NULL;
-       
-       *lenp = recv(so, (caddr_t)newmsg, reallen, 0);
+
+       while ((*lenp = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
+               if (errno == EINTR)
+                       continue;
+               plog(ASL_LEVEL_ERR, "failed to recv pfkey message: %s\n", strerror(errno));
+               break;
+       }
        if (*lenp < 0) {
                racoon_free(newmsg);
                return NULL;    /*fatal*/
@@ -2771,11 +2914,10 @@ int *lenp;
                racoon_free(newmsg);
                return NULL;
        }
-       
+
        return newmsg;
 }
 
-
 /* see handler.h */
 u_int32_t
 pk_getseq()
@@ -2795,26 +2937,18 @@ addnewsp(mhp)
        if (mhp[SADB_EXT_ADDRESS_SRC] == NULL
         || mhp[SADB_EXT_ADDRESS_DST] == NULL
         || mhp[SADB_X_EXT_POLICY] == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "inappropriate sadb spd management message passed.\n");
                return -1;
        }
 
-       saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
-       daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
-       xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
-
-#ifdef __linux__
-       /* bsd skips over per-socket policies because there will be no
-        * src and dst extensions in spddump messages. On Linux the only
-        * way to achieve the same is check for policy id.
-        */
-       if (xpl->sadb_x_policy_id % 8 >= 3) return 0;
-#endif
+       saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
+       daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+       xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
 
        new = newsp();
        if (new == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "failed to allocate buffer\n");
                return -1;
        }
@@ -2841,7 +2975,7 @@ addnewsp(mhp)
 
                /* validity check */
                if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                                "invalid msg length.\n");
                        return -1;
                }
@@ -2853,7 +2987,7 @@ addnewsp(mhp)
 
                        /* length check */
                        if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
-                               plog(LLV_ERROR, LOCATION, NULL,
+                               plog(ASL_LEVEL_ERR, 
                                        "invalid msg length.\n");
                                return -1;
                        }
@@ -2861,7 +2995,7 @@ addnewsp(mhp)
                        /* allocate request buffer */
                        *p_isr = newipsecreq();
                        if (*p_isr == NULL) {
-                               plog(LLV_ERROR, LOCATION, NULL,
+                               plog(ASL_LEVEL_ERR, 
                                        "failed to get new ipsecreq.\n");
                                return -1;
                        }
@@ -2875,7 +3009,7 @@ addnewsp(mhp)
                        case IPPROTO_IPCOMP:
                                break;
                        default:
-                               plog(LLV_ERROR, LOCATION, NULL,
+                               plog(ASL_LEVEL_ERR, 
                                        "invalid proto type: %u\n",
                                        xisr->sadb_x_ipsecrequest_proto);
                                return -1;
@@ -2888,7 +3022,7 @@ addnewsp(mhp)
                                break;
                        case IPSEC_MODE_ANY:
                        default:
-                               plog(LLV_ERROR, LOCATION, NULL,
+                               plog(ASL_LEVEL_ERR, 
                                        "invalid mode: %u\n",
                                        xisr->sadb_x_ipsecrequest_mode);
                                return -1;
@@ -2906,7 +3040,7 @@ addnewsp(mhp)
                                break;
 
                        default:
-                               plog(LLV_ERROR, LOCATION, NULL,
+                               plog(ASL_LEVEL_ERR, 
                                        "invalid level: %u\n",
                                        xisr->sadb_x_ipsecrequest_level);
                                return -1;
@@ -2935,17 +3069,17 @@ addnewsp(mhp)
 
                        /* validity check */
                        if (tlen < 0) {
-                               plog(LLV_ERROR, LOCATION, NULL,
+                               plog(ASL_LEVEL_ERR, 
                                        "becoming tlen < 0\n");
                        }
 
-                       xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
+                       xisr = ALIGNED_CAST(struct sadb_x_ipsecrequest *)((caddr_t)xisr
                                         + xisr->sadb_x_ipsecrequest_len);
                }
            }
                break;
        default:
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                        "invalid policy type.\n");
                return -1;
        }
@@ -2977,7 +3111,7 @@ addnewsp(mhp)
 /* proto/mode/src->dst spi */
 const char *
 sadbsecas2str(src, dst, proto, spi, mode)
-       struct sockaddr *src, *dst;
+       struct sockaddr_storage *src, *dst;
        int proto;
        u_int32_t spi;
        int mode;
@@ -3008,13 +3142,13 @@ sadbsecas2str(src, dst, proto, spi, mode)
        p += i;
        blen -= i;
 
-       i = snprintf(p, blen, "%s->", saddr2str(src));
+       i = snprintf(p, blen, "%s->", saddr2str((struct sockaddr *)src));
        if (i < 0 || i >= blen)
                return NULL;
        p += i;
        blen -= i;
 
-       i = snprintf(p, blen, "%s ", saddr2str(dst));
+       i = snprintf(p, blen, "%s ", saddr2str((struct sockaddr *)dst));
        if (i < 0 || i >= blen)
                return NULL;
        p += i;