summaryrefslogtreecommitdiff
path: root/package/isakmpd/patches
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2006-09-07 12:40:03 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2006-09-07 12:40:03 +0000
commit7ef4836b71fc990c63fbf8027499339c16ba5f90 (patch)
tree2a0f4d0cacbd184306a8a56929a3bfdf736f81e5 /package/isakmpd/patches
parent57127d8916fee08e09cc95256eaf5f53d4b1ba2b (diff)
upgrade isakmpd, add security fix
git-svn-id: svn://svn.openwrt.org/openwrt/branches/buildroot-ng/openwrt@4768 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/isakmpd/patches')
-rw-r--r--package/isakmpd/patches/01-standardize.patch133
-rw-r--r--package/isakmpd/patches/010-debian_3.patch1706
-rw-r--r--package/isakmpd/patches/020-standardize.patch59
-rw-r--r--package/isakmpd/patches/030-openssl_hashes.patch (renamed from package/isakmpd/patches/02-openssl_hashes.patch)0
-rw-r--r--package/isakmpd/patches/040-security_fix.patch22
5 files changed, 1787 insertions, 133 deletions
diff --git a/package/isakmpd/patches/01-standardize.patch b/package/isakmpd/patches/01-standardize.patch
deleted file mode 100644
index f97c77630e..0000000000
--- a/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/package/isakmpd/patches/010-debian_3.patch b/package/isakmpd/patches/010-debian_3.patch
new file mode 100644
index 0000000000..551ae1ffcd
--- /dev/null
+++ b/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/package/isakmpd/patches/020-standardize.patch b/package/isakmpd/patches/020-standardize.patch
new file mode 100644
index 0000000000..d3dfabf349
--- /dev/null
+++ b/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/package/isakmpd/patches/02-openssl_hashes.patch b/package/isakmpd/patches/030-openssl_hashes.patch
index 680db86a31..680db86a31 100644
--- a/package/isakmpd/patches/02-openssl_hashes.patch
+++ b/package/isakmpd/patches/030-openssl_hashes.patch
diff --git a/package/isakmpd/patches/040-security_fix.patch b/package/isakmpd/patches/040-security_fix.patch
new file mode 100644
index 0000000000..9128880107
--- /dev/null
+++ b/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;
+ }
+
+ /*