summaryrefslogtreecommitdiff
path: root/sbin/isakmpd/sysdep/linux
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2001-01-26 11:34:09 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2001-01-26 11:34:09 +0000
commita35fc8c0e0c41c0e6a4d15f10830e55a41173829 (patch)
tree395f7779b596a1ca851896ab70168d28a0f46039 /sbin/isakmpd/sysdep/linux
parent357f350df412081108ea92adbc0dd739527481df (diff)
Move in foreign OS support. The OpenBSD repository is now the official
isakmpd home.
Diffstat (limited to 'sbin/isakmpd/sysdep/linux')
-rw-r--r--sbin/isakmpd/sysdep/linux/GNUmakefile.sysdep77
-rw-r--r--sbin/isakmpd/sysdep/linux/Makefile.sysdep86
-rw-r--r--sbin/isakmpd/sysdep/linux/README16
-rw-r--r--sbin/isakmpd/sysdep/linux/klips.c687
-rw-r--r--sbin/isakmpd/sysdep/linux/klips.h56
-rw-r--r--sbin/isakmpd/sysdep/linux/sys/queue.h337
-rw-r--r--sbin/isakmpd/sysdep/linux/sysdep-os.h51
-rw-r--r--sbin/isakmpd/sysdep/linux/sysdep.c165
8 files changed, 1475 insertions, 0 deletions
diff --git a/sbin/isakmpd/sysdep/linux/GNUmakefile.sysdep b/sbin/isakmpd/sysdep/linux/GNUmakefile.sysdep
new file mode 100644
index 00000000000..6c694f49a28
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/GNUmakefile.sysdep
@@ -0,0 +1,77 @@
+# $Id: GNUmakefile.sysdep,v 1.1 2001/01/26 11:34:04 niklas Exp $
+
+#
+# Copyright (c) 1999 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.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Ericsson Radio Systems.
+# 4. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# 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.
+#
+
+# In order for this to work, invocations need to set FREESWAN to the
+# directory where FreeS/WAN is installed.
+
+ifndef FREESWAN
+FREESWAN= /usr/src/freeswan
+endif
+
+BINDIR= /usr/local/sbin
+# Partly good for RedHat 5.2, but man(1) does not find them so I have it
+# disabled for now.
+#MANDIR= /var/catman/cat
+#MAN5= isakmpd.conf.0
+#MAN8= isakmpd.0
+NOMAN=
+
+LIBGMP= ${FREESWAN}/gmp/libgmp.a
+LIBDES= ${FREESWAN}/libdes/libdes.a
+LIBSYSDEPDIR= ${.CURDIR}/sysdep/common/libsysdep
+LIBSYSDEP= ${LIBSYSDEPDIR}/libsysdep.a
+
+FEATURES= tripledes blowfish cast ec aggressive debug
+
+SRCS+= klips.c
+
+LDADD+= ${LIBSYSDEP} ${LIBGMP} ${LIBDES} -ldl
+DPADD+= ${LIBSYSDEP} ${LIBGMP} ${LIBDES}
+
+CFLAGS+= -I${FREESWAN}/gmp -I${FREESWAN}/libdes \
+ -I${FREESWAN}/klips -I${FREESWAN}/lib -DUSE_OLD_SOCKADDR \
+ -I${.CURDIR}/sysdep/common -DSYMBOL_PREFIX='"_"'
+
+HAVE_DLOPEN= defined
+
+${LIBSYSDEP}:
+ cd ${LIBSYSDEPDIR}; \
+ ${MAKE} --no-print-directory ${MAKEFLAGS} CFLAGS="${CFLAGS}" MKDEP="${MKDEP}"
+
+ifneq ($(findstring install,$(MAKECMDGOALS)),install)
+SUBDIR+= sysdep/common/libsysdep
+# The regress/ subdir is completely broken in the linux environment
+SUBDIR:= $(filter-out regress,${SUBDIR})
+endif
diff --git a/sbin/isakmpd/sysdep/linux/Makefile.sysdep b/sbin/isakmpd/sysdep/linux/Makefile.sysdep
new file mode 100644
index 00000000000..94ae607a2c6
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/Makefile.sysdep
@@ -0,0 +1,86 @@
+# $Id: Makefile.sysdep,v 1.1 2001/01/26 11:34:04 niklas Exp $
+
+#
+# Copyright (c) 1999 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.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Ericsson Radio Systems.
+# 4. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# 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.
+#
+
+# In order for this to work, invocations need to set FREESWAN to the
+# directory where FreeS/WAN is installed.
+
+BINDIR= /usr/local/sbin
+# Partly good for RedHat 5.2, but man(1) does not find them so I have it
+# disabled for now.
+#MANDIR= /var/catman/cat
+#MAN5= isakmpd.conf.0
+#MAN8= isakmpd.0
+NOMAN=
+
+IPSEC_SRCS= klips.c
+
+LDADD+= ${.CURDIR}/sysdep/common/libsysdep/libsysdep.a \
+ ${FREESWAN}/gmp/libgmp.a
+DPADD+= ${.CURDIR}/sysdep/common/libsysdep/libsysdep.a \
+ ${FREESWAN}/gmp/libgmp.a
+
+CFLAGS+= ${DEBUG} -I${FREESWAN}/gmp -I${FREESWAN}/libdes \
+ -I${FREESWAN}/klips -I${FREESWAN}/lib -DUSE_OLD_SOCKADDR \
+ -I${.CURDIR}/sysdep/common
+
+# XXX Is this test correct? Is the prefix "_" on ELF-systems too?
+HAVE_DLOPEN= defined
+LDADD+= -ldl
+DPADD+= /usr/lib/libdl.a
+CFLAGS+= -DSYMBOL_PREFIX='"_"'
+
+#USE_LIBCRYPTO= defined
+#USE_KEYNOTE= defined
+
+.ifndef USE_LIBCRYPTO
+DESLIB= ${FREESWAN}/libdes/libdes.a
+DESLIBDEP= ${FREESWAN}/libdes/libdes.a
+.endif
+
+# This is a hack in order to make sure libsysdep is built before the
+# linkstage of isakmpd. As a side effect the link is always done even if
+# not necessary. Well, I just don't care.
+GENERATED+= sysdep-target
+sysdep-target:
+ cd ${.CURDIR}/sysdep/common/libsysdep; ${MAKE} ${.MAKEFLAGS}
+
+.if make(clean)
+SUBDIR+= sysdep/common/libsysdep
+.endif
+
+# The regress/ subdir is completely broken in the linux environment
+.if !make(install)
+SUBDIR:= ${SUBDIR:Nregress}
+.endif
diff --git a/sbin/isakmpd/sysdep/linux/README b/sbin/isakmpd/sysdep/linux/README
new file mode 100644
index 00000000000..6238820e91d
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/README
@@ -0,0 +1,16 @@
+$Id: README,v 1.1 2001/01/26 11:34:04 niklas Exp $
+
+Currently, you have to manually configure any ipsec interfaces and do the
+association betweent these and the physical ones. This is done like
+this in FreeS/WAN:
+
+ipsec tncfg --attach --virtual ipsec0 --physical eth0
+ifconfig ipsec0 A.B.C.D netmask E.F.G.H
+
+Then there is one special configuration option in the IPSec-connection
+sections for Phase 2 of the configuration file, named Next-hop, which
+should be set to the next hop's IP address along the way to the peer:
+
+Next-hop= I.J.K.L
+
+This is specific to the way FreeS/WAN works.
diff --git a/sbin/isakmpd/sysdep/linux/klips.c b/sbin/isakmpd/sysdep/linux/klips.c
new file mode 100644
index 00000000000..cd042d7f718
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/klips.c
@@ -0,0 +1,687 @@
+/* $Id: klips.c,v 1.1 2001/01/26 11:34:04 niklas Exp $ */
+
+/*
+ * Copyright (c) 1999 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ericsson Radio Systems.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include <asm/types.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <linux/sockios.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <freeswan.h>
+#include <net/ipsec/radij.h>
+#include <net/ipsec/ipsec_encap.h>
+#include <net/ipsec/ipsec_netlink.h>
+#include <net/ipsec/ipsec_xform.h>
+#include <net/ipsec/ipsec_ipe4.h>
+#include <net/ipsec/ipsec_ah.h>
+#include <net/ipsec/ipsec_esp.h>
+
+#include "sysdep.h"
+
+#include "conf.h"
+#include "exchange.h"
+#include "hash.h"
+#include "ipsec.h"
+#include "ipsec_doi.h"
+#include "ipsec_num.h"
+#include "isakmp.h"
+#include "log.h"
+#include "klips.h"
+#include "sa.h"
+#include "timer.h"
+#include "transport.h"
+
+#define KLIPS_DEVICE "/dev/ipsec"
+
+#define PROC_ROUTE_FILE "/proc/net/route"
+#define PROC_ROUTE_FMT "%16s %128s %128s %X %d %d %d %128s %d %d %d\n"
+
+/* XXX Maybe these are available through some system-supplied define? */
+#define AH_NEW_XENCAP_LEN (3 * sizeof(u_short) + 2 * sizeof(u_char))
+#define ESP_NEW_XENCAP_LEN sizeof (struct espblkrply_edata)
+#define EMT_GRPSPIS_COMPLEN (sizeof (((struct encap_msghdr *)0)->em_rel[0]))
+
+/* How often should we check that connections we require to be up, are up? */
+#define KLIPS_CHECK_FREQ 60
+
+static int klips_socket;
+
+/* Open the KLIPS device. */
+int
+klips_open ()
+{
+ int fd;
+
+ fd = open (KLIPS_DEVICE, O_RDWR);
+ if (fd == -1)
+ {
+ log_error ("klips_open: open (\"%s\", O_RDWR) failed", KLIPS_DEVICE);
+ return -1;
+ }
+ klips_socket = fd;
+ return fd;
+}
+
+/* Write a KLIPS request down to the kernel. */
+static int
+klips_write (struct encap_msghdr *em)
+{
+ ssize_t n;
+
+ em->em_magic = EM_MAGIC;
+ em->em_version = 0;
+
+ LOG_DBG_BUF ((LOG_SYSDEP, 30, "klips_write: em", (u_int8_t *)em,
+ em->em_msglen));
+ n = write (klips_socket, em, em->em_msglen);
+ if (n == -1)
+ {
+ log_error ("write (%d, ...) failed", klips_socket);
+ return -1;
+ }
+ if ((size_t)n != em->em_msglen)
+ {
+ log_error ("write (%d, ...) returned prematurely", klips_socket);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Generate a SPI for protocol PROTO and the source/destination pair given by
+ * SRC, SRCLEN, DST & DSTLEN. Stash the SPI size in SZ.
+ */
+u_int8_t *
+klips_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, int srclen,
+ struct sockaddr *dst, int dstlen)
+{
+ u_int8_t *spi;
+ u_int32_t spinum;
+
+ *sz = IPSEC_SPI_SIZE;
+ spi = malloc (*sz);
+ if (!spi)
+ return 0;
+ do
+ spinum = sysdep_random ();
+ while (spinum < IPSEC_SPI_LOW);
+ spinum = htonl (spinum);
+ memcpy (spi, &spinum, *sz);
+
+ LOG_DBG_BUF ((LOG_SYSDEP, 50, "klips_get_spi: spi", spi, *sz));
+
+ return spi;
+}
+
+/* Group 2 SPIs in a chain. XXX Not fully implemented yet. */
+int
+klips_group_spis (struct sa *sa, struct proto *proto1, struct proto *proto2,
+ int incoming)
+{
+ struct encap_msghdr *emsg = 0;
+ struct sockaddr *dst;
+ int dstlen;
+
+ emsg = calloc (1, EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN);
+ if (!emsg)
+ return -1;
+
+ emsg->em_msglen = EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN;
+ emsg->em_type = EMT_GRPSPIS;
+
+ /*
+ * XXX The code below is wrong if we are in tunnel mode.
+ * The fix is to reorder stuff so the IP-in-IP SA will always come
+ * upfront, and if there are two such, one is dropped.
+ */
+ memcpy (&emsg->em_rel[0].emr_spi, proto1->spi[incoming],
+ sizeof emsg->em_rel[0].emr_spi);
+ memcpy (&emsg->em_rel[1].emr_spi, proto2->spi[incoming],
+ sizeof emsg->em_rel[1].emr_spi);
+ if (incoming)
+ sa->transport->vtbl->get_src (sa->transport, &dst, &dstlen);
+ else
+ sa->transport->vtbl->get_dst (sa->transport, &dst, &dstlen);
+ emsg->em_rel[0].emr_dst
+ = emsg->em_rel[1].emr_dst = ((struct sockaddr_in *)dst)->sin_addr;
+ /* XXX What if IPCOMP etc. comes along? */
+ emsg->em_rel[0].emr_proto
+ = proto1->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH;
+ emsg->em_rel[1].emr_proto
+ = proto2->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH;
+
+ if (klips_write (emsg))
+ goto cleanup;
+ free (emsg);
+
+ LOG_DBG ((LOG_SYSDEP, 50, "klips_group_spis: done"));
+
+ return 0;
+
+ cleanup:
+ if (emsg)
+ free (emsg);
+ return -1;
+}
+
+/* Store/update a SPI with full information into the kernel. */
+int
+klips_set_spi (struct sa *sa, struct proto *proto, int incoming)
+{
+ struct encap_msghdr *emsg = 0;
+ struct ipsec_proto *iproto = proto->data;
+ struct sockaddr *dst, *src;
+ int dstlen, srclen, keylen, hashlen;
+ size_t len;
+ struct ipe4_xdata *ip4x;
+
+ /* Actually works for all. */
+ struct espblkrply_edata *edx;
+
+ /* Actually works for all. */
+ struct ahhmacmd5_edata *amx;
+
+ switch (proto->proto)
+ {
+ case IPSEC_PROTO_IPSEC_ESP:
+ keylen = ipsec_esp_enckeylength (proto);
+ hashlen = ipsec_esp_authkeylength (proto);
+ len = EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN;
+ emsg = calloc (1, len);
+ if (!emsg)
+ return -1;
+
+ emsg->em_proto = IPPROTO_ESP;
+
+ edx = (struct espblkrply_edata *)emsg->em_dat;
+
+ /* Funny expression due to I just want one switch. */
+ switch (proto->id | (iproto->auth << 8))
+ {
+ case IPSEC_ESP_DES:
+ case IPSEC_ESP_DES_IV32:
+ case IPSEC_ESP_DES_IV64:
+ emsg->em_alg = XF_ESPDES;
+ break;
+
+ case IPSEC_ESP_3DES:
+ emsg->em_alg = XF_ESP3DES;
+ break;
+
+ case IPSEC_ESP_DES | (IPSEC_AUTH_HMAC_MD5 << 8):
+ case IPSEC_ESP_DES_IV32 | (IPSEC_AUTH_HMAC_MD5 << 8):
+ case IPSEC_ESP_DES_IV64 | (IPSEC_AUTH_HMAC_MD5 << 8):
+ emsg->em_alg = XF_ESPDESMD596;
+ break;
+
+ case IPSEC_ESP_3DES | (IPSEC_AUTH_HMAC_MD5 << 8):
+ emsg->em_alg = XF_ESP3DESMD596;
+ break;
+
+ case IPSEC_ESP_DES | (IPSEC_AUTH_HMAC_SHA << 8):
+ case IPSEC_ESP_DES_IV32 | (IPSEC_AUTH_HMAC_SHA << 8):
+ case IPSEC_ESP_DES_IV64 | (IPSEC_AUTH_HMAC_SHA << 8):
+ emsg->em_alg = XF_ESPDESSHA196;
+ break;
+
+ case IPSEC_ESP_3DES | (IPSEC_AUTH_HMAC_SHA << 8):
+ emsg->em_alg = XF_ESP3DESSHA196;
+ break;
+
+ default:
+ LOG_DBG ((LOG_SYSDEP, 10,
+ "klips_set_spi: Unsupported enc/auth alg negotiated"));
+ return -1;
+ }
+
+ /* XXX What if we have a protocol requiring IV? */
+ edx->eme_ivlen = EMT_ESPDES_IV_SZ;
+ edx->eme_klen = keylen;
+ edx->ame_klen = hashlen;
+#if 0
+ /* I have reason to believe Shared-SADB won't work at all in KLIPS. */
+ edx->eme_ooowin
+ = conf_get_str ("General", "Shared-SADB") ? 0 : iproto->replay_window;
+#else
+ edx->eme_ooowin = iproto->replay_window;
+#endif
+ /*
+ * XXX Pluto sets the unused by KLIPS flag EME_INITIATOR in
+ * edx->eme_flags, if the party is the initiator. Should we too?
+ */
+ edx->eme_flags = 0;
+ memcpy (edx->eme_key, iproto->keymat[incoming], keylen);
+ if (iproto->auth)
+ memcpy (edx->ame_key, iproto->keymat[incoming] + keylen, hashlen);
+ break;
+
+ case IPSEC_PROTO_IPSEC_AH:
+ hashlen = ipsec_ah_keylength (proto);
+ len = EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN + hashlen;
+ emsg = calloc (1, len);
+ if (!emsg)
+ return -1;
+
+ emsg->em_proto = IPPROTO_AH;
+
+ amx = (struct ahhmacmd5_edata *)emsg->em_dat;
+
+ switch (proto->id)
+ {
+ case IPSEC_AH_MD5:
+ emsg->em_alg = XF_AHHMACMD5;
+ break;
+
+ case IPSEC_AH_SHA:
+ emsg->em_alg = XF_AHHMACSHA1;
+ break;
+
+ default:
+ /* XXX Log? */
+ goto cleanup;
+ }
+
+ /* XXX Should we be able to send in different lengths here? */
+ amx->ame_alen = amx->ame_klen = hashlen;
+#if 0
+ /* I have reason to believe Shared-SADB won't work at all in KLIPS. */
+ amx->ame_ooowin
+ = conf_get_str ("General", "Shared-SADB") ? 0 : iproto->replay_window;
+#else
+ amx->ame_ooowin = iproto->replay_window;
+#endif
+ amx->ame_replayp = amx->ame_ooowin > 0;
+ memcpy (amx->ame_key, iproto->keymat[incoming], hashlen);
+ break;
+
+ default:
+ /* XXX Log? */
+ goto cleanup;
+ }
+
+ emsg->em_msglen = len;
+ emsg->em_type = EMT_SETSPI;
+ memcpy (&emsg->em_spi, proto->spi[incoming], sizeof emsg->em_spi);
+ emsg->em_flags = incoming ? EMT_INBOUND : 0;
+
+ /*
+ * XXX Addresses has to be thought through. Assumes IPv4.
+ */
+ sa->transport->vtbl->get_dst (sa->transport, &dst, &dstlen);
+ sa->transport->vtbl->get_src (sa->transport, &src, &srclen);
+ emsg->em_dst
+ = ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr;
+
+ /*
+ * Klips does not know about expirations, thus we need to do them inside
+ * isakmpd.
+ */
+ if (sa->seconds)
+ if (sa_setup_expirations (sa))
+ goto cleanup;
+
+ LOG_DBG ((LOG_SYSDEP, 10, "klips_set_spi: proto %d dst %s SPI 0x%x",
+ emsg->em_proto, inet_ntoa (emsg->em_dst), htonl (emsg->em_spi)));
+ if (klips_write (emsg))
+ goto cleanup;
+ free (emsg);
+
+ /* If we are tunneling we have to setup an IP in IP tunnel too. */
+ if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL)
+ {
+ len = EMT_SETSPI_FLEN + EMT_IPE4_ULEN;
+ emsg = calloc (1, len);
+ if (!emsg)
+ goto cleanup;
+
+ emsg->em_proto = IPPROTO_IPIP;
+ emsg->em_msglen = len;
+ emsg->em_type = EMT_SETSPI;
+ /*
+ * XXX Code in Pluto suggests this is not possible, but that we have
+ * to have a unique SPI for the IP4 SA.
+ */
+ memcpy (&emsg->em_spi, proto->spi[incoming], sizeof emsg->em_spi);
+ emsg->em_flags = 0;
+ emsg->em_alg = XF_IP4;
+
+ ip4x = (struct ipe4_xdata *)emsg->em_dat;
+ ip4x->i4_dst = emsg->em_dst
+ = ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr;
+ ip4x->i4_src
+ = ((struct sockaddr_in *)(incoming ? dst : src))->sin_addr;
+
+ LOG_DBG ((LOG_SYSDEP, 10, "klips_set_spi: proto %d dst %s SPI 0x%x",
+ emsg->em_proto, inet_ntoa (emsg->em_dst),
+ htonl (emsg->em_spi)));
+ if (klips_write (emsg))
+ goto cleanup;
+ free (emsg);
+
+ /*
+ * Grouping the IP-in-IP SA with the IPSec one means we must be careful
+ * in klips_group_spis so that we'll remove duplicate IP-in-IP SAs
+ * and get everything grouped in the right order.
+ *
+ * XXX Could we not share code with klips_group_spis here?
+ */
+ emsg = calloc (1, EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN);
+ if (!emsg)
+ goto cleanup;
+
+ emsg->em_msglen = EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN;
+ emsg->em_type = EMT_GRPSPIS;
+
+ memcpy (&emsg->em_rel[0].emr_spi, proto->spi[incoming],
+ sizeof emsg->em_rel[0].emr_spi);
+ memcpy (&emsg->em_rel[1].emr_spi, proto->spi[incoming],
+ sizeof emsg->em_rel[1].emr_spi);
+ emsg->em_rel[0].emr_dst = emsg->em_rel[1].emr_dst
+ = ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr;
+
+ emsg->em_rel[0].emr_proto = IPPROTO_IPIP;
+ /* XXX What if IPCOMP etc. comes along? */
+ emsg->em_rel[1].emr_proto
+ = proto->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH;
+
+ if (klips_write (emsg))
+ goto cleanup;
+ free (emsg);
+ }
+
+ LOG_DBG ((LOG_SYSDEP, 50, "klips_set_spi: done"));
+
+ return 0;
+
+ cleanup:
+ /* XXX Cleanup the potential SAs we have setup. */
+ if (emsg)
+ free (emsg);
+ return -1;
+}
+
+/*
+ * Delete the IPSec SA represented by the INCOMING direction in protocol PROTO
+ * of the IKE security association SA.
+ */
+int
+klips_delete_spi (struct sa *sa, struct proto *proto, int incoming)
+{
+ struct encap_msghdr *emsg = 0;
+ struct sockaddr *dst;
+ int dstlen;
+ struct ipsec_proto *iproto = proto->data;
+
+ emsg = calloc (1, EMT_SETSPI_FLEN);
+ if (!emsg)
+ return -1;
+
+ emsg->em_msglen = EMT_SETSPI_FLEN;
+ emsg->em_type = EMT_DELSPI;
+
+ memcpy (&emsg->em_spi, proto->spi[incoming], sizeof emsg->em_spi);
+ if (incoming)
+ sa->transport->vtbl->get_src (sa->transport, &dst, &dstlen);
+ else
+ sa->transport->vtbl->get_dst (sa->transport, &dst, &dstlen);
+ emsg->em_dst = ((struct sockaddr_in *)dst)->sin_addr;
+ /* XXX What if IPCOMP etc. comes along? */
+ emsg->em_proto
+ = (iproto->encap_mode == IPSEC_ENCAP_TUNNEL ? IPPROTO_IPIP
+ : proto->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH);
+
+ if (klips_write (emsg))
+ goto cleanup;
+ free (emsg);
+
+ LOG_DBG ((LOG_SYSDEP, 50, "klips_delete_spi: done"));
+
+ return 0;
+
+ cleanup:
+ if (emsg)
+ free (emsg);
+ return -1;
+}
+
+int
+klips_hex_decode (char *src, u_char *dst, int dstsize)
+{
+ char *p, *pe;
+ u_char *q, *qe, ch, cl;
+
+ pe = src + strlen (src);
+ qe = dst + dstsize;
+
+ for (p = src, q = dst; p < pe && q < qe && isxdigit ((int)*p); p += 2)
+ {
+ ch = tolower (p[0]);
+ cl = tolower (p[1]);
+
+ if ((ch >= '0') && (ch <= '9'))
+ ch -= '0';
+ else if ((ch >= 'a') && (ch <= 'f'))
+ ch -= 'a' - 10;
+ else
+ return -1;
+
+ if ((cl >= '0') && (cl <= '9'))
+ cl -= '0';
+ else if ((cl >= 'a') && (cl <= 'f'))
+ cl -= 'a' - 10;
+ else
+ return -1;
+
+ *q++ = (ch << 4) | cl;
+ }
+
+ return (int)(q - dst);
+}
+
+/* Consult kernel routing table for next-hop lookup. From dugsong@monkey.org */
+u_long
+klips_route_get (u_long dst)
+{
+ FILE *f;
+ char buf[BUFSIZ];
+ char ifbuf[16], netbuf[128], gatebuf[128], maskbuf[128];
+ int i, iflags, refcnt, use, metric, mss, win, irtt;
+ u_long ret, gate, net, mask;
+
+ if ((f = fopen (PROC_ROUTE_FILE, "r")) == NULL)
+ return dst;
+
+ ret = dst;
+
+ while (fgets (buf, sizeof buf, f) != NULL)
+ {
+ i = sscanf (buf, PROC_ROUTE_FMT, ifbuf, netbuf, gatebuf, &iflags,
+ &refcnt, &use, &metric, maskbuf, &mss, &win, &irtt);
+ if (i < 10 || !(iflags & RTF_UP))
+ continue;
+
+ klips_hex_decode (netbuf, (u_char *)&net, sizeof net);
+ klips_hex_decode (gatebuf, (u_char *)&gate, sizeof gate);
+ klips_hex_decode (maskbuf, (u_char *)&mask, sizeof mask);
+
+ net = htonl (net);
+ gate = htonl (gate);
+ mask = htonl (mask);
+
+ if ((dst & mask) == net)
+ {
+ if (gate != INADDR_ANY)
+ ret = gate;
+ break;
+ }
+ }
+
+ fclose (f);
+ return ret;
+}
+
+/* Enable a flow given a SA. */
+int
+klips_enable_sa (struct sa *sa, struct sa *isakmp_sa)
+{
+ struct ipsec_sa *isa = sa->data;
+ struct sockaddr *dst;
+ int dstlen;
+ struct proto *proto = TAILQ_FIRST (&sa->protos);
+ struct ipsec_proto *iproto = proto->data;
+ struct encap_msghdr emsg;
+ int s = -1;
+ struct rtentry rt;
+
+ sa->transport->vtbl->get_dst (sa->transport, &dst, &dstlen);
+
+ /* XXX Is this needed? */
+ memset (&emsg, '\0', sizeof emsg);
+
+ emsg.em_msglen = sizeof emsg;
+ emsg.em_type = EMT_RPLACEROUTE;
+
+ memcpy (&emsg.em_erspi, proto->spi[0], sizeof emsg.em_erspi);
+ emsg.em_erdst = ((struct sockaddr_in *)dst)->sin_addr;
+
+ LOG_DBG ((LOG_SYSDEP, 50, "klips_enable_sa: src %x %x dst %x %x",
+ ntohl (isa->src_net), ntohl (isa->src_mask), ntohl (isa->dst_net),
+ ntohl (isa->dst_mask)));
+
+ /* XXX Magic constant from Pluto (26 = AF_ISDN in BSD). */
+ emsg.em_eaddr.sen_family = emsg.em_emask.sen_family = 26;
+ emsg.em_eaddr.sen_type = SENT_IP4;
+ /* XXX Magic constant from Pluto. */
+ emsg.em_emask.sen_type = 255;
+ emsg.em_eaddr.sen_len = emsg.em_emask.sen_len
+ = sizeof (struct sockaddr_encap);
+
+ emsg.em_eaddr.sen_ip_src.s_addr = isa->src_net;
+ emsg.em_emask.sen_ip_src.s_addr = isa->src_mask;
+ emsg.em_eaddr.sen_ip_dst.s_addr = isa->dst_net;
+ emsg.em_emask.sen_ip_dst.s_addr = isa->dst_mask;
+
+ /* XXX What if IPCOMP etc. comes along? */
+ emsg.em_erproto
+ = (iproto->encap_mode == IPSEC_ENCAP_TUNNEL ? IPPROTO_IPIP
+ : proto->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH);
+
+ if (klips_write (&emsg))
+ {
+ emsg.em_type = EMT_SETEROUTE;
+ if (klips_write (&emsg))
+ goto cleanup;
+ }
+
+ s = socket (PF_INET, SOCK_DGRAM, AF_UNSPEC);
+ if (s == -1)
+ {
+ log_error ("klips_enable_sa: "
+ "socket(PF_INET, SOCK_DGRAM, AF_UNSPEC) failed");
+ goto cleanup;
+ }
+
+ memset (&rt, '\0', sizeof rt);
+ rt.rt_dst.sa_family = AF_INET;
+ ((struct sockaddr_in *)&rt.rt_dst)->sin_addr.s_addr = isa->dst_net;
+ rt.rt_genmask.sa_family = AF_INET;
+ ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = isa->dst_mask;
+ rt.rt_gateway.sa_family = AF_INET;
+
+ ((struct sockaddr_in *)&rt.rt_gateway)->sin_addr.s_addr
+ = klips_route_get (emsg.em_erdst.s_addr);
+
+ rt.rt_flags = RTF_UP | RTF_GATEWAY;
+ /* XXX What if we have multiple interfaces? */
+ rt.rt_dev = "ipsec0";
+
+ if (ioctl (s, SIOCDELRT, &rt) == -1 && errno != ESRCH)
+ {
+ log_error ("klips_enable_sa: ioctl (%d, SIOCDELRT, %p) failed", s, &rt);
+ goto cleanup;
+ }
+
+ if (ioctl (s, SIOCADDRT, &rt) == -1)
+ {
+ log_error ("klips_enable_sa: ioctl (%d, SIOCADDRT, %p) failed", s, &rt);
+ goto cleanup;
+ }
+
+ close (s);
+ return 0;
+
+ cleanup:
+ if (s != -1)
+ close (s);
+ return -1;
+}
+
+static void
+klips_stayalive (struct exchange *exchange, void *vconn, int fail)
+{
+ char *conn = vconn;
+ struct sa *sa;
+
+ /* XXX What if it is phase 1? */
+ sa = sa_lookup_by_name (conn, 2);
+ if (sa)
+ sa->flags |= SA_FLAG_STAYALIVE;
+}
+
+/* Establish the connection in VCONN and set the stayalive flag for it. */
+void
+klips_connection_check (char *conn)
+{
+ if (!sa_lookup_by_name (conn, 2))
+ {
+ LOG_DBG ((LOG_SYSDEP, 70, "klips_connection_check: SA for %s missing",
+ conn));
+ exchange_establish (conn, klips_stayalive, conn);
+ }
+ else
+ LOG_DBG ((LOG_SYSDEP, 70, "klips_connection_check: SA for %s exists",
+ conn));
+}
diff --git a/sbin/isakmpd/sysdep/linux/klips.h b/sbin/isakmpd/sysdep/linux/klips.h
new file mode 100644
index 00000000000..fdc1fcbe369
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/klips.h
@@ -0,0 +1,56 @@
+/* $Id: klips.h,v 1.1 2001/01/26 11:34:04 niklas Exp $ */
+
+/*
+ * Copyright (c) 1999 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ericsson Radio Systems.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _KLIPS_H_
+#define _KLIPS_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+struct proto;
+struct sa;
+struct sockaddr;
+
+extern void klips_connection_check (char *);
+extern int klips_delete_spi (struct sa *, struct proto *, int);
+extern int klips_enable_sa (struct sa *, struct sa *);
+extern u_int8_t *klips_get_spi (size_t *, u_int8_t, struct sockaddr *, int,
+ struct sockaddr *, int);
+extern int klips_group_spis (struct sa *, struct proto *, struct proto *,
+ int);
+extern int klips_open (void);
+extern int klips_set_spi (struct sa *, struct proto *, int);
+
+#endif /* _KLIPS_H_ */
diff --git a/sbin/isakmpd/sysdep/linux/sys/queue.h b/sbin/isakmpd/sysdep/linux/sys/queue.h
new file mode 100644
index 00000000000..6af6f7418bd
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/sys/queue.h
@@ -0,0 +1,337 @@
+/* $OpenBSD: queue.h,v 1.3 2001/01/26 11:34:05 niklas Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
+
+/*
+ * 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
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+/*
+ * This file defines four types of data structures: lists, simple queues,
+ * tail queues, and circular queues.
+ *
+ * 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 simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so only elements can only be removed from the
+ * head of 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 simple queue 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.
+ *
+ * A circle 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 circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+#define LIST_END(head) NULL
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ (head)->lh_first = NULL; \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \
+ if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_END(head) NULL
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_END(head) ((void *)(head))
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+} while (0)
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/sbin/isakmpd/sysdep/linux/sysdep-os.h b/sbin/isakmpd/sysdep/linux/sysdep-os.h
new file mode 100644
index 00000000000..4d5362e0d2f
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/sysdep-os.h
@@ -0,0 +1,51 @@
+/* $Id: sysdep-os.h,v 1.3 2001/01/26 11:34:04 niklas Exp $ */
+
+/*
+ * Copyright (c) 1998, 1999 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ericsson Radio Systems.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _SYSDEP_OS_H_
+#define _SYSDEP_OS_H_
+
+typedef u_int16_t in_port_t;
+typedef u_int32_t in_addr_t;
+
+#if 0
+/*
+ * Why -D__USE_GNU does not work in order to get this from stdio.h beats me.
+ */
+extern int asprintf __P((char **, const char *, ...));
+#endif
+
+#define DL_LAZY RTLD_LAZY
+
+#endif /* _SYSDEP_OS_H_ */
diff --git a/sbin/isakmpd/sysdep/linux/sysdep.c b/sbin/isakmpd/sysdep/linux/sysdep.c
new file mode 100644
index 00000000000..d96d6d86a10
--- /dev/null
+++ b/sbin/isakmpd/sysdep/linux/sysdep.c
@@ -0,0 +1,165 @@
+/* $Id: sysdep.c,v 1.3 2001/01/26 11:34:04 niklas Exp $ */
+
+/*
+ * Copyright (c) 1998, 1999 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Ericsson Radio Systems.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <md5.h>
+#include <unistd.h>
+
+#include "sysdep.h"
+
+#ifdef NEED_SYSDEP_APP
+#include "app.h"
+#include "conf.h"
+#include "ipsec.h"
+#include "klips.h"
+#endif NEED_SYSDEP_APP
+#include "log.h"
+#include "sysdep.h"
+
+extern char *__progname;
+
+u_int32_t
+sysdep_random ()
+{
+ u_int32_t rndval;
+ u_char sig[16];
+ MD5_CTX ctx;
+ int fd, i;
+ struct {
+ struct timeval tv;
+ u_int rnd[(128 - sizeof (struct timeval)) / sizeof (u_int)];
+ } rdat;
+
+ fd = open ("/dev/urandom", O_RDONLY);
+ if (fd != -1)
+ {
+ read (fd, rdat.rnd, sizeof(rdat.rnd));
+ close (fd);
+ }
+ MD5Init (&ctx);
+ MD5Update (&ctx, (char *)&rdat, sizeof(rdat));
+ MD5Final (sig, &ctx);
+
+ rndval = 0;
+ for (i = 0; i < 4; i++)
+ {
+ u_int32_t *tmp = (u_int32_t *)&sig[i * 4];
+ rndval ^= *tmp;
+ }
+
+ return rndval;
+}
+
+char *
+sysdep_progname ()
+{
+ return __progname;
+}
+
+/* As regress/ use this file I protect the sysdep_app_* stuff like this. */
+#ifdef NEED_SYSDEP_APP
+int
+sysdep_app_open ()
+{
+ return klips_open ();
+}
+
+void
+sysdep_app_handler (int fd)
+{
+}
+
+/* Check that the connection named NAME is active, or else make it active. */
+void
+sysdep_connection_check (char *name)
+{
+ klips_connection_check (name);
+}
+
+/*
+ * Generate a SPI for protocol PROTO and the source/destination pair given by
+ * SRC, SRCLEN, DST & DSTLEN. Stash the SPI size in SZ.
+ */
+u_int8_t *
+sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
+ int srclen, struct sockaddr *dst, int dstlen)
+{
+ if (app_none)
+ {
+ *sz = IPSEC_SPI_SIZE;
+ /* XXX should be random instead I think. */
+ return strdup ("\x12\x34\x56\x78");
+ }
+
+ return klips_get_spi (sz, proto, src, srclen, dst, dstlen);
+}
+
+int
+sysdep_cleartext (int fd)
+{
+ return 0;
+}
+
+int
+sysdep_ipsec_delete_spi (struct sa *sa, struct proto *proto, int incoming)
+{
+ return klips_delete_spi (sa, proto, incoming);
+}
+
+int
+sysdep_ipsec_enable_sa (struct sa *sa, struct sa *isakmp_sa)
+{
+ return klips_enable_sa (sa, isakmp_sa);
+}
+
+int
+sysdep_ipsec_group_spis (struct sa *sa, struct proto *proto1,
+ struct proto *proto2, int incoming)
+{
+ return klips_group_spis (sa, proto1, proto2, incoming);
+}
+
+int
+sysdep_ipsec_set_spi (struct sa *sa, struct proto *proto, int incoming)
+{
+ return klips_set_spi (sa, proto, incoming);
+}
+#endif