From ebea7120f4299640f8a2e60b8500757826822abe Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Thu, 7 Sep 2006 12:40:03 +0000
Subject: [PATCH] upgrade isakmpd, add security fix

SVN-Revision: 4768
---
 openwrt/package/isakmpd/Makefile              |   16 +-
 .../isakmpd/patches/01-standardize.patch      |  133 --
 .../isakmpd/patches/010-debian_3.patch        | 1706 +++++++++++++++++
 .../isakmpd/patches/020-standardize.patch     |   59 +
 ..._hashes.patch => 030-openssl_hashes.patch} |    0
 .../isakmpd/patches/040-security_fix.patch    |   22 +
 6 files changed, 1796 insertions(+), 140 deletions(-)
 delete mode 100644 openwrt/package/isakmpd/patches/01-standardize.patch
 create mode 100644 openwrt/package/isakmpd/patches/010-debian_3.patch
 create mode 100644 openwrt/package/isakmpd/patches/020-standardize.patch
 rename openwrt/package/isakmpd/patches/{02-openssl_hashes.patch => 030-openssl_hashes.patch} (100%)
 create mode 100644 openwrt/package/isakmpd/patches/040-security_fix.patch

diff --git a/openwrt/package/isakmpd/Makefile b/openwrt/package/isakmpd/Makefile
index 5e268e52a0..98cb36f2c2 100644
--- a/openwrt/package/isakmpd/Makefile
+++ b/openwrt/package/isakmpd/Makefile
@@ -9,14 +9,14 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=isakmpd
-PKG_VERSION:=20040115cvs
+PKG_VERSION:=20041012
 PKG_RELEASE:=1
 
-PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
-PKG_SOURCE_URL:=http://downloads.openwrt.org/sources/
-PKG_MD5SUM:=9f59b10d57cfed5e95743255f1c1620d
-PKG_CAT:=bzcat
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION).orig
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/i/isakmpd/
+PKG_MD5SUM:=e6d25a9e232fb186e1a48dc06453bd57
+PKG_CAT:=zcat
 
 PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
 
@@ -35,8 +35,10 @@ endef
 define Build/Compile
 	$(call Build/Compile/Default,LINUX_DIR="$(LINUX_DIR)" \
 		STAGING_DIR="$(STAGING_DIR)" \
-		DESTDIR="$(PKG_INSTALL_DIR)")
+		DESTDIR="$(PKG_INSTALL_DIR)" \
+	)
 	$(MAKE) -C $(PKG_BUILD_DIR) \
+		STAGING_DIR="$(STAGING_DIR)" \
 		DESTDIR="$(PKG_INSTALL_DIR)" \
 		INSTALL="install -c" \
 		install-bin
diff --git a/openwrt/package/isakmpd/patches/01-standardize.patch b/openwrt/package/isakmpd/patches/01-standardize.patch
deleted file mode 100644
index f97c77630e..0000000000
--- a/openwrt/package/isakmpd/patches/01-standardize.patch
+++ /dev/null
@@ -1,133 +0,0 @@
-diff -urN isakmpd/GNUmakefile isakmpd.new/GNUmakefile
---- isakmpd/GNUmakefile	2004-01-16 13:36:32.000000000 +0100
-+++ isakmpd.new/GNUmakefile	2006-09-03 17:33:03.000000000 +0200
-@@ -40,12 +40,12 @@
- # integrated, freebsd/netbsd means FreeBSD/NetBSD with KAME IPsec.
- # darwin means MacOS X 10.2 and later with KAME IPsec. linux means Linux-2.5
- # and later with native IPSec support.
--OS=		openbsd
-+#OS=		openbsd
- #OS=		netbsd
- #OS=		freebsd
- #OS=		freeswan
- #OS=		darwin
--#OS=		linux
-+OS=		linux
- 
- .CURDIR:=	$(shell pwd)
- VPATH=		${.CURDIR}/sysdep/${OS}
-@@ -53,11 +53,11 @@
- PROG=		isakmpd
- 
- ifndef BINDIR
--BINDIR=		/sbin
--endif
--ifndef LDSTATIC
--LDSTATIC=	-static
-+BINDIR=		/usr/sbin
- endif
-+#ifndef LDSTATIC
-+#LDSTATIC=	-static
-+#endif
- 
- SRCS=		app.c attribute.c cert.c connection.c \
- 		constants.c conf.c cookie.c crypto.c dh.c doi.c exchange.c \
-@@ -154,7 +154,7 @@
- 
- ifdef USE_KEYNOTE
- USE_LIBCRYPTO=	yes
--LDADD+=		-lkeynote -lm
-+LDADD+=		-L${LIBKEYNOTEDIR} -lkeynote -lm
- DPADD+=		${LIBKEYNOTE} ${LIBM}
- POLICY=		policy.c
- CFLAGS+=	-DUSE_KEYNOTE
-@@ -238,3 +238,16 @@
- 
- realcleandepend:
- 	rm -f .depend tags
-+
-+# Install rules
-+install: install-bin install-man
-+
-+install-bin: isakmpd
-+	-mkdir -p $(DESTDIR)$(BINDIR)
-+	$(INSTALL) $(INSTALL_OPTS) -m 755 isakmpd $(DESTDIR)$(BINDIR)
-+
-+install-man:
-+	-mkdir -p $(DESTDIR)$(MANDIR)/man8
-+	$(INSTALL) $(INSTALL_OPTS) -m 444 isakmpd.8 $(DESTDIR)$(MANDIR)/man8
-+	-mkdir -p $(DESTDIR)$(MANDIR)/man5
-+	$(INSTALL) $(INSTALL_OPTS) -m 444 isakmpd.conf.5 isakmpd.policy.5 $(DESTDIR)$(MANDIR)/man5
-diff -urN isakmpd/samples/Makefile isakmpd.new/samples/Makefile
---- isakmpd/samples/Makefile	2003-06-03 16:39:50.000000000 +0200
-+++ isakmpd.new/samples/Makefile	2006-09-03 17:07:24.000000000 +0200
-@@ -26,7 +26,7 @@
- #
- 
- FILES=		VPN-* policy singlehost-*
--TARGETDIR=	/usr/share/ipsec/isakmpd
-+TARGETDIR=	/usr/share/isakmpd/samples
- 
- # The mkdir below is for installation on OpenBSD pre 2.7
- install:
-diff -urN isakmpd/sysdep/linux/GNUmakefile.sysdep isakmpd.new/sysdep/linux/GNUmakefile.sysdep
---- isakmpd/sysdep/linux/GNUmakefile.sysdep	2004-01-16 13:36:42.000000000 +0100
-+++ isakmpd.new/sysdep/linux/GNUmakefile.sysdep	2006-09-03 17:16:48.000000000 +0200
-@@ -25,18 +25,20 @@
- # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- #
- 
--LIBGMP:=	/usr/lib/libgmp.a
--LIBCRYPTO:=	/usr/lib/libcrypto.a
-+LIBGMP:=	-lgmp
-+LIBCRYPTO:=	-lcrypto
- LIBSYSDEPDIR:=	${.CURDIR}/sysdep/common/libsysdep
- LIBSYSDEP:=	${LIBSYSDEPDIR}/libsysdep.a
- 
--LDADD+=		-lgmp ${LIBSYSDEP} ${LIBCRYPTO}
-+LIBKEYNOTEDIR:=	$(STAGING_DIR)/usr/include
-+
-+LDADD+=		-L$(STAGING_DIR)/usr/lib ${LIBGMP} ${LIBSYSDEP} ${LIBCRYPTO}
--DPADD+=		${LIBGMP} ${LIBSYSDEP}
-+DPADD+=		${LIBSYSDEP}
- 
- CFLAGS+=	-DHAVE_GETNAMEINFO -DUSE_OLD_SOCKADDR -DHAVE_PCAP \
- 		-DNEED_SYSDEP_APP -DMP_FLAVOUR=MP_FLAVOUR_GMP \
--		-I/usr/src/linux/include -I${.CURDIR}/sysdep/common \
--		-I/usr/include/openssl
-+		-I$(LINUX_DIR)/include -I${.CURDIR}/sysdep/common \
-+		-I$(STAGING_DIR)/usr/include/openssl -I${LIBKEYNOTEDIR}
- 
- FEATURES=	debug tripledes blowfish cast ec aggressive x509 policy
- 
-@@ -50,7 +52,7 @@
- # hack libsysdep.a dependenc
- ${LIBSYSDEPDIR}/.depend ${LIBSYSDEP}:
- 	cd ${LIBSYSDEPDIR} && \
--		${MAKE} --no-print-directory ${MAKEFLAGS} \
-+		${MAKE} --no-print-directory \
- 			CFLAGS="${CFLAGS}" MKDEP="${MKDEP}" ${MAKECMDGOALS}
- 
- ifeq ($(findstring clean,$(MAKECMDGOALS)),clean)
-diff -urN isakmpd/x509.c isakmpd.new/x509.c
---- isakmpd/x509.c	2004-01-06 01:09:19.000000000 +0100
-+++ isakmpd.new/x509.c	2006-09-03 17:07:24.000000000 +0200
-@@ -969,14 +969,14 @@
-    * trust.
-    */
-   X509_STORE_CTX_init (&csc, x509_cas, cert, NULL);
--#if OPENSSL_VERSION_NUMBER >= 0x00907000L
--  /* XXX See comment in x509_read_crls_from_dir.  */
--  if (x509_cas->flags & X509_V_FLAG_CRL_CHECK)
-+//#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-+    /* XXX See comment in x509_read_crls_from_dir.  */
-+   /*if (x509_cas->flags & X509_V_FLAG_CRL_CHECK)
-     {
-       X509_STORE_CTX_set_flags (&csc, X509_V_FLAG_CRL_CHECK);
-       X509_STORE_CTX_set_flags (&csc, X509_V_FLAG_CRL_CHECK_ALL);
-     }
--#endif
-+#endif */
-   res = X509_verify_cert (&csc);
-   err = csc.error;
-   X509_STORE_CTX_cleanup (&csc);
diff --git a/openwrt/package/isakmpd/patches/010-debian_3.patch b/openwrt/package/isakmpd/patches/010-debian_3.patch
new file mode 100644
index 0000000000..551ae1ffcd
--- /dev/null
+++ b/openwrt/package/isakmpd/patches/010-debian_3.patch
@@ -0,0 +1,1706 @@
+--- isakmpd-20041012.orig/dpd.c
++++ isakmpd-20041012/dpd.c
+@@ -26,6 +26,7 @@
+ 
+ #include <sys/types.h>
+ #include <stdlib.h>
++#include <memory.h>
+ 
+ #include "sysdep.h"
+ 
+@@ -174,6 +175,7 @@
+ 		}
+ 		break;
+ 	default:
++	;
+ 	}
+ 
+ 	/* Mark handled.  */
+@@ -223,6 +225,7 @@
+ 		    dpd_check_event, sa, &tv);
+ 		break;
+ 	default:
++	;
+ 	}
+ 	if (!sa->dpd_event) 
+ 		log_print("dpd_timer_reset: timer_add_event failed");
+--- isakmpd-20041012.orig/ipsec.c
++++ isakmpd-20041012/ipsec.c
+@@ -1020,6 +1020,52 @@
+ 	}
+ }
+ 
++/*
++ * deal with a NOTIFY of INVALID_SPI
++ */
++static void
++ipsec_invalid_spi (struct message *msg, struct payload *p)
++{
++  struct sockaddr *dst;
++  int invspisz, off;
++  u_int32_t spi;
++  u_int16_t totsiz;
++  u_int8_t spisz;
++
++  /* Any notification that make us do something should be protected */
++  if(!TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]))
++    {
++      LOG_DBG ((LOG_SA, 40,
++      	       "ipsec_invalid_spi: missing HASH payload in INVALID_SPI"
++      	       " notification"));
++      return;
++    }
++
++  /*
++   * get the invalid spi out of the variable sized notification data
++   * field, which is after the variable sized SPI field [which specifies
++   * the receiving entity's phase-1 SPI, not the invalid spi]
++   */
++  totsiz = GET_ISAKMP_GEN_LENGTH (p->p);
++  spisz = GET_ISAKMP_NOTIFY_SPI_SZ (p->p);
++  off = ISAKMP_NOTIFY_SPI_OFF + spisz;
++  invspisz = totsiz - off;
++
++  if (invspisz != sizeof spi)
++    {
++      LOG_DBG ((LOG_SA, 40,
++	       "ipsec_invalid_spi: SPI size %d in INVALID_SPI "
++	       "payload unsupported", spisz));
++       return;
++    }
++  memcpy (&spi, p->p + off, sizeof spi);
++
++  msg->transport->vtbl->get_dst (msg->transport, &dst);
++
++  /* delete matching SPI's from this peer */
++  ipsec_delete_spi_list (dst, 0, (u_int8_t *)&spi, 1, "INVALID_SPI");
++}
++
+ static int
+ ipsec_responder(struct message *msg)
+ {
+@@ -1205,7 +1251,9 @@
+ 			return dv != IPSEC_ENCAP_TUNNEL
+ 			    && dv != IPSEC_ENCAP_TRANSPORT
+ 			    && dv != IPSEC_ENCAP_UDP_ENCAP_TUNNEL
+-			    && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT;
++			    && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT
++			    && dv != IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT
++			    && dv != IPSEC_ENCAP_UDP_ENCAP_TRANSPORT_DRAFT;
+ #else
+ 			return dv < IPSEC_ENCAP_TUNNEL
+ 			    || dv > IPSEC_ENCAP_TRANSPORT;
+@@ -1837,7 +1885,7 @@
+ ipsec_get_id(char *section, int *id, struct sockaddr **addr,
+     struct sockaddr **mask, u_int8_t *tproto, u_int16_t *port)
+ {
+-	char	*type, *address, *netmask;
++    char	*type, *address, *netmask;
+ 
+ 	type = conf_get_str(section, "ID-type");
+ 	if (!type) {
+--- isakmpd-20041012.orig/GNUmakefile
++++ isakmpd-20041012/GNUmakefile
+@@ -40,12 +40,12 @@
+ # integrated, freebsd/netbsd means FreeBSD/NetBSD with KAME IPsec.
+ # darwin means MacOS X 10.2 and later with KAME IPsec. linux means Linux-2.5
+ # and later with native IPSec support.
+-OS=		openbsd
++#OS=		openbsd
+ #OS=		netbsd
+ #OS=		freebsd
+ #OS=		freeswan
+ #OS=		darwin
+-#OS=		linux
++OS=		linux
+ 
+ .CURDIR:=	$(shell pwd)
+ VPATH=		${.CURDIR}/sysdep/${OS}
+@@ -55,9 +55,10 @@
+ ifndef BINDIR
+ BINDIR=		/sbin
+ endif
+-ifndef LDSTATIC
+-LDSTATIC=	-static
+-endif
++
++#ifndef LDSTATIC
++#LDSTATIC=	-static
++#endif
+ 
+ SRCS=		app.c attribute.c cert.c connection.c \
+ 		constants.c conf.c cookie.c crypto.c dh.c doi.c exchange.c \
+@@ -131,11 +132,14 @@
+ ifneq ($(findstring install,$(MAKECMDGOALS)),install)
+ # Skip 'regress' until the regress/ structure has gmake makefiles for it.
+ #SUBDIR:=	regress
+-SUBDIR:=
++#SUBDIR:=	apps/certpatch
+ mksubdirs:
+ 	$(foreach DIR, ${SUBDIR}, \
+-		cd ${DIR}; ${MAKE} ${MAKEFLAGS} CFLAGS="${CFLAGS}" \
+-			MKDEP="${MKDEP}" ${MAKECMDGOALS})
++		cd ${.CURDIR}/${DIR}; ${MAKE} ${MAKECMDGOALS};)
++		
++#	$(foreach DIR, ${SUBDIR}, \
++#		cd ${DIR}; ${MAKE} CFLAGS="${CFLAGS}" \
++#			MKDEP="${MKDEP}" ${MAKECMDGOALS})
+ else
+ mksubdirs:
+ endif
+@@ -173,7 +177,7 @@
+ endif
+ 
+ SRCS+=		${IPSEC_SRCS} ${X509} ${POLICY} ${EC} ${AGGRESSIVE} ${DNSSEC} \
+-		$(ISAKMP_CFG)
++			$(ISAKMP_CFG) ${DPD} ${NAT_TRAVERSAL}
+ CFLAGS+=	${IPSEC_CFLAGS}
+ LDADD+=		${DESLIB}
+ DPADD+=		${DESLIBDEP}
+--- isakmpd-20041012.orig/exchange.h
++++ isakmpd-20041012/exchange.h
+@@ -221,6 +221,8 @@
+ #define EXCHANGE_FLAG_NAT_T_ENABLE	0x10	/* We are doing NAT-T.  */
+ #define EXCHANGE_FLAG_NAT_T_KEEPALIVE	0x20	/* We are the NAT:ed peer.  */
+ #define EXCHANGE_FLAG_DPD_CAP_PEER	0x40	/* Peer is DPD capable.  */
++#define EXCHANGE_FLAG_NAT_T_RFC		0x0080	/* Peer does RFC NAT-T. */
++#define EXCHANGE_FLAG_NAT_T_DRAFT	0x0100	/* Peer does draft NAT-T.*/
+ 
+ extern int      exchange_add_certs(struct message *);
+ extern void     exchange_finalize(struct message *);
+--- isakmpd-20041012.orig/log.c
++++ isakmpd-20041012/log.c
+@@ -79,7 +79,6 @@
+ 
+ struct packhdr {
+ 	struct pcap_pkthdr pcap;/* pcap file packet header */
+-	u_int32_t sa_family;	/* address family */
+ 	union {
+ 		struct ip       ip4;	/* IPv4 header (w/o options) */
+ 		struct ip6_hdr  ip6;	/* IPv6 header */
+@@ -97,7 +96,7 @@
+ static u_int8_t *packet_buf = NULL;
+ 
+ static int      udp_cksum(struct packhdr *, const struct udphdr *,
+-    u_int16_t *);
++    u_int16_t *, int);
+ static u_int16_t in_cksum(const u_int16_t *, int);
+ #endif				/* USE_DEBUG */
+ 
+@@ -539,11 +538,9 @@
+ 	udp.uh_ulen = htons(datalen);
+ 
+ 	/* ip */
+-	hdr.sa_family = htonl(src->sa_family);
+ 	switch (src->sa_family) {
+ 	default:
+ 		/* Assume IPv4. XXX Can 'default' ever happen here?  */
+-		hdr.sa_family = htonl(AF_INET);
+ 		hdr.ip.ip4.ip_src.s_addr = 0x02020202;
+ 		hdr.ip.ip4.ip_dst.s_addr = 0x01010101;
+ 		/* The rest of the setup is common to AF_INET.  */
+@@ -584,9 +581,7 @@
+ 	}
+ 
+ 	/* Calculate UDP checksum.  */
+-	udp.uh_sum = udp_cksum(&hdr, &udp, (u_int16_t *) packet_buf);
+-	hdrlen += sizeof hdr.sa_family;
+-
++	udp.uh_sum = udp_cksum(&hdr, &udp, (u_int16_t *) packet_buf, src->sa_family);
+ 	/* pcap file packet header */
+ 	gettimeofday(&tv, 0);
+ 	hdr.pcap.ts.tv_sec = tv.tv_sec;
+@@ -610,7 +605,7 @@
+ 
+ /* Copied from tcpdump/print-udp.c, mostly rewritten.  */
+ static int
+-udp_cksum(struct packhdr *hdr, const struct udphdr *u, u_int16_t *d)
++udp_cksum(struct packhdr *hdr, const struct udphdr *u, u_int16_t *d, int af)
+ {
+ 	struct ip	*ip4;
+ 	struct ip6_hdr	*ip6;
+@@ -639,7 +634,7 @@
+ 
+ 	/* Setup pseudoheader.  */
+ 	memset(phu.pa, 0, sizeof phu);
+-	switch (ntohl(hdr->sa_family)) {
++	switch (af) {
+ 	case AF_INET:
+ 		ip4 = &hdr->ip.ip4;
+ 		memcpy(&phu.ip4p.src, &ip4->ip_src, sizeof(struct in_addr));
+@@ -664,7 +659,7 @@
+ 
+ 	/* IPv6 wants a 0xFFFF checksum "on error", not 0x0.  */
+ 	if (tlen < 0)
+-		return (ntohl(hdr->sa_family) == AF_INET ? 0 : 0xFFFF);
++		return (af == AF_INET ? 0 : 0xFFFF);
+ 
+ 	sum = 0;
+ 	for (i = 0; i < hdrlen; i += 2)
+--- isakmpd-20041012.orig/nat_traversal.c
++++ isakmpd-20041012/nat_traversal.c
+@@ -1,4 +1,4 @@
+-/*	$OpenBSD: nat_traversal.c,v 1.7 2004/08/08 19:11:06 deraadt Exp $	*/
++/*	$OpenBSD: nat_traversal.c,v 1.17 2006/06/14 14:03:33 hshoexer Exp $	*/
+ 
+ /*
+  * Copyright (c) 2004 Håkan Olsson.  All rights reserved.
+@@ -48,40 +48,40 @@
+ #include "util.h"
+ #include "virtual.h"
+ 
++int	disable_nat_t = 0;
++
+ /*
+- * XXX According to draft-ietf-ipsec-nat-t-ike-07.txt, the NAT-T
+- * capability of the other peer is determined by a particular vendor ID
+- * sent as the first message. This vendor ID string is supposed to be a
+- * MD5 hash of "RFC XXXX", where XXXX is the future RFC number.
++ * NAT-T capability of the other peer is determined by a particular vendor
++ * ID sent in the first message. This vendor ID string is supposed to be a
++ * MD5 hash of "RFC 3947".
+  *
+  * These seem to be the "well" known variants of this string in use by
+  * products today.
+  */
+-static const char *isakmp_nat_t_cap_text[] = {
+-	"draft-ietf-ipsec-nat-t-ike-00",	/* V1 (XXX: may be obsolete) */
+-	"draft-ietf-ipsec-nat-t-ike-02\n",	/* V2 */
+-	"draft-ietf-ipsec-nat-t-ike-03",	/* V3 */
+-#ifdef notyet
+-	"RFC XXXX",
+-#endif
++
++static struct nat_t_cap isakmp_nat_t_cap[] = {
++	{ VID_DRAFT_V2_N, EXCHANGE_FLAG_NAT_T_DRAFT,
++	  "draft-ietf-ipsec-nat-t-ike-02\n", NULL, 0 },
++	{ VID_DRAFT_V3, EXCHANGE_FLAG_NAT_T_DRAFT,
++	  "draft-ietf-ipsec-nat-t-ike-03", NULL, 0 },
++	{ VID_RFC3947, EXCHANGE_FLAG_NAT_T_RFC,
++	  "RFC 3947", NULL, 0 },
+ };
+ 
++#define NUMNATTCAP	(sizeof isakmp_nat_t_cap / sizeof isakmp_nat_t_cap[0])
++
+ /* In seconds. Recommended in draft-ietf-ipsec-udp-encaps-09.  */
+ #define NAT_T_KEEPALIVE_INTERVAL	20
+ 
+-/* The MD5 hashes of the above strings is put in this array.  */
+-static char	**nat_t_hashes;
+-static size_t	  nat_t_hashsize;
+-
+ static int	nat_t_setup_hashes(void);
+-static int	nat_t_add_vendor_payload(struct message *, char *);
++static int	nat_t_add_vendor_payload(struct message *, struct nat_t_cap *);
+ static int	nat_t_add_nat_d(struct message *, struct sockaddr *);
+ static int	nat_t_match_nat_d_payload(struct message *, struct sockaddr *);
+ 
+ void
+ nat_t_init(void)
+ {
+-	nat_t_hashes = (char **)NULL;
++	nat_t_setup_hashes();
+ }
+ 
+ /* Generate the NAT-T capability marker hashes. Executed only once.  */
+@@ -89,7 +89,7 @@
+ nat_t_setup_hashes(void)
+ {
+ 	struct hash *hash;
+-	int n = sizeof isakmp_nat_t_cap_text / sizeof isakmp_nat_t_cap_text[0];
++	int n = NUMNATTCAP;
+ 	int i;
+ 
+ 	/* The draft says to use MD5.  */
+@@ -100,56 +100,49 @@
+ 		    "could not find MD5 hash structure!");
+ 		return -1;
+ 	}
+-	nat_t_hashsize = hash->hashsize;
+ 
+-	/* Allocate one more than is necessary, i.e NULL terminated.  */
+-	nat_t_hashes = (char **)calloc((size_t)(n + 1), sizeof(char *));
+-	if (!nat_t_hashes) {
+-		log_error("nat_t_setup_hashes: calloc (%lu,%lu) failed",
+-		    (unsigned long)n, (unsigned long)sizeof(char *));
+-		return -1;
+-	}
+-
+-	/* Populate with hashes.  */
++	/* Populate isakmp_nat_t_cap with hashes.  */
+ 	for (i = 0; i < n; i++) {
+-		nat_t_hashes[i] = (char *)malloc(nat_t_hashsize);
+-		if (!nat_t_hashes[i]) {
++		isakmp_nat_t_cap[i].hashsize = hash->hashsize;
++		isakmp_nat_t_cap[i].hash = (char *)malloc(hash->hashsize);
++		if (!isakmp_nat_t_cap[i].hash) {
+ 			log_error("nat_t_setup_hashes: malloc (%lu) failed",
+-			    (unsigned long)nat_t_hashsize);
++			    (unsigned long)hash->hashsize);
+ 			goto errout;
+ 		}
+ 
+ 		hash->Init(hash->ctx);
+ 		hash->Update(hash->ctx,
+-		    (unsigned char *)isakmp_nat_t_cap_text[i],
+-		    strlen(isakmp_nat_t_cap_text[i]));
+-		hash->Final(nat_t_hashes[i], hash->ctx);
++		    (unsigned char *)isakmp_nat_t_cap[i].text,
++		    strlen(isakmp_nat_t_cap[i].text));
++		hash->Final(isakmp_nat_t_cap[i].hash, hash->ctx);
+ 
+ 		LOG_DBG((LOG_EXCHANGE, 50, "nat_t_setup_hashes: "
+-		    "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap_text[i],
+-		    (unsigned long)nat_t_hashsize));
++		    "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap[i].text,
++		    (unsigned long)hash->hashsize));
+ 		LOG_DBG_BUF((LOG_EXCHANGE, 50, "nat_t_setup_hashes",
+-		    nat_t_hashes[i], nat_t_hashsize));
++		    isakmp_nat_t_cap[i].hash, hash->hashsize));
+ 	}
+ 
+ 	return 0;
+ 
+-  errout:
++errout:
+ 	for (i = 0; i < n; i++)
+-		if (nat_t_hashes[i])
+-			free(nat_t_hashes[i]);
+-	free(nat_t_hashes);
+-	nat_t_hashes = NULL;
++		if (isakmp_nat_t_cap[i].hash)
++			free(isakmp_nat_t_cap[i].hash);
+ 	return -1;
+ }
+ 
+ /* Add one NAT-T VENDOR payload.  */
+ static int
+-nat_t_add_vendor_payload(struct message *msg, char *hash)
++nat_t_add_vendor_payload(struct message *msg, struct nat_t_cap *cap)
+ {
+-	size_t	 buflen = nat_t_hashsize + ISAKMP_GEN_SZ;
++	size_t	  buflen = cap->hashsize + ISAKMP_GEN_SZ;
+ 	u_int8_t *buf;
+ 
++	if (disable_nat_t)
++		return 0;
++
+ 	buf = malloc(buflen);
+ 	if (!buf) {
+ 		log_error("nat_t_add_vendor_payload: malloc (%lu) failed",
+@@ -158,12 +151,11 @@
+ 	}
+ 
+ 	SET_ISAKMP_GEN_LENGTH(buf, buflen);
+-	memcpy(buf + ISAKMP_VENDOR_ID_OFF, hash, nat_t_hashsize);
++	memcpy(buf + ISAKMP_VENDOR_ID_OFF, cap->hash, cap->hashsize);
+ 	if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, buflen, 1)) {
+ 		free(buf);
+ 		return -1;
+ 	}
+-
+ 	return 0;
+ }
+ 
+@@ -171,16 +163,14 @@
+ int
+ nat_t_add_vendor_payloads(struct message *msg)
+ {
+-	int i = 0;
++	int i;
+ 
+-	if (!nat_t_hashes)
+-		if (nat_t_setup_hashes())
+-			return 0;  /* XXX should this be an error?  */
++	if (disable_nat_t)
++		return 0;
+ 
+-	while (nat_t_hashes[i])
+-		if (nat_t_add_vendor_payload(msg, nat_t_hashes[i++]))
++	for (i = 0; i < NUMNATTCAP; i++)
++		if (nat_t_add_vendor_payload(msg, &isakmp_nat_t_cap[i]))
+ 			return -1;
+-
+ 	return 0;
+ }
+ 
+@@ -192,36 +182,31 @@
+ {
+ 	u_int8_t *pbuf = p->p;
+ 	size_t	  vlen;
+-	int	  i = 0;
++	int	  i;
+ 
+-	/* Already checked? */
+-	if (p->flags & PL_MARK ||
+-	    msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER)
++	if (disable_nat_t)
+ 		return;
+ 
+-	if (!nat_t_hashes)
+-		if (nat_t_setup_hashes())
+-			return;
+-
+ 	vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ;
+-	if (vlen != nat_t_hashsize) {
+-		LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: "
+-		    "bad size %lu != %lu", (unsigned long)vlen,
+-		    (unsigned long)nat_t_hashsize));
+-		return;
+-	}
+ 
+-	while (nat_t_hashes[i])
+-		if (memcmp(nat_t_hashes[i++], pbuf + ISAKMP_GEN_SZ,
++	for (i = 0; i < NUMNATTCAP; i++) {
++		if (vlen != isakmp_nat_t_cap[i].hashsize) {
++			LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: "
++			    "bad size %lu != %lu", (unsigned long)vlen,
++			    (unsigned long)isakmp_nat_t_cap[i].hashsize));
++			continue;
++		}
++		if (memcmp(isakmp_nat_t_cap[i].hash, pbuf + ISAKMP_GEN_SZ,
+ 		    vlen) == 0) {
+ 			/* This peer is NAT-T capable.  */
+ 			msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER;
++			msg->exchange->flags |= isakmp_nat_t_cap[i].flags;
+ 			LOG_DBG((LOG_EXCHANGE, 10,
+ 			    "nat_t_check_vendor_payload: "
+ 			    "NAT-T capable peer detected"));
+ 			p->flags |= PL_MARK;
+-			return;
+ 		}
++	}
+ 
+ 	return;
+ }
+@@ -233,10 +218,8 @@
+ {
+ 	struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data;
+ 	struct hash	 *hash;
+-	struct prf	 *prf;
+ 	u_int8_t	 *res;
+ 	in_port_t	  port;
+-	int		  prf_type = PRF_HMAC; /* XXX */
+ 
+ 	hash = hash_get(ie->hash->type);
+ 	if (hash == NULL) {
+@@ -244,31 +227,25 @@
+ 		return NULL;
+ 	}
+ 
+-	prf = prf_alloc(prf_type, hash->type, msg->exchange->cookies,
+-	    ISAKMP_HDR_COOKIES_LEN);
+-	if(!prf) {
+-		log_print("nat_t_generate_nat_d_hash: prf_alloc failed");
+-		return NULL;
+-	}
++	*hashlen = hash->hashsize;
+ 
+-	*hashlen = prf->blocksize;
+ 	res = (u_int8_t *)malloc((unsigned long)*hashlen);
+ 	if (!res) {
+ 		log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed",
+ 		    (unsigned long)*hashlen);
+-		prf_free(prf);
+ 		*hashlen = 0;
+ 		return NULL;
+ 	}
+ 
+ 	port = sockaddr_port(sa);
+-	memset(res, 0, *hashlen);
+-
+-	prf->Update(prf->prfctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa));
+-	prf->Update(prf->prfctx, (unsigned char *)&port, sizeof port);
+-	prf->Final(res, prf->prfctx);
+-	prf_free (prf);
++	bzero(res, *hashlen);
+ 
++	hash->Init(hash->ctx);
++	hash->Update(hash->ctx, msg->exchange->cookies,
++	    sizeof msg->exchange->cookies);
++	hash->Update(hash->ctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa));
++	hash->Update(hash->ctx, (unsigned char *)&port, sizeof port);
++	hash->Final(res, hash->ctx);
+ 	return res;
+ }
+ 
+@@ -276,6 +253,7 @@
+ static int
+ nat_t_add_nat_d(struct message *msg, struct sockaddr *sa)
+ {
++	int	  ret;
+ 	u_int8_t *hbuf, *buf;
+ 	size_t	  hbuflen, buflen;
+ 
+@@ -298,11 +276,19 @@
+ 	memcpy(buf + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen);
+ 	free(hbuf);
+ 
+-	if (message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf, buflen, 1)) {
++	if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_RFC)
++		ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf,
++		    buflen, 1);
++	else if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT)
++		ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT,
++		    buf, buflen, 1);
++	else
++		ret = -1;
++		
++	if (ret) {
+ 		free(buf);
+ 		return -1;
+ 	}
+-
+ 	return 0;
+ }
+ 
+@@ -312,14 +298,14 @@
+ {
+ 	struct sockaddr *sa;
+ 
+-	msg->transport->vtbl->get_src(msg->transport, &sa);
++	/* Remote address first. */
++	msg->transport->vtbl->get_dst(msg->transport, &sa);
+ 	if (nat_t_add_nat_d(msg, sa))
+ 		return -1;
+ 
+-	msg->transport->vtbl->get_dst(msg->transport, &sa);
++	msg->transport->vtbl->get_src(msg->transport, &sa);
+ 	if (nat_t_add_nat_d(msg, sa))
+ 		return -1;
+-
+ 	return 0;
+ }
+ 
+@@ -336,8 +322,8 @@
+ 	 * If there are no NAT-D payloads in the message, return "found"
+ 	 * as this will avoid NAT-T (see nat_t_exchange_check_nat_d()).
+ 	 */
+-	p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D);
+-	if (!p)
++	if ((p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT)) == NULL &&
++	    (p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D)) == NULL)
+ 		return 1;
+ 
+ 	hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen);
+--- isakmpd-20041012.orig/udp_encap.c
++++ isakmpd-20041012/udp_encap.c
+@@ -61,6 +61,11 @@
+ 
+ #define UDP_SIZE 65536
+ 
++#if defined(USE_NAT_TRAVERSAL) && defined (LINUX_IPSEC)
++#include <linux/socket.h>
++#include <linux/udp.h>
++#endif
++
+ /* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do.  */
+ #ifndef SO_REUSEPORT
+ #define SO_REUSEPORT SO_REUSEADDR
+@@ -134,6 +139,18 @@
+ 	if (sysdep_cleartext(s, laddr->sa_family) == -1)
+ 		goto err;
+ 
++#if defined(USE_NAT_TRAVERSAL) && defined (LINUX_IPSEC)
++    {
++#ifndef SOL_UDP
++#define SOL_UDP 17
++#endif
++        int option = UDP_ENCAP_ESPINUDP;
++        if(setsockopt(s, SOL_UDP, UDP_ENCAP, &option,
++                      sizeof (option)) < 0)
++            goto err;
++    }
++#endif
++
+ 	/* Wildcard address ?  */
+ 	switch (laddr->sa_family) {
+ 	case AF_INET:
+--- isakmpd-20041012.orig/apps/Makefile
++++ isakmpd-20041012/apps/Makefile
+@@ -31,4 +31,4 @@
+ 
+ SUBDIR= certpatch
+ 
+-.include <bsd.subdir.mk>
++#.include <bsd.subdir.mk>
+--- isakmpd-20041012.orig/apps/certpatch/GNUmakefile
++++ isakmpd-20041012/apps/certpatch/GNUmakefile
+@@ -0,0 +1,55 @@
++#	$OpenBSD: Makefile,v 1.7 2003/06/03 14:35:00 ho Exp $
++#	$EOM: Makefile,v 1.6 2000/03/28 21:22:06 ho Exp $
++
++#
++# Copyright (c) 1999 Niels Provos.  All rights reserved.
++# Copyright (c) 2001 Niklas Hallqvist.  All rights reserved.
++#
++# Redistribution and use in source and binary forms, with or without
++# modification, are permitted provided that the following conditions
++# are met:
++# 1. Redistributions of source code must retain the above copyright
++#    notice, this list of conditions and the following disclaimer.
++# 2. Redistributions in binary form must reproduce the above copyright
++#    notice, this list of conditions and the following disclaimer in the
++#    documentation and/or other materials provided with the distribution.
++#
++# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++#
++
++#
++# This code was written under funding by Ericsson Radio Systems.
++#
++
++PROG=		certpatch
++SRCS=		certpatch.c
++BINDIR?=	/usr/sbin
++TOPSRC=		${.CURDIR}../..
++TOPOBJ!=	cd ${TOPSRC}; printf "all:\n\t@pwd\n" |${MAKE} -f-
++OS=			linux
++FEATURES!=	awk '/^FEATURES=/ { print $$0 }' ${.CURDIR}/../../Makefile | sed 's/FEATURES=.//'
++.PATH:		${TOPSRC} ${TOPSRC}/sysdep/${OS} ${TOPOBJ}
++CFLAGS+=	-I${TOPSRC} -I${TOPSRC}/sysdep/${OS} -I${TOPOBJ} -Wall
++LDFLAGS+=	-lcrypto -lssl -lgmp
++MAN=		certpatch.8
++
++CFLAGS+=	-DMP_FLAVOUR=MP_FLAVOUR_GMP
++LDADD+=		-lgmp
++DPADD+=		${LIBGMP}
++
++# Override LIBSYSDEPDIR definition from Makefile.sysdep
++LIBSYSDEPDIR=	${TOPSRC}/sysdep/common/libsysdep
++
++all:	${PROG}
++
++clean:	
++	rm -f ${PROG}
+--- isakmpd-20041012.orig/pf_key_v2.c
++++ isakmpd-20041012/pf_key_v2.c
+@@ -1055,6 +1055,10 @@
+ #endif
+ #if defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_UDPENCAP)
+ 	struct sadb_x_udpencap udpencap;
++#elif defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_NAT_T_TYPE)
++	struct sadb_x_nat_t_type nat_t_type;
++	struct sadb_x_nat_t_port nat_t_sport;
++	struct sadb_x_nat_t_port nat_t_dport;
+ #endif
+ #ifdef USE_DEBUG
+ 	char           *addr_str;
+@@ -1273,10 +1277,15 @@
+ 		log_print("pf_key_v2_set_spi: invalid proto %d", proto->proto);
+ 		goto cleanup;
+ 	}
+-	if (incoming)
++	if (incoming) {
+ 		sa->transport->vtbl->get_src(sa->transport, &dst);
+-	else
++		sa->transport->vtbl->get_dst(sa->transport, &src);
++	}
++	else {
+ 		sa->transport->vtbl->get_dst(sa->transport, &dst);
++		sa->transport->vtbl->get_src(sa->transport, &src);
++	}
++
+ #ifdef KAME
+ 	msg.sadb_msg_seq = (incoming ?
+ 	    pf_key_v2_seq_by_sa(proto->spi[incoming], sizeof ssa.sadb_sa_spi,
+@@ -1319,12 +1328,13 @@
+ 	ssa.sadb_sa_flags = 0;
+ #ifdef SADB_X_SAFLAGS_TUNNEL
+ 	if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL ||
+-	    iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL)
++	    iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL ||
++	    iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT)
+ 		ssa.sadb_sa_flags = SADB_X_SAFLAGS_TUNNEL;
+ #endif
+ 
+-#if defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_UDPENCAP)
+ 	if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE) {
++#if defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_UDPENCAP)
+ 		memset(&udpencap, 0, sizeof udpencap);
+ 		ssa.sadb_sa_flags |= SADB_X_SAFLAGS_UDPENCAP;
+ 		udpencap.sadb_x_udpencap_exttype = SADB_X_EXT_UDPENCAP;
+@@ -1334,8 +1344,40 @@
+ 		if (pf_key_v2_msg_add(update, (struct sadb_ext *)&udpencap, 0)
+ 		    == -1)
+ 			goto cleanup;
+-	}
++#elif defined (USE_NAT_TRAVERSAL) && defined (SADB_X_EXT_NAT_T_TYPE)
++#ifndef UDP_ENCAP_ESPINUDP
++#define UDP_ENCAP_ESPINUDP	2
++#endif
++		memset(&nat_t_type, 0, sizeof nat_t_type);
++		memset(&nat_t_sport, 0, sizeof nat_t_sport);
++		memset(&nat_t_dport, 0, sizeof nat_t_dport);
++
++		/* type = draft-udp-encap-06 */
++		nat_t_type.sadb_x_nat_t_type_len = sizeof nat_t_type / PF_KEY_V2_CHUNK;
++		nat_t_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
++		nat_t_type.sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP;
++		if(pf_key_v2_msg_add(update, (struct sadb_ext *)&nat_t_type, 0) == -1)
++			goto cleanup;
++
++		/* source port */
++		nat_t_sport.sadb_x_nat_t_port_len = sizeof nat_t_sport / 
++		                                           PF_KEY_V2_CHUNK;
++		nat_t_sport.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
++		nat_t_sport.sadb_x_nat_t_port_port = sockaddr_port(src);
++		if(pf_key_v2_msg_add(update, (struct sadb_ext *)&nat_t_sport, 0) == -1)
++			goto cleanup;
++
++		/* destination port */
++		nat_t_dport.sadb_x_nat_t_port_len = sizeof nat_t_dport / 
++		                                           PF_KEY_V2_CHUNK;
++		nat_t_dport.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
++		nat_t_dport.sadb_x_nat_t_port_port = sockaddr_port(dst);
++		if(pf_key_v2_msg_add(update, (struct sadb_ext *)&nat_t_dport, 0) == -1)
++			goto cleanup;
++
++		/* original address (transport mode checksum missing info) goes here */
+ #endif
++    }
+ 
+ 	if (pf_key_v2_msg_add(update, (struct sadb_ext *)&ssa, 0) == -1)
+ 		goto cleanup;
+@@ -1395,10 +1437,6 @@
+ 	/*
+ 	 * Setup the ADDRESS extensions.
+          */
+-	if (incoming)
+-		sa->transport->vtbl->get_dst(sa->transport, &src);
+-	else
+-		sa->transport->vtbl->get_src(sa->transport, &src);
+ 	len = sizeof *addr + PF_KEY_V2_ROUND(sysdep_sa_len(src));
+ 	addr = calloc(1, len);
+ 	if (!addr)
+@@ -2167,7 +2205,7 @@
+ 		pf_key_v2_msg_free(ret);
+ 	return -1;
+ 
+-#elif defined (SADB_X_SPDADD) && defined (SADB_X_SPDDELETE)
++#elif defined (SADB_X_SPDUPDATE) && defined (SADB_X_SPDDELETE)
+ 	struct sadb_msg msg;
+ 	struct sadb_x_policy *policy = 0;
+ 	struct sadb_x_ipsecrequest *ipsecrequest;
+@@ -2181,7 +2219,7 @@
+ 	struct sockaddr_in *ip4_sa;
+ 	struct sockaddr_in6 *ip6_sa;
+ 
+-	msg.sadb_msg_type = delete ? SADB_X_SPDDELETE : SADB_X_SPDADD;
++	msg.sadb_msg_type = delete ? SADB_X_SPDDELETE : SADB_X_SPDUPDATE;
+ 	msg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ 	msg.sadb_msg_seq = 0;
+ 	flow = pf_key_v2_msg_new(&msg, 0);
+--- isakmpd-20041012.orig/isakmp_num.cst
++++ isakmpd-20041012/isakmp_num.cst
+@@ -57,15 +57,18 @@
+   KD				17	# RFC 3547, Key Download
+   SEQ				18	# RFC 3547, Sequence Number
+   POP				19	# RFC 3547, Proof of possession
+-  RESERVED_MIN			20
++  NAT_D				20	# RFC 3947, NAT Discovery payload
++  NAT_OA			21	# RFC 3947, NAT Original Address payload
++  RESERVED_MIN			22
+   RESERVED_MAX			127
+   PRIVATE_MIN			128
+ # XXX values from draft-ietf-ipsec-nat-t-ike-01,02,03. Later drafts specify
+ # XXX NAT_D as payload 15 and NAT_OA as 16, but these are allocated by RFC
+ # XXX 3547 as seen above.
+-  NAT_D				130	# NAT Discovery payload
+-  NAT_OA			131	# NAT Original Address payload
++  NAT_D_DRAFT			130	# NAT Discovery payload
++  NAT_OA_DRAFT			131	# NAT Original Address payload
+   PRIVATE_MAX			255
++  MAX				255
+ .
+ 
+ # ISAKMP exchange types.
+--- isakmpd-20041012.orig/ipsec_num.cst
++++ isakmpd-20041012/ipsec_num.cst
+@@ -62,10 +62,10 @@
+ IPSEC_ENCAP
+   TUNNEL				1
+   TRANSPORT				2
+-  FUTURE_UDP_ENCAP_TUNNEL		3	# XXX Not yet assigned
+-  FUTURE_UDP_ENCAP_TRANSPORT		4	# XXX Not yet assigned
+-  UDP_ENCAP_TUNNEL			61443	# draft-ietf-ipsec-nat-t-ike
+-  UDP_ENCAP_TRANSPORT			61443	# draft-ietf-ipsec-nat-t-ike
++  UDP_ENCAP_TUNNEL			3
++  UDP_ENCAP_TRANSPORT			4
++  UDP_ENCAP_TUNNEL_DRAFT		61443	# draft-ietf-ipsec-nat-t-ike
++  UDP_ENCAP_TRANSPORT_DRAFT		61443	# draft-ietf-ipsec-nat-t-ike
+ .
+ 
+ # IPSEC authentication algorithm.
+--- isakmpd-20041012.orig/nat_traversal.h
++++ isakmpd-20041012/nat_traversal.h
+@@ -1,4 +1,4 @@
+-/*	$OpenBSD: nat_traversal.h,v 1.2 2004/06/21 23:27:10 ho Exp $	*/
++/*	$OpenBSD: nat_traversal.h,v 1.4 2005/07/25 15:03:47 hshoexer Exp $	*/
+ 
+ /*
+  * Copyright (c) 2004 Håkan Olsson.  All rights reserved.
+@@ -27,6 +27,24 @@
+ #ifndef _NAT_TRAVERSAL_H_
+ #define _NAT_TRAVERSAL_H_
+ 
++#define VID_DRAFT_V2	0
++#define VID_DRAFT_V2_N	1
++#define VID_DRAFT_V3	2
++#define VID_RFC3947	3
++
++struct nat_t_cap {
++	int		 id;
++	u_int32_t	 flags;
++	const char	*text;
++	char		*hash;
++	size_t		 hashsize;
++};
++
++/*
++ * Set if -T is given on the command line to disable NAT-T support.
++ */
++extern int	disable_nat_t;
++
+ void	nat_t_init(void);
+ int	nat_t_add_vendor_payloads(struct message *);
+ void	nat_t_check_vendor_payload(struct message *, struct payload *);
+--- isakmpd-20041012.orig/message.c
++++ isakmpd-20041012/message.c
+@@ -112,6 +112,7 @@
+ 	message_validate_hash, message_validate_sig, message_validate_nonce,
+ 	message_validate_notify, message_validate_delete,
+ 	message_validate_vendor, message_validate_attribute,
++	message_validate_nat_d, message_validate_nat_oa,
+ 	message_validate_nat_d, message_validate_nat_oa
+ };
+ 
+@@ -120,7 +121,7 @@
+ 	isakmp_id_fld, isakmp_cert_fld, isakmp_certreq_fld, isakmp_hash_fld,
+ 	isakmp_sig_fld, isakmp_nonce_fld, isakmp_notify_fld, isakmp_delete_fld,
+ 	isakmp_vendor_fld, isakmp_attribute_fld, isakmp_nat_d_fld,
+-	isakmp_nat_oa_fld
++	isakmp_nat_oa_fld, isakmp_nat_d_fld, isakmp_nat_oa_fld
+ };
+ 
+ /*
+@@ -138,7 +139,8 @@
+ 	ISAKMP_PAYLOAD_SAK, ISAKMP_PAYLOAD_SAT, ISAKMP_PAYLOAD_KD,
+ 	ISAKMP_PAYLOAD_SEQ, ISAKMP_PAYLOAD_POP
+ #endif
+-	ISAKMP_PAYLOAD_NAT_D, ISAKMP_PAYLOAD_NAT_OA
++	ISAKMP_PAYLOAD_NAT_D, ISAKMP_PAYLOAD_NAT_OA, 
++	ISAKMP_PAYLOAD_NAT_D_DRAFT, ISAKMP_PAYLOAD_NAT_OA_DRAFT
+ };
+ 
+ static u_int8_t payload_map[256];
+@@ -347,8 +349,8 @@
+ 		}
+ 		/* Ignore most private payloads.  */
+ 		if (next >= ISAKMP_PAYLOAD_PRIVATE_MIN &&
+-		    next != ISAKMP_PAYLOAD_NAT_D &&
+-		    next != ISAKMP_PAYLOAD_NAT_OA) {
++		    next != ISAKMP_PAYLOAD_NAT_D_DRAFT &&
++		    next != ISAKMP_PAYLOAD_NAT_OA_DRAFT) {
+ 			LOG_DBG((LOG_MESSAGE, 30, "message_parse_payloads: "
+ 			    "private next payload type %s in payload of "
+ 			    "type %d ignored",
+@@ -460,8 +462,10 @@
+ 		return ISAKMP_ATTRIBUTE_SZ;
+ #if defined (USE_NAT_TRAVERSAL)
+ 	case ISAKMP_PAYLOAD_NAT_D:
++	case ISAKMP_PAYLOAD_NAT_D_DRAFT:
+ 		return ISAKMP_NAT_D_SZ;
+ 	case ISAKMP_PAYLOAD_NAT_OA:
++	case ISAKMP_PAYLOAD_NAT_OA_DRAFT:
+ 		return ISAKMP_NAT_OA_SZ;
+ #endif
+ 	/* Not yet supported and any other unknown payloads. */
+--- isakmpd-20041012.orig/policy.c
++++ isakmpd-20041012/policy.c
+@@ -511,7 +511,10 @@
+ 							break;
+ 						}
+ #if defined (USE_NAT_TRAVERSAL)
+-					else if (decode_16(value) == IPSEC_ENCAP_UDP_ENCAP_TUNNEL)
++					else if (decode_16(value) ==
++					    IPSEC_ENCAP_UDP_ENCAP_TUNNEL ||
++					    decode_16(value) ==
++					    IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT)
+ 						switch (proto->proto) {
+ 						case IPSEC_PROTO_IPSEC_AH:
+ 							ah_encapsulation = "udp-encap-tunnel";
+@@ -1932,7 +1935,7 @@
+ void
+ policy_init(void)
+ {
+-	char           *ptr, *policy_file;
++	char           *ptr, *policy_file, *use_keynote;
+ 	char          **asserts;
+ 	size_t          sz, len;
+ 	int             fd, i;
+@@ -1940,10 +1943,11 @@
+ 	LOG_DBG((LOG_POLICY, 30, "policy_init: initializing"));
+ 
+ 	/* Do we want to use the policy modules?  */
+-	if (ignore_policy ||
+-	    strncmp("yes", conf_get_str("General", "Use-Keynote"), 3))
+-		return;
+-
++	use_keynote = conf_get_str("General", "Use-Keynote");
++	if (ignore_policy || 
++		(use_keynote && strncmp("yes", use_keynote, 3)))
++	         return;
++ 
+ 	/* Get policy file from configuration.  */
+ 	policy_file = conf_get_str("General", "Policy-file");
+ 	if (!policy_file)
+--- isakmpd-20041012.orig/ike_phase_1.c
++++ isakmpd-20041012/ike_phase_1.c
+@@ -1040,9 +1040,9 @@
+ 
+ 		/* Compare expected/desired and received remote ID */
+ 		if (bcmp(rid, payload->p + ISAKMP_ID_DATA_OFF, sz)) {
+-			free(rid);
+ 			log_print("ike_phase_1_recv_ID: "
+-			    "received remote ID other than expected %s", p);
++			    "received remote ID other than expected %s - %s", p, payload->p);
++			free(rid);
+ 			return -1;
+ 		}
+ 		free(rid);
+--- isakmpd-20041012.orig/x509.c
++++ isakmpd-20041012/x509.c
+@@ -910,7 +910,11 @@
+ 	X509_STORE_CTX_init(&csc, x509_cas, cert, NULL);
+ #if OPENSSL_VERSION_NUMBER >= 0x00907000L
+ 	/* XXX See comment in x509_read_crls_from_dir.  */
++#if OPENSSL_VERSION_NUMBER >= 0x00908000L
++	if (x509_cas->param->flags & X509_V_FLAG_CRL_CHECK) {
++#else
+ 	if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) {
++#endif
+ 		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK);
+ 		X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL);
+ 	}
+--- isakmpd-20041012.orig/sysdep/linux/sysdep.c
++++ isakmpd-20041012/sysdep/linux/sysdep.c
+@@ -169,22 +169,22 @@
+     return 0;
+ 
+   if (!(af == AF_INET || af == AF_INET6))
+-    {
++    { 
+       log_print ("sysdep_cleartext: unsupported protocol family %d", af);
+       return -1;
+     }
+ 
+   if (setsockopt (fd, af == AF_INET ? IPPROTO_IP : IPPROTO_IPV6,
+-		  af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
+-		  &pol_in, sizeof pol_in) < 0 ||
++          af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
++          &pol_in, sizeof pol_in) < 0 ||
+       setsockopt (fd, af == AF_INET ? IPPROTO_IP : IPPROTO_IPV6,
+-		  af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
+-		  &pol_out, sizeof pol_out) < 0)
+-    {
++          af == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY,
++          &pol_out, sizeof pol_out) < 0)
++    { 
+       log_error ("sysdep_cleartext: "
+-		 "setsockopt (%d, IPPROTO_IP%s, IP%s_IPSEC_POLICY, ...) "
+-		 "failed", fd, af == AF_INET ? "" : "V6",
+-		 af == AF_INET ? "" : "V6");
++         "setsockopt (%d, IPPROTO_IP%s, IP%s_IPSEC_POLICY, ...) "
++         "failed", fd, af == AF_INET ? "" : "V6",
++         af == AF_INET ? "" : "V6");
+       return -1;
+     }
+   return 0;
+--- isakmpd-20041012.orig/sysdep/linux/GNUmakefile.sysdep
++++ isakmpd-20041012/sysdep/linux/GNUmakefile.sysdep
+@@ -33,13 +33,13 @@
+ LDADD+=		-lgmp ${LIBSYSDEP} ${LIBCRYPTO}
+ DPADD+=		${LIBGMP} ${LIBSYSDEP}
+ 
+-CFLAGS+=	-DUSE_OLD_SOCKADDR -DHAVE_PCAP \
+-		-DNEED_SYSDEP_APP -DMP_FLAVOUR=MP_FLAVOUR_GMP \
+-		-I/usr/src/linux/include -I${.CURDIR}/sysdep/common \
++CFLAGS+=	-DHAVE_GETNAMEINFO -DUSE_OLD_SOCKADDR -DHAVE_PCAP \
++		-DNEED_SYSDEP_APP -DMP_FLAVOUR=MP_FLAVOUR_GMP -DUSE_AES \
++		-I${.CURDIR}/sysdep/linux/include -I${.CURDIR}/sysdep/common \
+ 		-I/usr/include/openssl
+ 
+ FEATURES=	debug tripledes blowfish cast ec aggressive x509 policy
+-FEATURES+=	des aes
++FEATURES+=	dpd nat_traversal isakmp_cfg des aes
+ 
+ IPSEC_SRCS=	pf_key_v2.c
+ IPSEC_CFLAGS=	-DUSE_PF_KEY_V2
+@@ -51,7 +51,7 @@
+ # hack libsysdep.a dependenc
+ ${LIBSYSDEPDIR}/.depend ${LIBSYSDEP}:
+ 	cd ${LIBSYSDEPDIR} && \
+-		${MAKE} --no-print-directory ${MAKEFLAGS} \
++		${MAKE} --no-print-directory \
+ 			CFLAGS="${CFLAGS}" MKDEP="${MKDEP}" ${MAKECMDGOALS}
+ 
+ ifeq ($(findstring clean,$(MAKECMDGOALS)),clean)
+--- isakmpd-20041012.orig/sysdep/linux/include/bitstring.h
++++ isakmpd-20041012/sysdep/linux/include/bitstring.h
+@@ -0,0 +1,132 @@
++/*	$OpenBSD: bitstring.h,v 1.4 2002/06/19 02:50:10 millert Exp $	*/
++/*	$NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $	*/
++
++/*
++ * Copyright (c) 1989, 1993
++ *	The Regents of the University of California.  All rights reserved.
++ *
++ * This code is derived from software contributed to Berkeley by
++ * Paul Vixie.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *	This product includes software developed by the University of
++ *	California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ *	@(#)bitstring.h	8.1 (Berkeley) 7/19/93
++ */
++
++#ifndef _BITSTRING_H_
++#define	_BITSTRING_H_
++
++/* modified for SV/AT and bitstring bugfix by M.R.Murphy, 11oct91
++ * bitstr_size changed gratuitously, but shorter
++ * bit_alloc   spelling error fixed
++ * the following were efficient, but didn't work, they've been made to
++ * work, but are no longer as efficient :-)
++ * bit_nclear, bit_nset, bit_ffc, bit_ffs
++ */
++typedef	unsigned char bitstr_t;
++
++/* internal macros */
++				/* byte of the bitstring bit is in */
++#define	_bit_byte(bit) \
++	((bit) >> 3)
++
++				/* mask for the bit within its byte */
++#define	_bit_mask(bit) \
++	(1 << ((bit)&0x7))
++
++/* external macros */
++				/* bytes in a bitstring of nbits bits */
++#define	bitstr_size(nbits) \
++	(((nbits) + 7) >> 3)
++
++				/* allocate a bitstring */
++#define	bit_alloc(nbits) \
++	(bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t))
++
++				/* allocate a bitstring on the stack */
++#define	bit_decl(name, nbits) \
++	((name)[bitstr_size(nbits)])
++
++				/* is bit N of bitstring name set? */
++#define	bit_test(name, bit) \
++	((name)[_bit_byte(bit)] & _bit_mask(bit))
++
++				/* set bit N of bitstring name */
++#define	bit_set(name, bit) \
++	((name)[_bit_byte(bit)] |= _bit_mask(bit))
++
++				/* clear bit N of bitstring name */
++#define	bit_clear(name, bit) \
++	((name)[_bit_byte(bit)] &= ~_bit_mask(bit))
++
++				/* clear bits start ... stop in bitstring */
++#define	bit_nclear(name, start, stop) do { \
++	register bitstr_t *_name = name; \
++	register int _start = start, _stop = stop; \
++	while (_start <= _stop) { \
++		bit_clear(_name, _start); \
++		_start++; \
++		} \
++} while(0)
++
++				/* set bits start ... stop in bitstring */
++#define	bit_nset(name, start, stop) do { \
++	register bitstr_t *_name = name; \
++	register int _start = start, _stop = stop; \
++	while (_start <= _stop) { \
++		bit_set(_name, _start); \
++		_start++; \
++		} \
++} while(0)
++
++				/* find first bit clear in name */
++#define	bit_ffc(name, nbits, value) do { \
++	register bitstr_t *_name = name; \
++	register int _bit, _nbits = nbits, _value = -1; \
++	for (_bit = 0; _bit < _nbits; ++_bit) \
++		if (!bit_test(_name, _bit)) { \
++			_value = _bit; \
++			break; \
++		} \
++	*(value) = _value; \
++} while(0)
++
++				/* find first bit set in name */
++#define	bit_ffs(name, nbits, value) do { \
++	register bitstr_t *_name = name; \
++	register int _bit, _nbits = nbits, _value = -1; \
++	for (_bit = 0; _bit < _nbits; ++_bit) \
++		if (bit_test(_name, _bit)) { \
++			_value = _bit; \
++			break; \
++		} \
++	*(value) = _value; \
++} while(0)
++
++#endif /* !_BITSTRING_H_ */
+--- isakmpd-20041012.orig/sysdep/linux/include/sys/queue.h
++++ isakmpd-20041012/sysdep/linux/include/sys/queue.h
+@@ -0,0 +1,453 @@
++/*
++ * Copyright (c) 1991, 1993
++ *	The Regents of the University of California.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *	This product includes software developed by the University of
++ *	California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
++ * $FreeBSD: src/sys/sys/queue.h,v 1.45 2001/12/11 11:49:58 sheldonh Exp $
++ */
++
++#ifndef _SYS_QUEUE_H_
++#define	_SYS_QUEUE_H_
++
++//#include <machine/ansi.h>	/* for __offsetof */
++
++/*
++ * This file defines four types of data structures: singly-linked lists,
++ * singly-linked tail queues, lists and tail queues.
++ *
++ * A singly-linked list is headed by a single forward pointer. The elements
++ * are singly linked for minimum space and pointer manipulation overhead at
++ * the expense of O(n) removal for arbitrary elements. New elements can be
++ * added to the list after an existing element or at the head of the list.
++ * Elements being removed from the head of the list should use the explicit
++ * macro for this purpose for optimum efficiency. A singly-linked list may
++ * only be traversed in the forward direction.  Singly-linked lists are ideal
++ * for applications with large datasets and few or no removals or for
++ * implementing a LIFO queue.
++ *
++ * A singly-linked tail queue is headed by a pair of pointers, one to the
++ * head of the list and the other to the tail of the list. The elements are
++ * singly linked for minimum space and pointer manipulation overhead at the
++ * expense of O(n) removal for arbitrary elements. New elements can be added
++ * to the list after an existing element, at the head of the list, or at the
++ * end of the list. Elements being removed from the head of the tail queue
++ * should use the explicit macro for this purpose for optimum efficiency.
++ * A singly-linked tail queue may only be traversed in the forward direction.
++ * Singly-linked tail queues are ideal for applications with large datasets
++ * and few or no removals or for implementing a FIFO queue.
++ *
++ * A list is headed by a single forward pointer (or an array of forward
++ * pointers for a hash table header). The elements are doubly linked
++ * so that an arbitrary element can be removed without a need to
++ * traverse the list. New elements can be added to the list before
++ * or after an existing element or at the head of the list. A list
++ * may only be traversed in the forward direction.
++ *
++ * A tail queue is headed by a pair of pointers, one to the head of the
++ * list and the other to the tail of the list. The elements are doubly
++ * linked so that an arbitrary element can be removed without a need to
++ * traverse the list. New elements can be added to the list before or
++ * after an existing element, at the head of the list, or at the end of
++ * the list. A tail queue may be traversed in either direction.
++ *
++ * For details on the use of these macros, see the queue(3) manual page.
++ *
++ *
++ *			SLIST	LIST	STAILQ	TAILQ
++ * _HEAD		+	+	+	+
++ * _HEAD_INITIALIZER	+	+	+	+
++ * _ENTRY		+	+	+	+
++ * _INIT		+	+	+	+
++ * _EMPTY		+	+	+	+
++ * _FIRST		+	+	+	+
++ * _NEXT		+	+	+	+
++ * _PREV		-	-	-	+
++ * _LAST		-	-	+	+
++ * _FOREACH		+	+	+	+
++ * _FOREACH_REVERSE	-	-	-	+
++ * _INSERT_HEAD		+	+	+	+
++ * _INSERT_BEFORE	-	+	-	+
++ * _INSERT_AFTER	+	+	+	+
++ * _INSERT_TAIL		-	-	+	+
++ * _REMOVE_HEAD		+	-	+	-
++ * _REMOVE		+	+	+	+
++ *
++ */
++
++/*
++ * Singly-linked List declarations.
++ */
++#define	SLIST_HEAD(name, type)						\
++struct name {								\
++	struct type *slh_first;	/* first element */			\
++}
++
++#define	SLIST_HEAD_INITIALIZER(head)					\
++	{ NULL }
++ 
++#define	SLIST_ENTRY(type)						\
++struct {								\
++	struct type *sle_next;	/* next element */			\
++}
++ 
++/*
++ * Singly-linked List functions.
++ */
++#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
++
++#define	SLIST_FIRST(head)	((head)->slh_first)
++
++#define	SLIST_FOREACH(var, head, field)					\
++	for ((var) = SLIST_FIRST((head));				\
++	    (var);							\
++	    (var) = SLIST_NEXT((var), field))
++
++#define	SLIST_INIT(head) do {						\
++	SLIST_FIRST((head)) = NULL;					\
++} while (0)
++
++#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
++	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
++	SLIST_NEXT((slistelm), field) = (elm);				\
++} while (0)
++
++#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
++	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
++	SLIST_FIRST((head)) = (elm);					\
++} while (0)
++
++#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
++
++#define	SLIST_REMOVE(head, elm, type, field) do {			\
++	if (SLIST_FIRST((head)) == (elm)) {				\
++		SLIST_REMOVE_HEAD((head), field);			\
++	}								\
++	else {								\
++		struct type *curelm = SLIST_FIRST((head));		\
++		while (SLIST_NEXT(curelm, field) != (elm))		\
++			curelm = SLIST_NEXT(curelm, field);		\
++		SLIST_NEXT(curelm, field) =				\
++		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
++	}								\
++} while (0)
++
++#define	SLIST_REMOVE_HEAD(head, field) do {				\
++	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
++} while (0)
++
++/*
++ * Singly-linked Tail queue declarations.
++ */
++#define	STAILQ_HEAD(name, type)						\
++struct name {								\
++	struct type *stqh_first;/* first element */			\
++	struct type **stqh_last;/* addr of last next element */		\
++}
++
++#define	STAILQ_HEAD_INITIALIZER(head)					\
++	{ NULL, &(head).stqh_first }
++
++#define	STAILQ_ENTRY(type)						\
++struct {								\
++	struct type *stqe_next;	/* next element */			\
++}
++
++/*
++ * Singly-linked Tail queue functions.
++ */
++#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
++
++#define	STAILQ_FIRST(head)	((head)->stqh_first)
++
++#define	STAILQ_FOREACH(var, head, field)				\
++	for((var) = STAILQ_FIRST((head));				\
++	   (var);							\
++	   (var) = STAILQ_NEXT((var), field))
++
++#define	STAILQ_INIT(head) do {						\
++	STAILQ_FIRST((head)) = NULL;					\
++	(head)->stqh_last = &STAILQ_FIRST((head));			\
++} while (0)
++
++#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
++	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
++		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
++	STAILQ_NEXT((tqelm), field) = (elm);				\
++} while (0)
++
++#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
++	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
++		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
++	STAILQ_FIRST((head)) = (elm);					\
++} while (0)
++
++#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
++	STAILQ_NEXT((elm), field) = NULL;				\
++	*(head)->stqh_last = (elm);					\
++	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
++} while (0)
++
++#define	STAILQ_LAST(head, type, field)					\
++	(STAILQ_EMPTY(head) ?						\
++		NULL :							\
++	        ((struct type *)					\
++		((char *)((head)->stqh_last) - __offsetof(struct type, field))))
++
++#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
++
++#define	STAILQ_REMOVE(head, elm, type, field) do {			\
++	if (STAILQ_FIRST((head)) == (elm)) {				\
++		STAILQ_REMOVE_HEAD(head, field);			\
++	}								\
++	else {								\
++		struct type *curelm = STAILQ_FIRST((head));		\
++		while (STAILQ_NEXT(curelm, field) != (elm))		\
++			curelm = STAILQ_NEXT(curelm, field);		\
++		if ((STAILQ_NEXT(curelm, field) =			\
++		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
++			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
++	}								\
++} while (0)
++
++#define	STAILQ_REMOVE_HEAD(head, field) do {				\
++	if ((STAILQ_FIRST((head)) =					\
++	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
++		(head)->stqh_last = &STAILQ_FIRST((head));		\
++} while (0)
++
++#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
++	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
++		(head)->stqh_last = &STAILQ_FIRST((head));		\
++} while (0)
++
++/*
++ * List declarations.
++ */
++#define	LIST_HEAD(name, type)						\
++struct name {								\
++	struct type *lh_first;	/* first element */			\
++}
++
++#define	LIST_HEAD_INITIALIZER(head)					\
++	{ NULL }
++
++#define	LIST_ENTRY(type)						\
++struct {								\
++	struct type *le_next;	/* next element */			\
++	struct type **le_prev;	/* address of previous next element */	\
++}
++
++/*
++ * List functions.
++ */
++
++#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
++
++#define	LIST_FIRST(head)	((head)->lh_first)
++
++#define	LIST_FOREACH(var, head, field)					\
++	for ((var) = LIST_FIRST((head));				\
++	    (var);							\
++	    (var) = LIST_NEXT((var), field))
++
++#define	LIST_INIT(head) do {						\
++	LIST_FIRST((head)) = NULL;					\
++} while (0)
++
++#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
++	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
++		LIST_NEXT((listelm), field)->field.le_prev =		\
++		    &LIST_NEXT((elm), field);				\
++	LIST_NEXT((listelm), field) = (elm);				\
++	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
++} while (0)
++
++#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
++	(elm)->field.le_prev = (listelm)->field.le_prev;		\
++	LIST_NEXT((elm), field) = (listelm);				\
++	*(listelm)->field.le_prev = (elm);				\
++	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
++} while (0)
++
++#define	LIST_INSERT_HEAD(head, elm, field) do {				\
++	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
++		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
++	LIST_FIRST((head)) = (elm);					\
++	(elm)->field.le_prev = &LIST_FIRST((head));			\
++} while (0)
++
++#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
++
++#define	LIST_REMOVE(elm, field) do {					\
++	if (LIST_NEXT((elm), field) != NULL)				\
++		LIST_NEXT((elm), field)->field.le_prev = 		\
++		    (elm)->field.le_prev;				\
++	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
++} while (0)
++
++/*
++ * Tail queue declarations.
++ */
++#define	TAILQ_HEAD(name, type)						\
++struct name {								\
++	struct type *tqh_first;	/* first element */			\
++	struct type **tqh_last;	/* addr of last next element */		\
++}
++
++#define	TAILQ_HEAD_INITIALIZER(head)					\
++	{ NULL, &(head).tqh_first }
++
++#define	TAILQ_ENTRY(type)						\
++struct {								\
++	struct type *tqe_next;	/* next element */			\
++	struct type **tqe_prev;	/* address of previous next element */	\
++}
++
++/*
++ * Tail queue functions.
++ */
++#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
++
++#define	TAILQ_FIRST(head)	((head)->tqh_first)
++
++#define	TAILQ_FOREACH(var, head, field)					\
++	for ((var) = TAILQ_FIRST((head));				\
++	    (var);							\
++	    (var) = TAILQ_NEXT((var), field))
++
++#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
++	for ((var) = TAILQ_LAST((head), headname);			\
++	    (var);							\
++	    (var) = TAILQ_PREV((var), headname, field))
++
++#define	TAILQ_INIT(head) do {						\
++	TAILQ_FIRST((head)) = NULL;					\
++	(head)->tqh_last = &TAILQ_FIRST((head));			\
++} while (0)
++
++#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
++	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
++		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
++		    &TAILQ_NEXT((elm), field);				\
++	else								\
++		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
++	TAILQ_NEXT((listelm), field) = (elm);				\
++	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
++} while (0)
++
++#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
++	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
++	TAILQ_NEXT((elm), field) = (listelm);				\
++	*(listelm)->field.tqe_prev = (elm);				\
++	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
++} while (0)
++
++#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
++	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
++		TAILQ_FIRST((head))->field.tqe_prev =			\
++		    &TAILQ_NEXT((elm), field);				\
++	else								\
++		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
++	TAILQ_FIRST((head)) = (elm);					\
++	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
++} while (0)
++
++#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
++	TAILQ_NEXT((elm), field) = NULL;				\
++	(elm)->field.tqe_prev = (head)->tqh_last;			\
++	*(head)->tqh_last = (elm);					\
++	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
++} while (0)
++
++#define	TAILQ_LAST(head, headname)					\
++	(*(((struct headname *)((head)->tqh_last))->tqh_last))
++
++#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
++
++#define	TAILQ_PREV(elm, headname, field)				\
++	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
++
++#define	TAILQ_REMOVE(head, elm, field) do {				\
++	if ((TAILQ_NEXT((elm), field)) != NULL)				\
++		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
++		    (elm)->field.tqe_prev;				\
++	else								\
++		(head)->tqh_last = (elm)->field.tqe_prev;		\
++	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
++} while (0)
++
++
++#ifdef _KERNEL
++
++/*
++ * XXX insque() and remque() are an old way of handling certain queues.
++ * They bogusly assumes that all queue heads look alike.
++ */
++
++struct quehead {
++	struct quehead *qh_link;
++	struct quehead *qh_rlink;
++};
++
++#ifdef	__GNUC__
++
++static __inline void
++insque(void *a, void *b)
++{
++	struct quehead *element = (struct quehead *)a,
++		 *head = (struct quehead *)b;
++
++	element->qh_link = head->qh_link;
++	element->qh_rlink = head;
++	head->qh_link = element;
++	element->qh_link->qh_rlink = element;
++}
++
++static __inline void
++remque(void *a)
++{
++	struct quehead *element = (struct quehead *)a;
++
++	element->qh_link->qh_rlink = element->qh_rlink;
++	element->qh_rlink->qh_link = element->qh_link;
++	element->qh_rlink = 0;
++}
++
++#else /* !__GNUC__ */
++
++void	insque __P((void *a, void *b));
++void	remque __P((void *a));
++
++#endif /* __GNUC__ */
++
++#endif /* _KERNEL */
++
++#endif /* !_SYS_QUEUE_H_ */
+--- isakmpd-20041012.orig/sysdep/common/pcap.h
++++ isakmpd-20041012/sysdep/common/pcap.h
+@@ -55,8 +55,13 @@
+ 	u_int32_t linktype;	/* data link type (DLT_*) */
+ };
+ 
++struct pcap_timeval {
++	int32_t tv_sec;		/* seconds */
++	int32_t tv_usec;	/* microseconds */
++};
++
+ struct pcap_pkthdr {
+-	struct timeval ts;	/* time stamp */
++	struct pcap_timeval ts;	/* time stamp */
+ 	u_int32_t caplen;	/* length of portion present */
+ 	u_int32_t len;		/* length this packet (off wire) */
+ };
+--- isakmpd-20041012.orig/sysdep/common/libsysdep/arc4random.c
++++ isakmpd-20041012/sysdep/common/libsysdep/arc4random.c
+@@ -78,7 +78,7 @@
+ static void
+ arc4_stir(struct arc4_stream *as)
+ {
+-	int     fd;
++	int     fd, i;
+ 	struct {
+ 		struct timeval tv;
+ 		u_int8_t rnd[128 - sizeof(struct timeval)];
+--- isakmpd-20041012.orig/x509v3.cnf
++++ isakmpd-20041012/x509v3.cnf
+@@ -0,0 +1,26 @@
++# default settings
++CERTPATHLEN             = 1
++CERTUSAGE               = digitalSignature,keyCertSign
++CERTIP                  = 0.0.0.0
++CERTFQDN                = nohost.nodomain
++
++# This section should be referenced when building an x509v3 CA
++# Certificate.
++# The default path length and the key usage can be overriden
++# modified by setting the CERTPATHLEN and CERTUSAGE environment 
++# variables.
++[x509v3_CA]
++basicConstraints=critical,CA:true,pathlen:$ENV::CERTPATHLEN
++keyUsage=$ENV::CERTUSAGE
++
++# This section should be referenced to add an IP Address
++# as an alternate subject name, needed by isakmpd
++# The address must be provided in the CERTIP environment variable
++[x509v3_IPAddr]
++subjectAltName=IP:$ENV::CERTIP
++
++# This section should be referenced to add a FQDN hostname
++# as an alternate subject name, needed by isakmpd
++# The address must be provided in the CERTFQDN environment variable
++[x509v3_FQDN]
++subjectAltName=DNS:$ENV::CERTFQDN
+
diff --git a/openwrt/package/isakmpd/patches/020-standardize.patch b/openwrt/package/isakmpd/patches/020-standardize.patch
new file mode 100644
index 0000000000..d3dfabf349
--- /dev/null
+++ b/openwrt/package/isakmpd/patches/020-standardize.patch
@@ -0,0 +1,59 @@
+diff -urN isakmpd/GNUmakefile isakmpd.new/GNUmakefile
+--- isakmpd/GNUmakefile	2004-01-16 13:36:32.000000000 +0100
++++ isakmpd.new/GNUmakefile	2006-09-03 17:33:03.000000000 +0200
+@@ -238,3 +238,16 @@
+ 
+ realcleandepend:
+ 	rm -f .depend tags
++
++# Install rules
++install: install-bin install-man
++
++install-bin: isakmpd
++	-mkdir -p $(DESTDIR)$(BINDIR)
++	$(INSTALL) $(INSTALL_OPTS) -m 755 isakmpd $(DESTDIR)$(BINDIR)
++
++install-man:
++	-mkdir -p $(DESTDIR)$(MANDIR)/man8
++	$(INSTALL) $(INSTALL_OPTS) -m 444 isakmpd.8 $(DESTDIR)$(MANDIR)/man8
++	-mkdir -p $(DESTDIR)$(MANDIR)/man5
++	$(INSTALL) $(INSTALL_OPTS) -m 444 isakmpd.conf.5 isakmpd.policy.5 $(DESTDIR)$(MANDIR)/man5
+diff -urN isakmpd/samples/Makefile isakmpd.new/samples/Makefile
+--- isakmpd/samples/Makefile	2003-06-03 16:39:50.000000000 +0200
++++ isakmpd.new/samples/Makefile	2006-09-03 17:07:24.000000000 +0200
+@@ -26,7 +26,7 @@
+ #
+ 
+ FILES=		VPN-* policy singlehost-*
+-TARGETDIR=	/usr/share/ipsec/isakmpd
++TARGETDIR=	/usr/share/isakmpd/samples
+ 
+ # The mkdir below is for installation on OpenBSD pre 2.7
+ install:
+
+diff -urN isakmp.old/sysdep/linux/GNUmakefile.sysdep isakmp.dev/sysdep/linux/GNUmakefile.sysdep
+--- isakmp.old/sysdep/linux/GNUmakefile.sysdep	2006-09-07 13:49:20.000000000 +0200
++++ isakmp.dev/sysdep/linux/GNUmakefile.sysdep	2006-09-07 13:51:41.000000000 +0200
+@@ -25,18 +25,18 @@
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #
+ 
+-LIBGMP:=	/usr/lib/libgmp.a
+-LIBCRYPTO:=	/usr/lib/libcrypto.a
++LIBGMP:=
++LIBCRYPTO:=	-lcrypto
+ LIBSYSDEPDIR:=	${.CURDIR}/sysdep/common/libsysdep
+ LIBSYSDEP:=	${LIBSYSDEPDIR}/libsysdep.a
+ 
+-LDADD+=		-lgmp ${LIBSYSDEP} ${LIBCRYPTO}
++LDADD+=		-L$(STAGING_DIR)/usr/lib -lgmp ${LIBSYSDEP} ${LIBCRYPTO}
+ DPADD+=		${LIBGMP} ${LIBSYSDEP}
+ 
+ CFLAGS+=	-DHAVE_GETNAMEINFO -DUSE_OLD_SOCKADDR -DHAVE_PCAP \
+ 		-DNEED_SYSDEP_APP -DMP_FLAVOUR=MP_FLAVOUR_GMP -DUSE_AES \
+ 		-I${.CURDIR}/sysdep/linux/include -I${.CURDIR}/sysdep/common \
+-		-I/usr/include/openssl
++		-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/usr/include/openssl -I$(LINUX_DIR)/include
+ 
+ FEATURES=	debug tripledes blowfish cast ec aggressive x509 policy
+ FEATURES+=	dpd nat_traversal isakmp_cfg des aes
diff --git a/openwrt/package/isakmpd/patches/02-openssl_hashes.patch b/openwrt/package/isakmpd/patches/030-openssl_hashes.patch
similarity index 100%
rename from openwrt/package/isakmpd/patches/02-openssl_hashes.patch
rename to openwrt/package/isakmpd/patches/030-openssl_hashes.patch
diff --git a/openwrt/package/isakmpd/patches/040-security_fix.patch b/openwrt/package/isakmpd/patches/040-security_fix.patch
new file mode 100644
index 0000000000..9128880107
--- /dev/null
+++ b/openwrt/package/isakmpd/patches/040-security_fix.patch
@@ -0,0 +1,22 @@
+Index: sbin/isakmpd/ipsec.c
+===================================================================
+RCS file: /cvs/src/sbin/isakmpd/ipsec.c,v
+retrieving revision 1.122
+retrieving revision 1.122.2.1
+diff -u -p -r1.122 -r1.122.2.1
+--- isakmpd/ipsec.c	23 Sep 2005 14:44:03 -0000	1.122
++++ isakmpd/ipsec.c	19 Aug 2006 20:23:28 -0000	1.122.2.1
+@@ -2076,9 +2076,10 @@ ipsec_proto_init(struct proto *proto, ch
+ {
+ 	struct ipsec_proto *iproto = proto->data;
+ 
+-	if (proto->sa->phase == 2 && section)
+-		iproto->replay_window = conf_get_num(section, "ReplayWindow",
+-		    DEFAULT_REPLAY_WINDOW);
++	if (proto->sa->phase == 2)
++		iproto->replay_window = section ? conf_get_num(section,
++		    "ReplayWindow", DEFAULT_REPLAY_WINDOW) :
++		    DEFAULT_REPLAY_WINDOW;
+ }
+ 
+ /*
-- 
2.30.2