aboutsummaryrefslogtreecommitdiffstats
path: root/main/ipsec-tools
diff options
context:
space:
mode:
Diffstat (limited to 'main/ipsec-tools')
-rw-r--r--main/ipsec-tools/00-verify-cert-leak.patch11
-rw-r--r--main/ipsec-tools/20-natoa-fix.patch33
-rw-r--r--main/ipsec-tools/30-natt-ports-cleanup.patch393
-rw-r--r--main/ipsec-tools/40-cmpsaddr-cleanup.patch1403
-rw-r--r--main/ipsec-tools/50-reverse-connect.patch207
-rw-r--r--main/ipsec-tools/60-debug-quick.patch211
-rw-r--r--main/ipsec-tools/APKBUILD59
-rw-r--r--main/ipsec-tools/racoon.confd19
-rw-r--r--main/ipsec-tools/racoon.initd58
9 files changed, 2394 insertions, 0 deletions
diff --git a/main/ipsec-tools/00-verify-cert-leak.patch b/main/ipsec-tools/00-verify-cert-leak.patch
new file mode 100644
index 0000000000..9e67813359
--- /dev/null
+++ b/main/ipsec-tools/00-verify-cert-leak.patch
@@ -0,0 +1,11 @@
+--- a/src/racoon/crypto_openssl.c 20 Apr 2009 13:22:41 -0000 1.18
++++ b/src/racoon/crypto_openssl.c 29 Apr 2009 10:48:51 -0000
+@@ -510,7 +510,7 @@
+ X509_STORE_CTX_set_flags (csc, X509_V_FLAG_CRL_CHECK_ALL);
+ #endif
+ error = X509_verify_cert(csc);
+- X509_STORE_CTX_cleanup(csc);
++ X509_STORE_CTX_free(csc);
+
+ /*
+ * if x509_verify_cert() is successful then the value of error is
diff --git a/main/ipsec-tools/20-natoa-fix.patch b/main/ipsec-tools/20-natoa-fix.patch
new file mode 100644
index 0000000000..91d7224e2a
--- /dev/null
+++ b/main/ipsec-tools/20-natoa-fix.patch
@@ -0,0 +1,33 @@
+Fix nat-oa parsing when rekeying.
+
+From: Timo Teras <timo.teras@iki.fi>
+
+
+---
+
+ src/racoon/handler.c | 11 +++++++++++
+ 1 files changed, 11 insertions(+), 0 deletions(-)
+
+
+diff --git a/src/racoon/handler.c b/src/racoon/handler.c
+index 6f91beb..960b5b3 100644
+--- a/src/racoon/handler.c
++++ b/src/racoon/handler.c
+@@ -736,6 +736,17 @@ initph2(iph2)
+ oakley_delivm(iph2->ivm);
+ iph2->ivm = NULL;
+ }
++
++#ifdef ENABLE_NATT
++ if (iph2->natoa_src) {
++ racoon_free(iph2->natoa_src);
++ iph2->natoa_src = NULL;
++ }
++ if (iph2->natoa_dst) {
++ racoon_free(iph2->natoa_dst);
++ iph2->natoa_dst = NULL;
++ }
++#endif
+ }
+
+ /*
diff --git a/main/ipsec-tools/30-natt-ports-cleanup.patch b/main/ipsec-tools/30-natt-ports-cleanup.patch
new file mode 100644
index 0000000000..19360347da
--- /dev/null
+++ b/main/ipsec-tools/30-natt-ports-cleanup.patch
@@ -0,0 +1,393 @@
+From Yvan Vanhullebus: Use SADB_X_EXT_NAT_T_* consistently for passing the
+
+From: Timo Teras <timo.teras@iki.fi>
+
+NAT-T port information.
+---
+
+ src/libipsec/libpfkey.h | 12 ++++++++
+ src/libipsec/pfkey.c | 49 +++++++++++++++++++++++++++++++++
+ src/racoon/isakmp.c | 11 +++++++
+ src/racoon/isakmp_inf.c | 37 +++++++++++++------------
+ src/racoon/pfkey.c | 69 +++++++++++++++++++++++++++++++++--------------
+ src/racoon/pfkey.h | 1 +
+ 6 files changed, 140 insertions(+), 39 deletions(-)
+
+
+diff --git a/src/libipsec/libpfkey.h b/src/libipsec/libpfkey.h
+index 8a503dd..c9b228b 100644
+--- a/src/libipsec/libpfkey.h
++++ b/src/libipsec/libpfkey.h
+@@ -117,6 +117,10 @@ u_int pfkey_set_softrate __P((u_int, u_int));
+ u_int pfkey_get_softrate __P((u_int));
+ int pfkey_send_getspi __P((int, u_int, u_int, struct sockaddr *,
+ struct sockaddr *, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
++int pfkey_send_getspi_nat __P((int, u_int, u_int,
++ struct sockaddr *, struct sockaddr *, u_int8_t, u_int16_t, u_int16_t,
++ u_int32_t, u_int32_t, u_int32_t, u_int32_t));
++
+ int pfkey_send_update2 __P((struct pfkey_send_sa_args *));
+ int pfkey_send_add2 __P((struct pfkey_send_sa_args *));
+ int pfkey_send_delete __P((int, u_int, u_int,
+@@ -155,6 +159,14 @@ int pfkey_send_migrate __P((int, struct sockaddr *, struct sockaddr *,
+ caddr_t, int, u_int32_t));
+ #endif
+
++/* XXX should be somewhere else !!!
++ */
++#ifdef SADB_X_NAT_T_NEW_MAPPING
++#define PFKEY_ADDR_X_PORT(ext) (ntohs(((struct sadb_x_nat_t_port *)ext)->sadb_x_nat_t_port_port))
++#define PFKEY_ADDR_X_NATTYPE(ext) ( ext != NULL && ((struct sadb_x_nat_t_type *)ext)->sadb_x_nat_t_type_type )
++#endif
++
++
+ int pfkey_open __P((void));
+ void pfkey_close __P((int));
+ int pfkey_set_buffer_size __P((int, int));
+diff --git a/src/libipsec/pfkey.c b/src/libipsec/pfkey.c
+index 0a944c2..b39ffca 100644
+--- a/src/libipsec/pfkey.c
++++ b/src/libipsec/pfkey.c
+@@ -380,10 +380,12 @@ pfkey_get_softrate(type)
+ * -1 : error occured, and set errno.
+ */
+ int
+-pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
++pfkey_send_getspi_nat(so, satype, mode, src, dst, natt_type, sport, dport, min, max, reqid, seq)
+ int so;
+ u_int satype, mode;
+ struct sockaddr *src, *dst;
++ u_int8_t natt_type;
++ u_int16_t sport, dport;
+ u_int32_t min, max, reqid, seq;
+ {
+ struct sadb_msg *newmsg;
+@@ -431,6 +433,14 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
+ len += sizeof(struct sadb_spirange);
+ }
+
++#ifdef SADB_X_EXT_NAT_T_TYPE
++ if(natt_type||sport||dport){
++ len += sizeof(struct sadb_x_nat_t_type);
++ len += sizeof(struct sadb_x_nat_t_port);
++ len += sizeof(struct sadb_x_nat_t_port);
++ }
++#endif
++
+ if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+@@ -466,6 +476,32 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
+ return -1;
+ }
+
++#ifdef SADB_X_EXT_NAT_T_TYPE
++ /* Add nat-t messages */
++ if (natt_type) {
++ p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE,
++ natt_type);
++ if (!p) {
++ free(newmsg);
++ return -1;
++ }
++
++ p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
++ sport);
++ if (!p) {
++ free(newmsg);
++ return -1;
++ }
++
++ p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
++ dport);
++ if (!p) {
++ free(newmsg);
++ return -1;
++ }
++ }
++#endif
++
+ /* proccessing spi range */
+ if (need_spirange) {
+ struct sadb_spirange spirange;
+@@ -501,6 +537,17 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
+ return len;
+ }
+
++int
++pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
++ int so;
++ u_int satype, mode;
++ struct sockaddr *src, *dst;
++ u_int32_t min, max, reqid, seq;
++{
++ return pfkey_send_getspi_nat(so, satype, mode, src, dst, 0, 0, 0,
++ min, max, reqid, seq);
++}
++
+ /*
+ * sending SADB_UPDATE message to the kernel.
+ * The length of key material is a_keylen + e_keylen.
+diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c
+index c8670f6..fe51653 100644
+--- a/src/racoon/isakmp.c
++++ b/src/racoon/isakmp.c
+@@ -3324,6 +3324,17 @@ purge_remote(iph1)
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
++#ifdef SADB_X_NAT_T_NEW_MAPPING
++ if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
++ /* NAT-T is enabled for this SADB entry; copy
++ * the ports from NAT-T extensions */
++ if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL)
++ set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
++ if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL)
++ set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
++ }
++#endif
++
+ if (sa->sadb_sa_state != SADB_SASTATE_LARVAL &&
+ sa->sadb_sa_state != SADB_SASTATE_MATURE &&
+ sa->sadb_sa_state != SADB_SASTATE_DYING) {
+diff --git a/src/racoon/isakmp_inf.c b/src/racoon/isakmp_inf.c
+index 1ada07f..a712825 100644
+--- a/src/racoon/isakmp_inf.c
++++ b/src/racoon/isakmp_inf.c
+@@ -1128,8 +1128,7 @@ purge_ipsec_spi(dst0, proto, spi, n)
+ size_t i;
+ caddr_t mhp[SADB_EXT_MAX + 1];
+ #ifdef ENABLE_NATT
+- struct sadb_x_nat_t_type *natt_type;
+- struct sadb_x_nat_t_port *natt_port;
++ int natt_port_forced;
+ #endif
+
+ plog(LLV_DEBUG2, LOCATION, NULL,
+@@ -1184,22 +1183,25 @@ purge_ipsec_spi(dst0, proto, spi, n)
+ continue;
+ }
+ #ifdef ENABLE_NATT
+- natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE];
+- if (natt_type && natt_type->sadb_x_nat_t_type_type) {
++ if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
+ /* NAT-T is enabled for this SADB entry; copy
+ * the ports from NAT-T extensions */
+- natt_port = (void *)mhp[SADB_X_EXT_NAT_T_SPORT];
+- if (extract_port(src) == 0 && natt_port != NULL)
+- set_port(src, ntohs(natt_port->sadb_x_nat_t_port_port));
+-
+- natt_port = (void *)mhp[SADB_X_EXT_NAT_T_DPORT];
+- if (extract_port(dst) == 0 && natt_port != NULL)
+- set_port(dst, ntohs(natt_port->sadb_x_nat_t_port_port));
+- }else{
+- /* Force default UDP ports, so CMPSADDR will match SAs with NO encapsulation
+- */
++ if (extract_port(src) == 0 &&
++ mhp[SADB_X_EXT_NAT_T_SPORT] != NULL) {
++ set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
++ }
++
++ if (extract_port(dst) == 0 &&
++ mhp[SADB_X_EXT_NAT_T_DPORT] != NULL) {
++ set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
++ }
++ natt_port_forced = 0;
++ } else {
++ /* Force default UDP ports, so
++ * CMPSADDR will match SAs with NO encapsulation */
+ set_port(src, PORT_ISAKMP);
+ set_port(dst, PORT_ISAKMP);
++ natt_port_forced = 1;
+ }
+ #endif
+ plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src));
+@@ -1215,10 +1217,9 @@ purge_ipsec_spi(dst0, proto, spi, n)
+ }
+
+ #ifdef ENABLE_NATT
+- if (natt_type == NULL ||
+- ! natt_type->sadb_x_nat_t_type_type) {
+- /* Set back port to 0 if it was forced to default UDP port
+- */
++ if (natt_port_forced) {
++ /* Set back port to 0 if it was forced
++ * to default UDP port */
+ set_port(src, 0);
+ set_port(dst, 0);
+ }
+diff --git a/src/racoon/pfkey.c b/src/racoon/pfkey.c
+index 610cc09..c210c5e 100644
+--- a/src/racoon/pfkey.c
++++ b/src/racoon/pfkey.c
+@@ -769,6 +769,28 @@ keylen_ealg(enctype, encklen)
+ return res;
+ }
+
++void
++pk_fixup_sa_addresses(mhp)
++ caddr_t *mhp;
++{
++ struct sockaddr *src, *dst;
++ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
++ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
++#ifdef ENABLE_NATT
++ if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
++ /* NAT-T is enabled for this SADB entry; copy
++ * the ports from NAT-T extensions */
++ if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL)
++ set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
++ if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL)
++ set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
++ }
++#else
++ set_port(src, 0);
++ set_port(dst, 0);
++#endif
++}
++
+ int
+ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
+ e_type, e_keylen, a_type, a_keylen, flags)
+@@ -866,6 +888,8 @@ pk_sendgetspi(iph2)
+ struct saprop *pp;
+ struct saproto *pr;
+ u_int32_t minspi, maxspi;
++ u_int8_t natt_type = 0;
++ u_int16_t sport = 0, dport = 0;
+
+ if (iph2->side == INITIATOR)
+ pp = iph2->proposal;
+@@ -919,19 +943,27 @@ pk_sendgetspi(iph2)
+ }
+
+ #ifdef ENABLE_NATT
+- if (! pr->udp_encap) {
+- /* Remove port information, that SA doesn't use it */
+- set_port(iph2->src, 0);
+- set_port(iph2->dst, 0);
++ if (pr->udp_encap) {
++ natt_type = iph2->ph1->natt_options->encaps_type;
++ sport=extract_port(src);
++ dport=extract_port(dst);
+ }
+ #endif
++ /* Always remove port information, it will be sent in
++ * SADB_X_EXT_NAT_T_[S|D]PORT if needed */
++ set_port(src, 0);
++ set_port(dst, 0);
++
+ plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
+- if (pfkey_send_getspi(
++ if (pfkey_send_getspi_nat(
+ lcconf->sock_pfkey,
+ satype,
+ mode,
+ dst, /* src of SA */
+ src, /* dst of SA */
++ natt_type,
++ dport,
++ sport,
+ minspi, maxspi,
+ pr->reqid_in, iph2->seq) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+@@ -1157,13 +1189,13 @@ pk_sendupdate(iph2)
+ #ifdef SADB_X_EXT_NAT_T_FRAG
+ sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
+ #endif
+- } else {
+- /* Remove port information, that SA doesn't use it */
+- set_port(sa_args.src, 0);
+- set_port(sa_args.dst, 0);
+ }
+-
+ #endif
++ /* Always remove port information, it will be sent in
++ * SADB_X_EXT_NAT_T_[S|D]PORT if needed */
++ set_port(sa_args.src, 0);
++ set_port(sa_args.dst, 0);
++
+ /* more info to fill in */
+ sa_args.spi = pr->spi;
+ sa_args.reqid = pr->reqid_in;
+@@ -1236,6 +1268,7 @@ pk_recvupdate(mhp)
+ return -1;
+ }
+ msg = (struct sadb_msg *)mhp[0];
++ pk_fixup_sa_addresses(mhp);
+ 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];
+@@ -1328,7 +1361,6 @@ pk_recvupdate(mhp)
+ /* Force the update of ph2's ports, as there is at least one
+ * situation where they'll mismatch with ph1's values
+ */
+-
+ #ifdef ENABLE_NATT
+ set_port(iph2->src, extract_port(iph2->ph1->local));
+ set_port(iph2->dst, extract_port(iph2->ph1->remote));
+@@ -1456,17 +1488,12 @@ pk_sendadd(iph2)
+ #ifdef SADB_X_EXT_NAT_T_FRAG
+ sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
+ #endif
+- } else {
+- /* Remove port information, that SA doesn't use it */
+- set_port(sa_args.src, 0);
+- set_port(sa_args.dst, 0);
+ }
+-
+-#else
+- /* Remove port information, it is not used without NAT-T */
++#endif
++ /* Always remove port information, it will be sent in
++ * SADB_X_EXT_NAT_T_[S|D]PORT if needed */
+ set_port(sa_args.src, 0);
+ set_port(sa_args.dst, 0);
+-#endif
+
+ /* more info to fill in */
+ sa_args.spi = pr->spi_p;
+@@ -1596,6 +1623,7 @@ pk_recvexpire(mhp)
+ }
+ msg = (struct sadb_msg *)mhp[0];
+ sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
++ pk_fixup_sa_addresses(mhp);
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+@@ -1721,6 +1749,7 @@ pk_recvacquire(mhp)
+ }
+ msg = (struct sadb_msg *)mhp[0];
+ xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
++ pk_fixup_sa_addresses(mhp);
+ sp_src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ sp_dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+@@ -1971,6 +2000,7 @@ pk_recvdelete(mhp)
+ }
+ msg = (struct sadb_msg *)mhp[0];
+ sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
++ pk_fixup_sa_addresses(mhp);
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+@@ -2709,7 +2739,6 @@ pk_recvspddump(mhp)
+ return -1;
+ }
+ msg = (struct sadb_msg *)mhp[0];
+-
+ 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];
+diff --git a/src/racoon/pfkey.h b/src/racoon/pfkey.h
+index a3acd1c..f1b037d 100644
+--- a/src/racoon/pfkey.h
++++ b/src/racoon/pfkey.h
+@@ -52,6 +52,7 @@ extern struct pfkey_st *pfkey_getpst __P((caddr_t *, int, int));
+ extern int pk_checkalg __P((int, int, int));
+
+ struct ph2handle;
++extern void pk_fixup_sa_addresses __P((caddr_t *mhp));
+ extern int pk_sendgetspi __P((struct ph2handle *));
+ extern int pk_sendupdate __P((struct ph2handle *));
+ extern int pk_sendadd __P((struct ph2handle *));
diff --git a/main/ipsec-tools/40-cmpsaddr-cleanup.patch b/main/ipsec-tools/40-cmpsaddr-cleanup.patch
new file mode 100644
index 0000000000..c5e3e4b330
--- /dev/null
+++ b/main/ipsec-tools/40-cmpsaddr-cleanup.patch
@@ -0,0 +1,1403 @@
+Get rid of CMPSADDR hack in port comparisons. Trac #295.
+
+From: Timo Teras <timo.teras@iki.fi>
+
+
+---
+
+ src/racoon/admin.c | 37 ++++---
+ src/racoon/grabmyaddr.c | 22 ++--
+ src/racoon/handler.c | 41 +++-----
+ src/racoon/handler.h | 7 -
+ src/racoon/isakmp.c | 90 ++++-------------
+ src/racoon/isakmp_cfg.c | 9 --
+ src/racoon/isakmp_inf.c | 111 ++++-----------------
+ src/racoon/isakmp_quick.c | 29 +++---
+ src/racoon/nattraversal.c | 8 +-
+ src/racoon/pfkey.c | 52 +++-------
+ src/racoon/policy.c | 22 ++--
+ src/racoon/remoteconf.c | 30 +-----
+ src/racoon/remoteconf.h | 3 -
+ src/racoon/sockmisc.c | 234 +++------------------------------------------
+ src/racoon/sockmisc.h | 15 +--
+ src/racoon/throttle.c | 2
+ 16 files changed, 170 insertions(+), 542 deletions(-)
+
+
+diff --git a/src/racoon/admin.c b/src/racoon/admin.c
+index 576e191..b67e545 100644
+--- a/src/racoon/admin.c
++++ b/src/racoon/admin.c
+@@ -167,6 +167,14 @@ end:
+ return error;
+ }
+
++static int admin_ph1_delete_sa(struct ph1handle *iph1, void *arg)
++{
++ if (iph1->status >= PHASE1ST_ESTABLISHED)
++ isakmp_info_send_d1(iph1);
++ purge_remote(iph1);
++ return 0;
++}
++
+ /*
+ * main child's process.
+ */
+@@ -257,7 +265,7 @@ admin_process(so2, combuf)
+ break;
+ }
+
+- iph1 = getph1byaddrwop(src, dst);
++ iph1 = getph1byaddr(src, dst, 0);
+ if (iph1 == NULL) {
+ l_ac_errno = ENOENT;
+ break;
+@@ -292,30 +300,25 @@ admin_process(so2, combuf)
+
+ case ADMIN_DELETE_SA: {
+ struct ph1handle *iph1;
+- struct sockaddr *dst;
+- struct sockaddr *src;
++ struct ph1selector sel;
+ char *loc, *rem;
+
+- src = (struct sockaddr *)
++ memset(&sel, 0, sizeof(sel));
++ sel.local = (struct sockaddr *)
+ &((struct admin_com_indexes *)
+ ((caddr_t)com + sizeof(*com)))->src;
+- dst = (struct sockaddr *)
++ sel.remote = (struct sockaddr *)
+ &((struct admin_com_indexes *)
+ ((caddr_t)com + sizeof(*com)))->dst;
+
+- loc = racoon_strdup(saddrwop2str(src));
+- rem = racoon_strdup(saddrwop2str(dst));
++ loc = racoon_strdup(saddr2str(sel.local));
++ rem = racoon_strdup(saddr2str(sel.remote));
+ STRDUP_FATAL(loc);
+ STRDUP_FATAL(rem);
+
+- if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
+- plog(LLV_ERROR, LOCATION, NULL,
+- "phase 1 for %s -> %s not found\n", loc, rem);
+- } else {
+- if (iph1->status >= PHASE1ST_ESTABLISHED)
+- isakmp_info_send_d1(iph1);
+- purge_remote(iph1);
+- }
++ plog(LLV_INFO, LOCATION, NULL,
++ "admin delete-sa %s %s\n", loc, rem);
++ enumph1(&sel, admin_ph1_delete_sa, NULL);
+
+ racoon_free(loc);
+ racoon_free(rem);
+@@ -360,7 +363,7 @@ admin_process(so2, combuf)
+ plog(LLV_INFO, LOCATION, NULL,
+ "Flushing all SAs for peer %s\n", rem);
+
+- while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
++ while ((iph1 = getph1bydstaddr(dst)) != NULL) {
+ loc = racoon_strdup(saddrwop2str(iph1->local));
+ STRDUP_FATAL(loc);
+
+@@ -429,7 +432,7 @@ admin_process(so2, combuf)
+ l_ac_errno = -1;
+
+ /* connected already? */
+- ph1 = getph1byaddrwop(src, dst);
++ ph1 = getph1byaddr(src, dst, 0);
+ if (ph1 != NULL) {
+ event_list = &ph1->evt_listeners;
+ if (ph1->status == PHASE1ST_ESTABLISHED)
+diff --git a/src/racoon/grabmyaddr.c b/src/racoon/grabmyaddr.c
+index f866dd5..cb1b638 100644
+--- a/src/racoon/grabmyaddr.c
++++ b/src/racoon/grabmyaddr.c
+@@ -100,7 +100,7 @@ myaddr_configured(addr)
+ return TRUE;
+
+ LIST_FOREACH(cfg, &configured, chain) {
+- if (cmpsaddrstrict(addr, (struct sockaddr *) &cfg->addr) == 0)
++ if (cmpsaddr(addr, (struct sockaddr *) &cfg->addr) == 0)
+ return TRUE;
+ }
+
+@@ -116,7 +116,7 @@ myaddr_open(addr, udp_encap)
+
+ /* Already open? */
+ LIST_FOREACH(my, &opened, chain) {
+- if (cmpsaddrstrict(addr, (struct sockaddr *) &my->addr) == 0)
++ if (cmpsaddr(addr, (struct sockaddr *) &my->addr) == 0)
+ return TRUE;
+ }
+
+@@ -156,7 +156,7 @@ myaddr_open_all_configured(addr)
+
+ LIST_FOREACH(cfg, &configured, chain) {
+ if (addr != NULL &&
+- cmpsaddrwop(addr, (struct sockaddr *) &cfg->addr) != 0)
++ cmpsaddr(addr, (struct sockaddr *) &cfg->addr) != 0)
+ continue;
+ if (!myaddr_open((struct sockaddr *) &cfg->addr, cfg->udp_encap))
+ return FALSE;
+@@ -187,8 +187,8 @@ myaddr_close_all_open(addr)
+ for (my = LIST_FIRST(&opened); my; my = next) {
+ next = LIST_NEXT(my, chain);
+
+- if (!cmpsaddrwop((struct sockaddr *) &addr,
+- (struct sockaddr *) &my->addr))
++ if (!cmpsaddr((struct sockaddr *) &addr,
++ (struct sockaddr *) &my->addr))
+ myaddr_delete(my);
+ }
+ }
+@@ -261,7 +261,7 @@ myaddr_getfd(addr)
+ struct myaddr *my;
+
+ LIST_FOREACH(my, &opened, chain) {
+- if (cmpsaddrstrict((struct sockaddr *) &my->addr, addr) == 0)
++ if (cmpsaddr((struct sockaddr *) &my->addr, addr) == 0)
+ return my->fd;
+ }
+
+@@ -273,19 +273,13 @@ myaddr_getsport(addr)
+ struct sockaddr *addr;
+ {
+ struct myaddr *my;
+- int bestmatch_port = -1;
+
+ LIST_FOREACH(my, &opened, chain) {
+- if (cmpsaddrstrict((struct sockaddr *) &my->addr, addr) == 0)
++ if (cmpsaddr((struct sockaddr *) &my->addr, addr) == 0)
+ return extract_port((struct sockaddr *) &my->addr);
+- if (cmpsaddrwop((struct sockaddr *) &my->addr, addr) != 0)
+- continue;
+- if (bestmatch_port == -1 ||
+- extract_port((struct sockaddr *) &my->addr) == PORT_ISAKMP)
+- bestmatch_port = extract_port((struct sockaddr *) &my->addr);
+ }
+
+- return bestmatch_port;
++ return PORT_ISAKMP;
+ }
+
+ void
+diff --git a/src/racoon/handler.c b/src/racoon/handler.c
+index 960b5b3..b33986f 100644
+--- a/src/racoon/handler.c
++++ b/src/racoon/handler.c
+@@ -120,11 +120,11 @@ enumph1(sel, enum_func, enum_arg)
+ LIST_FOREACH(p, &ph1tree, chain) {
+ if (sel != NULL) {
+ if (sel->local != NULL &&
+- CMPSADDR(sel->local, p->local) != 0)
++ cmpsaddr(sel->local, p->local) != 0)
+ continue;
+
+ if (sel->remote != NULL &&
+- CMPSADDR(sel->remote, p->remote) != 0)
++ cmpsaddr(sel->remote, p->remote) != 0)
+ continue;
+ }
+
+@@ -201,17 +201,12 @@ getph1(rmconf, local, remote, flags)
+ "status %d, skipping\n", p->status);
+ continue;
+ }
+- if (flags & GETPH1_F_WITHOUT_PORTS) {
+- if (local != NULL && cmpsaddrwop(local, p->local) != 0)
+- continue;
+- if (remote != NULL && cmpsaddrwop(remote, p->remote) != 0)
+- continue;
+- } else {
+- if (local != NULL && CMPSADDR(local, p->local) != 0)
+- continue;
+- if (remote != NULL && CMPSADDR(remote, p->remote) != 0)
+- continue;
+- }
++
++ if (local != NULL && cmpsaddr(local, p->local) != 0)
++ continue;
++
++ if (remote != NULL && cmpsaddr(remote, p->remote) != 0)
++ continue;
+
+ plog(LLV_DEBUG2, LOCATION, NULL, "matched\n");
+ return p;
+@@ -287,8 +282,8 @@ void migrate_dying_ph12(iph1)
+ if (p->status < PHASE1ST_DYING)
+ continue;
+
+- if (CMPSADDR(iph1->local, p->local) == 0
+- && CMPSADDR(iph1->remote, p->remote) == 0)
++ if (cmpsaddr(iph1->local, p->local) == 0
++ && cmpsaddr(iph1->remote, p->remote) == 0)
+ migrate_ph12(p, iph1);
+ }
+ }
+@@ -518,11 +513,11 @@ enumph2(sel, enum_func, enum_arg)
+ continue;
+
+ if (sel->src != NULL &&
+- CMPSADDR(sel->src, p->src) != 0)
++ cmpsaddr(sel->src, p->src) != 0)
+ continue;
+
+ if (sel->dst != NULL &&
+- CMPSADDR(sel->dst, p->dst) != 0)
++ cmpsaddr(sel->dst, p->dst) != 0)
+ continue;
+ }
+
+@@ -586,8 +581,8 @@ getph2byid(src, dst, spid)
+
+ LIST_FOREACH(p, &ph2tree, chain) {
+ if (spid == p->spid &&
+- cmpsaddrwild(src, p->src) == 0 &&
+- cmpsaddrwild(dst, p->dst) == 0){
++ cmpsaddr(src, p->src) == 0 &&
++ cmpsaddr(dst, p->dst) == 0){
+ /* Sanity check to detect zombie handlers
+ * XXX Sould be done "somewhere" more interesting,
+ * because we have lots of getph2byxxxx(), but this one
+@@ -614,8 +609,8 @@ getph2bysaddr(src, dst)
+ struct ph2handle *p;
+
+ LIST_FOREACH(p, &ph2tree, chain) {
+- if (cmpsaddrstrict(src, p->src) == 0 &&
+- cmpsaddrstrict(dst, p->dst) == 0)
++ if (cmpsaddr(src, p->src) == 0 &&
++ cmpsaddr(dst, p->dst) == 0)
+ return p;
+ }
+
+@@ -918,7 +913,7 @@ getcontacted(remote)
+ struct contacted *p;
+
+ LIST_FOREACH(p, &ctdtree, chain) {
+- if (cmpsaddrstrict(remote, p->remote) == 0)
++ if (cmpsaddr(remote, p->remote) == 0)
+ return p;
+ }
+
+@@ -997,7 +992,7 @@ check_recvdpkt(remote, local, rbuf)
+ /*
+ * the packet was processed before, but the remote address mismatches.
+ */
+- if (cmpsaddrstrict(remote, r->remote) != 0)
++ if (cmpsaddr(remote, r->remote) != 0)
+ return 2;
+
+ /*
+diff --git a/src/racoon/handler.h b/src/racoon/handler.h
+index c31753d..8f19c88 100644
+--- a/src/racoon/handler.h
++++ b/src/racoon/handler.h
+@@ -467,7 +467,6 @@ extern int enumph1 __P((struct ph1selector *ph1sel,
+ void *enum_arg));
+
+ #define GETPH1_F_ESTABLISHED 0x0001
+-#define GETPH1_F_WITHOUT_PORTS 0x0002
+
+ extern struct ph1handle *getph1 __P((struct remoteconf *rmconf,
+ struct sockaddr *local,
+@@ -476,10 +475,8 @@ extern struct ph1handle *getph1 __P((struct remoteconf *rmconf,
+
+ #define getph1byaddr(local, remote, est) \
+ getph1(NULL, local, remote, est ? GETPH1_F_ESTABLISHED : 0)
+-#define getph1byaddrwop(local, remote) \
+- getph1(NULL, local, remote, GETPH1_F_WITHOUT_PORTS)
+-#define getph1bydstaddrwop(remote) \
+- getph1(NULL, NULL, remote, GETPH1_F_WITHOUT_PORTS)
++#define getph1bydstaddr(remote) \
++ getph1(NULL, NULL, remote, 0)
+
+ #ifdef ENABLE_HYBRID
+ struct ph1handle *getph1bylogin __P((char *));
+diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c
+index fe51653..0de16d1 100644
+--- a/src/racoon/isakmp.c
++++ b/src/racoon/isakmp.c
+@@ -475,8 +475,8 @@ isakmp_main(msg, remote, local)
+ /* Floating ports for NAT-T */
+ if (NATT_AVAILABLE(iph1) &&
+ ! (iph1->natt_flags & NAT_PORTS_CHANGED) &&
+- ((cmpsaddrstrict(iph1->remote, remote) != 0) ||
+- (cmpsaddrstrict(iph1->local, local) != 0)))
++ ((cmpsaddr(iph1->remote, remote) != 0) ||
++ (cmpsaddr(iph1->local, local) != 0)))
+ {
+ /* prevent memory leak */
+ racoon_free(iph1->remote);
+@@ -517,7 +517,7 @@ isakmp_main(msg, remote, local)
+ #endif
+
+ /* must be same addresses in one stream of a phase at least. */
+- if (cmpsaddrstrict(iph1->remote, remote) != 0) {
++ if (cmpsaddr(iph1->remote, remote) != 0) {
+ char *saddr_db, *saddr_act;
+
+ saddr_db = racoon_strdup(saddr2str(iph1->remote));
+@@ -643,7 +643,7 @@ isakmp_main(msg, remote, local)
+ "exchange received.\n");
+ return -1;
+ }
+- if (cmpsaddrstrict(iph1->remote, remote) != 0) {
++ if (cmpsaddr(iph1->remote, remote) != 0) {
+ plog(LLV_WARNING, LOCATION, remote,
+ "remote address mismatched. "
+ "db=%s\n",
+@@ -1275,6 +1275,12 @@ isakmp_ph2begin_i(iph1, iph2)
+ }
+ #endif
+
++ /* fixup ph2 ports for this ph1 */
++ if (extract_port(iph2->src) == 0)
++ set_port(iph2->src, extract_port(iph1->local));
++ if (extract_port(iph2->dst) == 0)
++ set_port(iph2->dst, extract_port(iph1->remote));
++
+ /* found ISAKMP-SA. */
+ plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+ plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
+@@ -1353,15 +1359,6 @@ isakmp_ph2begin_r(iph1, msg)
+ delph2(iph2);
+ return -1;
+ }
+-#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
+- if (set_port(iph2->dst, 0) == NULL ||
+- set_port(iph2->src, 0) == NULL) {
+- plog(LLV_ERROR, LOCATION, NULL,
+- "invalid family: %d\n", iph2->dst->sa_family);
+- delph2(iph2);
+- return -1;
+- }
+-#endif
+
+ /* add new entry to isakmp status table */
+ insph2(iph2);
+@@ -2186,23 +2183,12 @@ isakmp_post_acquire(iph2)
+ return 0;
+ }
+
+- /*
+- * Search isakmp status table by address and port
+- * If NAT-T is in use, consider null ports as a
+- * wildcard and use IKE ports instead.
++ /*
++ * XXX Searching by IP addresses + ports might fail on
++ * some cases, we should use the ISAKMP identity to search
++ * matching ISAKMP.
+ */
+-#ifdef ENABLE_NATT
+- if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
+- if ((iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL) {
+- set_port(iph2->src, extract_port(iph1->local));
+- set_port(iph2->dst, extract_port(iph1->remote));
+- }
+- } else {
+- iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+- }
+-#else
+ iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+-#endif
+
+ /* no ISAKMP-SA found. */
+ if (iph1 == NULL) {
+@@ -2380,26 +2366,8 @@ isakmp_chkph1there(iph2)
+ return;
+ }
+
+- /*
+- * Search isakmp status table by address and port
+- * If NAT-T is in use, consider null ports as a
+- * wildcard and use IKE ports instead.
+- */
+-#ifdef ENABLE_NATT
+- if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
+- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: extract_port.\n");
+- if( (iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL){
+- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: found a ph1 wop.\n");
+- }
+- } else {
+- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: searching byaddr.\n");
+- iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+- if(iph1 != NULL)
+- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: found byaddr.\n");
+- }
+-#else
++ /* Search isakmp status table by address and port */
+ iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+-#endif
+
+ /* XXX Even if ph1 as responder is there, should we not start
+ * phase 2 negotiation ? */
+@@ -3321,20 +3289,10 @@ purge_remote(iph1)
+ msg = next;
+ continue;
+ }
++ pk_fixup_sa_addresses(mhp);
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+-#ifdef SADB_X_NAT_T_NEW_MAPPING
+- if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
+- /* NAT-T is enabled for this SADB entry; copy
+- * the ports from NAT-T extensions */
+- if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL)
+- set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
+- if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL)
+- set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
+- }
+-#endif
+-
+ if (sa->sadb_sa_state != SADB_SASTATE_LARVAL &&
+ sa->sadb_sa_state != SADB_SASTATE_MATURE &&
+ sa->sadb_sa_state != SADB_SASTATE_DYING) {
+@@ -3346,22 +3304,14 @@ purge_remote(iph1)
+ * check in/outbound SAs.
+ * Select only SAs where src == local and dst == remote (outgoing)
+ * or src == remote and dst == local (incoming).
+- * XXX we sometime have src/dst ports set to 0 and want to match
+- * iph1->local/remote with ports set to 500. This is a bug, see trac:2
+ */
+-#ifdef ENABLE_NATT
+- if ((cmpsaddrmagic(iph1->local, src) || cmpsaddrmagic(iph1->remote, dst)) &&
+- (cmpsaddrmagic(iph1->local, dst) || cmpsaddrmagic(iph1->remote, src))) {
+- msg = next;
+- continue;
+- }
+-#else
+- if ((CMPSADDR(iph1->local, src) || CMPSADDR(iph1->remote, dst)) &&
+- (CMPSADDR(iph1->local, dst) || CMPSADDR(iph1->remote, src))) {
++ if ((cmpsaddr(iph1->local, src) ||
++ cmpsaddr(iph1->remote, dst)) &&
++ (cmpsaddr(iph1->local, dst) ||
++ cmpsaddr(iph1->remote, src))) {
+ msg = next;
+ continue;
+ }
+-#endif
+
+ proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
+ iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
+diff --git a/src/racoon/isakmp_cfg.c b/src/racoon/isakmp_cfg.c
+index 62916f8..df763f8 100644
+--- a/src/racoon/isakmp_cfg.c
++++ b/src/racoon/isakmp_cfg.c
+@@ -1151,15 +1151,6 @@ isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
+ goto end;
+ }
+
+-#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
+- if (set_port(iph2->dst, 0) == NULL ||
+- set_port(iph2->src, 0) == NULL) {
+- plog(LLV_ERROR, LOCATION, NULL,
+- "invalid family: %d\n", iph1->remote->sa_family);
+- delph2(iph2);
+- goto end;
+- }
+-#endif
+ iph2->side = INITIATOR;
+ iph2->status = PHASE2ST_START;
+
+diff --git a/src/racoon/isakmp_inf.c b/src/racoon/isakmp_inf.c
+index a712825..6fa3498 100644
+--- a/src/racoon/isakmp_inf.c
++++ b/src/racoon/isakmp_inf.c
+@@ -903,15 +903,6 @@ isakmp_info_send_common(iph1, payload, np, flags)
+ delph2(iph2);
+ goto end;
+ }
+-#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
+- if (set_port(iph2->dst, 0) == NULL ||
+- set_port(iph2->src, 0) == NULL) {
+- plog(LLV_ERROR, LOCATION, NULL,
+- "invalid family: %d\n", iph1->remote->sa_family);
+- delph2(iph2);
+- goto end;
+- }
+-#endif
+ iph2->side = INITIATOR;
+ iph2->status = PHASE2ST_START;
+ iph2->msgid = isakmp_newmsgid2(iph1);
+@@ -1127,9 +1118,6 @@ purge_ipsec_spi(dst0, proto, spi, n)
+ u_int64_t created;
+ size_t i;
+ caddr_t mhp[SADB_EXT_MAX + 1];
+-#ifdef ENABLE_NATT
+- int natt_port_forced;
+-#endif
+
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "purge_ipsec_spi:\n");
+@@ -1169,6 +1157,7 @@ purge_ipsec_spi(dst0, proto, spi, n)
+ msg = next;
+ continue;
+ }
++ pk_fixup_sa_addresses(mhp);
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+ lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+@@ -1182,28 +1171,7 @@ purge_ipsec_spi(dst0, proto, spi, n)
+ msg = next;
+ continue;
+ }
+-#ifdef ENABLE_NATT
+- if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
+- /* NAT-T is enabled for this SADB entry; copy
+- * the ports from NAT-T extensions */
+- if (extract_port(src) == 0 &&
+- mhp[SADB_X_EXT_NAT_T_SPORT] != NULL) {
+- set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
+- }
+
+- if (extract_port(dst) == 0 &&
+- mhp[SADB_X_EXT_NAT_T_DPORT] != NULL) {
+- set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
+- }
+- natt_port_forced = 0;
+- } else {
+- /* Force default UDP ports, so
+- * CMPSADDR will match SAs with NO encapsulation */
+- set_port(src, PORT_ISAKMP);
+- set_port(dst, PORT_ISAKMP);
+- natt_port_forced = 1;
+- }
+-#endif
+ plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src));
+ plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst));
+
+@@ -1211,19 +1179,11 @@ purge_ipsec_spi(dst0, proto, spi, n)
+
+ /* don't delete inbound SAs at the moment */
+ /* XXX should we remove SAs with opposite direction as well? */
+- if (CMPSADDR(dst0, dst)) {
++ if (cmpsaddr(dst0, dst)) {
+ msg = next;
+ continue;
+ }
+
+-#ifdef ENABLE_NATT
+- if (natt_port_forced) {
+- /* Set back port to 0 if it was forced
+- * to default UDP port */
+- set_port(src, 0);
+- set_port(dst, 0);
+- }
+-#endif
+ for (i = 0; i < n; i++) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check spi(packet)=%u spi(db)=%u.\n",
+@@ -1354,37 +1314,33 @@ isakmp_info_recv_initialcontact(iph1, protectedph2)
+ msg = (struct sadb_msg *)buf->v;
+ end = (struct sadb_msg *)(buf->v + buf->l);
+
+- while (msg < end) {
++ for (; msg < end; msg = next) {
+ if ((msg->sadb_msg_len << 3) < sizeof(*msg))
+ break;
++
+ next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
+- if (msg->sadb_msg_type != SADB_DUMP) {
+- msg = next;
++ if (msg->sadb_msg_type != SADB_DUMP)
+ continue;
+- }
+
+ if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "pfkey_check (%s)\n", ipsec_strerror());
+- msg = next;
+ continue;
+ }
+
+ if (mhp[SADB_EXT_SA] == NULL
+ || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+- || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
+- msg = next;
++ || mhp[SADB_EXT_ADDRESS_DST] == NULL)
+ continue;
+- }
++
+ sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
++ pk_fixup_sa_addresses(mhp);
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+ if (sa->sadb_sa_state != SADB_SASTATE_MATURE
+- && sa->sadb_sa_state != SADB_SASTATE_DYING) {
+- msg = next;
++ && sa->sadb_sa_state != SADB_SASTATE_DYING)
+ continue;
+- }
+
+ /*
+ * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that
+@@ -1394,39 +1350,18 @@ isakmp_info_recv_initialcontact(iph1, protectedph2)
+ * racoon only deletes SA which is matched both the
+ * source address and the destination accress.
+ */
+-#ifdef ENABLE_NATT
+- /*
+- * XXX RFC 3947 says that whe MUST NOT use IP+port to find old SAs
+- * from this peer !
+- */
+- if(iph1->natt_flags & NAT_DETECTED){
+- if (CMPSADDR(iph1->local, src) == 0 &&
+- CMPSADDR(iph1->remote, dst) == 0)
+- ;
+- else if (CMPSADDR(iph1->remote, src) == 0 &&
+- CMPSADDR(iph1->local, dst) == 0)
+- ;
+- else {
+- msg = next;
+- continue;
+- }
+- } else
+-#endif
+- /* If there is no NAT-T, we don't have to check addr + port...
+- * XXX what about a configuration with a remote peers which is not
+- * NATed, but which NATs some other peers ?
+- * Here, the INITIAl-CONTACT would also flush all those NATed peers !!
+- */
+- if (cmpsaddrwop(iph1->local, src) == 0 &&
+- cmpsaddrwop(iph1->remote, dst) == 0)
+- ;
+- else if (cmpsaddrwop(iph1->remote, src) == 0 &&
+- cmpsaddrwop(iph1->local, dst) == 0)
+- ;
+- else {
+- msg = next;
++
++ /*
++ * Check that the IP and port match. But this is not optimal,
++ * since NAT-T can make the peer have multiple different
++ * ports. Correct thing to do is delete all entries with
++ * same identity. -TT
++ */
++ if ((cmpsaddr(iph1->local, src) != 0 ||
++ cmpsaddr(iph1->remote, dst) != 0) &&
++ (cmpsaddr(iph1->local, dst) != 0 ||
++ cmpsaddr(iph1->remote, src) != 0))
+ continue;
+- }
+
+ /*
+ * Make sure this is an SATYPE that we manage.
+@@ -1438,10 +1373,8 @@ isakmp_info_recv_initialcontact(iph1, protectedph2)
+ msg->sadb_msg_satype)
+ break;
+ }
+- if (i == pfkey_nsatypes) {
+- msg = next;
++ if (i == pfkey_nsatypes)
+ continue;
+- }
+
+ plog(LLV_INFO, LOCATION, NULL,
+ "purging spi=%u.\n", ntohl(sa->sadb_sa_spi));
+@@ -1461,8 +1394,6 @@ isakmp_info_recv_initialcontact(iph1, protectedph2)
+ remph2(iph2);
+ delph2(iph2);
+ }
+-
+- msg = next;
+ }
+
+ vfree(buf);
+diff --git a/src/racoon/isakmp_quick.c b/src/racoon/isakmp_quick.c
+index 804c1bf..46c84c1 100644
+--- a/src/racoon/isakmp_quick.c
++++ b/src/racoon/isakmp_quick.c
+@@ -610,17 +610,19 @@ quick_i2recv(iph2, msg0)
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
++#ifdef ENABLE_NATT
++ set_port(iph2->natoa_src,
++ extract_port((struct sockaddr *) &proposed_addr));
++#endif
+
+- if (cmpsaddrstrict((struct sockaddr *) &proposed_addr,
+- (struct sockaddr *) &got_addr) == 0) {
++ if (cmpsaddr((struct sockaddr *) &proposed_addr,
++ (struct sockaddr *) &got_addr) == 0) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDci matches proposal.\n");
+ #ifdef ENABLE_NATT
+ } else if (iph2->natoa_src != NULL
+- && cmpsaddrwop(iph2->natoa_src,
+- (struct sockaddr *) &got_addr) == 0
+- && extract_port((struct sockaddr *) &proposed_addr) ==
+- extract_port((struct sockaddr *) &got_addr)) {
++ && cmpsaddr(iph2->natoa_src,
++ (struct sockaddr *) &got_addr) == 0) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDci matches NAT-OAi.\n");
+ #endif
+@@ -656,16 +658,19 @@ quick_i2recv(iph2, msg0)
+ goto end;
+ }
+
+- if (cmpsaddrstrict((struct sockaddr *) &proposed_addr,
+- (struct sockaddr *) &got_addr) == 0) {
++#ifdef ENABLE_NATT
++ set_port(iph2->natoa_dst,
++ extract_port((struct sockaddr *) &proposed_addr));
++#endif
++
++ if (cmpsaddr((struct sockaddr *) &proposed_addr,
++ (struct sockaddr *) &got_addr) == 0) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDcr matches proposal.\n");
+ #ifdef ENABLE_NATT
+ } else if (iph2->natoa_dst != NULL
+- && cmpsaddrwop(iph2->natoa_dst,
+- (struct sockaddr *) &got_addr) == 0
+- && extract_port((struct sockaddr *) &proposed_addr) ==
+- extract_port((struct sockaddr *) &got_addr)) {
++ && cmpsaddr(iph2->natoa_dst,
++ (struct sockaddr *) &got_addr) == 0) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDcr matches NAT-OAr.\n");
+ #endif
+diff --git a/src/racoon/nattraversal.c b/src/racoon/nattraversal.c
+index f23341a..92095de 100644
+--- a/src/racoon/nattraversal.c
++++ b/src/racoon/nattraversal.c
+@@ -379,8 +379,8 @@ natt_keepalive_add (struct sockaddr *src, struct sockaddr *dst)
+ struct natt_ka_addrs *ka = NULL, *new_addr;
+
+ TAILQ_FOREACH (ka, &ka_tree, chain) {
+- if (cmpsaddrstrict(ka->src, src) == 0 &&
+- cmpsaddrstrict(ka->dst, dst) == 0) {
++ if (cmpsaddr(ka->src, src) == 0 &&
++ cmpsaddr(ka->dst, dst) == 0) {
+ ka->in_use++;
+ plog (LLV_INFO, LOCATION, NULL, "KA found: %s (in_use=%u)\n",
+ saddr2str_fromto("%s->%s", src, dst), ka->in_use);
+@@ -443,8 +443,8 @@ natt_keepalive_remove (struct sockaddr *src, struct sockaddr *dst)
+ plog (LLV_DEBUG, LOCATION, NULL, "KA tree dump: %s (in_use=%u)\n",
+ saddr2str_fromto("%s->%s", src, dst), ka->in_use);
+
+- if (cmpsaddrstrict(ka->src, src) == 0 &&
+- cmpsaddrstrict(ka->dst, dst) == 0 &&
++ if (cmpsaddr(ka->src, src) == 0 &&
++ cmpsaddr(ka->dst, dst) == 0 &&
+ -- ka->in_use <= 0) {
+
+ plog (LLV_DEBUG, LOCATION, NULL, "KA removing this one...\n");
+diff --git a/src/racoon/pfkey.c b/src/racoon/pfkey.c
+index c210c5e..3778ef2 100644
+--- a/src/racoon/pfkey.c
++++ b/src/racoon/pfkey.c
+@@ -774,8 +774,12 @@ pk_fixup_sa_addresses(mhp)
+ caddr_t *mhp;
+ {
+ struct sockaddr *src, *dst;
++
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
++ set_port(src, PORT_ISAKMP);
++ set_port(dst, PORT_ISAKMP);
++
+ #ifdef ENABLE_NATT
+ if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
+ /* NAT-T is enabled for this SADB entry; copy
+@@ -785,9 +789,6 @@ pk_fixup_sa_addresses(mhp)
+ if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL)
+ set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
+ }
+-#else
+- set_port(src, 0);
+- set_port(dst, 0);
+ #endif
+ }
+
+@@ -949,10 +950,6 @@ pk_sendgetspi(iph2)
+ dport=extract_port(dst);
+ }
+ #endif
+- /* Always remove port information, it will be sent in
+- * SADB_X_EXT_NAT_T_[S|D]PORT if needed */
+- set_port(src, 0);
+- set_port(dst, 0);
+
+ plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
+ if (pfkey_send_getspi_nat(
+@@ -1009,6 +1006,7 @@ pk_recvgetspi(mhp)
+ }
+ msg = (struct sadb_msg *)mhp[0];
+ sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
++ pk_fixup_sa_addresses(mhp);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+@@ -1183,18 +1181,14 @@ pk_sendupdate(iph2)
+ #ifdef ENABLE_NATT
+ if (pr->udp_encap) {
+ sa_args.l_natt_type = iph2->ph1->natt_options->encaps_type;
+- sa_args.l_natt_sport = extract_port (iph2->ph1->remote);
+- sa_args.l_natt_dport = extract_port (iph2->ph1->local);
++ sa_args.l_natt_sport = extract_port(iph2->ph1->remote);
++ sa_args.l_natt_dport = extract_port(iph2->ph1->local);
+ sa_args.l_natt_oa = iph2->natoa_src;
+ #ifdef SADB_X_EXT_NAT_T_FRAG
+ sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
+ #endif
+ }
+ #endif
+- /* Always remove port information, it will be sent in
+- * SADB_X_EXT_NAT_T_[S|D]PORT if needed */
+- set_port(sa_args.src, 0);
+- set_port(sa_args.dst, 0);
+
+ /* more info to fill in */
+ sa_args.spi = pr->spi;
+@@ -1358,14 +1352,6 @@ pk_recvupdate(mhp)
+ /* turn off schedule */
+ sched_cancel(&iph2->scr);
+
+- /* Force the update of ph2's ports, as there is at least one
+- * situation where they'll mismatch with ph1's values
+- */
+-#ifdef ENABLE_NATT
+- set_port(iph2->src, extract_port(iph2->ph1->local));
+- set_port(iph2->dst, extract_port(iph2->ph1->remote));
+-#endif
+-
+ /*
+ * 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.
+@@ -1418,7 +1404,7 @@ pk_sendadd(iph2)
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
+ return -1;
+- }
++ }
+
+ for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
+ /* validity check */
+@@ -1490,11 +1476,6 @@ pk_sendadd(iph2)
+ #endif
+ }
+ #endif
+- /* Always remove port information, it will be sent in
+- * SADB_X_EXT_NAT_T_[S|D]PORT if needed */
+- set_port(sa_args.src, 0);
+- set_port(sa_args.dst, 0);
+-
+ /* more info to fill in */
+ sa_args.spi = pr->spi_p;
+ sa_args.reqid = pr->reqid_out;
+@@ -1559,6 +1540,7 @@ pk_recvadd(mhp)
+ return -1;
+ }
+ msg = (struct sadb_msg *)mhp[0];
++ pk_fixup_sa_addresses(mhp);
+ 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];
+@@ -1749,7 +1731,9 @@ pk_recvacquire(mhp)
+ }
+ msg = (struct sadb_msg *)mhp[0];
+ xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+- pk_fixup_sa_addresses(mhp);
++ /* acquire does not have nat-t ports; so do not bother setting
++ * the default port 500; just use the port zero for wildcard
++ * matching the get a valid natted destination */
+ sp_src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ sp_dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+@@ -2884,8 +2868,8 @@ migrate_ph1_ike_addresses(iph1, arg)
+ u_int16_t port;
+
+ /* Already up-to-date? */
+- if (cmpsaddrwop(iph1->local, ma->local) == 0 &&
+- cmpsaddrwop(iph1->remote, ma->remote) == 0)
++ if (cmpsaddr(iph1->local, ma->local) == 0 &&
++ cmpsaddr(iph1->remote, ma->remote) == 0)
+ return 0;
+
+ if (iph1->status < PHASE1ST_ESTABLISHED) {
+@@ -2985,8 +2969,8 @@ migrate_ph2_ike_addresses(iph2, arg)
+ migrate_ph1_ike_addresses(iph2->ph1, arg);
+
+ /* Already up-to-date? */
+- if (CMPSADDR(iph2->src, ma->local) == 0 &&
+- CMPSADDR(iph2->dst, ma->remote) == 0)
++ if (cmpsaddr(iph2->src, ma->local) == 0 &&
++ cmpsaddr(iph2->dst, ma->remote) == 0)
+ return 0;
+
+ /* save src/dst as sa_src/sa_dst before rewriting */
+@@ -3206,8 +3190,8 @@ migrate_ph2_one_isr(spid, isr_cur, xisr_old, xisr_new)
+ "changing address families (%d to %d) for endpoints.\n",
+ osaddr->sa_family, nsaddr->sa_family);
+
+- if (CMPSADDR(osaddr, (struct sockaddr *)&saidx->src) ||
+- CMPSADDR(odaddr, (struct sockaddr *)&saidx->dst)) {
++ if (cmpsaddr(osaddr, (struct sockaddr *) &saidx->src) ||
++ cmpsaddr(odaddr, (struct sockaddr *) &saidx->dst)) {
+ plog(LLV_DEBUG, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "mismatch of addresses in saidx and xisr.\n");
+ return -1;
+diff --git a/src/racoon/policy.c b/src/racoon/policy.c
+index 850fa6b..058753f 100644
+--- a/src/racoon/policy.c
++++ b/src/racoon/policy.c
+@@ -141,16 +141,18 @@ getsp_r(spidx, iph2)
+ saddr2str(iph2->src));
+ plog(LLV_DEBUG, LOCATION, NULL, "src2: %s\n",
+ saddr2str((struct sockaddr *)&spidx->src));
+- if (cmpsaddrwop(iph2->src, (struct sockaddr *)&spidx->src)
+- || spidx->prefs != prefixlen)
++
++ if (cmpsaddr(iph2->src, (struct sockaddr *) &spidx->src) ||
++ spidx->prefs != prefixlen)
+ return NULL;
+
+ plog(LLV_DEBUG, LOCATION, NULL, "dst1: %s\n",
+ saddr2str(iph2->dst));
+ plog(LLV_DEBUG, LOCATION, NULL, "dst2: %s\n",
+ saddr2str((struct sockaddr *)&spidx->dst));
+- if (cmpsaddrwop(iph2->dst, (struct sockaddr *)&spidx->dst)
+- || spidx->prefd != prefixlen)
++
++ if (cmpsaddr(iph2->dst, (struct sockaddr *) &spidx->dst) ||
++ spidx->prefd != prefixlen)
+ return NULL;
+
+ plog(LLV_DEBUG, LOCATION, NULL, "looks to be transport mode\n");
+@@ -198,11 +200,11 @@ cmpspidxstrict(a, b)
+ || a->ul_proto != b->ul_proto)
+ return 1;
+
+- if (cmpsaddrstrict((struct sockaddr *)&a->src,
+- (struct sockaddr *)&b->src))
++ if (cmpsaddr((struct sockaddr *) &a->src,
++ (struct sockaddr *) &b->src))
+ return 1;
+- if (cmpsaddrstrict((struct sockaddr *)&a->dst,
+- (struct sockaddr *)&b->dst))
++ if (cmpsaddr((struct sockaddr *) &a->dst,
++ (struct sockaddr *) &b->dst))
+ return 1;
+
+ #ifdef HAVE_SECCTX
+@@ -259,7 +261,7 @@ cmpspidxwild(a, b)
+ a, b->prefs, saddr2str((struct sockaddr *)&sa1));
+ plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
+ b, b->prefs, saddr2str((struct sockaddr *)&sa2));
+- if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
++ if (cmpsaddr((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
+ return 1;
+
+ #ifndef __linux__
+@@ -277,7 +279,7 @@ cmpspidxwild(a, b)
+ a, b->prefd, saddr2str((struct sockaddr *)&sa1));
+ plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
+ b, b->prefd, saddr2str((struct sockaddr *)&sa2));
+- if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
++ if (cmpsaddr((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
+ return 1;
+
+ #ifdef HAVE_SECCTX
+diff --git a/src/racoon/remoteconf.c b/src/racoon/remoteconf.c
+index 73d80bc..88c622c 100644
+--- a/src/racoon/remoteconf.c
++++ b/src/racoon/remoteconf.c
+@@ -200,15 +200,9 @@ rmconf_match_type(rmsel, rmconf)
+ /* Check address */
+ if (rmsel->remote != NULL) {
+ if (rmconf->remote->sa_family != AF_UNSPEC) {
+- if (rmsel->flags & GETRMCONF_F_NO_PORTS) {
+- if (cmpsaddrwop(rmsel->remote,
+- rmconf->remote) != 0)
+- return 0;
+- } else {
+- if (cmpsaddrstrict(rmsel->remote,
+- rmconf->remote) != 0)
+- return 0;
+- }
++ if (cmpsaddr(rmsel->remote, rmconf->remote) != 0)
++ return 0;
++
+ /* Address matched */
+ ret = 2;
+ }
+@@ -262,7 +256,7 @@ void rmconf_selector_from_ph1(rmsel, iph1)
+ struct ph1handle *iph1;
+ {
+ memset(rmsel, 0, sizeof(*rmsel));
+- rmsel->flags = GETRMCONF_F_NO_PORTS;
++ rmsel->flags = 0;
+ rmsel->remote = iph1->remote;
+ rmsel->etype = iph1->etype;
+ rmsel->approval = iph1->approval;
+@@ -357,22 +351,8 @@ getrmconf(remote, flags)
+ int n = 0;
+
+ memset(&ctx, 0, sizeof(ctx));
+- ctx.sel.flags = flags | GETRMCONF_F_NO_PORTS;
++ ctx.sel.flags = flags;
+ ctx.sel.remote = remote;
+-#ifndef ENABLE_NATT
+- /*
+- * We never have ports set in our remote configurations, but when
+- * NAT-T is enabled, the kernel can have policies with ports and
+- * send us an acquire message for a destination that has a port set.
+- * If we do this port check here, we don't find the remote config.
+- *
+- * In an ideal world, we would be able to have remote conf with
+- * port, and the port could be a wildcard. That test could be used.
+- */
+- if (remote->sa_family != AF_UNSPEC &&
+- extract_port(remote) != IPSEC_PORT_ANY)
+- ctx.sel.flags &= ~GETRMCONF_F_NO_PORTS;
+-#endif /* ENABLE_NATT */
+
+ if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
+ plog(LLV_ERROR, LOCATION, remote,
+diff --git a/src/racoon/remoteconf.h b/src/racoon/remoteconf.h
+index 38faf03..b2e9e4a 100644
+--- a/src/racoon/remoteconf.h
++++ b/src/racoon/remoteconf.h
+@@ -189,8 +189,7 @@ extern int enumrmconf __P((struct rmconfselector *rmsel,
+ void *enum_arg));
+
+ #define GETRMCONF_F_NO_ANONYMOUS 0x0001
+-#define GETRMCONF_F_NO_PORTS 0x0002
+-#define GETRMCONF_F_NO_PASSIVE 0x0004
++#define GETRMCONF_F_NO_PASSIVE 0x0002
+
+ #define RMCONF_ERR_MULTIPLE ((struct remoteconf *) -1)
+
+diff --git a/src/racoon/sockmisc.c b/src/racoon/sockmisc.c
+index 5c1f9c7..2bc2177 100644
+--- a/src/racoon/sockmisc.c
++++ b/src/racoon/sockmisc.c
+@@ -80,87 +77,28 @@
+ const int niflags = 0;
+
+ /*
+- * compare two sockaddr without port number.
+- * OUT: 0: equal.
+- * 1: not equal.
+- */
+-int
+-cmpsaddrwop(addr1, addr2)
+- const struct sockaddr *addr1;
+- const struct sockaddr *addr2;
+-{
+- caddr_t sa1, sa2;
+-
+- if (addr1 == 0 && addr2 == 0)
+- return 0;
+- if (addr1 == 0 || addr2 == 0)
+- return 1;
+-
+-#ifdef __linux__
+- if (addr1->sa_family != addr2->sa_family)
+- return 1;
+-#else
+- if (addr1->sa_len != addr2->sa_len
+- || addr1->sa_family != addr2->sa_family)
+- return 1;
+-
+-#endif /* __linux__ */
+-
+- switch (addr1->sa_family) {
+- case AF_UNSPEC:
+- break;
+- case AF_INET:
+- sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
+- sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
+- if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+- return 1;
+- break;
+-#ifdef INET6
+- case AF_INET6:
+- sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
+- sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
+- if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+- return 1;
+- if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
+- ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
+- return 1;
+- break;
+-#endif
+- default:
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+-/*
+ * compare two sockaddr with port, taking care wildcard.
+ * addr1 is a subject address, addr2 is in a database entry.
+ * OUT: 0: equal.
+ * 1: not equal.
+ */
+ int
+-cmpsaddrwild(addr1, addr2)
++cmpsaddr(addr1, addr2)
+ const struct sockaddr *addr1;
+ const struct sockaddr *addr2;
+ {
+ caddr_t sa1, sa2;
+ u_short port1, port2;
+
+- if (addr1 == 0 && addr2 == 0)
+- return 0;
+- if (addr1 == 0 || addr2 == 0)
+- return 1;
++ if (addr1 == NULL && addr2 == NULL)
++ return CMPSADDR_MATCH;
+
+-#ifdef __linux__
+- if (addr1->sa_family != addr2->sa_family)
+- return 1;
+-#else
+- if (addr1->sa_len != addr2->sa_len
+- || addr1->sa_family != addr2->sa_family)
+- return 1;
++ if (addr1 == NULL || addr2 == NULL)
++ return CMPSADDR_MISMATCH;
+
+-#endif /* __linux__ */
++ if (addr1->sa_family != addr2->sa_family ||
++ sysdep_sa_len(addr1) != sysdep_sa_len(addr2))
++ return CMPSADDR_MISMATCH;
+
+ switch (addr1->sa_family) {
+ case AF_UNSPEC:
+@@ -170,12 +108,8 @@ cmpsaddrwild(addr1, addr2)
+ sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
+ port1 = ((struct sockaddr_in *)addr1)->sin_port;
+ port2 = ((struct sockaddr_in *)addr2)->sin_port;
+- if (!(port1 == IPSEC_PORT_ANY ||
+- port2 == IPSEC_PORT_ANY ||
+- port1 == port2))
+- return 1;
+ if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+- return 1;
++ return CMPSADDR_MISMATCH;
+ break;
+ #ifdef INET6
+ case AF_INET6:
+@@ -183,155 +117,23 @@ cmpsaddrwild(addr1, addr2)
+ sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
+ port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
+ port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
+- if (!(port1 == IPSEC_PORT_ANY ||
+- port2 == IPSEC_PORT_ANY ||
+- port1 == port2))
+- return 1;
+ if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+- return 1;
++ return CMPSADDR_MISMATCH;
+ if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
+ ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
+- return 1;
++ return CMPSADDR_MISMATCH;
+ break;
+ #endif
+ default:
+- return 1;
++ return CMPSADDR_MISMATCH;
+ }
+
+- return 0;
+-}
+-
+-/*
+- * compare two sockaddr with port, taking care specific situation:
+- * one addr has 0 as port, and the other has 500 (network order), return equal
+- * OUT: 0: equal.
+- * 1: not equal.
+- */
+-int
+-cmpsaddrmagic(addr1, addr2)
+- const struct sockaddr *addr1;
+- const struct sockaddr *addr2;
+-{
+- caddr_t sa1, sa2;
+- u_short port1, port2;
+-
+- if (addr1 == 0 && addr2 == 0)
+- return 0;
+- if (addr1 == 0 || addr2 == 0)
+- return 1;
+-
+-#ifdef __linux__
+- if (addr1->sa_family != addr2->sa_family)
+- return 1;
+-#else
+- if (addr1->sa_len != addr2->sa_len
+- || addr1->sa_family != addr2->sa_family)
+- return 1;
++ if (port1 == port2 ||
++ port1 == IPSEC_PORT_ANY ||
++ port2 == IPSEC_PORT_ANY)
++ return CMPSADDR_MATCH;
+
+-#endif /* __linux__ */
+-
+- switch (addr1->sa_family) {
+- case AF_UNSPEC:
+- break;
+- case AF_INET:
+- sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
+- sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
+- port1 = ((struct sockaddr_in *)addr1)->sin_port;
+- port2 = ((struct sockaddr_in *)addr2)->sin_port;
+- plog(LLV_DEBUG, LOCATION, NULL, "cmpsaddr_magic: port1 == %d, port2 == %d\n", port1, port2);
+- if (!((port1 == IPSEC_PORT_ANY && port2 == ntohs(PORT_ISAKMP)) ||
+- (port2 == IPSEC_PORT_ANY && port1 == ntohs(PORT_ISAKMP)) ||
+- (port1 == port2))){
+- plog(LLV_DEBUG, LOCATION, NULL, "cmpsaddr_magic: ports mismatch\n");
+- return 1;
+- }
+- plog(LLV_DEBUG, LOCATION, NULL, "cmpsaddr_magic: ports matched\n");
+- if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+- return 1;
+- break;
+-#ifdef INET6
+- case AF_INET6:
+- sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
+- sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
+- port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
+- port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
+- if (!((port1 == IPSEC_PORT_ANY && port2 == PORT_ISAKMP) ||
+- (port2 == IPSEC_PORT_ANY && port1 == PORT_ISAKMP) ||
+- (port1 == port2)))
+- return 1;
+- if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+- return 1;
+- if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
+- ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
+- return 1;
+- break;
+-#endif
+- default:
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * compare two sockaddr with strict match on port.
+- * OUT: 0: equal.
+- * 1: not equal.
+- */
+-int
+-cmpsaddrstrict(addr1, addr2)
+- const struct sockaddr *addr1;
+- const struct sockaddr *addr2;
+-{
+- caddr_t sa1, sa2;
+- u_short port1, port2;
+-
+- if (addr1 == 0 && addr2 == 0)
+- return 0;
+- if (addr1 == 0 || addr2 == 0)
+- return 1;
+-
+-#ifdef __linux__
+- if (addr1->sa_family != addr2->sa_family)
+- return 1;
+-#else
+- if (addr1->sa_len != addr2->sa_len
+- || addr1->sa_family != addr2->sa_family)
+- return 1;
+-
+-#endif /* __linux__ */
+-
+- switch (addr1->sa_family) {
+- case AF_INET:
+- sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
+- sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
+- port1 = ((struct sockaddr_in *)addr1)->sin_port;
+- port2 = ((struct sockaddr_in *)addr2)->sin_port;
+- if (port1 != port2)
+- return 1;
+- if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+- return 1;
+- break;
+-#ifdef INET6
+- case AF_INET6:
+- sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
+- sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
+- port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
+- port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
+- if (port1 != port2)
+- return 1;
+- if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+- return 1;
+- if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
+- ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
+- return 1;
+- break;
+-#endif
+- default:
+- return 1;
+- }
+-
+- return 0;
++ return CMPSADDR_WOP_MATCH;
+ }
+
+ /* get local address against the destination. */
+@@ -1129,7 +931,7 @@ naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr)
+ free(a2);
+ free(a3);
+ }
+- if (cmpsaddrwop(&sa, &naddr->sa.sa) == 0)
++ if (cmpsaddr(&sa, &naddr->sa.sa) == 0)
+ return naddr->prefix + port_score;
+
+ return -1;
+diff --git a/src/racoon/sockmisc.h b/src/racoon/sockmisc.h
+index fcc286f..0a58f44 100644
+--- a/src/racoon/sockmisc.h
++++ b/src/racoon/sockmisc.h
+@@ -54,16 +54,11 @@ struct netaddr {
+
+ extern const int niflags;
+
+-extern int cmpsaddrwop __P((const struct sockaddr *, const struct sockaddr *));
+-extern int cmpsaddrwild __P((const struct sockaddr *, const struct sockaddr *));
+-extern int cmpsaddrstrict __P((const struct sockaddr *, const struct sockaddr *));
+-extern int cmpsaddrmagic __P((const struct sockaddr *, const struct sockaddr *));
+-
+-#ifdef ENABLE_NATT
+-#define CMPSADDR(saddr1, saddr2) cmpsaddrstrict((saddr1), (saddr2))
+-#else
+-#define CMPSADDR(saddr1, saddr2) cmpsaddrwop((saddr1), (saddr2))
+-#endif
++#define CMPSADDR_MATCH 0
++#define CMPSADDR_WOP_MATCH 1
++#define CMPSADDR_MISMATCH 2
++
++extern int cmpsaddr __P((const struct sockaddr *, const struct sockaddr *));
+
+ extern struct sockaddr *getlocaladdr __P((struct sockaddr *));
+
+diff --git a/src/racoon/throttle.c b/src/racoon/throttle.c
+index 5ab62c3..64b566b 100644
+--- a/src/racoon/throttle.c
++++ b/src/racoon/throttle.c
+@@ -104,7 +104,7 @@ restart:
+ goto restart;
+ }
+
+- if (cmpsaddrwop(addr, (struct sockaddr *)&te->host) == 0) {
++ if (cmpsaddr(addr, (struct sockaddr *) &te->host) == 0) {
+ found = 1;
+ break;
+ }
diff --git a/main/ipsec-tools/50-reverse-connect.patch b/main/ipsec-tools/50-reverse-connect.patch
new file mode 100644
index 0000000000..c49eae347f
--- /dev/null
+++ b/main/ipsec-tools/50-reverse-connect.patch
@@ -0,0 +1,207 @@
+When new ISAKMP is required, allow incoming reverse connection to take
+
+From: Timo Teras <timo.teras@iki.fi>
+
+over pending phase1:s. Useful when the other party is firewalled or NATted.
+---
+
+ src/racoon/admin.c | 12 ++++++++++++
+ src/racoon/evt.c | 13 +++++++++++++
+ src/racoon/evt.h | 3 +++
+ src/racoon/handler.c | 28 +++++++++++++++++++++-------
+ src/racoon/isakmp.c | 39 ++++++++++++++++++++++++++++++++++-----
+ 5 files changed, 83 insertions(+), 12 deletions(-)
+
+
+diff --git a/src/racoon/admin.c b/src/racoon/admin.c
+index b67e545..710c9bf 100644
+--- a/src/racoon/admin.c
++++ b/src/racoon/admin.c
+@@ -414,11 +414,23 @@ admin_process(so2, combuf)
+ struct sockaddr *dst;
+ struct sockaddr *src;
+ char *name = NULL;
++ char *loc, *rem;
+
+ ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
+ src = (struct sockaddr *) &ndx->src;
+ dst = (struct sockaddr *) &ndx->dst;
+
++ loc = racoon_strdup(saddr2str(src));
++ rem = racoon_strdup(saddr2str(dst));
++ STRDUP_FATAL(loc);
++ STRDUP_FATAL(rem);
++
++ plog(LLV_INFO, LOCATION, NULL,
++ "admin establish-sa %x %s %s\n",
++ com->ac_proto, loc, rem);
++ racoon_free(loc);
++ racoon_free(rem);
++
+ if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
+ com->ac_len > sizeof(*com) + sizeof(*ndx))
+ name = (char *) ((caddr_t) ndx + sizeof(*ndx));
+diff --git a/src/racoon/evt.c b/src/racoon/evt.c
+index 4ce1334..000c1f8 100644
+--- a/src/racoon/evt.c
++++ b/src/racoon/evt.c
+@@ -396,4 +396,17 @@ evt_list_cleanup(list)
+ evt_unsubscribe(LIST_FIRST(list));
+ }
+
++void
++evt_list_move(from, to)
++ struct evt_listener_list *from, *to;
++{
++ struct evt_listener *l;
++
++ while (!LIST_EMPTY(from)) {
++ l = LIST_FIRST(from);
++ LIST_REMOVE(l, ll_chain);
++ LIST_INSERT_HEAD(to, l, ll_chain);
++ }
++}
++
+ #endif /* ENABLE_ADMINPORT */
+diff --git a/src/racoon/evt.h b/src/racoon/evt.h
+index 0ce65bd..ba7fb57 100644
+--- a/src/racoon/evt.h
++++ b/src/racoon/evt.h
+@@ -124,6 +124,8 @@ void evt_phase2 __P((const struct ph2handle *ph2, int type, vchar_t *optdata));
+ vchar_t *evt_dump __P((void));
+
+ int evt_subscribe __P((struct evt_listener_list *list, int fd));
++void evt_list_move __P((struct evt_listener_list *from,
++ struct evt_listener_list *to));
+ void evt_list_init __P((struct evt_listener_list *list));
+ void evt_list_cleanup __P((struct evt_listener_list *list));
+
+@@ -136,6 +138,7 @@ void evt_list_cleanup __P((struct evt_listener_list *list));
+ #define evt_phase2(ph2, type, optdata) ;
+
+ #define evt_subscribe(eventlist, fd) ;
++#deifne evt_list_move(from, to) ;
+ #define evt_list_init(eventlist) ;
+ #define evt_list_cleanup(eventlist) ;
+ #define evt_get_fdmask(nfds, fdset) nfds
+diff --git a/src/racoon/handler.c b/src/racoon/handler.c
+index b33986f..9fd3817 100644
+--- a/src/racoon/handler.c
++++ b/src/racoon/handler.c
+@@ -269,26 +269,40 @@ migrate_ph12(old_iph1, new_iph1)
+ }
+
+ /*
+- * the iph1 is new, migrate all phase2s that belong to a dying or dead ph1
++ * the iph1 is new, migrate all phase2s that belong to a dying or dead ph1.
+ */
+ void migrate_dying_ph12(iph1)
+ struct ph1handle *iph1;
+ {
+- struct ph1handle *p;
++ struct ph1handle *p, *next;
+
+- LIST_FOREACH(p, &ph1tree, chain) {
++ for (p = LIST_FIRST(&ph1tree); p; p = next) {
++ next = LIST_NEXT(p, chain);
+ if (p == iph1)
+ continue;
+- if (p->status < PHASE1ST_DYING)
++
++ /* Same remote? */
++ if (cmpsaddr(iph1->local, p->local) > CMPSADDR_WOP_MATCH ||
++ cmpsaddr(iph1->remote, p->remote) > CMPSADDR_WOP_MATCH ||
++ iph1->rmconf != p->rmconf)
+ continue;
+
+- if (cmpsaddr(iph1->local, p->local) == 0
+- && cmpsaddr(iph1->remote, p->remote) == 0)
++ /* migrate phase2:s from expiring entries */
++ if (p->status >= PHASE1ST_DYING)
+ migrate_ph12(p, iph1);
++
++ /* and allow reverse connections to release
++ * pending connections that do not work due
++ * to firewall or nat */
++ if (iph1->side == RESPONDER && p->side == INITIATOR &&
++ p->status < PHASE1ST_MSG3RECEIVED) {
++ evt_list_move(&p->evt_listeners, &iph1->evt_listeners);
++ remph1(p);
++ delph1(p);
++ }
+ }
+ }
+
+-
+ /*
+ * dump isakmp-sa
+ */
+diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c
+index 0de16d1..2dfda2f 100644
+--- a/src/racoon/isakmp.c
++++ b/src/racoon/isakmp.c
+@@ -2138,13 +2138,33 @@ isakmp_ph2delete(iph2)
+
+ remph2(iph2);
+ delph2(iph2);
+-
+- return;
+ }
+
+ /* %%%
+ * Interface between PF_KEYv2 and ISAKMP
+ */
++
++static void
++isakmp_chkph2there(p)
++ struct sched *p;
++{
++ struct ph2handle *iph2 = container_of(p, struct ph2handle, sce);
++ struct ph2handle *tmp;
++
++ /* Check if a similar phase2 appared meanwhile */
++ remph2(iph2);
++ tmp = getph2byid(iph2->src, iph2->dst, iph2->spid);
++ if (tmp == NULL) {
++ /* Nope, lets start this then */
++ insph2(iph2);
++ isakmp_chkph1there(iph2);
++ } else {
++ /* Yes, delete this initiation attempt as redundant */
++ evt_phase2(iph2, EVT_PHASE2_UP, NULL);
++ delph2(iph2);
++ }
++}
++
+ /*
+ * receive ACQUIRE from kernel, and begin either phase1 or phase2.
+ * if phase1 has been finished, begin phase2.
+@@ -2220,8 +2240,14 @@ isakmp_post_acquire(iph2)
+ /*NOTREACHED*/
+ }
+
+- /* found established ISAKMP-SA */
+- /* i.e. iph1->status == PHASE1ST_ESTABLISHED */
++ /* found established ISAKMP-SA, if this is a RESPONDER ISAKMP-SA
++ * add a small delay; this will make sure the initiator gets
++ * an first attempt at rekeying, and usually avoids duplicate ph2:s */
++ if (iph1->side == RESPONDER) {
++ iph2->retry_checkph1 = 1;
++ sched_schedule(&iph2->sce, 1, isakmp_chkph2there);
++ return 0;
++ }
+
+ /* found ISAKMP-SA. */
+ plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
+@@ -2388,7 +2414,10 @@ isakmp_chkph1there(iph2)
+ plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(iph2->dst));
+
+ /* begin quick mode */
+- (void)isakmp_ph2begin_i(iph1, iph2);
++ if (isakmp_ph2begin_i(iph1, iph2)) {
++ remph2(iph2);
++ delph2(iph2);
++ }
+ return;
+ }
+
diff --git a/main/ipsec-tools/60-debug-quick.patch b/main/ipsec-tools/60-debug-quick.patch
new file mode 100644
index 0000000000..a5c3346ee9
--- /dev/null
+++ b/main/ipsec-tools/60-debug-quick.patch
@@ -0,0 +1,211 @@
+debugging prints for quick mode errors
+
+From: Timo Teras <timo.teras@iki.fi>
+
+
+---
+
+ src/racoon/isakmp.c | 21 ++++++++++++++-------
+ src/racoon/isakmp_quick.c | 46 ++++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 53 insertions(+), 14 deletions(-)
+
+
+diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c
+index 2dfda2f..87ce598 100644
+--- a/src/racoon/isakmp.c
++++ b/src/racoon/isakmp.c
+@@ -817,7 +817,8 @@ ph1_main(iph1, msg)
+
+ if (iph1->side == RESPONDER && iph1->status == PHASE1ST_START) {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+- "failed to pre-process packet.\n");
++ "failed to pre-process ph1 packet (side: %d, status %d).\n",
++ iph1->side, iph1->status);
+ return -1;
+ } else {
+ /* ignore the error and keep phase 1 handler */
+@@ -845,7 +846,8 @@ ph1_main(iph1, msg)
+ [iph1->side]
+ [iph1->status])(iph1, msg) != 0) {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+- "failed to process packet.\n");
++ "failed to process ph1 packet (side: %d, status: %d).\n",
++ iph1->side, iph1->status);
+ return -1;
+ }
+
+@@ -997,7 +999,8 @@ quick_main(iph2, msg)
+ [iph2->status])(iph2, msg);
+ if (error != 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+- "failed to pre-process packet.\n");
++ "failed to pre-process ph2 packet (side: %d, status %d).\n",
++ iph2->side, iph2->status);
+ if (error == ISAKMP_INTERNAL_ERROR)
+ return 0;
+ isakmp_info_send_n1(iph2->ph1, error, NULL);
+@@ -1025,7 +1028,8 @@ quick_main(iph2, msg)
+ [iph2->side]
+ [iph2->status])(iph2, msg) != 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+- "failed to process packet.\n");
++ "failed to process ph2 packet (side: %d, status: %d).\n",
++ iph2->side, iph2->status);
+ return -1;
+ }
+
+@@ -1233,7 +1237,8 @@ isakmp_ph1begin_r(msg, remote, local, etype)
+ [iph1->side]
+ [iph1->status])(iph1, msg) < 0) {
+ plog(LLV_ERROR, LOCATION, remote,
+- "failed to process packet.\n");
++ "failed to process ph1 packet (side: %d, status: %d).\n",
++ iph1->side, iph1->status);
+ remph1(iph1);
+ delph1(iph1);
+ return -1;
+@@ -1386,7 +1391,8 @@ isakmp_ph2begin_r(iph1, msg)
+ [iph2->status])(iph2, msg);
+ if (error != 0) {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+- "failed to pre-process packet.\n");
++ "failed to pre-process ph2 packet (side: %d, status: %d).\n",
++ iph2->side, iph2->status);
+ if (error != ISAKMP_INTERNAL_ERROR)
+ isakmp_info_send_n1(iph2->ph1, error, NULL);
+ /*
+@@ -1404,7 +1410,8 @@ isakmp_ph2begin_r(iph1, msg)
+ [iph2->side]
+ [iph2->status])(iph2, msg) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+- "failed to process packet.\n");
++ "failed to process ph2 packet (side: %d, status: %d).\n",
++ iph2->side, iph2->status);
+ /* don't release handler */
+ return -1;
+ }
+diff --git a/src/racoon/isakmp_quick.c b/src/racoon/isakmp_quick.c
+index 46c84c1..2657407 100644
+--- a/src/racoon/isakmp_quick.c
++++ b/src/racoon/isakmp_quick.c
+@@ -495,18 +495,27 @@ quick_i2recv(iph2, msg0)
+ "isn't supported.\n");
+ break;
+ }
+- if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0)
++ if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "duplicate ISAKMP_NPTYPE_SA.\n");
+ goto end;
++ }
+ break;
+
+ case ISAKMP_NPTYPE_NONCE:
+- if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
++ if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "duplicate ISAKMP_NPTYPE_NONCE.\n");
+ goto end;
++ }
+ break;
+
+ case ISAKMP_NPTYPE_KE:
+- if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
++ if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "duplicate ISAKMP_NPTYPE_KE.\n");
+ goto end;
++ }
+ break;
+
+ case ISAKMP_NPTYPE_ID:
+@@ -517,6 +526,8 @@ quick_i2recv(iph2, msg0)
+ if (isakmp_p2ph(&idcr, pa->ptr) < 0)
+ goto end;
+ } else {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "too many ISAKMP_NPTYPE_ID payloads.\n");
+ goto end;
+ }
+ break;
+@@ -557,6 +568,8 @@ quick_i2recv(iph2, msg0)
+ iph2->natoa_dst = daddr;
+ else {
+ racoon_free(daddr);
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "too many ISAKMP_NPTYPE_NATOA payloads.\n");
+ goto end;
+ }
+ }
+@@ -718,6 +731,8 @@ quick_i2recv(iph2, msg0)
+
+ /* validity check SA payload sent from responder */
+ if (ipsecdoi_checkph2proposal(iph2) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "proposal check failed.\n");
+ error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+ goto end;
+ }
+@@ -1077,8 +1092,11 @@ quick_r1recv(iph2, msg0)
+ }
+ /* decrypt packet */
+ msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
+- if (msg == NULL)
++ if (msg == NULL) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "Packet decryption failed.\n");
+ goto end;
++ }
+
+ /* create buffer for using to validate HASH(1) */
+ /*
+@@ -1162,18 +1180,27 @@ quick_r1recv(iph2, msg0)
+ "Multi SAs isn't supported.\n");
+ goto end;
+ }
+- if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0)
++ if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "duplicate ISAKMP_NPTYPE_SA.\n");
+ goto end;
++ }
+ break;
+
+ case ISAKMP_NPTYPE_NONCE:
+- if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
++ if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "duplicate ISAKMP_NPTYPE_NONCE.\n");
+ goto end;
++ }
+ break;
+
+ case ISAKMP_NPTYPE_KE:
+- if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
++ if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "duplicate ISAKMP_NPTYPE_KE.\n");
+ goto end;
++ }
+ break;
+
+ case ISAKMP_NPTYPE_ID:
+@@ -1241,6 +1268,9 @@ quick_r1recv(iph2, msg0)
+ iph2->natoa_src = daddr;
+ else {
+ racoon_free(daddr);
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "received too many NAT-OA payloads.\n");
++ error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+ goto end;
+ }
+ }
+@@ -1333,6 +1363,8 @@ quick_r1recv(iph2, msg0)
+ case 0:
+ /* select single proposal or reject it. */
+ if (ipsecdoi_selectph2proposal(iph2) < 0) {
++ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
++ "no proposal chosen.\n");
+ error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+ goto end;
+ }
diff --git a/main/ipsec-tools/APKBUILD b/main/ipsec-tools/APKBUILD
new file mode 100644
index 0000000000..b947b9b695
--- /dev/null
+++ b/main/ipsec-tools/APKBUILD
@@ -0,0 +1,59 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ipsec-tools
+pkgver=0.8_alpha20090422
+_myver=0.8-alpha20090422
+pkgrel=0
+pkgdesc="User-space IPsec tools for various IPsec implementations"
+url="http://ipsec-tools.sourceforge.net/"
+license="BSD"
+depends="openssl uclibc"
+makedepends="openssl-dev bison flex"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$_myver.tar.gz
+ racoon.initd
+ racoon.confd
+ 00-verify-cert-leak.patch
+ 20-natoa-fix.patch
+ 30-natt-ports-cleanup.patch
+ 40-cmpsaddr-cleanup.patch
+ 50-reverse-connect.patch
+ 60-debug-quick.patch
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$_myver"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+ sed -i 's:-Werror::g' configure
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var/lib \
+ --with-kernel-headers=/usr/include \
+ --disable-security-context \
+ --enable-adminport \
+ --enable-dpd \
+ --enable-frag \
+ --enable-hybrid \
+ --enable-ipv6 \
+ --enable-natt
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ install -D -m755 ../racoon.initd "$pkgdir"/etc/init.d/racoon
+ install -D -m644 ../racoon.confd "$pkgdir"/etc/conf.d/racoon
+}
+
+md5sums="8327401b5d1aa91e9c554d2cc536f823 ipsec-tools-0.8-alpha20090422.tar.gz
+16d66458442750e6401fa459e93172b7 racoon.initd
+788e3de82c1c6532dab0dc0c19c1bf40 racoon.confd
+e0abf570c29519e8e36406dfc3bbe3c8 00-verify-cert-leak.patch
+2adb8796c75f62811b08c8370c75312c 20-natoa-fix.patch
+17b3f05426537afa1e94947c39b10163 30-natt-ports-cleanup.patch
+5fcaf5a01340132d4bfe55997bc5c60b 40-cmpsaddr-cleanup.patch
+91eb6da2726c4ed83df990f6908a7553 50-reverse-connect.patch
+baa13d7f0f48955c792f7fcd42a8587a 60-debug-quick.patch"
diff --git a/main/ipsec-tools/racoon.confd b/main/ipsec-tools/racoon.confd
new file mode 100644
index 0000000000..66f8ed7674
--- /dev/null
+++ b/main/ipsec-tools/racoon.confd
@@ -0,0 +1,19 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-firewall/ipsec-tools/files/racoon.conf.d,v 1.3 2004/07/14 23:29:57 agriffis Exp $
+
+# Config file for /etc/init.d/racoon
+
+# See the manual pages for racoon or run `racoon --help`
+# for valid command-line options
+
+RACOON_OPTS="-4"
+
+RACOON_CONF="/etc/racoon/racoon.conf"
+RACOON_PSK_FILE="/etc/racoon/psk.txt"
+SETKEY_CONF="/etc/ipsec.conf"
+
+# Comment or remove the following if you don't want the policy tables
+# to be flushed when racoon is stopped.
+
+RACOON_RESET_TABLES="true"
diff --git a/main/ipsec-tools/racoon.initd b/main/ipsec-tools/racoon.initd
new file mode 100644
index 0000000000..16fdec7e3a
--- /dev/null
+++ b/main/ipsec-tools/racoon.initd
@@ -0,0 +1,58 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+depend() {
+ before netmount
+ use net
+}
+
+checkconfig() {
+ if [ ! -e ${SETKEY_CONF} ] ; then
+ eerror "You need to configure setkey before starting racoon."
+ return 1
+ fi
+ if [ ! -e ${RACOON_CONF} ] ; then
+ eerror "You need a configuration file to start racoon."
+ return 1
+ fi
+ if [ ! -z ${RACOON_PSK_FILE} ] ; then
+ if [ ! -f ${RACOON_PSK_FILE} ] ; then
+ eerror "PSK file not found as specified."
+ eerror "Set RACOON_PSK_FILE in /etc/conf.d/racoon."
+ return 1
+ fi
+ case "`ls -Lldn ${RACOON_PSK_FILE}`" in
+ -r--------*)
+ ;;
+ *)
+ eerror "Your defined PSK file should be mode 400 for security!"
+ return 1
+ ;;
+ esac
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ einfo "Loading ipsec policies from ${SETKEY_CONF}."
+ /usr/sbin/setkey -f ${SETKEY_CONF}
+ if [ $? -eq 1 ] ; then
+ eerror "Error while loading ipsec policies"
+ fi
+ ebegin "Starting racoon"
+ start-stop-daemon -S -x /usr/sbin/racoon -- -f ${RACOON_CONF} ${RACOON_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping racoon"
+ start-stop-daemon -K -p /var/run/racoon.pid
+ eend $?
+ if [ -n "${RACOON_RESET_TABLES}" ]; then
+ ebegin "Flushing policy entries"
+ /usr/sbin/setkey -F
+ /usr/sbin/setkey -FP
+ eend $?
+ fi
+}