diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-01-26 11:34:09 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-01-26 11:34:09 +0000 |
commit | a35fc8c0e0c41c0e6a4d15f10830e55a41173829 (patch) | |
tree | 395f7779b596a1ca851896ab70168d28a0f46039 /sbin/isakmpd/sysdep/linux | |
parent | 357f350df412081108ea92adbc0dd739527481df (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.sysdep | 77 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/Makefile.sysdep | 86 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/README | 16 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/klips.c | 687 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/klips.h | 56 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/sys/queue.h | 337 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/sysdep-os.h | 51 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/sysdep.c | 165 |
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 |