diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/include/net/sock.h linux-patched/include/net/sock.h
--- linux/include/net/sock.h	Wed Aug 27 15:52:54 2003
+++ linux-patched/include/net/sock.h	Wed Aug 27 15:58:59 2003
@@ -245,6 +245,12 @@
 	__u32	end_seq;
 };
 
+#if 1
+struct udp_opt {
+	__u32 esp_in_udp;
+};
+#endif
+
 struct tcp_opt {
 	int	tcp_header_len;	/* Bytes of tcp header to send		*/
 
@@ -584,6 +590,9 @@
 #if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE)
 		struct spx_opt		af_spx;
 #endif /* CONFIG_SPX */
+#if 1
+		struct udp_opt 		af_udp;
+#endif
 
 	} tp_pinfo;
 
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/Config.in linux-patched/net/Config.in
--- linux/net/Config.in	Wed Aug 27 15:52:58 2003
+++ linux-patched/net/Config.in	Wed Aug 27 15:58:59 2003
@@ -88,4 +88,9 @@
 #bool 'Network code profiler' CONFIG_NET_PROFILE
 endmenu
 
+tristate 'IP Security Protocol (FreeS/WAN IPSEC)' CONFIG_IPSEC
+if [ "$CONFIG_IPSEC" != "n" ]; then
+  source net/ipsec/Config.in
+fi
+
 endmenu
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/Makefile linux-patched/net/Makefile
--- linux/net/Makefile	Wed Aug 27 15:52:57 2003
+++ linux-patched/net/Makefile	Wed Aug 27 15:58:59 2003
@@ -17,6 +17,7 @@
 subdir-$(CONFIG_NET)		+= 802 sched
 subdir-$(CONFIG_INET)		+= ipv4
 subdir-$(CONFIG_NETFILTER)	+= ipv4/netfilter
+subdir-$(CONFIG_IPSEC)		+= ipsec
 subdir-$(CONFIG_UNIX)		+= unix
 subdir-$(CONFIG_IPV6)		+= ipv6
 
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/Config.in linux-patched/net/ipsec/Config.in
--- linux/net/ipsec/Config.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/Config.in	Thu Sep  5 04:53:52 2002
@@ -0,0 +1,63 @@
+#
+# IPSEC configuration
+# Copyright (C) 1998, 1999, 2000,2001  Richard Guy Briggs.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+
+comment 'IPSec options (FreeS/WAN)'
+
+bool '   IPSEC: IP-in-IP encapsulation (tunnel mode)' CONFIG_IPSEC_IPIP
+
+bool '   IPSEC: Authentication Header' CONFIG_IPSEC_AH
+if [ "$CONFIG_IPSEC_AH" = "y" -o "$CONFIG_IPSEC_ESP" = "y" ]; then
+  bool '      HMAC-MD5 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_MD5
+  bool '      HMAC-SHA1 authentication algorithm' CONFIG_IPSEC_AUTH_HMAC_SHA1
+fi
+
+bool '   IPSEC: Encapsulating Security Payload' CONFIG_IPSEC_ESP
+if [ "$CONFIG_IPSEC_ESP" = "y" ]; then
+  bool '      3DES encryption algorithm' CONFIG_IPSEC_ENC_3DES
+fi
+
+bool '   IPSEC Modular Extensions' CONFIG_IPSEC_ALG
+if [ "$CONFIG_IPSEC_ALG" != "n" ]; then
+	source net/ipsec/alg/Config.in
+fi
+
+bool '   IPSEC: IP Compression' CONFIG_IPSEC_IPCOMP
+
+bool '   IPSEC Debugging Option' CONFIG_IPSEC_DEBUG
+
+bool '   IPSEC NAT-Traversal' CONFIG_IPSEC_NAT_TRAVERSAL
+
+#
+#
+# $Log: super-freeswan-1.99.8-delsol1.diff,v $
+# Revision 1.1  2003/09/09 09:20:34  john
+# Initial import
+#
+# Revision 1.3  2002/09/05 03:53:52  ken
+# Added NAT-T Patch
+#
+# Revision 1.2  2002/09/05 03:27:08  ken
+# Applied freeswan-alg-0.8.0-BASE-klips.diff
+#
+# Revision 1.1.1.1  2002/09/05 03:13:17  ken
+# 1.98b
+#
+# Revision 1.25  2002/02/21 19:55:12  mcr
+# 	removed all traces of IPSEC_CONFIG_REGRESS because it
+# 	screwed up 2.2's "make menuconfig" scripts.
+#
+# Revision 1.24  2002/01/28 20:24:31  mcr
+# 	commented out IPSEC_REGRESS option from user visible config.
+#
+#
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/Makefile linux-patched/net/ipsec/Makefile
--- linux/net/ipsec/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/Makefile	Fri Feb  7 13:14:24 2003
@@ -0,0 +1,333 @@
+# Makefile for KLIPS kernel code
+# Copyright (C) 1998, 1999, 2000,2001  Richard Guy Briggs.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+ifndef TOPDIR
+TOPDIR  := /usr/src/linux
+endif
+
+subdir-  := 
+subdir-n := 
+subdir-y :=
+subdir-m :=
+
+O_TARGET := ipsec.o
+obj-y := ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o
+obj-y += ipsec_life.o ipsec_proc.o
+obj-y += ipsec_tunnel.o ipsec_rcv.o sysctl_net_ipsec.o 
+obj-y +=  pfkey_v2.o pfkey_v2_parser.o 
+
+export-objs := radij.o
+
+obj-$(CONFIG_IPSEC_ALG) +=ipsec_alg.o alg/ipsec_alg_static.o
+export-objs += ipsec_alg.o
+subdir-m += alg
+
+# 'override CFLAGS' should really be 'EXTRA_CFLAGS'
+EXTRA_CFLAGS += -Ilibfreeswan -Ilibdes
+ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.2-2)
+EXTRA_CFLAGS += -DREDHAT_BOGOSITY
+endif
+ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.3-12)
+EXTRA_CFLAGS += -DREDHAT_BOGOSITY
+endif
+
+#ifeq ($(CONFIG_IPSEC_DEBUG),y)
+#EXTRA_CFLAGS += -g
+#endif
+
+EXTRA_CFLAGS += $(KLIPSCOMPILE)
+EXTRA_CFLAGS += -Wall
+#EXTRA_CFLAGS += -Werror
+#EXTRA_CFLAGS += -Wconversion 
+#EXTRA_CFLAGS += -Wmissing-prototypes 
+EXTRA_CFLAGS += -Wpointer-arith 
+#EXTRA_CFLAGS += -Wcast-qual 
+#EXTRA_CFLAGS += -Wmissing-declarations 
+EXTRA_CFLAGS += -Wstrict-prototypes
+#EXTRA_CFLAGS += -pedantic
+#EXTRA_CFLAGS += -O3
+#EXTRA_CFLAGS += -W
+#EXTRA_CFLAGS += -Wwrite-strings 
+#EXTRA_CFLAGS += -Wbad-function-cast 
+
+obj-$(CONFIG_IPSEC_ENC_3DES) += libdes/libdes.a
+obj-$(CONFIG_IPSEC_AUTH_HMAC_MD5) += ipsec_md5c.o
+obj-$(CONFIG_IPSEC_AUTH_HMAC_SHA1) += ipsec_sha1.o
+obj-$(CONFIG_IPSEC_IPCOMP) += ipcomp.o zlib/zlib.a
+subdir-$(CONFIG_IPSEC_IPCOMP) += zlib
+subdir-$(CONFIG_IPSEC) += libfreeswan
+obj-y += libfreeswan/libkernel.a
+
+###
+### Pre Rules.make
+###
+# undo O_TARGET, obj-y if no static
+ifneq ($(CONFIG_IPSEC),y)
+O_TARGET := 
+ipsec_obj-y := $(obj-y)
+obj-y :=
+subdir-y :=
+endif
+
+# Define obj-m if modular ipsec 
+ifeq ($(CONFIG_IPSEC),m)
+obj-m += ipsec.o
+endif
+
+
+# These rules translate from new to old makefile rules
+# Translate to Rules.make lists.
+multi-used      := $(filter $(list-multi), $(obj-y) $(obj-m))
+multi-objs      := $(foreach m, $(multi-used), $($(basename $(m))-objs))
+active-objs     := $(sort $(multi-objs) $(obj-y) $(obj-m))
+O_OBJS          := $(obj-y)
+M_OBJS          := $(obj-m)
+MIX_OBJS        := $(filter $(export-objs), $(active-objs))
+OX_OBJS := $(export-objs)
+SUB_DIRS := $(subdir-y)
+ALL_SUB_DIRS := $(subdir-y) $(subdir-m)
+MOD_SUB_DIRS := $(subdir-m)
+
+#   dunno why, but some 2.2 setups may need explicit -DEXPORT_SYMTAB
+#   uncomment next line if ipsec_alg.c compilation fails with
+#   "parse error before `EXPORT_SYMTAB_not_defined'"  --Juanjo
+# CFLAGS_ipsec_alg.o += -DEXPORT_SYMTAB
+#
+
+include $(TOPDIR)/Rules.make
+
+###
+### Post Rules.make
+###
+# for modular ipsec, no O_TARGET defined => define ipsec.o creation rules
+ifeq ($(CONFIG_IPSEC),m)
+ipsec.o : $(ipsec_obj-y)
+	rm -f $@
+	$(LD) $(LD_EXTRAFLAGS) -r $(ipsec_obj-y) -o $@
+endif
+
+$(ipsec_obj-y) $(obj-y) $(obj-m):  $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h
+
+libdes/libdes.a:
+	( cd libdes && \
+	if test " `arch | sed 's/^i[3456]/x/'`" = " x86" ; \
+	then $(MAKE) CC='$(CC)' CFLAG='$(CFLAGS)' TESTING='' x86-elf ; \
+	else $(MAKE) CC='$(CC)' CFLAG='$(CFLAGS)' libdes.a ; \
+	fi )
+
+libfreeswan/libkernel.a:
+	$(MAKE) -C libfreeswan
+
+zlib/zlib.a:
+	$(MAKE) -C zlib
+
+alg/ipsec_alg_static.o: dummy
+	$(MAKE) -C alg CC='$(CC)' CFLAGS='$(CFLAGS)' ipsec_alg_static.o
+
+clean:
+	$(MAKE) -C alg clean
+	-rm -f *.o
+
+tags TAGS: *.c *.h libfreeswan/*.c libfreeswan/*.h
+	find . -name '*.[ch]' |xargs etags
+	find . -name '*.[ch]' |xargs ctags
+
+tar:
+		tar -cvf /dev/f1 .
+
+#
+# $Log: super-freeswan-1.99.8-delsol1.diff,v $
+# Revision 1.1  2003/09/09 09:20:34  john
+# Initial import
+#
+# Revision 1.3  2003/02/07 13:14:24  ken
+# Pullin jjo's ALG 0.8.1rc branch
+#
+# Revision 1.2.2.1  2003/02/06 22:09:49  jjo
+# sync to alg-0.8.1-rc4
+#
+# Revision 1.2  2002/09/05 03:27:08  ken
+# Applied freeswan-alg-0.8.0-BASE-klips.diff
+#
+# Revision 1.1.1.1  2002/09/05 03:13:17  ken
+# 1.98b
+#
+# Revision 1.39  2002/01/17 04:39:40  rgb
+# Take compile options from top level Makefile.inc
+#
+# Revision 1.38  2001/11/27 05:28:07  rgb
+# Shut off -Werror until we figure out a graceful way of quieting down the
+# pfkey_ops defined but not used complaint in the case of SMP in
+# pfkey_v2.c.
+#
+# Revision 1.37  2001/11/27 05:10:15  rgb
+# Added -Ilibdes and removed lib/des* symlinks.
+#
+# Revision 1.36  2001/11/26 09:23:47  rgb
+# Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+#
+# Revision 1.35.2.1  2001/09/25 02:17:50  mcr
+# 	added ipsec_sa, ipsec_life, ipsec_proc.
+# 	added -Werror to compile flags (see fix for zlib/zutil.h)
+#
+# Revision 1.3  2001/09/21 04:41:26  mcr
+# 	actually, ipsec_proc.c and ipsec_life.c were never actually compiled.
+#
+# Revision 1.2  2001/09/21 04:11:33  mcr
+# 	first compilable version.
+#
+# Revision 1.1.1.2  2001/09/17 01:17:52  mcr
+#   snapshot 2001-09-16
+#
+# Revision 1.35  2001/09/07 22:09:12  rgb
+# Quiet down compilation.
+#
+# Revision 1.34  2001/08/11 17:10:23  henry
+# update bogosity stuff to cover RH7.1 update
+#
+# Revision 1.33  2001/06/14 19:35:07  rgb
+# Update copyright date.
+#
+# Revision 1.32  2001/06/13 21:00:50  rgb
+# Added a kludge to get around RedHat kernel version bogosity...
+#
+# Revision 1.31  2001/01/29 22:19:06  rgb
+# Convert to 2.4 new style with back compat.
+#
+# Revision 1.30  2000/09/29 19:51:57  rgb
+# Moved klips/net/ipsec/ipcomp_* to zlib/* (Svenning).
+#
+# Revision 1.29  2000/09/15 11:37:01  rgb
+# Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+# IPCOMP zlib deflate code.
+#
+# Revision 1.28  2000/09/15 04:55:25  rgb
+# Clean up pfkey object inclusion into the default object.
+#
+# Revision 1.27  2000/09/12 03:20:47  rgb
+# Cleared out now unused pfkeyv2 switch.
+# Enabled sysctl.
+#
+# Revision 1.26  2000/09/08 19:12:55  rgb
+# Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+#
+# Revision 1.25  2000/06/16 03:09:16  rgb
+# Shut up cast lost warning due to changes in 2.4.0-test1.
+#
+# Revision 1.24  2000/03/16 06:40:48  rgb
+# Hardcode PF_KEYv2 support.
+#
+# Revision 1.23  2000/02/14 21:10:38  rgb
+# Added gcc debug flag when KLIPS_DEBUG is swtiched on.
+#
+# Revision 1.22  2000/01/21 09:44:29  rgb
+# Added compiler switches to be a lot more fussy.
+#
+# Revision 1.21  1999/11/25 23:35:20  rgb
+# Removed quotes to fix Alpha compile issues.
+#
+# Revision 1.20  1999/11/17 15:49:34  rgb
+# Changed all occurrences of ../../../lib in pathnames to libfreeswan,
+# which refers to the /usr/src/linux/net/ipsec/lib directory setup by the
+# klink target in the top-level Makefile; and libdeslite.o to
+# libdes/libdes.a.
+# Added SUB_DIRS := lib definition for the kernel libraries.
+#
+# Revision 1.19  1999/04/27 19:06:47  rgb
+# dd libs and dependancies to tags generation.
+#
+# Revision 1.18  1999/04/16 16:28:12  rgb
+# Minor bugfix to avoid including DES if only AH is used.
+#
+# Revision 1.17  1999/04/15 15:37:23  rgb
+# Forward check changes from POST1_00 branch.
+#
+# Revision 1.14.2.1  1999/03/30 17:29:17  rgb
+# Add support for pfkey.
+#
+# Revision 1.16  1999/04/11 00:28:56  henry
+# GPL boilerplate
+#
+# Revision 1.15  1999/04/06 04:54:25  rgb
+# Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+# patch shell fixes.
+#
+# Revision 1.14  1999/02/18 16:50:45  henry
+# update for new DES library
+#
+# Revision 1.13  1999/02/12 21:11:45  rgb
+# Prepare for newer LIBDES (patch from P.Onion).
+#
+# Revision 1.12  1999/01/26 02:05:08  rgb
+# Remove references to INET_GET_PROTOCOL.
+# Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+# Change from transform switch to algorithm switch.
+#
+# Revision 1.11  1999/01/22 06:16:09  rgb
+# Added algorithm switch code config option.
+#
+# Revision 1.10  1998/11/08 05:31:21  henry
+# be a little fussier
+#
+# Revision 1.9  1998/11/08 05:29:41  henry
+# revisions for new libdes handling
+#
+# Revision 1.8  1998/08/12 00:05:48  rgb
+# Added new xforms to Makefile (moved des-cbc to des-old).
+#
+# Revision 1.7  1998/07/27 21:48:47  rgb
+# Add libkernel.
+#
+# Revision 1.6  1998/07/14 15:50:47  rgb
+# Add dependancies on linux config files.
+#
+# Revision 1.5  1998/07/09 17:44:06  rgb
+# Added 'clean' and 'tags' targets.
+# Added TOPDIR macro.
+# Change module back from symbol exporting to not.
+#
+# Revision 1.3  1998/06/25 19:25:04  rgb
+# Rearrange to support static linking and objects with exported symbol
+# tables.
+#
+# Revision 1.1  1998/06/18 21:27:42  henry
+# move sources from klips/src to klips/net/ipsec, to keep stupid
+# kernel-build scripts happier in the presence of symlinks
+#
+# Revision 1.3  1998/04/15 23:18:43  rgb
+# Unfixed the ../../libdes fix to avoid messing up Henry's script.
+#
+# Revision 1.2  1998/04/14 17:50:47  rgb
+# Fixed to find the new location of libdes.
+#
+# Revision 1.1  1998/04/09 03:05:22  henry
+# sources moved up from linux/net/ipsec
+# modifications to centralize libdes code
+#
+# Revision 1.1.1.1  1998/04/08 05:35:02  henry
+# RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+#
+# Revision 0.5  1997/06/03 04:24:48  ji
+# Added ESP-3DES-MD5-96
+#
+# Revision 0.4  1997/01/15 01:32:59  ji
+# Added new transforms.
+#
+# Revision 0.3  1996/11/20 14:22:53  ji
+# *** empty log message ***
+#
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/Makefile.inc linux-patched/net/ipsec/Makefile.inc
--- linux/net/ipsec/Makefile.inc	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/Makefile.inc	Wed Aug 27 15:58:54 2003
@@ -0,0 +1,182 @@
+# FreeS/WAN pathnames and other master configuration
+# Copyright (C) 2001, 2002  Henry Spencer.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+
+
+
+# Variables in this file with names starting with INC_ are not for use
+# by Makefiles which include it; they are subject to change without warning.
+#
+# "Final" and "finally" refer to where the files will end up on the
+# running IPsec system, as opposed to where they get installed by our
+# Makefiles.  (The two are different for cross-compiles and the like,
+# where our Makefiles are not the end of the installation process.)
+# Paths with FINAL in their names are the only ones that the installed
+# software itself depends on.  (Very few things should know about the
+# FINAL paths; think twice and consult Henry before making something new
+# depend on them.)  All other paths are install targets.
+# See also DESTDIR, below.
+
+
+
+### boilerplate, do not change
+SHELL=/bin/sh
+
+
+
+### install pathnames
+
+# DESTDIR can be used to supply a prefix to all install targets.
+# (Note that "final" pathnames, signifying where files will eventually
+# reside rather than where install puts them, are exempt from this.)
+# The prefixing is done in this file, so as to have central control over
+# it; DESTDIR itself should never appear in any other Makefile.
+DESTDIR?=
+
+# "local" part of tree, used in building other pathnames
+INC_USRLOCAL=/usr/local
+
+# PUBDIR is where the "ipsec" command goes; beware, many things define PATH
+# settings which are assumed to include it (or at least, to include *some*
+# copy of the "ipsec" command).
+PUBDIR=$(DESTDIR)$(INC_USRLOCAL)/sbin
+
+# BINDIR is where commands get put, FINALBINDIR is where the "ipsec"
+# command will look for them when it is run.
+FINALBINDIR=$(INC_USRLOCAL)/lib/ipsec
+BINDIR=$(DESTDIR)$(FINALBINDIR)
+
+# where the appropriate manpage tree is located
+# location within INC_USRLOCAL
+INC_MANDIR=man
+# the full pathname
+MANTREE=$(DESTDIR)$(INC_USRLOCAL)/$(INC_MANDIR)
+# all relevant subdirectories of MANTREE
+MANPLACES=man3 man5 man8
+
+# where configuration files go
+FINALCONFDIR=/etc
+CONFDIR=$(DESTDIR)$(FINALCONFDIR)
+
+# An attempt is made to automatically figure out where boot/shutdown scripts 
+# will finally go:  the first directory in INC_RCDIRS which exists gets them.
+# If none of those exists (or INC_RCDIRS is empty), INC_RCDEFAULT gets them.
+# With a non-null DESTDIR, INC_RCDEFAULT will be used unless one of the
+# INC_RCDIRS directories has been pre-created under DESTDIR.
+INC_RCDIRS=/etc/rc.d/init.d /etc/rc.d /etc/init.d /sbin/init.d
+INC_RCDEFAULT=/etc/rc.d/init.d
+
+# RCDIR is where boot/shutdown scripts go; FINALRCDIR is where they think
+# will finally be (so utils/Makefile can create a symlink in BINDIR to the
+# place where the boot/shutdown script will finally be, rather than the
+# place where it is installed).
+FINALRCDIR=$(shell for d in $(INC_RCDIRS) ; \
+		do if test -d $(DESTDIR)/$$d ; \
+		then echo $$d ; exit 0 ; \
+		fi ; done ; echo $(INC_RCDEFAULT) )
+RCDIR=$(DESTDIR)$(FINALRCDIR)
+
+
+
+### kernel pathnames
+
+# Kernel location:  where patches are inserted, where kernel builds are done.
+KERNELSRC?=/usr/src/redhat/BUILD/kernel-2.4.9/linux-patched
+
+# things whose existence indicates what kernel version we have
+DIRIN22=$(KERNELSRC)/net/netlink
+FILIN24=$(KERNELSRC)/net/khttpd/main.c
+
+# where kernel configuration outputs are located
+KCFILE=$(KERNELSRC)/.config
+ACFILE=$(KERNELSRC)/include/linux/autoconf.h
+VERFILE=$(KERNELSRC)/include/linux/version.h
+
+
+
+### misc installation stuff
+
+# what program to use when installing things
+INSTALL=install
+
+# flags to the install program, for programs, manpages, and config files
+# -b has install make backups (n.b., unlinks original), --suffix controls
+# how backup names are composed.
+# Note that the install procedures will never overwrite an existing config
+# file, which is why -b is not specified for them.
+INSTBINFLAGS=-b --suffix=.old
+INSTMANFLAGS=
+INSTCONFFLAGS=
+
+
+
+### misc configuration, included here in hopes that other files will not
+### have to be changed for common customizations.
+
+# extra compile flags, for userland and kernel stuff, e.g. -g for debug info
+# (caution, this stuff is still being sorted out, will change in future)
+USERCOMPILE=-g -O3
+KLIPSCOMPILE=-O3
+
+# command used to link/copy KLIPS into kernel source tree
+# There are good reasons why this is "ln -s"; only people like distribution
+# builders should ever change it.
+KLIPSLINK=ln -s
+
+# extra options for use in kernel build
+KERNMAKEOPTS=
+
+# kernel Makefile targets to be done before build
+# Can be overridden if you are *sure* your kernel doesn't need them.  (2.2.xx
+# and later reportedly do not.)
+KERNDEP=dep
+KERNCLEAN=clean
+
+# kernel make name:  zImage for 2.0.xx, bzImage for 2.2.xx and later, and
+# boot on non-x86s (what ever happened to standards?)
+INC_B=$(shell test -d $(DIRIN22) && echo b)
+KERNEL=$(shell if expr " `uname -m`" : ' i.86' >/dev/null ; \
+	then echo $(INC_B)zImage ; \
+	else echo boot ; \
+	fi)
+
+# temporary directory to be used when building RPMs, and where to put the
+# resulting RPM tree
+RPMKERNDIR := $(shell echo `pwd`/tmp.rpmkernel)
+RPMTMPDIR := $(shell echo `pwd`/tmp.rpmbuild)
+RPMDEST := $(shell echo `pwd`/rpms)
+# Newer versions of RPM do not permit building of packages with the "rpm" 
+# command. For RedHat systems with older version of RPM, use:
+# RPMBUILD=rpm
+# instead.
+RPMBUILD=rpmbuild
+
+#
+# Set this to a RedHat kernel-sources RPM. This normally extracts into
+# /usr/src/linux-2.4, but you might have extracted it elsewhere with
+# rpm2cpio.
+#
+RH_KERNELSRC=/usr/src/linux-2.4
+
+#RH_KERNELSRC=/a3/kernel_sources/linux-2.4.2
+#RH_KERNELSRC=/a3/kernel_sources/linux-2.4.9-13
+#RH_KERNELSRC=/c2/kernel/rh/linux-2.4.9-13
+
+# the following is a list of symbols which will be used to construct
+# the module goo to identify which module goes with each kernel.
+MODULE_GOO_LIST=irq_stat netif_rx register_sysctl_table send_sig
+MODULE_GOO_LIST+=kmalloc __kfree_skb __ip_select_ident alloc_skb
+MODULE_GOO_LIST+=icmp_send ip_fragment sock_register 
+
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/Makefile.ver linux-patched/net/ipsec/Makefile.ver
--- linux/net/ipsec/Makefile.ver	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/Makefile.ver	Tue Jul  8 20:02:03 2003
@@ -0,0 +1 @@
+IPSECVERSION=super-freeswan-1.99.8
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_1des.in linux-patched/net/ipsec/alg/Config.alg_1des.in
--- linux/net/ipsec/alg/Config.alg_1des.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_1des.in	Fri Feb  7 14:39:36 2003
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        1DES **INSECURE** encryption algorithm (modular alg)' CONFIG_IPSEC_ALG_1DES
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_3des.in linux-patched/net/ipsec/alg/Config.alg_3des.in
--- linux/net/ipsec/alg/Config.alg_3des.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_3des.in	Thu Sep  5 04:36:54 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        3DES encryption algorithm (modular alg)' CONFIG_IPSEC_ALG_3DES
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_aes.in linux-patched/net/ipsec/alg/Config.alg_aes.in
--- linux/net/ipsec/alg/Config.alg_aes.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_aes.in	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        AES encryption algorithm' CONFIG_IPSEC_ALG_AES
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_blowfish.in linux-patched/net/ipsec/alg/Config.alg_blowfish.in
--- linux/net/ipsec/alg/Config.alg_blowfish.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_blowfish.in	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        BLOWFISH encryption algorithm' CONFIG_IPSEC_ALG_BLOWFISH
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_cast.in linux-patched/net/ipsec/alg/Config.alg_cast.in
--- linux/net/ipsec/alg/Config.alg_cast.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_cast.in	Thu Sep  5 04:48:04 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        CAST encryption algorithm' CONFIG_IPSEC_ALG_CAST
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_cryptoapi.in linux-patched/net/ipsec/alg/Config.alg_cryptoapi.in
--- linux/net/ipsec/alg/Config.alg_cryptoapi.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_cryptoapi.in	Fri Feb 21 23:23:03 2003
@@ -0,0 +1,6 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  dep_tristate '        CRYPTOAPI ciphers support (needs cryptoapi patch)' CONFIG_IPSEC_ALG_CRYPTOAPI $CONFIG_CRYPTO
+  if [ "$CONFIG_IPSEC_ALG_CRYPTOAPI" != "n" ]; then
+    bool '          CRYPTOAPI proprietary ciphers ' CONFIG_IPSEC_ALG_NON_LIBRE
+  fi
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_md5.in linux-patched/net/ipsec/alg/Config.alg_md5.in
--- linux/net/ipsec/alg/Config.alg_md5.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_md5.in	Thu Sep  5 04:31:27 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        HMAC_MD5 auth algorithm (modular alg)' CONFIG_IPSEC_ALG_MD5
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_null.in linux-patched/net/ipsec/alg/Config.alg_null.in
--- linux/net/ipsec/alg/Config.alg_null.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_null.in	Thu Sep  5 04:49:06 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        NULL encryption algorithm' CONFIG_IPSEC_ALG_NULL
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_serpent.in linux-patched/net/ipsec/alg/Config.alg_serpent.in
--- linux/net/ipsec/alg/Config.alg_serpent.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_serpent.in	Thu Sep  5 04:43:55 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        SERPENT encryption algorithm' CONFIG_IPSEC_ALG_SERPENT
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_sha1.in linux-patched/net/ipsec/alg/Config.alg_sha1.in
--- linux/net/ipsec/alg/Config.alg_sha1.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_sha1.in	Thu Sep  5 04:34:24 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        HMAC_SHA1 auth algorithm (modular alg)' CONFIG_IPSEC_ALG_SHA1
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_sha2.in linux-patched/net/ipsec/alg/Config.alg_sha2.in
--- linux/net/ipsec/alg/Config.alg_sha2.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_sha2.in	Thu Sep  5 04:34:24 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        HMAC_SHA2 auth algorithm' CONFIG_IPSEC_ALG_SHA2
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.alg_twofish.in linux-patched/net/ipsec/alg/Config.alg_twofish.in
--- linux/net/ipsec/alg/Config.alg_twofish.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.alg_twofish.in	Thu Sep  5 04:41:17 2002
@@ -0,0 +1,3 @@
+if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
+  tristate '        TWOFISH encryption algorithm' CONFIG_IPSEC_ALG_TWOFISH
+fi
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Config.in linux-patched/net/ipsec/alg/Config.in
--- linux/net/ipsec/alg/Config.in	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Config.in	Tue May 20 02:12:35 2003
@@ -0,0 +1,13 @@
+#Placeholder
+source net/ipsec/alg/Config.alg_md5.in
+source net/ipsec/alg/Config.alg_sha1.in
+source net/ipsec/alg/Config.alg_sha2.in
+source net/ipsec/alg/Config.alg_3des.in
+source net/ipsec/alg/Config.alg_aes.in
+source net/ipsec/alg/Config.alg_blowfish.in
+source net/ipsec/alg/Config.alg_twofish.in
+source net/ipsec/alg/Config.alg_serpent.in
+source net/ipsec/alg/Config.alg_cast.in
+source net/ipsec/alg/Config.alg_null.in
+source net/ipsec/alg/Config.alg_cryptoapi.in
+source net/ipsec/alg/Config.alg_1des.in
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile linux-patched/net/ipsec/alg/Makefile
--- linux/net/ipsec/alg/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,104 @@
+# $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+KLIPSDIR:= $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)/..
+
+#LIBCRYPTO:=$(KLIPSDIR)/../../../libcrypto
+LIBCRYPTO:=$(KLIPSDIR)/libcrypto
+EXTRA_CFLAGS:=-I$(KLIPSDIR) -I$(KLIPSDIR)/libfreeswan -I$(LIBCRYPTO)/include -I$(LIBCRYPTO)
+ifeq ($(CONFIG_IPSEC_DEBUG),y)
+EXTRA_CFLAGS += -g
+endif
+EXTRA_CFLAGS += -Wall -Wpointer-arith -Wstrict-prototypes
+
+MOD_LIST_NAME := NET_MISC_MODULES
+
+#O_TARGET := ipsec_alg_static.o
+
+subdir-  := 
+subdir-n := 
+subdir-y :=
+subdir-m :=
+
+obj-y := ipsec_alg_static_init.o
+
+ARCH_ASM-y :=
+ARCH_ASM-$(CONFIG_M586)		:= i586
+ARCH_ASM-$(CONFIG_M586TSC)	:= i586
+ARCH_ASM-$(CONFIG_M586MMX)	:= i586
+ARCH_ASM-$(CONFIG_MK6)		:= i586
+ARCH_ASM-$(CONFIG_M686)		:= i686
+ARCH_ASM-$(CONFIG_MPENTIUMIII)	:= i686
+ARCH_ASM-$(CONFIG_MPENTIUM4)	:= i686
+ARCH_ASM-$(CONFIG_MK7)		:= i686
+ARCH_ASM-$(CONFIG_MCRUSOE)	:= i586
+ARCH_ASM-$(CONFIG_MWINCHIPC6)	:= i586
+ARCH_ASM-$(CONFIG_MWINCHIP2)	:= i586
+ARCH_ASM-$(CONFIG_MWINCHIP3D)	:= i586
+ARCH_ASM-$(CONFIG_USERMODE)	:= i586
+
+ARCH_ASM :=$(ARCH_ASM-y)
+ifdef NO_ASM
+ARCH_ASM :=
+endif
+
+## debug:
+#$(warning CONFIG_M586=$(CONFIG_M586))
+#$(warning CONFIG_M686=$(CONFIG_M686))
+#$(warning ARCH_ASM=$(ARCH_ASM))
+# The algorithm makefiles may put dependences, short-circuit them
+null:
+
+makefiles=$(wildcard Makefile.alg_*)
+ifneq ($(makefiles),)
+#include Makefile.alg_aes
+#include Makefile.alg_aes-opt
+include $(makefiles)
+endif
+
+# These rules translate from new to old makefile rules
+# Translate to Rules.make lists.
+multi-used      := $(filter $(list-multi), $(obj-y) $(obj-m))
+multi-objs      := $(foreach m, $(multi-used), $($(basename $(m))-objs))
+active-objs     := $(sort $(multi-objs) $(obj-y) $(obj-m))
+O_OBJS          := $(obj-y)
+M_OBJS          := $(obj-m)
+MIX_OBJS        := $(filter $(export-objs), $(active-objs))
+#OX_OBJS := $(export-objs)
+SUB_DIRS := $(subdir-y)
+ALL_SUB_DIRS := $(subdir-y) $(subdir-m)
+MOD_SUB_DIRS := $(subdir-m)
+
+
+ifdef TOPDIR
+include $(TOPDIR)/Rules.make
+endif
+
+ipsec_alg_static.o: $(obj-y) 
+	rm -f $@
+	$(LD) $(LD_EXTRAFLAGS) $(obj-y) -r -o $@
+
+perlasm: $(LIBCRYPTO)/perlasm
+	ln -sf $? $@
+
+$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h ../ipsec_alg.h
+$(alg_obj-y) $(alg_obj-m): perlasm $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h ../ipsec_alg.h
+
+
+alg_modules: perlasm $(ALG_MODULES)
+	@echo "ALG_MODULES=$(ALG_MODULES)"
+
+
+#
+# Construct alg. init. function: call ipsec_ALGO_init() for every static algo
+# Needed when there are static algos (with static or modular ipsec.o)
+#
+ipsec_alg_static_init.c: $(TOPDIR)/include/linux/autoconf.h Makefile $(makefiles) scripts/mk-static_init.c.sh
+	@echo "Re-creating $@"
+	$(SHELL) scripts/mk-static_init.c.sh $(static_init-func-y) > $@
+
+clean:
+	@for i in $(ALG_SUBDIRS);do test -d $$i && make -C $$i clean;done;exit 0
+	@find . -type l  -exec rm -f {} \;
+	-rm -f perlasm
+	-rm -rf $(ALG_SUBDIRS)
+	-rm -f *.o ipsec_alg_static_init.c
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_1des linux-patched/net/ipsec/alg/Makefile.alg_1des
--- linux/net/ipsec/alg/Makefile.alg_1des	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_1des	Fri Mar 28 13:56:19 2003
@@ -0,0 +1,20 @@
+MOD_1DES += ipsec_1des.o
+
+ALG_MODULES += $(MOD_1DES)
+ALG_SUBDIRS += libdes
+
+obj-$(CONFIG_IPSEC_ALG_1DES) += $(MOD_1DES)
+static_init-func-$(CONFIG_IPSEC_ALG_1DES)+= ipsec_1des_init
+alg_obj-$(CONFIG_IPSEC_ALG_1DES) += ipsec_alg_1des.o
+
+DES_1DES_OBJS=ipsec_alg_1des.o ../libdes/libdes.a
+
+$(MOD_1DES): $(DES_1DES_OBJS)
+	$(LD) -r $(DES_1DES_OBJS) -o $@
+
+# avoid multiple rules for libdes.a
+ifeq ($(LIBDES),)
+LIBDES:=../libdes/libdes.a
+$(LIBDES):
+	$(MAKE) -C .. libdes/libdes.a
+endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_3des linux-patched/net/ipsec/alg/Makefile.alg_3des
--- linux/net/ipsec/alg/Makefile.alg_3des	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_3des	Fri Mar 28 13:56:19 2003
@@ -0,0 +1,20 @@
+MOD_3DES += ipsec_3des.o
+
+ALG_MODULES += $(MOD_3DES)
+ALG_SUBDIRS += libdes
+
+obj-$(CONFIG_IPSEC_ALG_3DES) += $(MOD_3DES)
+static_init-func-$(CONFIG_IPSEC_ALG_3DES)+= ipsec_3des_init
+alg_obj-$(CONFIG_IPSEC_ALG_3DES) += ipsec_alg_3des.o
+
+DES_3DES_OBJS=ipsec_alg_3des.o ../libdes/libdes.a
+
+$(MOD_3DES): $(DES_3DES_OBJS)
+	$(LD) -r $(DES_3DES_OBJS) -o $@
+
+# avoid multiple rules for libdes.a
+ifeq ($(LIBDES),)
+LIBDES:=../libdes/libdes.a
+$(LIBDES):
+	$(MAKE) -C .. libdes/libdes.a
+endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_aes linux-patched/net/ipsec/alg/Makefile.alg_aes
--- linux/net/ipsec/alg/Makefile.alg_aes	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_aes	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,23 @@
+MOD_AES := ipsec_aes.o
+
+ALG_MODULES += $(MOD_AES)
+ALG_SUBDIRS += libaes
+
+obj-$(CONFIG_IPSEC_ALG_AES) += $(MOD_AES)
+static_init-func-$(CONFIG_IPSEC_ALG_AES)+= ipsec_aes_init
+alg_obj-$(CONFIG_IPSEC_ALG_AES) += ipsec_alg_aes.o
+
+AES_OBJS := ipsec_alg_aes.o libaes/libaes.a 
+
+$(MOD_AES): libaes $(AES_OBJS) 
+	$(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@
+
+libaes: $(LIBCRYPTO)/libaes
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+	cd $@/asm && ln -sf $?/asm/*.S .
+
+libaes/libaes.a: libaes
+	( cd libaes && \
+		$(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libaes.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_blowfish linux-patched/net/ipsec/alg/Makefile.alg_blowfish
--- linux/net/ipsec/alg/Makefile.alg_blowfish	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_blowfish	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,23 @@
+MOD_BLOWFISH := ipsec_blowfish.o
+
+ALG_MODULES += $(MOD_BLOWFISH)
+ALG_SUBDIRS += libblowfish
+
+obj-$(CONFIG_IPSEC_ALG_BLOWFISH) += $(MOD_BLOWFISH)
+static_init-func-$(CONFIG_IPSEC_ALG_BLOWFISH)+= ipsec_blowfish_init
+alg_obj-$(CONFIG_IPSEC_ALG_BLOWFISH) += ipsec_alg_blowfish.o
+
+BLOWFISH_OBJS:= ipsec_alg_blowfish.o libblowfish/libblowfish.a
+
+$(MOD_BLOWFISH): libblowfish $(BLOWFISH_OBJS)
+	$(LD) -r $(BLOWFISH_OBJS) -o $@
+
+libblowfish : $(LIBCRYPTO)/libblowfish 
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+	cd $@/asm && ln -sf $?/asm/*.pl .
+
+libblowfish/libblowfish.a:
+	( cd libblowfish && \
+		$(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libblowfish.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_cast linux-patched/net/ipsec/alg/Makefile.alg_cast
--- linux/net/ipsec/alg/Makefile.alg_cast	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_cast	Thu Sep  5 04:48:04 2002
@@ -0,0 +1,23 @@
+MOD_CAST := ipsec_cast.o
+
+ALG_MODULES += $(MOD_CAST)
+ALG_SUBDIRS += libcast
+
+obj-$(CONFIG_IPSEC_ALG_CAST) += $(MOD_CAST)
+static_init-func-$(CONFIG_IPSEC_ALG_CAST)+= ipsec_cast_init
+alg_obj-$(CONFIG_IPSEC_ALG_CAST) += ipsec_alg_cast.o
+
+CAST_OBJS := ipsec_alg_cast.o libcast/libcast.a
+
+$(MOD_CAST): libcast $(CAST_OBJS)
+	$(LD) -r $(CAST_OBJS) -o $@
+
+libcast : $(LIBCRYPTO)/libcast 
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+	cd $@/asm && ln -sf $?/asm/*.pl .
+
+libcast/libcast.a:
+	( cd libcast && \
+		$(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libcast.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_cryptoapi linux-patched/net/ipsec/alg/Makefile.alg_cryptoapi
--- linux/net/ipsec/alg/Makefile.alg_cryptoapi	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_cryptoapi	Fri Feb  7 14:39:36 2003
@@ -0,0 +1,11 @@
+MOD_CRYPTOAPI := ipsec_cryptoapi.o
+
+ALG_MODULES += $(MOD_CRYPTOAPI)
+
+obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += $(MOD_CRYPTOAPI)
+static_init-func-$(CONFIG_IPSEC_ALG_CRYPTOAPI)+= ipsec_cryptoapi_init
+alg_obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += ipsec_alg_cryptoapi.o
+
+CRYPTOAPI_OBJS := ipsec_alg_cryptoapi.o 
+$(MOD_CRYPTOAPI): $(CRYPTOAPI_OBJS)
+	$(LD) -r $(CRYPTOAPI_OBJS) -o $@
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_md5 linux-patched/net/ipsec/alg/Makefile.alg_md5
--- linux/net/ipsec/alg/Makefile.alg_md5	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_md5	Thu Sep  5 04:31:27 2002
@@ -0,0 +1,23 @@
+MOD_MD5 := ipsec_md5.o
+
+ALG_MODULES += $(MOD_MD5)
+ALG_SUBDIRS += libmd5
+
+obj-$(CONFIG_IPSEC_ALG_MD5) += $(MOD_MD5)
+static_init-func-$(CONFIG_IPSEC_ALG_MD5)+= ipsec_md5_init
+alg_obj-$(CONFIG_IPSEC_ALG_MD5) += ipsec_alg_md5.o
+
+MD5_OBJS :=ipsec_alg_md5.o libmd5/libmd5.a
+
+$(MOD_MD5): libmd5 $(MD5_OBJS)
+	$(LD) $(EXTRA_LDFLAGS) -r $(MD5_OBJS) -o $@
+
+libmd5 : $(LIBCRYPTO)/libmd5 
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+	cd $@/asm && ln -sf $?/asm/*.pl .
+
+libmd5/libmd5.a:
+	( cd libmd5 && \
+		$(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libmd5.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_null linux-patched/net/ipsec/alg/Makefile.alg_null
--- linux/net/ipsec/alg/Makefile.alg_null	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_null	Thu Sep  5 04:49:06 2002
@@ -0,0 +1,13 @@
+MOD_NULL := ipsec_null.o
+
+ALG_MODULES += $(MOD_NULL)
+ALG_SUBDIRS += 
+
+obj-$(CONFIG_IPSEC_ALG_NULL) += ipsec_null.o
+static_init-func-$(CONFIG_IPSEC_ALG_NULL)+= ipsec_null_init
+alg_obj-$(CONFIG_IPSEC_ALG_NULL) += ipsec_alg_null.o
+
+NULL_OBJS=ipsec_alg_null.o
+ipsec_null.o: $(NULL_OBJS)
+	$(LD) -r $(NULL_OBJS) -o $@
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_serpent linux-patched/net/ipsec/alg/Makefile.alg_serpent
--- linux/net/ipsec/alg/Makefile.alg_serpent	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_serpent	Thu Sep  5 04:43:55 2002
@@ -0,0 +1,21 @@
+MOD_SERPENT := ipsec_serpent.o
+
+ALG_MODULES += $(MOD_SERPENT)
+ALG_SUBDIRS += libserpent
+
+obj-$(CONFIG_IPSEC_ALG_SERPENT) += $(MOD_SERPENT)
+static_init-func-$(CONFIG_IPSEC_ALG_SERPENT)+= ipsec_serpent_init
+alg_obj-$(CONFIG_IPSEC_ALG_SERPENT) += ipsec_alg_serpent.o
+
+SERPENT_OBJS=ipsec_alg_serpent.o libserpent/libserpent.a
+$(MOD_SERPENT) : libserpent $(SERPENT_OBJS)
+	$(LD) -r $(SERPENT_OBJS) -o $@
+
+libserpent : $(LIBCRYPTO)/libserpent 
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+
+libserpent/libserpent.a:
+	( cd libserpent && \
+		$(MAKE) CC='$(CC)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libserpent.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_sha1 linux-patched/net/ipsec/alg/Makefile.alg_sha1
--- linux/net/ipsec/alg/Makefile.alg_sha1	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_sha1	Thu Sep  5 04:34:24 2002
@@ -0,0 +1,23 @@
+MOD_SHA1 := ipsec_sha1.o
+
+ALG_MODULES += $(MOD_SHA1)
+ALG_SUBDIRS += libsha1
+
+obj-$(CONFIG_IPSEC_ALG_SHA1) += $(MOD_SHA1)
+static_init-func-$(CONFIG_IPSEC_ALG_SHA1)+= ipsec_sha1_init
+alg_obj-$(CONFIG_IPSEC_ALG_SHA1) += ipsec_alg_sha1.o
+
+SHA1_OBJS :=ipsec_alg_sha1.o libsha1/libsha1.a
+
+$(MOD_SHA1): libsha1 $(SHA1_OBJS)
+	$(LD) $(EXTRA_LDFLAGS) -r $(SHA1_OBJS) -o $@
+
+libsha1 : $(LIBCRYPTO)/libsha1 
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+	cd $@/asm && ln -sf $?/asm/*.pl .
+
+libsha1/libsha1.a:
+	( cd libsha1 && \
+		$(MAKE) CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libsha1.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_sha2 linux-patched/net/ipsec/alg/Makefile.alg_sha2
--- linux/net/ipsec/alg/Makefile.alg_sha2	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_sha2	Thu Sep  5 04:34:24 2002
@@ -0,0 +1,22 @@
+MOD_SHA2 := ipsec_sha2.o
+
+ALG_MODULES += $(MOD_SHA2)
+ALG_SUBDIRS += libsha2
+
+obj-$(CONFIG_IPSEC_ALG_SHA2) += $(MOD_SHA2)
+static_init-func-$(CONFIG_IPSEC_ALG_SHA2)+= ipsec_sha2_init
+alg_obj-$(CONFIG_IPSEC_ALG_SHA2) += ipsec_alg_sha2.o
+
+SHA2_OBJS := ipsec_alg_sha2.o libsha2/libsha2.a
+
+$(MOD_SHA2): libsha2 $(SHA2_OBJS)
+	$(LD) $(EXTRA_LDFLAGS) -r $(SHA2_OBJS) -o $@
+
+libsha2 : $(LIBCRYPTO)/libsha2 
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+	
+libsha2/libsha2.a:
+	( cd libsha2 && \
+		$(MAKE) CC='$(CC)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libsha2.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/Makefile.alg_twofish linux-patched/net/ipsec/alg/Makefile.alg_twofish
--- linux/net/ipsec/alg/Makefile.alg_twofish	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/Makefile.alg_twofish	Thu Sep  5 04:41:17 2002
@@ -0,0 +1,21 @@
+MOD_TWOFISH := ipsec_twofish.o
+
+ALG_MODULES += $(MOD_TWOFISH)
+ALG_SUBDIRS += libtwofish
+
+obj-$(CONFIG_IPSEC_ALG_TWOFISH) += $(MOD_TWOFISH)
+static_init-func-$(CONFIG_IPSEC_ALG_TWOFISH)+= ipsec_twofish_init
+alg_obj-$(CONFIG_IPSEC_ALG_TWOFISH) += ipsec_alg_twofish.o
+
+TWOFISH_OBJS := ipsec_alg_twofish.o libtwofish/libtwofish.a
+$(MOD_TWOFISH): libtwofish $(TWOFISH_OBJS)
+	$(LD) -r $(TWOFISH_OBJS) -o $@
+
+libtwofish : $(LIBCRYPTO)/libtwofish 
+	test -d $@ || mkdir $@ ;exit 0
+	test -d $@/asm || mkdir $@/asm;exit 0
+	cd $@ && ln -sf $?/Makefile $?/*.[chS] .
+
+libtwofish/libtwofish.a:
+	( cd libtwofish && \
+		$(MAKE) CC='$(CC)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' EXTRA_CFLAGS='$(EXTRA_CFLAGS)' libtwofish.a ;)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_1des.c linux-patched/net/ipsec/alg/ipsec_alg_1des.c
--- linux/net/ipsec/alg/ipsec_alg_1des.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_1des.c	Mon Mar 17 11:50:43 2003
@@ -0,0 +1,161 @@
+/*
+ * ipsec_alg 1DES cipher 
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_1DES
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+#include <linux/socket.h>
+#include <linux/in.h>
+#include "ipsec_param.h"
+#include "ipsec_sa.h"
+#include "ipsec_alg.h"
+#include "../libdes/des.h"
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int I_know_des_is_insecure=0;
+MODULE_PARM(I_know_des_is_insecure, "i");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+static int esp_id=0;
+MODULE_PARM(esp_id, "i");
+
+#define ESP_DES			2
+
+#define ESP_DES_CBC_BLKLEN	8	/* 64 bit blocks */
+#define ESP_DES_KEY_SZ		8	/* 56 bits keylen :P */
+
+struct des1_eks{
+	des_key_schedule ctx[1];
+};
+static int _1des_set_key(struct ipsec_alg_enc *alg,__u8 *key_e, const __u8 * key, size_t keysize) {
+	des_key_schedule *ctx=((struct des1_eks*)key_e)->ctx;
+	int error;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _1des_set_key: "
+				"key_e=%p key=%p keysize=%d\n",
+				key_e, key, keysize);
+	if (!I_know_des_is_insecure)
+		printk(KERN_WARNING "You should NOT use 1DES except for testing purposes !\n");
+	des_set_odd_parity((des_cblock *)key);
+	error = des_set_key((des_cblock *)key, ctx[0]);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:des_set_key:"
+			"ctx[%d]=%p, error=%d \n",
+			0, ctx[0], error);
+	if (error == -1)
+		printk("klips_debug: _1des_set_key: "
+				"parity error in 1des key\n");
+	else if (error == -2)
+		printk("klips_debug: _1des_set_key: "
+				"illegal weak 1des key \n");
+	if (error)
+		return error;
+	return 0;
+}
+void des_cbc_encrypt(des_cblock *input, des_cblock *output,
+		long length, des_key_schedule ks, 
+		des_cblock *ivec, int enc);
+
+static int _1des_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	char iv_buf[ESP_DES_CBC_BLKLEN];
+	des_key_schedule *ctx=((struct des1_eks*)key_e)->ctx;
+	*((__u32*)&(iv_buf)) = ((__u32*)(iv))[0];
+	*((__u32*)&(iv_buf)+1) = ((__u32*)(iv))[1];
+	if (debug > 1) {
+		printk(KERN_DEBUG "klips_debug:_1des_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				ctx, in, ilen, iv, encrypt);
+	}
+	des_cbc_encrypt((des_cblock*) in, (des_cblock*) in, ilen, ctx[0], (des_cblock *)iv_buf, encrypt);
+	return ilen;
+}
+static struct ipsec_alg_enc ipsec_alg_1DES = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_name: 	"1des",
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_DES,
+	ixt_blocksize:	ESP_DES_CBC_BLKLEN,
+	ixt_keyminbits:	ESP_DES_KEY_SZ*7, /*  7bits key+1bit parity  */
+	ixt_keymaxbits:	ESP_DES_KEY_SZ*7, /*  7bits key+1bit parity  */
+	ixt_e_keylen:	ESP_DES_KEY_SZ,
+	ixt_e_ctx_size:	sizeof(struct des1_eks),
+	ixt_e_set_key:	_1des_set_key,
+	ixt_e_cbc_encrypt:_1des_cbc_encrypt,
+};
+	
+IPSEC_ALG_MODULE_INIT(ipsec_1des_init)
+{
+	int ret, test_ret;
+	if (esp_id)
+		ipsec_alg_1DES.ixt_alg_id=esp_id;
+	if (excl) ipsec_alg_1DES.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_1DES);
+	printk("ipsec_1des_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_1DES.ixt_alg_type, 
+			ipsec_alg_1DES.ixt_alg_id, 
+			ipsec_alg_1DES.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_1DES.ixt_alg_type,
+				ipsec_alg_1DES.ixt_alg_id, 
+				test);
+		printk("ipsec_1des_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_1DES.ixt_alg_type, 
+				ipsec_alg_1DES.ixt_alg_id, 
+				test_ret);
+	}
+	if (!I_know_des_is_insecure)
+		printk(KERN_WARNING "You should NOT load 1DES support except for testing purposes !\n");
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT(ipsec_1des_fini)
+{
+	unregister_ipsec_alg_enc(&ipsec_alg_1DES);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_3des.c linux-patched/net/ipsec/alg/ipsec_alg_3des.c
--- linux/net/ipsec/alg/ipsec_alg_3des.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_3des.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,160 @@
+/*
+ * ipsec_alg 3DES cipher
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_3DES
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+#include <linux/socket.h>
+#include <linux/in.h>
+#include "ipsec_param.h"
+#include "ipsec_sa.h"
+#include "ipsec_alg.h"
+#include "../libdes/des.h"
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+static int esp_id=0;
+MODULE_PARM(esp_id, "i");
+
+#define ESP_3DES		3
+
+#define ESP_3DES_CBC_BLKLEN	8	/* 64 bit blocks */
+#define ESP_DES_KEY_SZ		8
+#define ESP_3DES_KEY_SZ		8*3 	/* 3DES */
+
+struct des3_eks{
+	des_key_schedule ctx[3];
+};
+static int _3des_set_key(struct ipsec_alg_enc *alg,__u8 *key_e, const __u8 * key, size_t keysize) {
+	des_key_schedule *ctx=((struct des3_eks*)key_e)->ctx;
+	int i, error;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _3des_set_key: "
+				"key_e=%p key=%p keysize=%d\n",
+				key_e, key, keysize);
+	for(i = 0; i < 3; i++) {
+		des_set_odd_parity((des_cblock *)(key+ESP_DES_KEY_SZ * i));
+		error = des_set_key((des_cblock *)(key+ESP_DES_KEY_SZ * i),
+				    ctx[i]);
+		if (debug > 0)
+			printk(KERN_DEBUG "klips_debug:des_set_key:"
+				"ctx[%d]=%p, error=%d \n",
+				i, ctx[i], error);
+		if (error == -1)
+			printk("klips_debug: _3des_set_key: "
+					"parity error in des key %d/3\n",
+					i + 1);
+		else if (error == -2)
+			printk("klips_debug: _3des_set_key: "
+					"illegal weak des key %d/3\n", i + 1);
+		if (error)
+			return error;
+	}
+	return 0;
+}
+void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output,
+		long length, des_key_schedule ks1, des_key_schedule ks2,
+		des_key_schedule ks3, des_cblock *ivec, int enc);
+
+static int _3des_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	char iv_buf[ESP_3DES_CBC_BLKLEN];
+	des_key_schedule *ctx=((struct des3_eks*)key_e)->ctx;
+	*((__u32*)&(iv_buf)) = ((__u32*)(iv))[0];
+	*((__u32*)&(iv_buf)+1) = ((__u32*)(iv))[1];
+	if (debug > 1) {
+		printk(KERN_DEBUG "klips_debug:_3des_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				ctx, in, ilen, iv, encrypt);
+	}
+	des_ede3_cbc_encrypt((des_cblock*) in, (des_cblock*) in, ilen, ctx[0], ctx[1], ctx[2], (des_cblock *)iv_buf, encrypt);
+	return ilen;
+}
+static struct ipsec_alg_enc ipsec_alg_3DES = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_name: 	"3des",
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_3DES,
+	ixt_blocksize:	ESP_3DES_CBC_BLKLEN,
+	ixt_keyminbits:	ESP_3DES_KEY_SZ*7, /*  7bits key+1bit parity  */
+	ixt_keymaxbits:	ESP_3DES_KEY_SZ*7, /*  7bits key+1bit parity  */
+	ixt_e_keylen:	ESP_3DES_KEY_SZ,
+	ixt_e_ctx_size:	sizeof(struct des3_eks),
+	ixt_e_set_key:	_3des_set_key,
+	ixt_e_cbc_encrypt:_3des_cbc_encrypt,
+};
+	
+IPSEC_ALG_MODULE_INIT(ipsec_3des_init)
+{
+	int ret, test_ret;
+	if (esp_id)
+		ipsec_alg_3DES.ixt_alg_id=esp_id;
+	if (excl) ipsec_alg_3DES.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_3DES);
+	printk("ipsec_3des_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_3DES.ixt_alg_type, 
+			ipsec_alg_3DES.ixt_alg_id, 
+			ipsec_alg_3DES.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_3DES.ixt_alg_type,
+				ipsec_alg_3DES.ixt_alg_id, 
+				test);
+		printk("ipsec_3des_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_3DES.ixt_alg_type, 
+				ipsec_alg_3DES.ixt_alg_id, 
+				test_ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT(ipsec_3des_fini)
+{
+	unregister_ipsec_alg_enc(&ipsec_alg_3DES);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_aes.c linux-patched/net/ipsec/alg/ipsec_alg_aes.c
--- linux/net/ipsec/alg/ipsec_alg_aes.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_aes.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,253 @@
+/*
+ * ipsec_alg AES cipher stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * Fixes by:
+ * 	PK:	Pawel Krawczyk <kravietz@aba.krakow.pl>
+ * Fixes list:
+ * 	PK:	make XCBC comply with latest draft (keylength)
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_AES
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#include "libaes/aes_cbc.h"
+
+#define CONFIG_IPSEC_ALG_AES_MAC 1
+
+#define AES_CONTEXT_T aes_context
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+static int keyminbits=0;
+MODULE_PARM(keyminbits, "i");
+static int keymaxbits=0;
+MODULE_PARM(keymaxbits, "i");
+
+#if CONFIG_IPSEC_ALG_AES_MAC
+#include "libaes/aes_xcbc_mac.h"
+
+/*	
+ *	Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt).
+ *	We use 9 for non-modular algorithm and none for modular, thus
+ *	forcing user to specify one on module load. -kravietz
+ */
+#ifdef MODULE
+static int auth_id=0;
+#else
+static int auth_id=9;
+#endif
+MODULE_PARM(auth_id, "i");
+#endif
+
+#define ESP_AES			12	/* truely _constant_  :)  */
+
+/* 128, 192 or 256 */
+#define ESP_AES_KEY_SZ_MIN	16 	/* 128 bit secret key */
+#define ESP_AES_KEY_SZ_MAX	32 	/* 256 bit secret key */
+#define ESP_AES_CBC_BLK_LEN	16	/* AES-CBC block size */
+
+/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt
+ * -kravietz
+ */
+#define ESP_AES_MAC_KEY_SZ	16	/* 128 bit MAC key */
+#define ESP_AES_MAC_BLK_LEN	16	/* 128 bit block */
+
+static int _aes_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) {
+	int ret;
+	AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e;
+	ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_aes_set_key:"
+				"ret=%d key_e=%p key=%p keysize=%d\n",
+				ret, key_e, key, keysize);
+	return ret;
+}
+static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				key_e, in, ilen, iv, encrypt);
+	return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt);
+}
+#if CONFIG_IPSEC_ALG_AES_MAC
+static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) {
+	aes_context_mac *ctxm=(aes_context_mac *)key_a;
+	return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL;
+}
+static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) {
+	int ret;
+	char hash_buf[16];
+	aes_context_mac *ctxm=(aes_context_mac *)key_a;
+	ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf);
+	memcpy(hash, hash_buf, hashlen);
+	return ret;
+}
+static struct ipsec_alg_auth ipsec_alg_AES_MAC = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_AUTH,
+	ixt_alg_id: 	0,
+	ixt_name: 	"aes_mac",
+	ixt_blocksize:	ESP_AES_MAC_BLK_LEN,
+	ixt_keyminbits:	ESP_AES_MAC_KEY_SZ*8,
+	ixt_keymaxbits:	ESP_AES_MAC_KEY_SZ*8,
+	ixt_a_keylen:	ESP_AES_MAC_KEY_SZ,
+	ixt_a_ctx_size:	sizeof(aes_context_mac),
+	ixt_a_hmac_set_key:	_aes_mac_set_key,
+	ixt_a_hmac_hash:_aes_mac_hash,
+};
+#endif /* CONFIG_IPSEC_ALG_AES_MAC */
+static struct ipsec_alg_enc ipsec_alg_AES = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_AES,
+	ixt_name: 	"aes",
+	ixt_blocksize:	ESP_AES_CBC_BLK_LEN, 
+	ixt_keyminbits:	ESP_AES_KEY_SZ_MIN*8,
+	ixt_keymaxbits:	ESP_AES_KEY_SZ_MAX*8,
+	ixt_e_keylen:	ESP_AES_KEY_SZ_MAX,
+	ixt_e_ctx_size:	sizeof(AES_CONTEXT_T),
+	ixt_e_set_key:	_aes_set_key,
+	ixt_e_cbc_encrypt:_aes_cbc_encrypt,
+};
+	
+IPSEC_ALG_MODULE_INIT( ipsec_aes_init )
+{
+	int ret, test_ret;
+	if (keyminbits)
+		ipsec_alg_AES.ixt_keyminbits=keyminbits;
+	if (keymaxbits) {
+		ipsec_alg_AES.ixt_keymaxbits=keymaxbits;
+		if (keymaxbits*8>ipsec_alg_AES.ixt_keymaxbits)
+			ipsec_alg_AES.ixt_e_keylen=keymaxbits*8;
+	}
+	if (excl) ipsec_alg_AES.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_AES);
+	printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_AES.ixt_alg_type, 
+			ipsec_alg_AES.ixt_alg_id, 
+			ipsec_alg_AES.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_AES.ixt_alg_type,
+				ipsec_alg_AES.ixt_alg_id, 
+				test);
+		printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_AES.ixt_alg_type, 
+				ipsec_alg_AES.ixt_alg_id, 
+				test_ret);
+	}
+#if CONFIG_IPSEC_ALG_AES_MAC
+	if (auth_id!=0){
+		int ret;
+		ipsec_alg_AES_MAC.ixt_alg_id=auth_id;
+		ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC);
+		printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+				ipsec_alg_AES_MAC.ixt_alg_type, 
+				ipsec_alg_AES_MAC.ixt_alg_id, 
+				ipsec_alg_AES_MAC.ixt_name, 
+				ret);
+		if (ret==0 && test) {
+			test_ret=ipsec_alg_test(
+					ipsec_alg_AES_MAC.ixt_alg_type,
+					ipsec_alg_AES_MAC.ixt_alg_id, 
+					test);
+			printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+					ipsec_alg_AES_MAC.ixt_alg_type, 
+					ipsec_alg_AES_MAC.ixt_alg_id, 
+					test_ret);
+		}
+	} else {
+		printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id);
+	}
+#endif /* CONFIG_IPSEC_ALG_AES_MAC */
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT( ipsec_aes_fini )
+{
+#if CONFIG_IPSEC_ALG_AES_MAC
+	if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC);
+#endif /* CONFIG_IPSEC_ALG_AES_MAC */
+	unregister_ipsec_alg_enc(&ipsec_alg_AES);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+#if 0+NOT_YET
+#ifndef MODULE
+/*
+ * 	This is intended for static module setups, currently
+ * 	doesn't work for modular ipsec.o with static algos inside
+ */
+static int setup_keybits(const char *str)
+{
+	unsigned aux;
+	char *end;
+
+	aux = simple_strtoul(str,&end,0);
+	if (aux != 128 && aux != 192 && aux != 256)
+		return 0;
+	keyminbits = aux;
+
+	if (*end == 0 || *end != ',')
+		return 1;
+	str=end+1;
+	aux = simple_strtoul(str, NULL, 0);
+	if (aux != 128 && aux != 192 && aux != 256)
+		return 0;
+	if (aux >= keyminbits)
+		keymaxbits = aux;
+	return 1;
+}
+__setup("ipsec_aes_keybits=", setup_keybits);
+#endif
+#endif
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_blowfish.c linux-patched/net/ipsec/alg/ipsec_alg_blowfish.c
--- linux/net/ipsec/alg/ipsec_alg_blowfish.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_blowfish.c	Thu May  8 14:48:39 2003
@@ -0,0 +1,143 @@
+/*
+ * ipsec_alg BLOWFISH cipher stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_BLOWFISH
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#include "libblowfish/blowfish.h"
+#define blowfish_context BF_KEY
+
+#define ESP_BLOWFISH			7	/* truely _constant_  :)  */
+
+#define ESP_BLOWFISH_KEY_SZ_MIN	12 	/* 96 bit secret key min */
+#define ESP_BLOWFISH_KEY_SZ		16 	/* 128 bit secret key */
+#define ESP_BLOWFISH_KEY_SZ_MAX		56 	/* 448 bit secret key */
+#define ESP_BLOWFISH_CBC_BLK_LEN	8  	/* block size */
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+static int keyminbits=0;
+MODULE_PARM(keyminbits, "i");
+static int keymaxbits=0;
+MODULE_PARM(keymaxbits, "i");
+
+static int _blowfish_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) {
+	blowfish_context *ctx=(blowfish_context*)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_blowfish_set_key:"
+				"key_e=%p key=%p keysize=%d\n",
+				key_e, key, keysize);
+	BF_set_key(ctx, keysize, (unsigned char *)key);
+	return 0;
+}
+static int _blowfish_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 *iv, int encrypt) {
+	/* blowfish toasts passed IV */
+	__u8    iv_buf[ESP_BLOWFISH_CBC_BLK_LEN];
+	blowfish_context *ctx=(blowfish_context*)key_e;
+	*((__u32*)&(iv_buf)) = ((__u32*)(iv))[0];
+	*((__u32*)&(iv_buf)+1) = ((__u32*)(iv))[1];
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_blowfish_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				key_e, in, ilen, iv_buf, encrypt);
+	BF_cbc_encrypt(in, in, ilen, ctx, iv_buf, encrypt);
+	return ilen;
+}
+static struct ipsec_alg_enc ipsec_alg_BLOWFISH = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_BLOWFISH,
+	ixt_name: 	"blowfish",
+	ixt_blocksize:	ESP_BLOWFISH_CBC_BLK_LEN,
+	ixt_keyminbits:	ESP_BLOWFISH_KEY_SZ_MIN*8,
+	ixt_keymaxbits:	ESP_BLOWFISH_KEY_SZ_MAX*8,
+	ixt_e_keylen:	ESP_BLOWFISH_KEY_SZ,	
+	ixt_e_ctx_size:	sizeof(blowfish_context),
+	ixt_e_set_key:	_blowfish_set_key,
+	ixt_e_cbc_encrypt:_blowfish_cbc_encrypt,
+};
+
+IPSEC_ALG_MODULE_INIT(ipsec_blowfish_init)
+{
+	int ret, test_ret;
+	if (keyminbits)
+		ipsec_alg_BLOWFISH.ixt_keyminbits=keyminbits;
+	if (keymaxbits) {
+		ipsec_alg_BLOWFISH.ixt_keymaxbits=keymaxbits;
+		if (keymaxbits*8>ipsec_alg_BLOWFISH.ixt_keymaxbits)
+			ipsec_alg_BLOWFISH.ixt_e_keylen=keymaxbits*8;
+	}
+	if (excl) ipsec_alg_BLOWFISH.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_BLOWFISH);
+	printk("ipsec_blowfish_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_BLOWFISH.ixt_alg_type, 
+			ipsec_alg_BLOWFISH.ixt_alg_id, 
+			ipsec_alg_BLOWFISH.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_BLOWFISH.ixt_alg_type,
+				ipsec_alg_BLOWFISH.ixt_alg_id, 
+				test);
+		printk("ipsec_blowfish_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_BLOWFISH.ixt_alg_type, 
+				ipsec_alg_BLOWFISH.ixt_alg_id, 
+				test_ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT(ipsec_blowfish_fini)
+{
+	unregister_ipsec_alg_enc(&ipsec_alg_BLOWFISH);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_cast.c linux-patched/net/ipsec/alg/ipsec_alg_cast.c
--- linux/net/ipsec/alg/ipsec_alg_cast.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_cast.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,144 @@
+/*
+ * ipsec_alg CAST cipher stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CAST
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#define cast_context cast_key
+#include "libcast/cast.h"
+
+#define ESP_CAST		6	/* quite constant :) */
+
+#define ESP_CAST_KEY_SZ_MIN	5
+#define ESP_CAST_KEY_SZ		16 	/* 128 bit secret key */
+#define ESP_CAST_CBC_BLK_LEN	8	/* CAST-CBC block size */
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+static int keyminbits=0;
+MODULE_PARM(keyminbits, "i");
+static int keymaxbits=0;
+MODULE_PARM(keymaxbits, "i");
+
+#undef cast_context
+#define cast_context CAST_KEY
+static int _cast_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) {
+	cast_context *ctx=(cast_context *)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_cast_set_key:"
+				"key_e=%p key=%p keysize=%d\n",
+				key_e, key, keysize);
+	CAST_set_key(ctx, keysize, (u_int8_t *)key);
+	return 0;
+}
+static int _cast_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	/* cast toasts passed IV */
+	__u8    iv_buf[ESP_CAST_CBC_BLK_LEN];
+	cast_context *ctx=(cast_context *)key_e;
+	*((__u32*)&(iv_buf)) = ((__u32*)(iv))[0];
+	*((__u32*)&(iv_buf)+1) = ((__u32*)(iv))[1];
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_cast_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				key_e, in, ilen, iv, encrypt);
+	CAST_cbc_encrypt(in, in, ilen, ctx, iv_buf, encrypt);
+	return ilen;
+}
+static struct ipsec_alg_enc ipsec_alg_CAST = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_CAST,
+	ixt_name: 	"cast",
+	ixt_blocksize:	ESP_CAST_CBC_BLK_LEN, 
+	ixt_keyminbits:	ESP_CAST_KEY_SZ_MIN*8,
+	ixt_keymaxbits:	ESP_CAST_KEY_SZ*8,
+	ixt_e_keylen:	ESP_CAST_KEY_SZ,
+	ixt_e_ctx_size:	sizeof(cast_context),
+	ixt_e_set_key:	_cast_set_key,
+	ixt_e_cbc_encrypt:_cast_cbc_encrypt,
+};
+	
+IPSEC_ALG_MODULE_INIT(ipsec_cast_init)
+{
+	int ret, test_ret;
+	if (keyminbits)
+		ipsec_alg_CAST.ixt_keyminbits=keyminbits;
+	if (keymaxbits) {
+		ipsec_alg_CAST.ixt_keymaxbits=keymaxbits;
+		if (keymaxbits*8>ipsec_alg_CAST.ixt_keymaxbits)
+			ipsec_alg_CAST.ixt_e_keylen=keymaxbits*8;
+	}
+	if (excl) ipsec_alg_CAST.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_CAST);
+	printk("ipsec_cast_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_CAST.ixt_alg_type, 
+			ipsec_alg_CAST.ixt_alg_id, 
+			ipsec_alg_CAST.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_CAST.ixt_alg_type,
+				ipsec_alg_CAST.ixt_alg_id, 
+				test);
+		printk("ipsec_cast_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_CAST.ixt_alg_type, 
+				ipsec_alg_CAST.ixt_alg_id, 
+				test_ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT(ipsec_cast_fini)
+{
+	unregister_ipsec_alg_enc(&ipsec_alg_CAST);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_cryptoapi.c linux-patched/net/ipsec/alg/ipsec_alg_cryptoapi.c
--- linux/net/ipsec/alg/ipsec_alg_cryptoapi.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_cryptoapi.c	Fri Feb  7 14:39:36 2003
@@ -0,0 +1,556 @@
+/*
+ * ipsec_alg to linux cryptoapi GLUE
+ *
+ * Authors: CODE.ar TEAM
+ * 	Harpo MAxx <harpo@linuxmendoza.org.ar>
+ * 	JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 	Luciano Ruete <docemeses@softhome.net>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * Example usage:
+ *   modinfo -p ipsec_cryptoapi   (quite useful info, including supported algos)
+ *   modprobe ipsec_cryptoapi
+ *   modprobe ipsec_cryptoapi test=1
+ *   modprobe ipsec_cryptoapi excl=1                     (exclusive cipher/algo)
+ *   modprobe ipsec_cryptoapi latebind=1                 (defer cipher binding)
+ *   modprobe ipsec_cryptoapi noauto=1  aes=1 twofish=1  (only these ciphers)
+ *   modprobe ipsec_cryptoapi aes=128,128                (force these keylens)
+ *   modprobe ipsec_cryptoapi des_ede3=0                 (everything but 3DES)
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/* warn the innocent */
+#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE)
+#warning "No linux cryptoapi setup found... you *MUST*  install it ! (www.kerneli.org)"
+#endif
+/*	Low freeswan header coupling	*/
+#include <ipsec_alg.h>
+#include <linux/crypto.h>
+
+#ifndef  CRYPTO_API_VERSION_CODE
+#error "you *MUST*  install linux cryptoapi ! (www.kerneli.org)"
+#endif
+#define ESP_3DES		3
+#define CIPHERNAME_3DES		"des_ede3-cbc"
+
+#define ESP_AES			12
+#define CIPHERNAME_AES		"aes-cbc"
+
+#define ESP_BLOWFISH		7	/* truely _constant_  :)  */
+#define CIPHERNAME_BLOWFISH	"blowfish-cbc"
+
+#define ESP_CAST		6	/* quite constant :) */
+#define CIPHERNAME_CAST		"cast5-cbc"
+
+#define ESP_SERPENT		252	/* from ipsec drafts */
+#define CIPHERNAME_SERPENT	"serpent-cbc"
+
+#define ESP_TWOFISH		253	/* from ipsec drafts */
+#define CIPHERNAME_TWOFISH	"twofish-cbc"
+
+#define AH_MD5			2
+#define DIGESTNAME_MD5		"md5"
+
+#define AH_SHA			3
+#define DIGESTNAME_SHA1		"sha1"
+
+
+#ifdef CONFIG_IPSEC_ALG_NON_LIBRE
+#define ESP_MARS		249	/* from ipsec drafts */
+#define CIPHERNAME_MARS		"mars-cbc"
+
+#define ESP_RC6			250	/* from ipsec drafts */
+#define CIPHERNAME_RC6		"rc6-cbc"
+#endif /* CONFIG_IPSEC_ALG_NON_LIBRE */
+
+MODULE_AUTHOR("CODE.ar team: Harpo MAxx, Juanjo Ciarlante, Luciano Ruete");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+
+static int noauto = 0;
+MODULE_PARM(noauto,"i");
+MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones");
+
+static int latebind = 0;
+MODULE_PARM(latebind,"i");
+MODULE_PARM_DESC(latebind, "Bind cryptoapi ciphers at SA creation time");
+
+static int des_ede3[] = {-1, -1};
+static int aes[] = {-1, -1};
+static int blowfish[] = {-1, -1};
+static int cast[] = {-1, -1};
+static int serpent[] = {-1, -1};
+static int twofish[] = {-1, -1};
+#ifdef CONFIG_IPSEC_ALG_NON_LIBRE
+static int mars[] = {-1, -1};
+static int rc6[] = {-1, -1};
+#endif /* CONFIG_IPSEC_ALG_NON_LIBRE */
+
+MODULE_PARM(des_ede3,"1-2i");
+MODULE_PARM(aes,"1-2i");
+MODULE_PARM(blowfish,"1-2i");
+MODULE_PARM(cast,"1-2i");
+MODULE_PARM(serpent,"1-2i");
+MODULE_PARM(twofish,"1-2i");
+#ifdef CONFIG_IPSEC_ALG_NON_LIBRE
+MODULE_PARM(mars,"1-2i");
+MODULE_PARM(rc6,"1-2i");
+#endif /* CONFIG_IPSEC_ALG_NON_LIBRE */
+MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse");
+MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens");
+MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens");
+MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens");
+MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens");
+MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens");
+#ifdef CONFIG_IPSEC_ALG_NON_LIBRE
+MODULE_PARM_DESC(mars, "0: disable | 1: force_enable | min,max: keybitlens");
+MODULE_PARM_DESC(rc6, "0: disable | 1: force_enable | min,max: keybitlens");
+#endif /* CONFIG_IPSEC_ALG_NON_LIBRE */
+
+struct ipsec_alg_capi_cipher {
+	const char *ciphername;	/* cryptoapi's ciphername */
+	int *parm;		/* lkm param for this cipher */
+	struct cipher_implementation *ci;	/* actual ci */
+	struct ipsec_alg_enc alg;	/* note it's not a pointer */
+	atomic_t ci_usecnt;		/* ci use count */
+};
+static struct ipsec_alg_capi_cipher alg_capi_carray[] = {
+	{ CIPHERNAME_AES,     aes    , NULL, { ixt_alg_id: ESP_AES, }},
+	{ CIPHERNAME_TWOFISH, twofish, NULL, { ixt_alg_id: ESP_TWOFISH, }},
+	{ CIPHERNAME_SERPENT, serpent, NULL, { ixt_alg_id: ESP_SERPENT, }},
+	{ CIPHERNAME_CAST,    cast   , NULL, { ixt_alg_id: ESP_CAST, }},
+	{ CIPHERNAME_BLOWFISH,blowfish,NULL, { ixt_alg_id: ESP_BLOWFISH, }},
+	{ CIPHERNAME_3DES,    des_ede3,NULL, { ixt_alg_id: ESP_3DES, }},
+#ifdef CONFIG_IPSEC_ALG_NON_LIBRE
+	{ CIPHERNAME_MARS,    mars   , NULL, { ixt_alg_id: ESP_MARS, }},
+	{ CIPHERNAME_RC6,     rc6    , NULL, { ixt_alg_id: ESP_RC6, }},
+#endif /* CONFIG_IPSEC_ALG_NON_LIBRE */
+	{ NULL, NULL, NULL, {} }
+};
+#ifdef NOT_YET
+struct ipsec_alg_capi_digest {
+	const char *digestname;	/* cryptoapi's digestname */
+	struct digest_implementation *di;
+	struct ipsec_alg_auth alg;	/* note it's not a pointer */
+};
+static struct ipsec_alg_capi_cipher alg_capi_darray[] = {
+	{ DIGESTNAME_MD5,     NULL, { ixt_alg_id: AH_MD5, }},
+	{ DIGESTNAME_SHA1,    NULL, { ixt_alg_id: AH_SHA, }},
+	{ NULL, NULL, {} }
+};
+#endif
+/*
+ * 	"generic" linux cryptoapi setup_cipher() function
+ */
+static struct cipher_implementation *
+setup_cipher (const char *ciphername)
+{
+	struct cipher_implementation *ci;
+	/* 	1: atomic */
+	ci = find_cipher_by_name (ciphername, 1); 
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:setup_cipher():"
+				"ciphername=%s ci=%p\n"
+				, ciphername, ci);
+	if (!ci) {
+		printk (KERN_INFO "cipher \"%s\" not found\n", ciphername);
+		return NULL;
+	}
+	return ci;
+}
+
+/*
+ * 	map cryptoapi's bitmaps to KLIPS min,max bitlens,
+ * 	considering user passed parms for forced bitlens.
+ * 	smells quite heuristic ...
+ */
+static void
+setup_keylens(struct ipsec_alg_capi_cipher *cptr, struct cipher_implementation *ci,  int *keyminbitsp, int *keymaxbitsp)
+{
+	struct capi_keysz {
+		int mask;
+		int len;
+	};
+	struct capi_keysz *kz;
+	struct capi_keysz capi_keysz_array[] = {
+		{ CIPHER_KEYSIZE_40   , 40 },
+		{ CIPHER_KEYSIZE_56   , 56 },
+		{ CIPHER_KEYSIZE_64   , 64 },
+		{ CIPHER_KEYSIZE_80   , 80 },
+		{ CIPHER_KEYSIZE_96   , 96 },
+		{ CIPHER_KEYSIZE_112  , 112 },
+		{ CIPHER_KEYSIZE_128  , 128 },
+		{ CIPHER_KEYSIZE_160  , 160 },
+		{ CIPHER_KEYSIZE_168  , 168 },
+		{ CIPHER_KEYSIZE_192  , 192 },
+		{ CIPHER_KEYSIZE_256  , 256 },
+		{ 0 , 0 }
+	};
+	if (cptr->parm[0] > 1 && cptr->parm[1] > 1) {
+		*keyminbitsp=cptr->parm[0];
+		*keymaxbitsp=cptr->parm[1];
+	} else {
+		*keyminbitsp=*keymaxbitsp=0;
+		for (kz=capi_keysz_array; kz->mask; kz++) {
+			if (kz->mask & ci->key_size_mask) {
+				if (!*keyminbitsp) *keyminbitsp=kz->len;
+				*keymaxbitsp=kz->len;
+			}
+		}
+	}
+}
+/*
+ * 	setups ipsec_alg_capi_cipher "hyper" struct components, calling
+ * 	register_ipsec_alg for cointaned ipsec_alg object
+ */
+static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e);
+static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen);
+static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt);
+
+static int
+setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr, struct cipher_implementation *ci)
+{
+	int ret;
+	int keyminbits, keymaxbits;
+	cptr->ci = NULL;
+	atomic_set (& cptr->ci_usecnt, 0);
+	cptr->alg.ixt_version = IPSEC_ALG_VERSION;
+	cptr->alg.ixt_module = THIS_MODULE;
+	atomic_set (& cptr->alg.ixt_refcnt, 0);
+	strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name));
+
+	cptr->alg.ixt_blocksize=ci->blocksize;
+	setup_keylens(cptr, ci, &keyminbits, &keymaxbits);
+	cptr->alg.ixt_state = 0;
+	if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL;
+	cptr->alg.ixt_keyminbits=keyminbits;
+	cptr->alg.ixt_keymaxbits=keymaxbits;
+	cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8;
+	cptr->alg.ixt_e_ctx_size = 0;
+	cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT;
+	cptr->alg.ixt_e_new_key = _capi_new_key;
+	cptr->alg.ixt_e_destroy_key = _capi_destroy_key;
+	cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt;
+	cptr->alg.ixt_data = cptr;
+
+	ret=register_ipsec_alg_enc(&cptr->alg);
+	printk("setup_ipsec_alg_capi_cipher(): " 
+			"alg_type=%d alg_id=%d name=%s "
+			"keyminbits=%d keymaxbits=%d, ret=%d\n", 
+				cptr->alg.ixt_alg_type, 
+				cptr->alg.ixt_alg_id, 
+				cptr->alg.ixt_name, 
+				cptr->alg.ixt_keyminbits,
+				cptr->alg.ixt_keymaxbits,
+				ret);
+	return ret;
+}
+/*
+ * 	bind cryptoapi cipher to ipsec_alg_capi_cipher "hyper" struct 
+ * 	it will also create 1 lock() inside cipher
+ */
+static struct cipher_implementation *
+_capi_ci_bind(struct ipsec_alg_capi_cipher *cptr, struct cipher_implementation *ci)
+{
+	if (atomic_read(&cptr->ci_usecnt) == 0) {
+		cptr->ci=ci? ci : setup_cipher(cptr->ciphername);
+	}
+	if (cptr->ci) {
+		atomic_inc(&cptr->ci_usecnt);
+		cptr->ci->lock();
+	}
+	return cptr->ci;
+}
+/*
+ * 	unbind cryptoapi cipher from ipsec_alg_capi_cipher "hyper" struct,
+ * 	will do 1 unlock()
+ */
+static void
+_capi_ci_unbind(struct ipsec_alg_capi_cipher *cptr)
+{
+	struct cipher_implementation *ci = cptr->ci;
+	if (ci) {
+		if (atomic_dec_and_test(&cptr->ci_usecnt) ) {
+			cptr->ci = NULL;
+		}
+		ci->unlock();
+	}
+}
+/*
+ * 	called in ipsec_sa_wipe() time, will destroy key contexts
+ * 	and do 1 unbind()
+ */
+static void 
+_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e)
+{
+	struct cipher_context *cx = (struct cipher_context *)key_e;
+	struct cipher_implementation* ci=cx->ci;
+	struct ipsec_alg_capi_cipher *cptr = alg->ixt_data;
+
+
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _capi_destroy_key:"
+				"name=%s key_e=%p ci=%p\n",
+				alg->ixt_name, key_e, ci);
+	if (!cx) {
+		printk(KERN_ERR "klips_debug: _capi_destroy_key:"
+				"name=%s NULL key_e!\n",
+				alg->ixt_name);
+		return;
+	}
+
+	ci->wipe_context(cx);
+	ci->free_context(cx);
+	/* ci->unlock(); */
+	_capi_ci_unbind(cptr);
+}
+	
+/*
+ * 	create new key context, need alg->ixt_data to know which
+ * 	(of many) cipher inside this module is the target
+ */
+static __u8 *
+_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen)
+{
+	struct cipher_context *cx = NULL;
+	struct ipsec_alg_capi_cipher *cptr;
+	struct cipher_implementation *ci;
+
+	cptr = alg->ixt_data;
+	if (!cptr) {
+		printk(KERN_ERR "_capi_new_key(): "
+				"NULL ixt_data (?!) for \"%s\" algo\n" 
+				, alg->ixt_name);
+		goto err;
+	}
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_capi_new_key:"
+				"name=%s cptr=%p key=%p keysize=%d\n",
+				alg->ixt_name, cptr, key, keylen);
+	
+	/* 
+	 * 	sortof "cache": try to bind the cipher (will be noop if
+	 *	already in use); if 1st SA using this cipher will
+	 *	end doing find_cipher_by_name()
+	 *	
+	 *	this logic is needed to support "latebind"
+	 */
+	if (!(ci=_capi_ci_bind(cptr, NULL)))
+		goto err;
+	/* ci->lock (); */
+
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_capi_new_key (after setup):"
+				"name=%s ci=%p\n",
+				alg->ixt_name, ci);
+	/*	
+	 *	alloc cipher context for this key
+	 */
+	cx = ci->realloc_context (NULL, ci, keylen);
+	if (!cx) {
+		printk(KERN_ERR "_capi_new_key(): "
+				"NULL cx for \"%s\" cryptoapi algo\n" 
+			, alg->ixt_name);
+		/* ci->unlock (); */
+		goto err;
+	}
+	if (ci->set_key (cx, key, keylen) < 0) {
+		printk(KERN_ERR "_capi_new_key(): "
+				"failed new_key() for \"%s\" cryptoapi algo\n" 
+			, alg->ixt_name);
+		ci->wipe_context (cx);
+		ci->free_context (cx);
+		/* ci->unlock (); */
+		cx=NULL;
+	}
+err:
+	/*
+	 * 	unbind 1 lease if failed (bad key, ENOMEM, etc ...) 
+	 */
+	if (!cx)
+		_capi_ci_unbind(cptr);
+
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_capi_new_key:"
+				"name=%s key=%p keylen=%d cx=%p\n",
+				alg->ixt_name, key, keylen, cx);
+	return (__u8 *) cx;
+}
+/*
+ * 	core encryption function: will use cx->ci to call actual cipher's
+ * 	cbc function
+ */
+static int 
+_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	int error;
+	struct cipher_context *cx=(struct cipher_context *)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:"
+				"cx=%p key_e=%p "
+				"in=%p out=%p ilen=%d iv=%p encrypt=%d\n"
+				, cx , key_e
+				, in, in, ilen, iv, encrypt);
+	/* this _iv() functions seems to appear AFTER 2.4.18.1 */
+	if (encrypt)
+		error = cx->ci->encrypt_atomic_iv (cx, in, in, ilen, iv);
+	else
+		error = cx->ci->decrypt_atomic_iv (cx, in, in, ilen, iv);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:"
+				"error=%d\n"
+				, error);
+	return (error<0)? error : ilen;
+}
+/*
+ * 	main initialization loop: for each cipher in list, do
+ * 	1) setup cryptoapi cipher else continue
+ * 	2) register ipsec_alg object
+ * 	   dont bind (lock) cipher if latebind specified, it will
+ * 	   get re-searched and locked at SA creation time (_new_key())
+ */
+static int
+setup_cipher_list (struct ipsec_alg_capi_cipher* clist) 
+{
+	struct ipsec_alg_capi_cipher *cptr;
+	struct cipher_implementation *ci;
+	/* foreach cipher in list ... */
+	for (cptr=clist;cptr->ciphername;cptr++) {
+		/* 
+		 * see if cipher has been disabled (0) or
+		 * if noauto set and not enabled (1)
+		 */
+		if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) {
+			if (debug>0)
+				printk(KERN_INFO "setup_cipher_list(): "
+					"ciphername=%s skipped at user request: "
+					"noauto=%d parm[0]=%d parm[1]=%d\n"
+					, cptr->ciphername
+					, noauto
+					, cptr->parm[0]
+					, cptr->parm[1]);
+			continue;
+		}
+		/* 
+		 * 	use a temp ci to avoid touching cptr->ci,
+		 * 	if register ipsec_alg success then bind cipher
+		 */
+		ci = setup_cipher(cptr->ciphername);
+		if (ci) {
+			ci->lock();
+			if (debug > 0)
+				printk(KERN_DEBUG "klips_debug:"
+						"setup_cipher_list():"
+						"ciphername=%s found\n"
+				, cptr->ciphername);
+			if (setup_ipsec_alg_capi_cipher(cptr, ci) == 0) {
+				if (latebind==0)
+					_capi_ci_bind(cptr, ci);
+			} else {
+				printk(KERN_ERR "klips_debug:"
+						"setup_cipher_list():"
+						"ciphername=%s failed ipsec_alg_register\n"
+				, cptr->ciphername);
+			}
+			ci->unlock();
+		}
+	}
+	return 0;
+}
+/*
+ * 	deregister ipsec_alg objects and unbind ciphers
+ */
+static int
+unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) 
+{
+	struct ipsec_alg_capi_cipher *cptr;
+	/* foreach cipher in list ... */
+	for (cptr=clist;cptr->ciphername;cptr++) {
+		if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) {
+			unregister_ipsec_alg_enc(&cptr->alg);
+			if (latebind==0)
+				_capi_ci_unbind(cptr);
+		}
+	}
+	return 0;
+}
+/*
+ * 	test loop for registered algos
+ */
+static int
+test_cipher_list (struct ipsec_alg_capi_cipher* clist) 
+{
+	int test_ret;
+	struct ipsec_alg_capi_cipher *cptr;
+	/* foreach cipher in list ... */
+	for (cptr=clist;cptr->ciphername;cptr++) {
+		if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) {
+			test_ret=ipsec_alg_test(
+					cptr->alg.ixt_alg_type,
+					cptr->alg.ixt_alg_id, 
+					test);
+			printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", 
+					cptr->alg.ixt_alg_type, 
+					cptr->alg.ixt_alg_id, 
+					test_ret);
+		}
+	}
+	return 0;
+}
+
+IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init )
+{
+	int ret, test_ret;
+	if ((ret=setup_cipher_list(alg_capi_carray)) < 0)
+		return  -EPROTONOSUPPORT;
+	if (ret==0 && test) {
+		test_ret=test_cipher_list(alg_capi_carray);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT( ipsec_cryptoapi_fini )
+{
+	unsetup_cipher_list(alg_capi_carray);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_md5.c linux-patched/net/ipsec/alg/ipsec_alg_md5.c
--- linux/net/ipsec/alg/ipsec_alg_md5.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_md5.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,122 @@
+/*
+ * ipsec_alg MD5 hash stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_MD5
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#include "libmd5/md5.h"
+#include "libmd5/hmac_md5.h"
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+
+#define AH_MD5		2
+
+static int _md5_hmac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) {
+	md5_hmac_context *hctx=(md5_hmac_context*)(key_a);
+	md5_hmac_set_key(hctx, key, keylen);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _md5_hmac_set_key(): "
+				"key_a=%p key=%p keysize=%d\n",
+				key_a, key, keylen);
+	return 0;
+}
+static int _md5_hmac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) {
+	md5_hmac_context *hctx=(md5_hmac_context*)(key_a);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _md5_hmac_hash(): "
+				"key_a=%p dat=%p len=%d hash=%p hashlen=%d\n",
+				key_a, dat, len, hash, hashlen);
+	md5_hmac_hash(hctx, dat, len, hash, hashlen);
+	return 0;
+}
+static struct ipsec_alg_auth ipsec_alg_MD5 = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_AUTH,
+	ixt_alg_id: 	AH_MD5,
+	ixt_name: 	"md5",
+	ixt_blocksize:	MD5_BLOCKSIZE,
+	ixt_keyminbits:	128,
+	ixt_keymaxbits:	128,
+	ixt_a_keylen:	128/8,
+	ixt_a_ctx_size:	sizeof(md5_hmac_context),
+	ixt_a_hmac_set_key:	_md5_hmac_set_key,
+	ixt_a_hmac_hash:	_md5_hmac_hash,
+};
+IPSEC_ALG_MODULE_INIT( ipsec_md5_init )
+{
+	int ret, test_ret;
+	if (excl) ipsec_alg_MD5.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_auth(&ipsec_alg_MD5);
+	printk("ipsec_md5_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_MD5.ixt_alg_type, 
+			ipsec_alg_MD5.ixt_alg_id, 
+			ipsec_alg_MD5.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_MD5.ixt_alg_type,
+				ipsec_alg_MD5.ixt_alg_id, 
+				test);
+		printk("ipsec_md5_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_MD5.ixt_alg_type, 
+				ipsec_alg_MD5.ixt_alg_id, 
+				test_ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT( ipsec_md5_fini )
+{
+	unregister_ipsec_alg_auth(&ipsec_alg_MD5);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_null.c linux-patched/net/ipsec/alg/ipsec_alg_null.c
--- linux/net/ipsec/alg/ipsec_alg_null.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_null.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,133 @@
+/*
+ * ipsec_alg NULL cipher stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * Fixes by:
+ * 	DDR:	David De Reu <DeReu@tComLabs.com> 
+ * Fixes:
+ * 	DDR:	comply to RFC2410 and make it interop with other impl.
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_NULL
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+
+#define ESP_NULL		11	/* from ipsec drafts */
+#define ESP_NULL_BLK_LEN	1	/* from RFC 2410 */
+#define ESP_NULL_IV_LEN		0	/* from RFC 2410 */
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+
+typedef int null_context;
+
+struct null_eks{
+	null_context null_ctx;
+};
+static int _null_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) {
+	null_context *ctx=&((struct null_eks*)key_e)->null_ctx;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_null_set_key:"
+				"key_e=%p key=%p keysize=%d\n",
+				key_e, key, keysize);
+	*ctx = 1;
+	return 0;
+}
+static int _null_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	null_context *ctx=&((struct null_eks*)key_e)->null_ctx;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_null_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				key_e, in, ilen, iv, encrypt);
+	(*ctx)++;
+	return ilen;
+}
+static struct ipsec_alg_enc ipsec_alg_NULL = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_NULL,
+	ixt_name: 	"null",
+	ixt_blocksize:	ESP_NULL_BLK_LEN, 
+	ixt_ivlen:	ESP_NULL_IV_LEN,
+	ixt_keyminbits:	0,
+	ixt_keymaxbits:	0,
+	ixt_e_keylen:	0,
+	ixt_e_ctx_size:	sizeof(null_context),
+	ixt_e_set_key:	_null_set_key,
+	ixt_e_cbc_encrypt:_null_cbc_encrypt,
+};
+	
+IPSEC_ALG_MODULE_INIT(ipsec_null_init)
+{
+	int ret, test_ret;
+	if (excl) ipsec_alg_NULL.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_NULL);
+	printk("ipsec_null_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_NULL.ixt_alg_type, 
+			ipsec_alg_NULL.ixt_alg_id, 
+			ipsec_alg_NULL.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_NULL.ixt_alg_type,
+				ipsec_alg_NULL.ixt_alg_id, 
+				test);
+		printk("ipsec_null_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_NULL.ixt_alg_type, 
+				ipsec_alg_NULL.ixt_alg_id, 
+				test_ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT(ipsec_null_fini)
+{
+	unregister_ipsec_alg_enc(&ipsec_alg_NULL);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_serpent.c linux-patched/net/ipsec/alg/ipsec_alg_serpent.c
--- linux/net/ipsec/alg/ipsec_alg_serpent.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_serpent.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,139 @@
+/*
+ * ipsec_alg SERPENT cipher stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_SERPENT
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#include "libserpent/serpent.h"
+#include "libserpent/serpent_cbc.h"
+
+#define ESP_SERPENT		252	/* from ipsec drafts */
+
+/* 128, 192 or 256 */
+#define ESP_SERPENT_KEY_SZ_MIN	16 	/* 128 bit secret key */
+#define ESP_SERPENT_KEY_SZ_MAX	32 	/* 256 bit secret key */
+#define ESP_SERPENT_CBC_BLK_LEN	16	/* SERPENT-CBC block size */
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+static int keyminbits=0;
+MODULE_PARM(keyminbits, "i");
+static int keymaxbits=0;
+MODULE_PARM(keymaxbits, "i");
+
+static int _serpent_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) {
+	serpent_context *ctx=(serpent_context *)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_serpent_set_key:"
+				"key_e=%p key=%p keysize=%d\n",
+				key_e, key, keysize);
+	serpent_set_key(ctx, key,  keysize);
+	return 0;
+}
+static int _serpent_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	serpent_context *ctx=(serpent_context *)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_serpent_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				key_e, in, ilen, iv, encrypt);
+	serpent_cbc_encrypt(ctx, in, in, ilen, iv, encrypt);
+	return ilen;
+}
+static struct ipsec_alg_enc ipsec_alg_SERPENT = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_SERPENT,
+	ixt_name: 	"serpent",
+	ixt_blocksize:	ESP_SERPENT_CBC_BLK_LEN,
+	ixt_keyminbits:	ESP_SERPENT_KEY_SZ_MIN * 8,
+	ixt_keymaxbits:	ESP_SERPENT_KEY_SZ_MAX * 8,
+	ixt_e_keylen:	ESP_SERPENT_KEY_SZ_MAX,
+	ixt_e_ctx_size:	sizeof(serpent_context),
+	ixt_e_set_key:	_serpent_set_key,
+	ixt_e_cbc_encrypt:_serpent_cbc_encrypt,
+};
+	
+IPSEC_ALG_MODULE_INIT(ipsec_serpent_init)
+{
+	int ret, test_ret;
+	if (keyminbits)
+		ipsec_alg_SERPENT.ixt_keyminbits=keyminbits;
+	if (keymaxbits) {
+		ipsec_alg_SERPENT.ixt_keymaxbits=keymaxbits;
+		if (keymaxbits*8>ipsec_alg_SERPENT.ixt_keymaxbits)
+			ipsec_alg_SERPENT.ixt_e_keylen=keymaxbits*8;
+	}
+	if (excl) ipsec_alg_SERPENT.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_SERPENT);
+	printk("ipsec_serpent_init(alg_type=%d alg_id=%d name=%s): ret=%d\n",
+			ipsec_alg_SERPENT.ixt_alg_type,
+			ipsec_alg_SERPENT.ixt_alg_id,
+			ipsec_alg_SERPENT.ixt_name,
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_SERPENT.ixt_alg_type,
+				ipsec_alg_SERPENT.ixt_alg_id,
+				test);
+		printk("ipsec_serpent_init(alg_type=%d alg_id=%d): test_ret=%d\n",
+				ipsec_alg_SERPENT.ixt_alg_type,
+				ipsec_alg_SERPENT.ixt_alg_id,
+				test_ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT(ipsec_serpent_fini)
+{
+	unregister_ipsec_alg_enc(&ipsec_alg_SERPENT);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_sha1.c linux-patched/net/ipsec/alg/ipsec_alg_sha1.c
--- linux/net/ipsec/alg/ipsec_alg_sha1.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_sha1.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,122 @@
+/*
+ * ipsec_alg SHA1 hash stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_SHA1
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#include "libsha1/sha.h"
+#include "libsha1/hmac_sha1.h"
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+
+#define AH_SHA		3
+
+static int _sha1_hmac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) {
+	sha1_hmac_context *hctx=(sha1_hmac_context*)(key_a);
+	sha1_hmac_set_key(hctx, key, keylen);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _sha1_hmac_set_key(): "
+				"key_a=%p key=%p keysize=%d\n",
+				key_a, key, keylen);
+	return 0;
+}
+static int _sha1_hmac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) {
+	sha1_hmac_context *hctx=(sha1_hmac_context*)(key_a);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _sha1_hmac_hash(): "
+				"key_a=%p dat=%p len=%d hash=%p hashlen=%d\n",
+				key_a, dat, len, hash, hashlen);
+	sha1_hmac_hash(hctx, dat, len, hash, hashlen);
+	return 0;
+}
+static struct ipsec_alg_auth ipsec_alg_SHA1 = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_AUTH,
+	ixt_alg_id: 	AH_SHA,
+	ixt_name: 	"sha1",
+	ixt_blocksize:	SHA1_BLOCKSIZE,
+	ixt_keyminbits:	160,
+	ixt_keymaxbits:	160,
+	ixt_a_keylen:	160/8,
+	ixt_a_ctx_size:	sizeof(sha1_hmac_context),
+	ixt_a_hmac_set_key:	_sha1_hmac_set_key,
+	ixt_a_hmac_hash:	_sha1_hmac_hash,
+};
+IPSEC_ALG_MODULE_INIT( ipsec_sha1_init )
+{
+	int ret, test_ret;
+	if (excl) ipsec_alg_SHA1.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_auth(&ipsec_alg_SHA1);
+	printk("ipsec_sha1_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_SHA1.ixt_alg_type, 
+			ipsec_alg_SHA1.ixt_alg_id, 
+			ipsec_alg_SHA1.ixt_name, 
+			ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_SHA1.ixt_alg_type,
+				ipsec_alg_SHA1.ixt_alg_id, 
+				test);
+		printk("ipsec_sha1_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_SHA1.ixt_alg_type, 
+				ipsec_alg_SHA1.ixt_alg_id, 
+				test_ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT( ipsec_sha1_fini )
+{
+	unregister_ipsec_alg_auth(&ipsec_alg_SHA1);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_sha2.c linux-patched/net/ipsec/alg/ipsec_alg_sha2.c
--- linux/net/ipsec/alg/ipsec_alg_sha2.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_sha2.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,185 @@
+/*
+ * ipsec_alg SHA2 hash stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_SHA2
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#include "libsha2/sha2.h"
+#include "libsha2/hmac_sha2.h"
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+
+/* almost constants ...: draft-ietf-ipsec-ciph-aes-cbc-03.txt */
+#define AH_SHA2_256               5
+#define AH_SHA2_384               6
+#define AH_SHA2_512               7
+
+static int _sha256_hmac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) {
+	sha256_hmac_context *hctx=(sha256_hmac_context*)(key_a);
+	sha256_hmac_set_key(hctx, key, keylen);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _sha256_hmac_set_key(): "
+				"key_a=%p key=%p keysize=%d\n",
+				key_a, key, keylen);
+	return 0;
+}
+static int _sha256_hmac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) {
+	sha256_hmac_context *hctx=(sha256_hmac_context*)(key_a);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _sha256_hmac_hash(): "
+				"key_a=%p dat=%p len=%d hash=%p hashlen=%d\n",
+				key_a, dat, len, hash, hashlen);
+	sha256_hmac_hash(hctx, dat, len, hash, hashlen);
+	return 0;
+}
+static int _sha512_hmac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) {
+	sha512_hmac_context *hctx=(sha512_hmac_context*)(key_a);
+	sha512_hmac_set_key(hctx, key, keylen);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _sha512_hmac_set_key(): "
+				"key_a=%p key=%p keysize=%d\n",
+				key_a, key, keylen);
+	return 0;
+}
+static int _sha512_hmac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) {
+	sha512_hmac_context *hctx=(sha512_hmac_context*)(key_a);
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug: _sha512_hmac_hash(): "
+				"key_a=%p dat=%p len=%d hash=%p hashlen=%d\n",
+				key_a, dat, len, hash, hashlen);
+	sha512_hmac_hash(hctx, dat, len, hash, hashlen);
+	return 0;
+}
+static struct ipsec_alg_auth ipsec_alg_SHA2_256 = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_AUTH,
+	ixt_alg_id: 	AH_SHA2_256,
+	ixt_name: 	"sha2_256",
+	ixt_blocksize:	SHA256_BLOCKSIZE,
+	ixt_keyminbits:	256,
+	ixt_keymaxbits:	256,
+	ixt_a_keylen:	256/8,
+	ixt_a_ctx_size:	sizeof(sha256_hmac_context),
+	ixt_a_hmac_set_key:	_sha256_hmac_set_key,
+	ixt_a_hmac_hash:	_sha256_hmac_hash,
+};
+static struct ipsec_alg_auth ipsec_alg_SHA2_512 = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_AUTH,
+	ixt_alg_id: 	AH_SHA2_512,
+	ixt_name: 	"sha2_512",
+	ixt_blocksize:	SHA512_BLOCKSIZE,
+	ixt_keyminbits:	512,
+	ixt_keymaxbits:	512,
+	ixt_a_keylen:	512/8,
+	ixt_a_ctx_size:	sizeof(sha512_hmac_context),
+	ixt_a_hmac_set_key:	_sha512_hmac_set_key,
+	ixt_a_hmac_hash:	_sha512_hmac_hash,
+};
+	
+IPSEC_ALG_MODULE_INIT( ipsec_sha2_init )
+{
+	int ret, test_ret;
+	if (excl) ipsec_alg_SHA2_256.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_auth(&ipsec_alg_SHA2_256);
+	printk("ipsec_sha2_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_SHA2_256.ixt_alg_type, 
+			ipsec_alg_SHA2_256.ixt_alg_id, 
+			ipsec_alg_SHA2_256.ixt_name, 
+			ret);
+	if (ret != 0) 
+		goto out;
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_SHA2_256.ixt_alg_type,
+				ipsec_alg_SHA2_256.ixt_alg_id, 
+				test);
+		printk("ipsec_sha2_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_SHA2_256.ixt_alg_type, 
+				ipsec_alg_SHA2_256.ixt_alg_id, 
+				test_ret);
+	}
+	if (excl) ipsec_alg_SHA2_512.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_auth(&ipsec_alg_SHA2_512);
+	printk("ipsec_sha2_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+			ipsec_alg_SHA2_512.ixt_alg_type, 
+			ipsec_alg_SHA2_512.ixt_alg_id, 
+			ipsec_alg_SHA2_512.ixt_name, 
+			ret);
+	if (ret != 0) 
+		goto out_256;
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_SHA2_512.ixt_alg_type,
+				ipsec_alg_SHA2_512.ixt_alg_id, 
+				test);
+		printk("ipsec_sha2_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+				ipsec_alg_SHA2_512.ixt_alg_type, 
+				ipsec_alg_SHA2_512.ixt_alg_id, 
+				test_ret);
+	}
+	goto out;
+out_256:
+	unregister_ipsec_alg_auth(&ipsec_alg_SHA2_256);
+out:
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT( ipsec_sha2_fini )
+{
+	unregister_ipsec_alg_auth(&ipsec_alg_SHA2_512);
+	unregister_ipsec_alg_auth(&ipsec_alg_SHA2_256);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_NO_SYMBOLS;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/ipsec_alg_twofish.c linux-patched/net/ipsec/alg/ipsec_alg_twofish.c
--- linux/net/ipsec/alg/ipsec_alg_twofish.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/ipsec_alg_twofish.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,138 @@
+/*
+ * ipsec_alg TWOFISH cipher stubs
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+
+/*	
+ *	special case: ipsec core modular with this static algo inside:
+ *	must avoid MODULE magic for this file
+ */
+#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_TWOFISH
+#undef MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/string.h>
+
+/* Check if __exit is defined, if not null it */
+#ifndef __exit
+#define __exit
+#endif
+
+/*	Low freeswan header coupling	*/
+#include "ipsec_alg.h"
+#include "libtwofish/twofish.h"
+#include "libtwofish/twofish_cbc.h"
+
+#define ESP_TWOFISH		253	/* from ipsec drafts */
+
+/* 128, 192 or 256 */
+#define ESP_TWOFISH_KEY_SZ_MIN	16 	/* 128 bit secret key */
+#define ESP_TWOFISH_KEY_SZ_MAX	32 	/* 256 bit secret key */
+#define ESP_TWOFISH_CBC_BLK_LEN	16	/* TWOFISH-CBC block size */
+
+MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
+static int debug=0;
+MODULE_PARM(debug, "i");
+static int test=0;
+MODULE_PARM(test, "i");
+static int excl=0;
+MODULE_PARM(excl, "i");
+static int keyminbits=0;
+MODULE_PARM(keyminbits, "i");
+static int keymaxbits=0;
+MODULE_PARM(keymaxbits, "i");
+
+static int _twofish_set_key(struct ipsec_alg_enc *alg, __u8 * key_e, const __u8 * key, size_t keysize) {
+	twofish_context *ctx=(twofish_context *)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_twofish_set_key:"
+				"key_e=%p key=%p keysize=%d\n",
+				key_e, key, keysize);
+	twofish_set_key(ctx, key,  keysize);
+	return 0;
+}
+static int _twofish_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
+	twofish_context *ctx=(twofish_context *)key_e;
+	if (debug > 0)
+		printk(KERN_DEBUG "klips_debug:_twofish_cbc_encrypt:"
+				"key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
+				key_e, in, ilen, iv, encrypt);
+	twofish_cbc_encrypt(ctx, in, in, ilen, iv, encrypt);
+	return ilen;
+}
+static struct ipsec_alg_enc ipsec_alg_TWOFISH = {
+	ixt_version:	IPSEC_ALG_VERSION,
+	ixt_module:	THIS_MODULE,
+	ixt_refcnt:	ATOMIC_INIT(0),
+	ixt_alg_type:	IPSEC_ALG_TYPE_ENCRYPT,
+	ixt_alg_id: 	ESP_TWOFISH,
+	ixt_name: 	"twofish",
+	ixt_blocksize:	ESP_TWOFISH_CBC_BLK_LEN, 
+	ixt_keyminbits:	ESP_TWOFISH_KEY_SZ_MIN * 8,
+	ixt_keymaxbits:	ESP_TWOFISH_KEY_SZ_MAX * 8,
+	ixt_e_keylen:	ESP_TWOFISH_KEY_SZ_MAX,
+	ixt_e_ctx_size:	sizeof(twofish_context),
+	ixt_e_set_key:	_twofish_set_key,
+	ixt_e_cbc_encrypt:_twofish_cbc_encrypt,
+};
+	
+IPSEC_ALG_MODULE_INIT( ipsec_twofish_init )
+{
+	int ret, test_ret;
+	if (keyminbits)
+		ipsec_alg_TWOFISH.ixt_keyminbits=keyminbits;
+	if (keymaxbits) {
+		ipsec_alg_TWOFISH.ixt_keymaxbits=keymaxbits;
+		if (keymaxbits*8>ipsec_alg_TWOFISH.ixt_keymaxbits)
+			ipsec_alg_TWOFISH.ixt_e_keylen=keymaxbits*8;
+	}
+	if (excl) ipsec_alg_TWOFISH.ixt_state |= IPSEC_ALG_ST_EXCL;
+	ret=register_ipsec_alg_enc(&ipsec_alg_TWOFISH);
+	printk("ipsec_twofish_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
+				ipsec_alg_TWOFISH.ixt_alg_type, 
+				ipsec_alg_TWOFISH.ixt_alg_id, 
+				ipsec_alg_TWOFISH.ixt_name, ret);
+	if (ret==0 && test) {
+		test_ret=ipsec_alg_test(
+				ipsec_alg_TWOFISH.ixt_alg_type,
+				ipsec_alg_TWOFISH.ixt_alg_id, 
+				test);
+		printk("ipsec_twofish_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
+			ipsec_alg_TWOFISH.ixt_alg_type, 
+			ipsec_alg_TWOFISH.ixt_alg_id, 
+			ret);
+	}
+	return ret;
+}
+IPSEC_ALG_MODULE_EXIT( ipsec_twofish_fini )
+{
+	unregister_ipsec_alg_enc(&ipsec_alg_TWOFISH);
+	return;
+}
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/alg/scripts/mk-static_init.c.sh linux-patched/net/ipsec/alg/scripts/mk-static_init.c.sh
--- linux/net/ipsec/alg/scripts/mk-static_init.c.sh	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/alg/scripts/mk-static_init.c.sh	Thu Sep  5 04:36:54 2002
@@ -0,0 +1,17 @@
+#!/bin/sh
+cat << EOF
+#include <linux/kernel.h>
+#include "../ipsec_alg.h"
+$(for i in $*; do
+	test -z "$i" && continue
+	echo "extern int $i(void);"
+done)
+void ipsec_alg_static_init(void){ 
+	int __attribute__ ((unused)) err=0;
+$(for i in $*; do
+	test -z "$i" && continue
+	echo "	if ((err=$i()) < 0)"
+	echo "		printk(KERN_WARNING \"$i() returned %d\", err);"
+done)
+}
+EOF
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/defconfig linux-patched/net/ipsec/defconfig
--- linux/net/ipsec/defconfig	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/defconfig	Fri Jul  4 20:07:34 2003
@@ -0,0 +1,132 @@
+
+#
+# RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+#
+
+#
+# FreeS/WAN IPSec implementation, KLIPS kernel config defaults
+#
+
+#
+# First, lets override stuff already set or not in the kernel config.
+#
+# We can't even think about leaving this off...
+CONFIG_INET=y
+
+#
+# This must be on for subnet protection.
+CONFIG_IP_FORWARD=y
+
+# Shut off IPSEC masquerading if it has been enabled, since it will 
+# break the compile.  IPPROTO_ESP and IPPROTO_AH were included in 
+# net/ipv4/ip_masq.c when they should have gone into include/linux/in.h.
+CONFIG_IP_MASQUERADE_IPSEC=n
+
+#
+# Next, lets set the recommended FreeS/WAN configuration.
+#
+
+# To config as static (preferred), 'y'.  To config as module, 'm'.
+CONFIG_IPSEC=m
+
+# To do tunnel mode IPSec, this must be enabled.
+CONFIG_IPSEC_IPIP=y
+
+# To enable authentication, say 'y'.   (Highly recommended)
+CONFIG_IPSEC_AH=y
+
+# Authentication algorithm(s):
+CONFIG_IPSEC_AUTH_HMAC_MD5=y
+CONFIG_IPSEC_AUTH_HMAC_SHA1=y
+
+# To enable encryption, say 'y'.   (Highly recommended)
+CONFIG_IPSEC_ESP=y
+
+# Encryption algorithm(s):
+CONFIG_IPSEC_ENC_3DES=y
+
+# IP Compression: new, probably still has minor bugs.
+CONFIG_IPSEC_IPCOMP=y
+
+# To enable userspace-switchable KLIPS debugging, say 'y'.
+CONFIG_IPSEC_DEBUG=y
+
+# modular algo extensions (and new ALGOs)
+CONFIG_IPSEC_ALG=y
+CONFIG_IPSEC_ALG_AES=m
+CONFIG_IPSEC_ALG_TWOFISH=m
+CONFIG_IPSEC_ALG_SERPENT=m
+
+# NAT Traversal
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+
+# Use CryptoAPI for ALG?
+CONFIG_IPSEC_ALG_CRYPTOAPI=n
+
+# NAT Traversal
+CONFIG_IPSEC_NAT_TRAVERSAL=y
+
+#
+#
+# $Log: super-freeswan-1.99.8-delsol1.diff,v $
+# Revision 1.1  2003/09/09 09:20:34  john
+# Initial import
+#
+# Revision 1.5  2003/07/04 19:07:34  ken
+# Added NAT-T 0.6 diff/patch from Tuomo
+#
+# Revision 1.4  2003/02/21 22:59:21  ken
+# Set default for CONFIG_IPSEC_ALG_CRYPTOAPI=n
+#
+# Revision 1.3  2002/09/05 16:50:58  ken
+# Enabled NAT-T by default
+#
+# Revision 1.2  2002/09/05 03:27:08  ken
+# Applied freeswan-alg-0.8.0-BASE-klips.diff
+#
+# Revision 1.1.1.1  2002/09/05 03:13:17  ken
+# 1.98b
+#
+# Revision 1.20  2002/04/02 04:07:40  mcr
+# 	default build is now 'm'odule for KLIPS
+#
+# Revision 1.19  2002/03/08 18:57:17  rgb
+# Added a blank line at the beginning of the file to make it easier for
+# other projects to patch ./arch/i386/defconfig, for example
+# LIDS+grSecurity requested by Jason Pattie.
+#
+# Revision 1.18  2000/11/30 17:26:56  rgb
+# Cleaned out unused options and enabled ipcomp by default.
+#
+# Revision 1.17  2000/09/15 11:37:01  rgb
+# Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+# IPCOMP zlib deflate code.
+#
+# Revision 1.16  2000/09/08 19:12:55  rgb
+# Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+#
+# Revision 1.15  2000/05/24 19:37:13  rgb
+# *** empty log message ***
+#
+# Revision 1.14  2000/05/11 21:14:57  henry
+# just commenting the FOOBAR=y lines out is not enough
+#
+# Revision 1.13  2000/05/10 20:17:58  rgb
+# Comment out netlink defaults, which are no longer needed.
+#
+# Revision 1.12  2000/05/10 19:13:38  rgb
+# Added configure option to shut off no eroute passthrough.
+#
+# Revision 1.11  2000/03/16 07:09:46  rgb
+# Hardcode PF_KEYv2 support.
+# Disable IPSEC_ICMP by default.
+# Remove DES config option from defaults file.
+#
+# Revision 1.10  2000/01/11 03:09:42  rgb
+# Added a default of 'y' to PF_KEYv2 keying I/F.
+#
+# Revision 1.9  1999/05/08 21:23:12  rgb
+# Added support for 2.2.x kernels.
+#
+# Revision 1.8  1999/04/06 04:54:25  rgb
+# Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+# patch shell fixes.
+#
+#
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipcomp.c linux-patched/net/ipsec/ipcomp.c
--- linux/net/ipsec/ipcomp.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipcomp.c	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,742 @@
+/*
+ * IPCOMP zlib interface code.
+ * Copyright (C) 2000  Svenning Soerensen <svenning@post5.tele.dk>
+ * Copyright (C) 2000, 2001  Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+char ipcomp_c_version[] = "RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+/* SSS */
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/kernel.h> /* printk() */
+
+#define IPSEC_KLIPS1_COMPAT
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+
+#include <freeswan.h>
+#ifdef NET_21
+# include <net/dst.h>
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+# define proto_priv cb
+#endif /* NET21 */
+#include <asm/checksum.h>
+#include <net/ip.h>
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_sa.h"
+
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_tunnel.h"
+#include "ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */
+#include "ipcomp.h"
+#include "zlib/zlib.h"
+#include "zlib/zutil.h"
+
+#include <pfkeyv2.h> /* SADB_X_CALG_DEFLATE */
+
+#ifdef CONFIG_IPSEC_DEBUG
+int sysctl_ipsec_debug_ipcomp = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+static
+struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask);
+
+static
+voidpf my_zcalloc(voidpf opaque, uInt items, uInt size)
+{
+	return (voidpf) kmalloc(items*size, GFP_ATOMIC);
+}
+
+static
+void my_zfree(voidpf opaque, voidpf address)
+{
+	kfree(address);
+}
+
+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags)
+{
+	struct iphdr *iph;
+	unsigned int iphlen, pyldsz, cpyldsz;
+	unsigned char *buffer;
+	z_stream zs;
+	int zresult;
+	
+	KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+		    "klips_debug:skb_compress: .\n");
+
+	if(!skb) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_compress: "
+			    "passed in NULL skb, returning ERROR.\n");
+		if (flags) *flags |= IPCOMP_PARMERROR;
+		return skb;
+	}
+
+	if(!tdb) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_compress: "
+			    "passed in NULL tdb needed for cpi, returning ERROR.\n");
+		if (flags) *flags |= IPCOMP_PARMERROR;
+		return skb;
+	}
+
+	if (!flags) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_compress: "
+			    "passed in NULL flags, returning ERROR.\n");
+#ifdef NET_21
+		kfree_skb(skb);
+#else /* NET_21 */
+		dev_kfree_skb(skb, FREE_WRITE);
+#endif /* NET_21 */
+		return NULL;
+	}
+	
+#ifdef NET_21
+	iph = skb->nh.iph;
+#else /* NET_21 */
+	iph = skb->ip_hdr;
+#endif /* NET_21 */
+
+	switch (iph->protocol) {
+	case IPPROTO_COMP:
+	case IPPROTO_AH:
+	case IPPROTO_ESP:
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_compress: "
+			    "skipping compression of packet with ip protocol %d.\n",
+			    iph->protocol);
+		*flags |= IPCOMP_UNCOMPRESSABLE;
+		return skb;
+	}
+	
+	/* Don't compress packets already fragmented */
+	if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_compress: "
+			    "skipping compression of fragmented packet.\n");
+		*flags |= IPCOMP_UNCOMPRESSABLE;
+		return skb;
+	}
+	
+	iphlen = iph->ihl << 2;
+	pyldsz = ntohs(iph->tot_len) - iphlen;
+
+	/* Don't compress less than 90 bytes (rfc 2394) */
+	if (pyldsz < 90) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_compress: "
+			    "skipping compression of tiny packet, len=%d.\n",
+			    pyldsz);
+		*flags |= IPCOMP_UNCOMPRESSABLE;
+		return skb;
+	}
+	
+	/* Adaptive decision */
+	if (tdb->tdb_comp_adapt_skip) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_compress: "
+			    "skipping compression: tdb_comp_adapt_skip=%d.\n",
+			    tdb->tdb_comp_adapt_skip);
+		tdb->tdb_comp_adapt_skip--;
+		*flags |= IPCOMP_UNCOMPRESSABLE;
+		return skb;
+	}
+
+	zs.zalloc = my_zcalloc;
+	zs.zfree = my_zfree;
+	zs.opaque = 0;
+	
+	/* We want to use deflateInit2 because we don't want the adler
+	   header. */
+	zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11,
+			       DEF_MEM_LEVEL,  Z_DEFAULT_STRATEGY);
+	if (zresult != Z_OK) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_compress: "
+			    "deflateInit2() returned error %d (%s), "
+			    "skipping compression.\n",
+			    zresult,
+			    zs.msg ? zs.msg : zError(zresult));
+		*flags |= IPCOMP_COMPRESSIONERROR;
+		return skb;
+	}
+	
+
+	/* Max output size. Result should be max this size.
+	 * Implementation specific tweak:
+	 * If it's not at least 32 bytes and 6.25% smaller than
+	 * the original packet, it's probably not worth wasting
+	 * the receiver's CPU cycles decompressing it.
+	 * Your mileage may vary.
+	 */
+	cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4);
+
+	buffer = kmalloc(cpyldsz, GFP_ATOMIC);
+	if (!buffer) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_compress: "
+			    "unable to kmalloc(%d, GFP_ATOMIC), "
+			    "skipping compression.\n",
+			    cpyldsz);
+		*flags |= IPCOMP_COMPRESSIONERROR;
+		deflateEnd(&zs);
+		return skb;
+	}
+	
+#ifdef CONFIG_IPSEC_DEBUG
+	if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
+		__u8 *c;
+		int i;
+
+		c = (__u8*)iph + iphlen;
+		for(i = 0; i < pyldsz; i++, c++) {
+			if(!(i % 16)) {
+				printk(KERN_INFO "skb_compress:   before:");
+			}
+			printk("%02x ", *c);
+			if(!((i + 1) % 16)) {
+				printk("\n");
+			}
+		}
+		if(i % 16) {
+			printk("\n");
+		}
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	zs.next_in = (char *) iph + iphlen; /* start of payload */
+	zs.avail_in = pyldsz;
+	zs.next_out = buffer;     /* start of compressed payload */
+	zs.avail_out = cpyldsz;
+	
+	/* Finish compression in one step */
+	zresult = deflate(&zs, Z_FINISH);
+
+	/* Free all dynamically allocated buffers */
+	deflateEnd(&zs);
+	if (zresult != Z_STREAM_END) {
+		*flags |= IPCOMP_UNCOMPRESSABLE;
+		kfree(buffer);
+
+		/* Adjust adaptive counters */
+		if (++(tdb->tdb_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) {
+			KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+				    "klips_debug:skb_compress: "
+				    "first %d packets didn't compress, "
+				    "skipping next %d\n",
+				    IPCOMP_ADAPT_INITIAL_TRIES,
+				    IPCOMP_ADAPT_INITIAL_SKIP);
+			tdb->tdb_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP;
+		}
+		else if (tdb->tdb_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) {
+			KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+				    "klips_debug:skb_compress: "
+				    "next %d packets didn't compress, "
+				    "skipping next %d\n",
+				    IPCOMP_ADAPT_SUBSEQ_TRIES,
+				    IPCOMP_ADAPT_SUBSEQ_SKIP);
+			tdb->tdb_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP;
+			tdb->tdb_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES;
+		}
+
+		return skb;
+	}
+	
+	/* resulting compressed size */
+	cpyldsz -= zs.avail_out;
+	
+	/* Insert IPCOMP header */
+	((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol;
+	((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0;
+	/* use the bottom 16 bits of the spi for the cpi.  The top 16 bits are
+	   for internal reference only. */
+	((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(tdb->tdb_said.spi) & 0x0000ffff));
+	KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+		    "klips_debug:skb_compress: "
+		    "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n",
+		    ntohl(tdb->tdb_said.spi),
+		    ntohl(tdb->tdb_said.spi) & 0x0000ffff,
+		    ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi),
+		    pyldsz,
+		    cpyldsz);
+	
+	/* Update IP header */
+	iph->protocol = IPPROTO_COMP;
+	iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz);
+#if 1 /* XXX checksum is done by ipsec_tunnel ? */
+	iph->check = 0;
+	iph->check = ip_fast_csum((char *) iph, iph->ihl);
+#endif
+	
+	/* Copy compressed payload */
+	memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr),
+	       buffer,
+	       cpyldsz);
+	kfree(buffer);
+	
+	/* Update skb length/tail by "unputting" the shrinkage */
+	skb_put(skb,
+		cpyldsz + sizeof(struct ipcomphdr) - pyldsz);
+	
+#ifdef CONFIG_IPSEC_DEBUG
+	if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
+		__u8 *c;
+		int i;
+		
+		c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr);
+		for(i = 0; i < cpyldsz; i++, c++) {
+			if(!(i % 16)) {
+				printk(KERN_INFO "skb_compress:   result:");
+			}
+			printk("%02x ", *c);
+			if(!((i + 1) % 16)) {
+				printk("\n");
+			}
+		}
+		if(i % 16) {
+			printk("\n");
+		}
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+	
+	tdb->tdb_comp_adapt_skip = 0;
+	tdb->tdb_comp_adapt_tries = 0;
+	
+	return skb;
+}
+
+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags)
+{
+	struct sk_buff *nskb = NULL;
+
+	/* original ip header */
+	struct iphdr *oiph, *iph;
+	unsigned int iphlen, pyldsz, cpyldsz;
+	z_stream zs;
+	int zresult;
+
+	KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+		    "klips_debug:skb_decompress: .\n");
+
+	if(!skb) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "passed in NULL skb, returning ERROR.\n");
+		if (flags) *flags |= IPCOMP_PARMERROR;
+		return skb;
+	}
+
+	if(!tdb && sysctl_ipsec_inbound_policy_check) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "passed in NULL tdb needed for comp alg, returning ERROR.\n");
+		if (flags) *flags |= IPCOMP_PARMERROR;
+		return skb;
+	}
+
+	if (!flags) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "passed in NULL flags, returning ERROR.\n");
+#ifdef NET_21
+		kfree_skb(skb);
+#else /* NET_21 */
+		dev_kfree_skb(skb, FREE_WRITE);
+#endif /* NET_21 */
+		return NULL;
+	}
+	
+#ifdef NET_21
+	oiph = skb->nh.iph;
+#else /* NET_21 */
+	oiph = skb->ip_hdr;
+#endif /* NET_21 */
+	
+	iphlen = oiph->ihl << 2;
+	
+	if (oiph->protocol != IPPROTO_COMP) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "called with non-IPCOMP packet (protocol=%d),"
+			    "skipping decompression.\n",
+			    oiph->protocol);
+		*flags |= IPCOMP_PARMERROR;
+		return skb;
+	}
+	
+	if ( (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0)
+	     || ((((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi
+		!= htons(SADB_X_CALG_DEFLATE))
+		 && sysctl_ipsec_inbound_policy_check
+		 && (!tdb || (tdb && (tdb->tdb_encalg != SADB_X_CALG_DEFLATE)))) ) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "called with incompatible IPCOMP packet (flags=%d, "
+			    "cpi=%d), tdb-compalg=%d, skipping decompression.\n",
+			    ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags),
+			    ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi),
+			    tdb ? tdb->tdb_encalg : 0);
+		*flags |= IPCOMP_PARMERROR;
+		
+		return skb;
+	}
+	
+	if (ntohs(oiph->frag_off) & ~0x4000) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "called with fragmented IPCOMP packet, "
+			    "skipping decompression.\n");
+		*flags |= IPCOMP_PARMERROR;
+		return skb;
+	}
+	
+	/* original compressed payload size */
+	cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr);
+
+	zs.zalloc = my_zcalloc;
+	zs.zfree = my_zfree;
+	zs.opaque = 0;
+	
+	zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr);
+	zs.avail_in = cpyldsz;
+	
+	/* Maybe we should be a bit conservative about memory
+	   requirements and use inflateInit2 */
+	/* Beware, that this might make us unable to decompress packets
+	   from other implementations - HINT: check PGPnet source code */
+	/* We want to use inflateInit2 because we don't want the adler
+	   header. */
+	zresult = inflateInit2(&zs, -15); 
+	if (zresult != Z_OK) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "inflateInit2() returned error %d (%s), "
+			    "skipping decompression.\n",
+			    zresult,
+			    zs.msg ? zs.msg : zError(zresult));
+		*flags |= IPCOMP_DECOMPRESSIONERROR;
+
+		return skb;
+	}
+	
+	/* We have no way of knowing the exact length of the resulting
+	   decompressed output before we have actually done the decompression.
+	   For now, we guess that the packet will not be bigger than the
+	   attached ipsec device's mtu or 16260, whichever is biggest.
+	   This may be wrong, since the sender's mtu may be bigger yet.
+	   XXX This must be dealt with later XXX
+	*/
+	
+	/* max payload size */
+	pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu)
+			  : (65520 - iphlen);
+	KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+		    "klips_debug:skb_decompress: "
+		    "max payload size: %d\n", pyldsz);
+	
+	while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) && 
+	       (nskb = skb_copy_ipcomp(skb,
+				       pyldsz - cpyldsz - sizeof(struct ipcomphdr),
+				       GFP_ATOMIC)) == NULL) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "unable to skb_copy_ipcomp(skb, %d, GFP_ATOMIC), "
+			    "trying with less payload size.\n",
+			    pyldsz - cpyldsz - sizeof(struct ipcomphdr));
+		pyldsz >>=1;
+	}
+	
+	if (!nskb) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "unable to allocate memory, dropping packet.\n");
+		*flags |= IPCOMP_DECOMPRESSIONERROR;
+		inflateEnd(&zs);
+
+		return skb;
+	}
+	
+#ifdef CONFIG_IPSEC_DEBUG
+	if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
+		__u8 *c;
+		int i;
+		
+		c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr);
+		for(i = 0; i < cpyldsz; i++, c++) {
+			if(!(i % 16)) {
+				printk(KERN_INFO "skb_decompress:   before:");
+			}
+			printk("%02x ", *c);
+			if(!((i + 1) % 16)) {
+				printk("\n");
+			}
+		}
+		if(i % 16) {
+			printk("\n");
+		}
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#ifdef NET_21
+	iph = nskb->nh.iph;
+#else /* NET_21 */
+	iph = nskb->ip_hdr;
+#endif /* NET_21 */
+	zs.next_out = (char *)iph + iphlen;
+	zs.avail_out = pyldsz;
+
+	zresult = inflate(&zs, Z_SYNC_FLUSH);
+
+	/* work around a bug in zlib, which sometimes wants to taste an extra
+	 * byte when being used in the (undocumented) raw deflate mode.
+	 */
+	if (zresult == Z_OK && !zs.avail_in && zs.avail_out) {
+		__u8 zerostuff = 0;
+		
+		zs.next_in = &zerostuff;
+		zs.avail_in = 1;
+		zresult = inflate(&zs, Z_FINISH);
+	}
+
+	inflateEnd(&zs);
+	if (zresult != Z_STREAM_END) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_error:skb_decompress: "
+			    "inflate() returned error %d (%s), "
+			    "skipping decompression.\n",
+			    zresult,
+			    zs.msg ? zs.msg : zError(zresult));
+		*flags |= IPCOMP_DECOMPRESSIONERROR;
+#ifdef NET_21
+		kfree_skb(nskb);
+#else /* NET_21 */
+		dev_kfree_skb(nskb, FREE_WRITE);
+#endif /* NET_21 */
+
+		return skb;
+	}
+	
+	/* Update IP header */
+	/* resulting decompressed size */
+	pyldsz -= zs.avail_out;
+	iph->tot_len = htons(iphlen + pyldsz);
+	iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh;
+	KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+		    "klips_debug:skb_decompress: "
+		    "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n",
+		    tdb ? ntohl(tdb->tdb_said.spi) : 0,
+		    tdb ? ntohl(tdb->tdb_said.spi) & 0x0000ffff : 0,
+		    ntohs(((struct ipcomphdr*)(((char*)oiph)+iphlen))->ipcomp_cpi),
+		    cpyldsz,
+		    pyldsz,
+		    iph->protocol);
+	
+#if 1 /* XXX checksum is done by ipsec_rcv ? */
+	iph->check = 0;
+	iph->check = ip_fast_csum((char*) iph, iph->ihl);
+#endif
+	
+	/* Update skb length/tail by "unputting" the unused data area */
+	skb_put(nskb, -zs.avail_out);
+	
+#ifdef NET_21
+	kfree_skb(skb);
+#else /* NET_21 */
+	dev_kfree_skb(skb, FREE_WRITE);
+#endif /* NET_21 */
+	
+	if (iph->protocol == IPPROTO_COMP)
+	{
+#ifdef CONFIG_IPSEC_DEBUG
+		if(sysctl_ipsec_debug_ipcomp)
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_decompress: "
+			    "Eh? inner packet is also compressed, dropping.\n");
+#endif /* CONFIG_IPSEC_DEBUG */
+		
+#ifdef NET_21
+		kfree_skb(nskb);
+#else /* NET_21 */
+		dev_kfree_skb(nskb, FREE_WRITE);
+#endif /* NET_21 */
+		return NULL;
+	}
+	
+#ifdef CONFIG_IPSEC_DEBUG
+	if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
+		__u8 *c;
+		int i;
+		
+		c = (__u8*)iph + iphlen;
+		for(i = 0; i < pyldsz; i++, c++) {
+			if(!(i % 16)) {
+				printk(KERN_INFO "skb_decompress:   result:");
+			}
+			printk("%02x ", *c);
+			if(!((i + 1) % 16)) {
+				printk("\n");
+			}
+		}
+		if(i % 16) {
+			printk("\n");
+		}
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+	
+	return nskb;
+}
+
+
+/* this is derived from skb_copy() in linux 2.2.14 */
+/* May be incompatible with other kernel versions!! */
+static
+struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask)
+{
+        struct sk_buff *n;
+	struct iphdr *iph;
+        unsigned long offset;
+        unsigned int iphlen;
+	
+	if(!skb) {
+		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
+			    "klips_debug:skb_copy_ipcomp: "
+			    "passed in NULL skb, returning NULL.\n");
+		return NULL;
+	}
+
+        /*
+         *      Allocate the copy buffer
+         */
+	
+#ifdef NET_21
+	iph = skb->nh.iph;
+#else /* NET_21 */
+	iph = skb->ip_hdr;
+#endif /* NET_21 */
+        if (!iph) return NULL;
+        iphlen = iph->ihl << 2;
+	
+        n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask);
+        if(n==NULL)
+                return NULL;
+	
+        /*
+         *      Shift between the two data areas in bytes
+         */
+	
+        offset=n->head-skb->head;
+
+        /* Set the data pointer */
+        skb_reserve(n,skb->data-skb->head);
+        /* Set the tail pointer and length */
+        skb_put(n,skb->len+data_growth);
+        /* Copy the bytes up to and including the ip header */
+        memcpy(n->head,
+	       skb->head,
+	       ((char *)iph - (char *)skb->head) + iphlen);
+        n->list=NULL;
+	n->next=NULL;
+	n->prev=NULL;
+        n->sk=NULL;
+        n->dev=skb->dev;
+	if (skb->h.raw)
+		n->h.raw=skb->h.raw+offset;
+	else
+		n->h.raw=NULL;
+        n->protocol=skb->protocol;
+#ifdef NET_21
+        n->csum = 0;
+        n->priority=skb->priority;
+        n->dst=dst_clone(skb->dst);
+        n->nh.raw=skb->nh.raw+offset;
+#ifndef NETDEV_23
+        n->is_clone=0;
+#endif /* NETDEV_23 */
+        atomic_set(&n->users, 1);
+        n->destructor = NULL;
+        n->security=skb->security;
+        memcpy(n->cb, skb->cb, sizeof(skb->cb));
+#ifdef CONFIG_IP_FIREWALL
+        n->fwmark = skb->fwmark;
+#endif
+#else /* NET_21 */
+	n->link3=NULL;
+	n->when=skb->when;
+	n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
+	n->saddr=skb->saddr;
+	n->daddr=skb->daddr;
+	n->raddr=skb->raddr;
+	n->seq=skb->seq;
+	n->end_seq=skb->end_seq;
+	n->ack_seq=skb->ack_seq;
+	n->acked=skb->acked;
+	n->free=1;
+	n->arp=skb->arp;
+	n->tries=0;
+	n->lock=0;
+	n->users=0;
+	memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
+#endif /* NET_21 */
+	if (skb->mac.raw)
+		n->mac.raw=skb->mac.raw+offset;
+	else
+		n->mac.raw=NULL;
+#ifndef NETDEV_23
+	n->used=skb->used;
+#endif /* !NETDEV_23 */
+        n->pkt_type=skb->pkt_type;
+#ifndef NETDEV_23
+	n->pkt_bridged=skb->pkt_bridged;
+#endif /* NETDEV_23 */
+	n->ip_summed=0;
+        n->stamp=skb->stamp;
+#ifndef NETDEV_23 /* this seems to have been removed in 2.4 */
+#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
+        n->shapelatency=skb->shapelatency;       /* Latency on frame */
+        n->shapeclock=skb->shapeclock;           /* Time it should go out */
+        n->shapelen=skb->shapelen;               /* Frame length in clocks */
+        n->shapestamp=skb->shapestamp;           /* Stamp for shaper    */
+        n->shapepend=skb->shapepend;             /* Pending */
+#endif /* defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) */
+#endif /* NETDEV_23 */
+#ifdef CONFIG_HIPPI
+        n->private.ifield=skb->private.ifield;
+#endif /* CONFIG_HIPPI */
+
+        return n;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipcomp.h linux-patched/net/ipsec/ipcomp.h
--- linux/net/ipsec/ipcomp.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipcomp.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,59 @@
+/*
+ * IPCOMP zlib interface code.
+ * Copyright (C) 2000  Svenning Soerensen <svenning@post5.tele.dk>
+ * Copyright (C) 2000, 2001  Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+
+ RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+
+ */
+
+/* SSS */
+
+#ifndef _IPCOMP_H
+#define _IPCOMP_H
+
+/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */
+#define IPCOMP_PREFIX
+
+#ifndef IPPROTO_COMP
+#define IPPROTO_COMP 108
+#endif /* IPPROTO_COMP */
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int sysctl_ipsec_debug_ipcomp;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+struct ipcomphdr {			/* IPCOMP header */
+    __u8    ipcomp_nh;		/* Next header (protocol) */
+    __u8    ipcomp_flags;	/* Reserved, must be 0 */
+    __u16   ipcomp_cpi;		/* Compression Parameter Index */
+};
+
+extern struct inet_protocol comp_protocol;
+extern int sysctl_ipsec_debug_ipcomp;
+
+#define IPCOMP_UNCOMPRESSABLE     0x000000001
+#define IPCOMP_COMPRESSIONERROR   0x000000002
+#define IPCOMP_PARMERROR          0x000000004
+#define IPCOMP_DECOMPRESSIONERROR 0x000000008
+
+#define IPCOMP_ADAPT_INITIAL_TRIES	8
+#define IPCOMP_ADAPT_INITIAL_SKIP	4
+#define IPCOMP_ADAPT_SUBSEQ_TRIES	2
+#define IPCOMP_ADAPT_SUBSEQ_SKIP	8
+
+/* Function prototypes */
+struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags);
+struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags);
+
+#endif /* _IPCOMP_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_ah.h linux-patched/net/ipsec/ipsec_ah.h
--- linux/net/ipsec/ipsec_ah.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_ah.h	Thu Sep  5 04:27:08 2002
@@ -0,0 +1,205 @@
+/*
+ * Authentication Header declarations
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#include "ipsec_md5h.h"
+#include "ipsec_sha1.h"
+
+#ifndef IPPROTO_AH
+#define IPPROTO_AH 51
+#endif /* IPPROTO_AH */
+
+#define AH_FLENGTH		12		/* size of fixed part */
+#define AHMD5_KMAX		64		/* MD5 max 512 bits key */
+#define AHMD5_AMAX		12		/* MD5 96 bits of authenticator */
+
+#define AHMD596_KLEN		16		/* MD5 128 bits key */
+#define AHSHA196_KLEN		20		/* SHA1 160 bits key */
+
+#define AHMD596_ALEN    	16		/* MD5 128 bits authentication length */
+#define AHSHA196_ALEN		20		/* SHA1 160 bits authentication length */
+
+#define AHMD596_BLKLEN  	64		/* MD5 block length */
+#define AHSHA196_BLKLEN 	64		/* SHA1 block length */
+#define AHSHA2_256_BLKLEN 	64		/* SHA2-256 block length */
+#define AHSHA2_384_BLKLEN 	128 		/* SHA2-384 block length (?) */
+#define AHSHA2_512_BLKLEN 	128		/* SHA2-512 block length */
+
+#define AH_BLKLEN_MAX 		128		/* keep up to date! */
+
+#define AH_AMAX         	AHSHA196_ALEN   /* keep up to date! */
+#define AHHMAC_HASHLEN  	12              /* authenticator length of 96bits */
+#define AHHMAC_RPLLEN   	4               /* 32 bit replay counter */
+
+#define DB_AH_PKTRX		0x0001
+#define DB_AH_PKTRX2		0x0002
+#define DB_AH_DMP		0x0004
+#define DB_AH_TDB		0x0010
+#define DB_AH_XF		0x0020
+#define DB_AH_INAU		0x0040
+#define DB_AH_REPLAY		0x0100
+
+#ifdef __KERNEL__
+
+/* General HMAC algorithm is described in RFC 2104 */
+
+#define		HMAC_IPAD	0x36
+#define		HMAC_OPAD	0x5C
+
+struct md5_ctx {
+	MD5_CTX ictx;		/* context after H(K XOR ipad) */
+	MD5_CTX	octx;		/* context after H(K XOR opad) */
+};
+
+struct sha1_ctx {
+	SHA1_CTX ictx;		/* context after H(K XOR ipad) */
+	SHA1_CTX octx;		/* context after H(K XOR opad) */
+};
+
+extern struct inet_protocol ah_protocol;
+
+struct options;
+
+extern int 
+ah_rcv(struct sk_buff *skb,
+       struct device *dev,
+       struct options *opt, 
+       __u32 daddr,
+       unsigned short len,
+       __u32 saddr,
+       int redo,
+       struct inet_protocol *protocol);
+
+struct ah				/* Generic AH header */
+{
+	__u8	ah_nh;			/* Next header (protocol) */
+	__u8	ah_hl;			/* AH length, in 32-bit words */
+	__u16	ah_rv;			/* reserved, must be 0 */
+	__u32	ah_spi;			/* Security Parameters Index */
+        __u32   ah_rpl;                 /* Replay prevention */
+	__u8	ah_data[AHHMAC_HASHLEN];/* Authentication hash */
+};
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_ah;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* __KERNEL__ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.2  2002/09/05 03:27:08  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.16  2002/02/20 01:27:06  rgb
+ * Ditched a pile of structs only used by the old Netlink interface.
+ *
+ * Revision 1.15  2001/12/11 02:35:57  rgb
+ * Change "struct net_device" to "struct device" for 2.2 compatibility.
+ *
+ * Revision 1.14  2001/11/26 09:23:47  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.13.2.1  2001/09/25 02:18:24  mcr
+ * 	replace "struct device" with "struct netdevice"
+ *
+ * Revision 1.13  2001/06/14 19:35:08  rgb
+ * Update copyright date.
+ *
+ * Revision 1.12  2000/09/12 03:21:20  rgb
+ * Cleared out unused htonq.
+ *
+ * Revision 1.11  2000/09/08 19:12:55  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.10  2000/01/21 06:13:10  rgb
+ * Tidied up spacing.
+ * Added macros for HMAC padding magic numbers.(kravietz)
+ *
+ * Revision 1.9  1999/12/07 18:16:23  rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.8  1999/04/11 00:28:56  henry
+ * GPL boilerplate
+ *
+ * Revision 1.7  1999/04/06 04:54:25  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.6  1999/01/26 02:06:01  rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ *
+ * Revision 1.5  1999/01/22 06:17:49  rgb
+ * Updated macro comments.
+ * Added context types to support algorithm switch code.
+ * 64-bit clean-up -- converting 'u long long' to __u64.
+ *
+ * Revision 1.4  1998/07/14 15:54:56  rgb
+ * Add #ifdef __KERNEL__ to protect kernel-only structures.
+ *
+ * Revision 1.3  1998/06/30 18:05:16  rgb
+ * Comment out references to htonq.
+ *
+ * Revision 1.2  1998/06/25 19:33:46  rgb
+ * Add prototype for protocol receive function.
+ * Rearrange for more logical layout.
+ *
+ * Revision 1.1  1998/06/18 21:27:43  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.4  1998/05/18 22:28:43  rgb
+ * Disable key printing facilities from /proc/net/ipsec_*.
+ *
+ * Revision 1.3  1998/04/21 21:29:07  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/12 22:03:17  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:05:55  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Added definitions for new AH transforms.
+ *
+ * Revision 0.3  1996/11/20 14:35:48  ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_alg.c linux-patched/net/ipsec/ipsec_alg.c
--- linux/net/ipsec/ipsec_alg.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_alg.c	Fri Feb  7 13:14:24 2003
@@ -0,0 +1,847 @@
+/*
+ * Modular extensions service and registration functions
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * Version: 0.7.3
+ *
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/kernel.h> /* printk() */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/types.h>
+#include <linux/string.h>	/* memcmp() */
+#include <linux/random.h>	/* get_random_bytes() */
+#include <linux/errno.h>  /* error codes */
+#ifdef SPINLOCK
+# ifdef SPINLOCK_23
+#  include <linux/spinlock.h> /* *lock* */
+# else /* SPINLOCK_23 */
+#  include <asm/spinlock.h> /* *lock* */
+# endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+# define proto_priv cb
+#endif /* NET21 */
+#include "ipsec_param.h"
+#include <freeswan.h>
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_tunnel.h"
+#include "ipsec_rcv.h"
+#if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH)
+# include "ipsec_ah.h"
+#endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */
+#ifdef CONFIG_IPSEC_ESP
+# include "ipsec_esp.h"
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_IPCOMP
+# include "ipcomp.h"
+#endif /* CONFIG_IPSEC_COMP */
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_sa.h"
+#include "ipsec_alg.h"
+
+#if SADB_EALG_MAX < 255
+#warning Compiling with limited ESP support ( SADB_EALG_MAX < 256 )
+#endif
+
+static rwlock_t ipsec_alg_lock = RW_LOCK_UNLOCKED;
+#define IPSEC_ALG_HASHSZ	16	/* must be power of 2, even 2^0=1 */
+static struct list_head ipsec_alg_hash_table[IPSEC_ALG_HASHSZ];
+
+/*	Old gcc's will fail here 	*/
+#define barf_out(fmt, args...)  do { printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixt->ixt_name , ## args)\
+	; goto out; } while(0)
+
+/* 
+ * 	Must be already protected by lock 
+ */
+static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) {
+	if (ixt->ixt_module)
+		__MOD_INC_USE_COUNT(ixt->ixt_module);
+	atomic_inc(&ixt->ixt_refcnt);
+}
+static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) {
+	atomic_dec(&ixt->ixt_refcnt);
+	if (ixt->ixt_module)
+		__MOD_DEC_USE_COUNT(ixt->ixt_module);
+}
+/*
+ * 	simple hash function, optimized for 0-hash (1 list) special
+ * 	case
+ */
+#if IPSEC_ALG_HASHSZ > 1
+static inline unsigned ipsec_alg_hashfn(int alg_type, int alg_id) {
+	return ((alg_type^alg_id)&(IPSEC_ALG_HASHSZ-1));
+}
+#else
+#define ipsec_alg_hashfn(x,y) (0)
+#endif
+
+/*****************************************************************
+ *
+ * 	INTERNAL table handling: insert, delete, find
+ *
+ *****************************************************************/
+
+/*	
+ *	hash table initialization, called from ipsec_alg_init()
+ */
+static void ipsec_alg_hash_init(void) {
+	struct list_head *head = ipsec_alg_hash_table;
+	int i = IPSEC_ALG_HASHSZ;
+	do {
+		INIT_LIST_HEAD(head);
+		head++;
+		i--;
+	} while (i);
+}
+/*
+ * 	hash list lookup by {alg_type, alg_id} and table head,
+ * 	must be already protected by lock
+ */
+static struct ipsec_alg *__ipsec_alg_find(unsigned alg_type, unsigned alg_id, struct list_head * head) {
+	struct list_head *p;
+	struct ipsec_alg *ixt=NULL;
+	for (p=head->next; p!=head; p=p->next) {
+		ixt = list_entry(p, struct ipsec_alg, ixt_list);
+		if (ixt->ixt_alg_type == alg_type && ixt->ixt_alg_id==alg_id) {
+			goto out;
+		}
+	}
+	ixt=NULL;
+out:
+	return ixt;
+}
+/*
+ * 	inserts (in front) a new entry in hash table, 
+ * 	called from ipsec_alg_register() when new algorithm is registered.
+ */
+static int ipsec_alg_insert(struct ipsec_alg *ixt) {
+	int ret=-EINVAL;
+	unsigned hashval=ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id);
+	struct list_head *head= ipsec_alg_hash_table + hashval;
+	struct ipsec_alg *ixt_cur;
+	/* 	new element must be virgin ... */
+	if (ixt->ixt_list.next != &ixt->ixt_list || 
+		ixt->ixt_list.prev != &ixt->ixt_list) {
+		printk(KERN_ERR "ipsec_alg_insert: ixt object \"%s\" "
+				"list head not initialized\n",
+				ixt->ixt_name);
+		return ret;
+	}
+	write_lock_bh(&ipsec_alg_lock);
+	ixt_cur = __ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head);
+	/* if previous (current) ipsec_alg found check excl flag of _anyone_ */
+	if (ixt_cur && ((ixt->ixt_state|ixt_cur->ixt_state) & IPSEC_ALG_ST_EXCL))
+		barf_out("ipsec_alg for alg_type=%d, alg_id=%d already exist. "
+				"Not loaded (ret=%d).\n",
+				ixt->ixt_alg_type,
+				ixt->ixt_alg_id, ret=-EEXIST);
+	list_add(&ixt->ixt_list, head);
+	ixt->ixt_state |= IPSEC_ALG_ST_REGISTERED;
+	ret=0;
+out:
+	write_unlock_bh(&ipsec_alg_lock);
+	return ret;
+}
+/*
+ * 	deletes an existing entry in hash table, 
+ * 	called from ipsec_alg_unregister() when algorithm is unregistered.
+ */
+static int ipsec_alg_delete(struct ipsec_alg *ixt) {
+	write_lock_bh(&ipsec_alg_lock);
+	list_del(&ixt->ixt_list);
+	write_unlock_bh(&ipsec_alg_lock);
+	return 0;
+}
+/*
+ * 	here @user context (read-only when @kernel bh context) 
+ * 	-> no bh disabling
+ *
+ * 	called from ipsec_sa_init() -> ipsec_alg_sa_init()
+ */
+static struct ipsec_alg *ipsec_alg_get(int alg_type, int alg_id) {
+	unsigned hashval=ipsec_alg_hashfn(alg_type, alg_id);
+	struct list_head *head= ipsec_alg_hash_table + hashval;
+	struct ipsec_alg *ixt;
+	read_lock(&ipsec_alg_lock);
+	ixt=__ipsec_alg_find(alg_type, alg_id, head);
+	if (ixt) __ipsec_alg_usage_inc(ixt);
+	read_unlock(&ipsec_alg_lock);
+	return ixt;
+}
+
+static void ipsec_alg_put(struct ipsec_alg *ixt) {
+	__ipsec_alg_usage_dec((struct ipsec_alg *)ixt);
+}
+
+/*****************************************************************
+ *
+ * 	INTERFACE for ENC services: key creation, encrypt function
+ *
+ *****************************************************************/
+
+/*
+ * 	main encrypt service entry point
+ * 	called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and
+ * 	ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT
+ */
+int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat, int ilen, const __u8 * iv, int encrypt) {
+	int ret;
+	struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_alg_esp_encrypt: "
+		    "entering with encalg=%d, ixt_e=%p\n",
+		    sa_p->ips_encalg, ixt_e);
+	if (!ixt_e) {
+		KLIPS_PRINT(debug_rcv||debug_tunnel,
+			    "klips_debug:ipsec_alg_esp_encrypt: "
+			    "NULL ipsec_alg_enc object\n");
+		return -1;
+	}
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_alg_esp_encrypt: "
+		    "calling cbc_encrypt encalg=%d "
+		    "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n",
+			sa_p->ips_encalg, 
+			sa_p->ips_key_e, idat, ilen, iv, encrypt);
+	ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, sa_p->ips_key_e, idat, ilen, iv, encrypt);
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_alg_esp_encrypt: "
+		    "returned ret=%d\n",
+		    ret);
+	return ret;
+}
+/*
+ * 	encryption key context creation function
+ * 	called from pfkey_v2_parser.c:pfkey_ips_init() 
+ */
+int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) {
+	int ret=-EINVAL;
+	int keyminbits, keymaxbits;
+	caddr_t ekp;
+	struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:ipsec_alg_enc_key_create: "
+		    "entering with encalg=%d ixt_e=%p\n",
+		    sa_p->ips_encalg, ixt_e);
+	if (!ixt_e) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_alg_enc_key_create: "
+			    "NULL ipsec_alg_enc object\n");
+		return -EPROTO;
+	}
+
+	/* 
+	 * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo 
+	 */
+	switch(ixt_e->ixt_alg_id) {
+		case ESP_3DES:
+			keyminbits=keymaxbits=192;break;
+		case ESP_DES:
+			keyminbits=keymaxbits=64;break;
+		default:
+			keyminbits=ixt_e->ixt_keyminbits;
+			keymaxbits=ixt_e->ixt_keymaxbits;
+	}
+	if(sa_p->ips_key_bits_e<keyminbits || 
+			sa_p->ips_key_bits_e>keymaxbits) {
+		KLIPS_PRINT(debug_pfkey,
+				"klips_debug:ipsec_alg_enc_key_create: "
+				"incorrect encryption key size for id=%d: %d bits -- "
+				"must be between %d,%d bits\n" /*octets (bytes)\n"*/,
+				ixt_e->ixt_alg_id,
+				sa_p->ips_key_bits_e, keyminbits, keymaxbits);
+		ret=-EINVAL;
+		goto ixt_out;
+	}
+	/* save encryption key pointer */
+	ekp = sa_p->ips_key_e;
+
+
+	if (ixt_e->ixt_e_new_key) {
+		sa_p->ips_key_e = ixt_e->ixt_e_new_key(ixt_e,
+				ekp, sa_p->ips_key_bits_e/8);
+		ret =  (sa_p->ips_key_e)? 0 : -EINVAL;
+	} else {
+		if((sa_p->ips_key_e = (caddr_t)
+		    kmalloc((sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size),
+			    GFP_ATOMIC)) == NULL) {
+			ret=-ENOMEM;
+			goto ixt_out;
+		}
+		/* zero-out key_e */
+		memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size);
+
+		/* I cast here to allow more decoupling in alg module */
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_alg_enc_key_create: about to call:"
+				    "set_key(key_e=%p, ekp=%p, key_size=%d)\n",
+				    (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
+		ret = ixt_e->ixt_e_set_key(ixt_e, (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
+	}
+	/* paranoid */
+	memset(ekp, 0, sa_p->ips_key_bits_e/8);
+	kfree(ekp);
+ixt_out:
+	return ret;
+}
+
+/***************************************************************
+ *
+ * 	INTERFACE for AUTH services: key creation, hash functions
+ *
+ ***************************************************************/
+
+/*
+ * 	auth key context creation function
+ * 	called from pfkey_v2_parser.c:pfkey_ips_init() 
+ */
+int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) {
+	int ret=-EINVAL;
+	struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth;
+	int keyminbits, keymaxbits;
+	unsigned char *akp;
+	unsigned int aks;
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:ipsec_alg_auth_key_create: "
+		    "entering with authalg=%d ixt_a=%p\n",
+		    sa_p->ips_authalg, ixt_a);
+	if (!ixt_a) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_alg_auth_key_create: "
+			    "NULL ipsec_alg_auth object\n");
+		return -EPROTO;
+	}
+	keyminbits=ixt_a->ixt_keyminbits;
+	keymaxbits=ixt_a->ixt_keymaxbits;
+	if(sa_p->ips_key_bits_a<keyminbits || sa_p->ips_key_bits_a>keymaxbits) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_alg_auth_key_create: incorrect auth"
+			    "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/,
+			    sa_p->ips_key_bits_a, keyminbits, keymaxbits);
+		ret=-EINVAL;
+		goto ixt_out;
+	}
+	/* save auth key pointer */
+	sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */
+	akp = sa_p->ips_key_a;
+	aks = sa_p->ips_key_a_size;
+
+	/* will hold: 2 ctx and a blocksize buffer: kb */
+	sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size;
+	if((sa_p->ips_key_a = 
+		(caddr_t) kmalloc(sa_p->ips_key_a_size, GFP_ATOMIC)) == NULL) {
+		ret=-ENOMEM;
+		goto ixt_out;
+	}
+	ixt_a->ixt_a_hmac_set_key(ixt_a, sa_p->ips_key_a, akp, sa_p->ips_key_bits_a/8); /* XXX XXX */
+	ret=0;
+	memset(akp, 0, aks);
+	kfree(akp);
+			
+ixt_out:
+	return ret;
+}
+int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) {
+	struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth;
+	if (!ixt_a) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_sa_esp_hash: "
+			    "NULL ipsec_alg_auth object\n");
+		return -EPROTO;
+	}
+	KLIPS_PRINT(debug_tunnel|debug_rcv,
+			"klips_debug:ipsec_sa_esp_hash: "
+			"hashing %p (%d bytes) to %p (%d bytes)\n",
+			espp, len,
+			hash, hashlen);
+	ixt_a->ixt_a_hmac_hash(ixt_a,
+			sa_p->ips_key_a, 
+			espp, len,
+			hash, hashlen);
+	return 0;
+}
+
+/***************************************************************
+ *
+ * 	INTERFACE for module loading,testing, and unloading
+ *
+ ***************************************************************/
+
+/* validation for registering (enc) module */
+static int check_enc(struct ipsec_alg_enc *ixt) {
+	int ret=-EINVAL;
+	if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_EALG_MAX)
+		barf_out("invalid alg_id=%d >= %d\n", ixt->ixt_alg_id, SADB_EALG_MAX);
+	if (ixt->ixt_blocksize==0) /*  || ixt->ixt_blocksize%2) need for ESP_NULL */
+		barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize);
+	if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_e_keylen==0)
+		goto zero_key_ok;
+	if (ixt->ixt_keyminbits==0)
+		barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits);
+	if (ixt->ixt_keymaxbits==0)
+		barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits);
+	if (ixt->ixt_e_keylen==0)
+		barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen);
+zero_key_ok:
+	if (ixt->ixt_e_ctx_size==0 && ixt->ixt_e_new_key == NULL)
+		barf_out(KERN_ERR "invalid key_e_size=%d and ixt_e_new_key=NULL\n", ixt->ixt_e_ctx_size);
+	if (ixt->ixt_e_cbc_encrypt==NULL)
+		barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n");
+	ret=0;
+out:
+	return ret;
+}
+
+/* validation for registering (auth) module */
+static int check_auth(struct ipsec_alg_auth *ixt) {
+	int ret=-EINVAL;
+	if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_AALG_MAX)
+		barf_out("invalid alg_id=%d > %d (SADB_AALG_MAX)\n", ixt->ixt_alg_id, SADB_AALG_MAX);
+	if (ixt->ixt_blocksize==0 || ixt->ixt_blocksize%2)
+		barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize);
+	if (ixt->ixt_blocksize>AH_BLKLEN_MAX)
+		barf_out(KERN_ERR "sorry blocksize=%d > %d. "
+			"Please increase AH_BLKLEN_MAX and recompile\n", 
+			ixt->ixt_blocksize,
+			AH_BLKLEN_MAX);
+	if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_a_keylen==0)
+		goto zero_key_ok;
+	if (ixt->ixt_keyminbits==0)
+		barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits);
+	if (ixt->ixt_keymaxbits==0)
+		barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits);
+	if (ixt->ixt_keymaxbits!=ixt->ixt_keyminbits)
+		barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n");
+	if (ixt->ixt_a_keylen==0)
+		barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen);
+zero_key_ok:
+	if (ixt->ixt_a_ctx_size==0)
+		barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size);
+	if (ixt->ixt_a_hmac_set_key==NULL)
+		barf_out(KERN_ERR "a_hmac_set_key() must be not NULL\n");
+	if (ixt->ixt_a_hmac_hash==NULL)
+		barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n");
+	ret=0;
+out:
+	return ret;
+}
+
+/* 
+ * Generic (enc, auth) registration entry point 
+ */
+int register_ipsec_alg(struct ipsec_alg *ixt) {
+	int ret=-EINVAL;
+	/*	Validation 	*/
+	if (ixt==NULL)
+		barf_out("NULL ipsec_alg object passed\n");
+	if ((ixt->ixt_version&0xffffff00) != (IPSEC_ALG_VERSION&0xffffff00))
+		barf_out("incorrect version: %d.%d.%d-%d, "
+			"must be %d.%d.%d[-%d]\n",
+				IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), 
+				IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION));
+	switch(ixt->ixt_alg_type) {
+		case IPSEC_ALG_TYPE_AUTH:
+			if ((ret=check_auth((struct ipsec_alg_auth *)ixt)<0))
+				goto out;
+			break;
+		case IPSEC_ALG_TYPE_ENCRYPT: 
+			if ((ret=check_enc((struct ipsec_alg_enc *)ixt)<0))
+				goto out;
+ 			/* 
+			 * Adapted two lines below: 
+			 * 	ivlen == 0 is possible (NULL enc has blocksize==1)
+			 *
+			 * fixed NULL support by David De Reu <DeReu@tComLabs.com>
+ 			 */
+			if (ixt->ixt_ivlen == 0 && ixt->ixt_blocksize > 1)
+				ixt->ixt_ivlen = ixt->ixt_blocksize*8;
+			break;
+		default:
+			barf_out("alg_type=%d not supported", ixt->ixt_alg_type);
+	}
+	INIT_LIST_HEAD(&ixt->ixt_list);
+	ret = ipsec_alg_insert(ixt);
+	if (ret<0) 
+		barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed."
+				"Not loaded (ret=%d).\n",
+				ixt->ixt_alg_id, ret);
+
+	ret = pfkey_list_insert_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP]));
+	if (ret==0) {
+		ixt->ixt_state |= IPSEC_ALG_ST_SUPP;
+		/*	send register event to userspace	*/
+		pfkey_register_reply(SADB_SATYPE_ESP, NULL);
+	} else
+		printk(KERN_ERR "pfkey_list_insert_supported returned %d. "
+				"Loading anyway.\n", ret);
+	ret=0;
+out:
+	return ret;
+}
+
+/* 
+ * 	unregister ipsec_alg object from own tables, if 
+ * 	success => calls pfkey_list_remove_supported()
+ */
+int unregister_ipsec_alg(struct ipsec_alg *ixt) {
+	int ret= -EINVAL;
+	switch(ixt->ixt_alg_type) {
+		case IPSEC_ALG_TYPE_AUTH:
+		case IPSEC_ALG_TYPE_ENCRYPT: 
+			break;
+		default:
+			/*	this is not a typo :) */
+			barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", 
+				ixt->ixt_name);
+	}
+
+	ret=ipsec_alg_delete(ixt);
+	if (ixt->ixt_state&IPSEC_ALG_ST_SUPP) {
+		ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP;
+		pfkey_list_remove_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP]));
+		/*	send register event to userspace	*/
+		pfkey_register_reply(SADB_SATYPE_ESP, NULL);
+	}
+
+out:
+	return ret;
+}
+/*
+ * 	Must be called from user context
+ * 	used at module load type for testing algo implementation
+ */
+static int ipsec_alg_test_encrypt(int enc_alg, int test) {
+	int ret;
+	caddr_t buf = NULL;
+	int iv_size, keysize, key_e_size;
+	struct ipsec_alg_enc *ixt_e;
+	void *tmp_key_e = NULL;
+	#define BUFSZ	1024
+	#define MARGIN	0
+	#define test_enc   (buf+MARGIN)
+	#define test_dec   (test_enc+BUFSZ+MARGIN)
+	#define test_tmp   (test_dec+BUFSZ+MARGIN)
+	#define test_key_e (test_tmp+BUFSZ+MARGIN)
+	#define test_iv    (test_key_e+key_e_size+MARGIN)
+	#define test_key   (test_iv+iv_size+MARGIN)
+	#define test_size  (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7)
+	ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg);
+	if (ixt_e==NULL) {
+		KLIPS_PRINT(1, 
+			    "klips_debug: ipsec_alg_test_encrypt: "
+			    "encalg=%d object not found\n",
+			    enc_alg);
+		ret=-EINVAL;
+		goto out;
+	}
+	iv_size=ixt_e->ixt_ivlen / 8;
+	key_e_size=ixt_e->ixt_e_ctx_size;
+	keysize=ixt_e->ixt_e_keylen;
+	KLIPS_PRINT(1, 
+		    "klips_debug: ipsec_alg_test_encrypt: "
+		    "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n",
+		    enc_alg, iv_size, key_e_size, keysize);
+	if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
+		ret= -ENOMEM;
+		goto out;
+	}
+	get_random_bytes(test_key, keysize);
+	get_random_bytes(test_iv, iv_size);
+	if (ixt_e->ixt_e_new_key) {
+		tmp_key_e = ixt_e->ixt_e_new_key(ixt_e, test_key, keysize);
+		ret = tmp_key_e ? 0 : -EINVAL;
+	} else {
+		tmp_key_e = test_key_e;
+		ret = ixt_e->ixt_e_set_key(ixt_e, test_key_e, test_key, keysize);
+	}
+	if (ret < 0)
+		goto out;
+	get_random_bytes(test_enc, BUFSZ);
+	memcpy(test_tmp, test_enc, BUFSZ);
+	ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_enc, BUFSZ, test_iv, 1);
+	printk(KERN_INFO
+		    "klips_info: ipsec_alg_test_encrypt: "
+		    "cbc_encrypt=1 ret=%d\n", 
+		    	ret);
+	ret=memcmp(test_enc, test_tmp, BUFSZ);
+	printk(KERN_INFO
+		    "klips_info: ipsec_alg_test_encrypt: "
+		    "memcmp(enc, tmp) ret=%d: %s\n", ret,
+			ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" );
+	memcpy(test_dec, test_enc, BUFSZ);
+	ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_dec, BUFSZ, test_iv, 0);
+	printk(KERN_INFO
+		    "klips_info: ipsec_alg_test_encrypt: "
+		    "cbc_encrypt=0 ret=%d\n", ret);
+	ret=memcmp(test_dec, test_tmp, BUFSZ);
+	printk(KERN_INFO
+		    "klips_info: ipsec_alg_test_encrypt: "
+		    "memcmp(dec,tmp) ret=%d: %s\n", ret,
+			ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" );
+	{
+		/*	Shamelessly taken from drivers/md sources  O:)  */
+		unsigned long now;
+		int i, count, max=0;
+		int encrypt, speed;
+		for (encrypt=0; encrypt <2;encrypt ++) {
+			for (i = 0; i < 5; i++) {
+				now = jiffies;
+				count = 0;
+				while (jiffies == now) {
+					mb();
+					ixt_e->ixt_e_cbc_encrypt(ixt_e, 
+							tmp_key_e, test_tmp, 
+							BUFSZ, test_iv, encrypt);
+					mb();
+					count++;
+					mb();
+				}
+				if (count > max)
+					max = count;
+			}
+			speed = max * (HZ * BUFSZ / 1024);
+			printk(KERN_INFO
+				    "klips_info: ipsec_alg_test_encrypt: "
+				    "%s %s speed=%d KB/s\n", 
+				    ixt_e->ixt_name,
+				    encrypt? "encrypt": "decrypt", speed);
+		}
+	}
+out:
+	if (tmp_key_e && ixt_e->ixt_e_destroy_key) ixt_e->ixt_e_destroy_key(ixt_e, tmp_key_e);
+	if (buf) kfree(buf);
+	if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e);
+	return ret;
+	#undef test_enc  
+	#undef test_dec  
+	#undef test_tmp  
+	#undef test_key_e
+	#undef test_iv   
+	#undef test_key  
+	#undef test_size 
+}
+/*
+ * 	Must be called from user context
+ * 	used at module load type for testing algo implementation
+ */
+static int ipsec_alg_test_auth(int auth_alg, int test) {
+	int ret;
+	caddr_t buf = NULL;
+	int blocksize, keysize, key_a_size;
+	struct ipsec_alg_auth *ixt_a;
+	#define BUFSZ	1024
+	#define MARGIN	0
+	#define test_auth  (buf+MARGIN)
+	#define test_key_a (test_auth+BUFSZ+MARGIN)
+	#define test_key   (test_key_a+key_a_size+MARGIN)
+	#define test_hash  (test_key+keysize+MARGIN)
+	#define test_size  (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4)
+	ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg);
+	if (ixt_a==NULL) {
+		KLIPS_PRINT(1, 
+			    "klips_debug: ipsec_alg_test_auth: "
+			    "encalg=%d object not found\n",
+			    auth_alg);
+		ret=-EINVAL;
+		goto out;
+	}
+	blocksize=ixt_a->ixt_blocksize;
+	key_a_size=ixt_a->ixt_a_ctx_size;
+	keysize=ixt_a->ixt_a_keylen;
+	KLIPS_PRINT(1, 
+		    "klips_debug: ipsec_alg_test_auth: "
+		    "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n",
+		    auth_alg, blocksize, key_a_size, keysize);
+	if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
+		ret= -ENOMEM;
+		goto out;
+	}
+	get_random_bytes(test_key, keysize);
+	ret = ixt_a->ixt_a_hmac_set_key(ixt_a, test_key_a, test_key, keysize);
+	if (ret < 0 )
+		goto out;
+	get_random_bytes(test_auth, BUFSZ);
+	ret=ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
+	printk(KERN_INFO
+		    "klips_info: ipsec_alg_test_auth: "
+		    "ret=%d\n", ret);
+	{
+		/*	Shamelessly taken from drivers/md sources  O:)  */
+		unsigned long now;
+		int i, count, max=0;
+		int speed;
+		for (i = 0; i < 5; i++) {
+			now = jiffies;
+			count = 0;
+			while (jiffies == now) {
+				mb();
+				ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
+				mb();
+				count++;
+				mb();
+			}
+			if (count > max)
+				max = count;
+		}
+		speed = max * (HZ * BUFSZ / 1024);
+		printk(KERN_INFO
+				"klips_info: ipsec_alg_test_auth: "
+				"%s hash speed=%d KB/s\n", 
+				ixt_a->ixt_name,
+				speed);
+	}
+out:
+	if (buf) kfree(buf);
+	if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a);
+	return ret;
+	#undef test_auth 
+	#undef test_key_a
+	#undef test_key  
+	#undef test_hash 
+	#undef test_size 
+}
+int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) {
+	switch(alg_type) {
+		case IPSEC_ALG_TYPE_ENCRYPT:
+			return ipsec_alg_test_encrypt(alg_id, test);
+			break;
+		case IPSEC_ALG_TYPE_AUTH:
+			return ipsec_alg_test_auth(alg_id, test);
+			break;
+	}
+	printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: "
+			"alg_type=%d alg_id=%d\n",
+			alg_type, alg_id);
+	return -EINVAL;
+}
+int ipsec_alg_init(void) {
+	KLIPS_PRINT(1, "klips_info:ipsec_alg_init: "
+			"KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n",
+			IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION),
+			SADB_EALG_MAX, SADB_AALG_MAX);
+	/*	Initialize tables */
+	write_lock_bh(&ipsec_alg_lock);
+	ipsec_alg_hash_init();
+	write_unlock_bh(&ipsec_alg_lock);
+	/*	Initialize static algos 	*/
+	KLIPS_PRINT(1, "klips_info:ipsec_alg_init: "
+		"calling ipsec_alg_static_init()\n");
+	ipsec_alg_static_init();
+	return 0;
+}
+
+/**********************************************
+ *
+ * 	INTERFACE for ipsec_sa init and wipe
+ *
+ **********************************************/
+
+/*	
+ *	Called from pluto -> pfkey_v2_parser.c:pfkey_ipsec_sa_init()	
+ */
+int ipsec_alg_sa_init(struct ipsec_sa *sa_p) {
+	struct ipsec_alg_enc *ixt_e;
+	struct ipsec_alg_auth *ixt_a;
+
+	/*	Only ESP for now ... */
+	if (sa_p->ips_said.proto != IPPROTO_ESP)
+		return -EPROTONOSUPPORT;
+	KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :"
+			"entering for encalg=%d, authalg=%d\n",
+			    sa_p->ips_encalg, sa_p->ips_authalg);
+	if ((ixt_e=(struct ipsec_alg_enc *)
+		ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg))) {
+		KLIPS_PRINT(debug_pfkey,
+		    "klips_debug: ipsec_alg_sa_init() :"
+		    "found ipsec_alg (ixt_e=%p) for encalg=%d\n",
+		    ixt_e, sa_p->ips_encalg);
+		sa_p->ips_alg_enc=ixt_e;
+	}
+	if ((ixt_a=(struct ipsec_alg_auth *)
+		ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg))) {
+		KLIPS_PRINT(debug_pfkey,
+		    "klips_debug: ipsec_alg_sa_init() :"
+		    "found ipsec_alg (ixt_a=%p) for auth=%d\n",
+		    ixt_a, sa_p->ips_authalg);
+		sa_p->ips_alg_auth=ixt_a;
+	}
+	return 0;
+}
+
+/*	
+ *	Called from pluto -> ipsec_sa.c:ipsec_sa_delchain()
+ */
+int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) {
+	struct ipsec_alg *ixt;
+	if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_enc)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :"
+				"unlinking for encalg=%d\n",
+				ixt->ixt_alg_id);
+		ipsec_alg_put(ixt);
+	}
+	if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_auth)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :"
+				"unlinking for authalg=%d\n",
+				ixt->ixt_alg_id);
+		ipsec_alg_put(ixt);
+	}
+	return 0;
+}
+/*
+ * 	As the author of this module, I ONLY ALLOW using it from
+ * 	GPL (or same LICENSE TERMS as kernel source) modules.
+ *
+ * 	In respect to hardware crypto engines this means:
+ * 	* Closed-source device drivers ARE NOT ALLOWED to use 
+ * 	  this interface.
+ * 	* Closed-source VHDL/Verilog firmware running on 
+ * 	  the crypto hardware device IS ALLOWED to use this interface
+ * 	  via a GPL (or same LICENSE TERMS as kernel source) device driver.
+ * 	--Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording)
+ */
+
+/*	
+ *	These symbols can only be used from GPL modules	
+ *	for now, I'm disabling this because it creates false
+ *	symbol problems for old modutils.
+ */
+
+/* #ifndef EXPORT_SYMBOL_GPL */
+#undef EXPORT_SYMBOL_GPL
+#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL
+/* #endif */
+EXPORT_SYMBOL_GPL(register_ipsec_alg);
+EXPORT_SYMBOL_GPL(unregister_ipsec_alg);
+EXPORT_SYMBOL_GPL(ipsec_alg_test);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_alg.h linux-patched/net/ipsec/ipsec_alg.h
--- linux/net/ipsec/ipsec_alg.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_alg.h	Fri Feb  7 13:14:24 2003
@@ -0,0 +1,256 @@
+/*
+ * Modular extensions service and registration functions interface
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+#ifndef IPSEC_ALG_H
+#define IPSEC_ALG_H
+
+/* 
+ *   gcc >= 3.2 has removed __FUNCTION__, replaced by C99 __func__
+ *   *BUT* its a compiler variable.
+ */
+#if (__GNUC__ >= 3)
+#ifndef __FUNCTION__
+#define __FUNCTION__ __func__
+#endif
+#endif
+
+/*	Version 0.8.1-0 */
+#define IPSEC_ALG_VERSION	0x00080100
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <asm/atomic.h>
+/*	
+ *	The following structs are used via pointers in ipsec_alg object to
+ *	avoid ipsec_alg.h coupling with freeswan headers, thus simplifying
+ *	module development
+ */
+struct ipsec_sa;
+struct esp;
+
+/**************************************
+ *
+ *	Main registration object 
+ *
+ *************************************/
+#define IPSEC_ALG_VERSION_QUAD(v)	\
+	(v>>24),((v>>16)&0xff),((v>>8)&0xff),(v&0xff)
+/*	
+ *	Main ipsec_alg objects: "OOPrograming wannabe"
+ *	Hierachy (carefully handled with _minimal_ cast'ing):
+ *
+ *      ipsec_alg+
+ *		 +->ipsec_alg_enc  (ixt_alg_type=SADB_EXT_SUPPORTED_ENCRYPT)
+ *		 +->ipsec_alg_auth (ixt_alg_type=SADB_EXT_SUPPORTED_AUTH)
+ */
+
+/***************************************************************
+ *
+ * 	INTERFACE object: struct ipsec_alg
+ *
+ ***************************************************************/
+
+/* 
+ * 	common part for every struct ipsec_alg_*	
+ * 	(sortof poor's man OOP)
+ */
+#define IPSEC_ALG_STRUCT_COMMON \
+	unsigned ixt_version;	/* only allow this version (or 'near')*/ \
+	struct list_head ixt_list;	/* dlinked list */ \
+	struct module *ixt_module;	/* THIS_MODULE */ \
+	unsigned ixt_state;		/* state flags */ \
+	atomic_t ixt_refcnt; 	/* ref. count when pointed from ipsec_sa */ \
+	char ixt_name[16];	/* descriptive short name, eg. "3des" */ \
+	void *ixt_data;		/* private for algo implementation */ \
+	uint8_t  ixt_blocksize;	/* blocksize in bytes */ \
+	\
+	/* THIS IS A COPY of struct supported (lib/pfkey.h)        \
+	 * please keep in sync until we migrate 'supported' stuff  \
+	 * to ipsec_alg \
+	 */ \
+	uint16_t ixt_alg_type;	/* correspond to IPSEC_ALG_{ENCRYPT,AUTH} */ \
+	uint8_t  ixt_alg_id;	/* enc. alg. number, eg. ESP_3DES */ \
+	uint8_t  ixt_ivlen;	/* ivlen in bits, expected to be multiple of 8! */ \
+	uint16_t ixt_keyminbits;/* min. keybits (of entropy) */ \
+	uint16_t ixt_keymaxbits;/* max. keybits (of entropy) */
+
+#define ixt_support ixt_alg_type
+	
+#define IPSEC_ALG_ST_SUPP	0x01
+#define IPSEC_ALG_ST_REGISTERED 0x02
+#define IPSEC_ALG_ST_EXCL	0x04
+struct ipsec_alg {
+	IPSEC_ALG_STRUCT_COMMON
+};
+/* 
+ * 	Note the const in cbc_encrypt IV arg:
+ * 	some ciphers like to toast passed IV (eg. 3DES): make a local IV copy
+ */
+struct ipsec_alg_enc {
+	IPSEC_ALG_STRUCT_COMMON
+	unsigned ixt_e_keylen;		/* raw key length in bytes          */
+	unsigned ixt_e_ctx_size;	/* sa_p->key_e_size */
+	int (*ixt_e_set_key)(struct ipsec_alg_enc *alg, __u8 *key_e, const __u8 *key, size_t keysize);
+	__u8 *(*ixt_e_new_key)(struct ipsec_alg_enc *alg, const __u8 *key, size_t keysize);
+	void (*ixt_e_destroy_key)(struct ipsec_alg_enc *alg, __u8 *key_e);
+	int (*ixt_e_cbc_encrypt)(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, const __u8 *iv, int encrypt);
+};
+struct ipsec_alg_auth {
+	IPSEC_ALG_STRUCT_COMMON
+	unsigned ixt_a_keylen;		/* raw key length in bytes          */
+	unsigned ixt_a_ctx_size;	/* sa_p->key_a_size */
+	unsigned ixt_a_authlen;		/* 'natural' auth. hash len (bytes) */
+	int (*ixt_a_hmac_set_key)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *key, int keylen);
+	int (*ixt_a_hmac_hash)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen);
+};
+/*	
+ *	These are _copies_ of SADB_EXT_SUPPORTED_{AUTH,ENCRYPT}, 
+ *	to avoid header coupling for true constants
+ *	about headers ... "cp is your friend" --Linus
+ */
+#define IPSEC_ALG_TYPE_AUTH	14
+#define IPSEC_ALG_TYPE_ENCRYPT	15
+
+/***************************************************************
+ *
+ * 	INTERFACE for module loading,testing, and unloading
+ *
+ ***************************************************************/
+/*	-  registration calls 	*/
+int register_ipsec_alg(struct ipsec_alg *);
+int unregister_ipsec_alg(struct ipsec_alg *);
+/*	-  optional (simple test) for algos 	*/
+int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int testparm);
+/*	inline wrappers (usefull for type validation */
+static inline int register_ipsec_alg_enc(struct ipsec_alg_enc *ixt) {
+	return register_ipsec_alg((struct ipsec_alg*)ixt);
+}
+static inline int unregister_ipsec_alg_enc(struct ipsec_alg_enc *ixt) {
+	return unregister_ipsec_alg((struct ipsec_alg*)ixt);
+}
+static inline int register_ipsec_alg_auth(struct ipsec_alg_auth *ixt) {
+	return register_ipsec_alg((struct ipsec_alg*)ixt);
+}
+static inline int unregister_ipsec_alg_auth(struct ipsec_alg_auth *ixt) {
+	return unregister_ipsec_alg((struct ipsec_alg*)ixt);
+}
+
+/*****************************************************************
+ *
+ * 	INTERFACE for ENC services: key creation, encrypt function
+ *
+ *****************************************************************/
+
+#define IPSEC_ALG_ENCRYPT 1
+#define IPSEC_ALG_DECRYPT 0
+
+/* 	encryption key context creation function */
+int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p);
+/* 
+ * 	ipsec_alg_esp_encrypt(): encrypt ilen bytes in idat returns
+ * 	0 or ERR<0
+ */
+int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 *idat, int ilen, const __u8 *iv, int action);
+
+/***************************************************************
+ *
+ * 	INTERFACE for AUTH services: key creation, hash functions
+ *
+ ***************************************************************/
+int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p);
+int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) ;
+#define ipsec_alg_sa_esp_update(c,k,l) ipsec_alg_sa_esp_hash(c,k,l,NULL,0)
+
+/* only called from ipsec_init.c */
+int ipsec_alg_init(void);
+
+/* algo module glue for static algos */
+void ipsec_alg_static_init(void);
+typedef int (*ipsec_alg_init_func_t) (void);
+
+/**********************************************
+ *
+ * 	INTERFACE for ipsec_sa init and wipe
+ *
+ **********************************************/
+
+/* returns true if ipsec_sa has ipsec_alg obj attached */
+#define IPSEC_ALG_SA_ESP_ENC(sa_p) ((sa_p)->ips_alg_enc)
+#define IPSEC_ALG_SA_ESP_AUTH(sa_p) ((sa_p)->ips_alg_auth)
+/* 
+ * Initializes ipsec_sa's ipsec_alg object, using already loaded
+ * proto, authalg, encalg.; links ipsec_alg objects (enc, auth)
+ */
+int ipsec_alg_sa_init(struct ipsec_sa *sa_p);
+/* 
+ * Destroys ipsec_sa's ipsec_alg object
+ * unlinking ipsec_alg objects
+ */
+int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p);
+
+/**********************************************
+ *
+ * 	2.2 backport for some 2.4 useful module stuff
+ *
+ **********************************************/
+#ifdef MODULE
+#ifndef THIS_MODULE
+#define THIS_MODULE          (&__this_module)
+#endif
+#ifndef module_init
+typedef int (*__init_module_func_t)(void);
+typedef void (*__cleanup_module_func_t)(void);
+
+#define module_init(x) \
+        int init_module(void) __attribute__((alias(#x))); \
+        static inline __init_module_func_t __init_module_inline(void) \
+        { return x; }
+#define module_exit(x) \
+        void cleanup_module(void) __attribute__((alias(#x))); \
+        static inline __cleanup_module_func_t __cleanup_module_inline(void) \
+        { return x; }
+#endif
+
+#define IPSEC_ALG_MODULE_INIT( func_name )	\
+	static int func_name(void);		\
+	module_init(func_name);			\
+	static int __init func_name(void)
+#define IPSEC_ALG_MODULE_EXIT( func_name )	\
+	static void func_name(void);		\
+	module_exit(func_name);			\
+	static void __exit func_name(void)
+#else	/* not MODULE */
+#ifndef THIS_MODULE
+#define THIS_MODULE          NULL
+#endif
+/*	
+ *	I only want module_init() magic 
+ *	when algo.c file *is THE MODULE*, in all other
+ *	cases, initialization is called explicitely from ipsec_alg_init()
+ */
+#define IPSEC_ALG_MODULE_INIT( func_name )	\
+	extern int func_name(void);		\
+	int func_name(void)
+#define IPSEC_ALG_MODULE_EXIT( func_name )	\
+	extern void func_name(void);		\
+	void func_name(void)
+#endif
+
+#endif /* IPSEC_ALG_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_encap.h linux-patched/net/ipsec/ipsec_encap.h
--- linux/net/ipsec/ipsec_encap.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_encap.h	Thu Dec 12 03:32:07 2002
@@ -0,0 +1,143 @@
+/*
+ * declarations relevant to encapsulation-like operations
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#ifndef _IPSEC_ENCAP_H_
+
+#define SENT_IP4	16	/* data is two struct in_addr + proto + ports*/
+			/* (2 * sizeof(struct in_addr)) */
+			/* sizeof(struct sockaddr_encap)
+			   - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */
+
+struct sockaddr_encap
+{
+	__u8	sen_len;		/* length */
+	__u8	sen_family;		/* AF_ENCAP */
+	__u16	sen_type;		/* see SENT_* */
+	union
+	{
+		struct			/* SENT_IP4 */
+		{
+			struct in_addr Src;
+			struct in_addr Dst;
+			__u8 Proto;
+			__u16 Sport;
+			__u16 Dport;
+		} Sip4;
+	} Sen;
+};
+
+#define sen_ip_src	Sen.Sip4.Src
+#define sen_ip_dst	Sen.Sip4.Dst
+#define sen_proto       Sen.Sip4.Proto
+#define sen_sport       Sen.Sip4.Sport
+#define sen_dport       Sen.Sip4.Dport
+
+#ifndef AF_ENCAP
+#define AF_ENCAP 26
+#endif /* AF_ENCAP */
+
+#define _IPSEC_ENCAP_H_
+#endif /* _IPSEC_ENCAP_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.2  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.16  2001/11/26 09:23:47  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.15.2.1  2001/09/25 02:18:54  mcr
+ * 	struct eroute moved to ipsec_eroute.h
+ *
+ * Revision 1.15  2001/09/14 16:58:36  rgb
+ * Added support for storing the first and last packets through a HOLD.
+ *
+ * Revision 1.14  2001/09/08 21:13:31  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.13  2001/06/14 19:35:08  rgb
+ * Update copyright date.
+ *
+ * Revision 1.12  2001/05/27 06:12:10  rgb
+ * Added structures for pid, packet count and last access time to eroute.
+ * Added packet count to beginning of /proc/net/ipsec_eroute.
+ *
+ * Revision 1.11  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.10  2000/03/22 16:15:36  rgb
+ * Fixed renaming of dev_get (MB).
+ *
+ * Revision 1.9  2000/01/21 06:13:26  rgb
+ * Added a macro for AF_ENCAP
+ *
+ * Revision 1.8  1999/12/31 14:56:55  rgb
+ * MB fix for 2.3 dev-use-count.
+ *
+ * Revision 1.7  1999/11/18 04:09:18  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.6  1999/09/24 00:34:13  rgb
+ * Add Marc Boucher's support for 2.3.xx+.
+ *
+ * Revision 1.5  1999/04/11 00:28:57  henry
+ * GPL boilerplate
+ *
+ * Revision 1.4  1999/04/06 04:54:25  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.3  1998/10/19 14:44:28  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.2  1998/07/14 18:19:33  rgb
+ * Added #ifdef __KERNEL__ directives to restrict scope of header.
+ *
+ * Revision 1.1  1998/06/18 21:27:44  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2  1998/04/21 21:29:10  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1  1998/04/09 03:05:58  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Minor cosmetic changes.
+ *
+ * Revision 0.3  1996/11/20 14:35:48  ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_eroute.h linux-patched/net/ipsec/ipsec_eroute.h
--- linux/net/ipsec/ipsec_eroute.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_eroute.h	Thu Dec 12 03:32:07 2002
@@ -0,0 +1,103 @@
+/*
+ * @(#) declarations of eroute structures
+ *
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
+ * Copyright (C) 2001                    Michael Richardson <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ * derived from ipsec_encap.h 1.15 on 2001/9/18 by mcr.
+ *
+ */
+
+#ifndef _IPSEC_EROUTE_H_
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+
+/*
+ * The "type" is really part of the address as far as the routing
+ * system is concerned. By using only one bit in the type field
+ * for each type, we sort-of make sure that different types of
+ * encapsulation addresses won't be matched against the wrong type.
+ */
+
+/*
+ * An entry in the radix tree 
+ */
+
+struct rjtentry
+{
+	struct	radij_node rd_nodes[2];	/* tree glue, and other values */
+#define	rd_key(r)	((struct sockaddr_encap *)((r)->rd_nodes->rj_key))
+#define	rd_mask(r)	((struct sockaddr_encap *)((r)->rd_nodes->rj_mask))
+	short	rd_flags;
+	short	rd_count;
+};
+
+struct ident
+{
+	__u16	type;	/* identity type */
+	__u64	id;	/* identity id */
+	__u8	len;	/* identity len */
+	caddr_t	data;	/* identity data */
+};
+
+/*
+ * An encapsulation route consists of a pointer to a 
+ * radix tree entry and a SAID (a destination_address/SPI/protocol triple).
+ */
+
+struct eroute
+{
+	struct rjtentry er_rjt;
+	struct sa_id er_said;
+	uint32_t er_pid;
+	uint32_t er_count;
+	uint64_t er_lasttime;
+	struct sockaddr_encap er_eaddr; /* MCR get rid of _encap, it is silly*/
+	struct sockaddr_encap er_emask;
+        struct ident er_ident_s;
+        struct ident er_ident_d;
+	struct sk_buff* er_first;
+	struct sk_buff* er_last;
+};
+
+#define er_dst er_said.dst
+#define er_spi er_said.spi
+
+#define _IPSEC_EROUTE_H_
+#endif /* _IPSEC_EROUTE_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.2  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.2  2001/11/26 09:16:13  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:18:54  mcr
+ * 	struct eroute moved to ipsec_eroute.h
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_errs.h linux-patched/net/ipsec/ipsec_errs.h
--- linux/net/ipsec/ipsec_errs.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_errs.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,50 @@
+/*
+ * @(#) definition of ipsec_errs structure
+ *
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ */
+
+/* 
+ * This file describes the errors/statistics that FreeSWAN collects.
+ *
+ */
+
+struct ipsec_errs {
+	__u32		ips_alg_errs;	       /* number of algorithm errors */
+	__u32		ips_auth_errs;	       /* # of authentication errors */
+	__u32		ips_encsize_errs;      /* # of encryption size errors*/
+	__u32		ips_encpad_errs;       /* # of encryption pad  errors*/
+	__u32		ips_replaywin_errs;    /* # of pkt sequence errors */
+};
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.2  2001/11/26 09:16:13  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:25:57  mcr
+ * 	lifetime structure created and common functions created.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_esp.h linux-patched/net/ipsec/ipsec_esp.h
--- linux/net/ipsec/ipsec_esp.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_esp.h	Thu Sep  5 04:27:08 2002
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#include "ipsec_md5h.h"
+#include "ipsec_sha1.h"
+
+#include "des.h"
+
+#ifndef IPPROTO_ESP
+#define IPPROTO_ESP 50
+#endif /* IPPROTO_ESP */
+
+#define ESP_HEADER_LEN		8	/* 64 bits header (spi+rpl)*/
+
+#define EMT_ESPDESCBC_ULEN	20	/* coming from user mode */
+#define EMT_ESPDES_KMAX		64	/* 512 bit secret key enough? */
+#define EMT_ESPDES_KEY_SZ	8	/* 56 bit secret key with parity = 64 bits */
+#define EMT_ESP3DES_KEY_SZ	24	/* 168 bit secret key with parity = 192 bits */
+#define EMT_ESPDES_IV_SZ	8	/* IV size */
+#define ESP_DESCBC_BLKLEN       8       /* DES-CBC block size */
+
+#define ESP_IV_MAXSZ		16	/* This is _critical_ */
+#define ESP_IV_MAXSZ_INT	(ESP_IV_MAXSZ/sizeof(int))
+
+#define DB_ES_PKTRX	0x0001
+#define DB_ES_PKTRX2	0x0002
+#define DB_ES_TDB	0x0010
+#define DB_ES_XF	0x0020
+#define DB_ES_IPAD	0x0040
+#define DB_ES_INAU	0x0080
+#define DB_ES_OINFO	0x0100
+#define DB_ES_OINFO2	0x0200
+#define DB_ES_OH	0x0400
+#define DB_ES_REPLAY	0x0800
+
+#ifdef __KERNEL__
+struct des_eks {
+	des_key_schedule ks;
+};
+
+extern struct inet_protocol esp_protocol;
+
+struct options;
+
+extern int
+esp_rcv(struct sk_buff *skb,
+	struct device *dev,
+	struct options *opt, 
+	__u32 daddr,
+	unsigned short len,
+	__u32 saddr,
+	int redo,
+	struct inet_protocol *protocol);
+
+/* XXX: only for 64 bits IVs, eg. ESP_3DES */
+struct esp
+{
+	__u32	esp_spi;		/* Security Parameters Index */
+        __u32   esp_rpl;                /* Replay counter */
+	__u8	esp_iv[8];		/* iv */
+};
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_esp;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* __KERNEL__ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.2  2002/09/05 03:27:08  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.17  2002/02/20 01:27:07  rgb
+ * Ditched a pile of structs only used by the old Netlink interface.
+ *
+ * Revision 1.16  2001/12/11 02:35:57  rgb
+ * Change "struct net_device" to "struct device" for 2.2 compatibility.
+ *
+ * Revision 1.15  2001/11/26 09:23:48  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.14.2.3  2001/10/23 04:16:42  mcr
+ * 	get definition of des_key_schedule from des.h
+ *
+ * Revision 1.14.2.2  2001/10/22 20:33:13  mcr
+ * 	use "des_key_schedule" structure instead of cooking our own.
+ *
+ * Revision 1.14.2.1  2001/09/25 02:18:25  mcr
+ * 	replace "struct device" with "struct netdevice"
+ *
+ * Revision 1.14  2001/06/14 19:35:08  rgb
+ * Update copyright date.
+ *
+ * Revision 1.13  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.12  2000/08/01 14:51:50  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.11  2000/01/10 16:36:20  rgb
+ * Ditch last of EME option flags, including initiator.
+ *
+ * Revision 1.10  1999/12/07 18:16:22  rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.9  1999/04/11 00:28:57  henry
+ * GPL boilerplate
+ *
+ * Revision 1.8  1999/04/06 04:54:25  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.7  1999/01/26 02:06:00  rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ *
+ * Revision 1.6  1999/01/22 15:22:05  rgb
+ * Re-enable IV in the espblkrply_edata structure to avoid breaking pluto
+ * until pluto can be fixed properly.
+ *
+ * Revision 1.5  1999/01/22 06:18:16  rgb
+ * Updated macro comments.
+ * Added key schedule types to support algorithm switch code.
+ *
+ * Revision 1.4  1998/08/12 00:07:32  rgb
+ * Added data structures for new xforms: null, {,3}dessha1.
+ *
+ * Revision 1.3  1998/07/14 15:57:01  rgb
+ * Add #ifdef __KERNEL__ to protect kernel-only structures.
+ *
+ * Revision 1.2  1998/06/25 19:33:46  rgb
+ * Add prototype for protocol receive function.
+ * Rearrange for more logical layout.
+ *
+ * Revision 1.1  1998/06/18 21:27:45  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.6  1998/06/05 02:28:08  rgb
+ * Minor comment fix.
+ *
+ * Revision 1.5  1998/05/27 22:34:00  rgb
+ * Changed structures to accomodate key separation.
+ *
+ * Revision 1.4  1998/05/18 22:28:43  rgb
+ * Disable key printing facilities from /proc/net/ipsec_*.
+ *
+ * Revision 1.3  1998/04/21 21:29:07  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/12 22:03:20  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:06:00  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5  1997/06/03 04:24:48  ji
+ * Added ESP-3DES-MD5-96 transform.
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Added definitions for new ESP transforms.
+ *
+ * Revision 0.3  1996/11/20 14:35:48  ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_init.c linux-patched/net/ipsec/ipsec_init.c
--- linux/net/ipsec/ipsec_init.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_init.c	Thu Sep  5 04:27:08 2002
@@ -0,0 +1,663 @@
+/*
+ * @(#) Initialization code.
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
+ *                                 2001  Michael Richardson <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * /proc system code was split out into ipsec_proc.c after rev. 1.70.
+ *
+ */
+
+char ipsec_init_c_version[] = "RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/in.h>          /* struct sockaddr_in */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+#endif /* NET_21 */
+
+#include <asm/checksum.h>
+#include <net/ip.h>
+
+#ifdef CONFIG_PROC_FS
+# include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+
+#ifdef NETLINK_SOCK
+# include <linux/netlink.h>
+#else
+# include <net/netlink.h>
+#endif
+
+#include "radij.h"
+
+#include "ipsec_life.h"
+#include "ipsec_stats.h"
+#include "ipsec_sa.h"
+
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_tunnel.h"
+
+#include "ipsec_rcv.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+
+#ifdef CONFIG_IPSEC_IPCOMP
+# include "ipcomp.h"
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#include "ipsec_proto.h"
+#include "ipsec_alg.h"
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#if !defined(CONFIG_IPSEC_ESP) && !defined(CONFIG_IPSEC_AH)
+#error "kernel configuration must include ESP or AH"
+#endif
+
+/*
+ * seems to be present in 2.4.10 (Linus), but also in some RH and other
+ * distro kernels of a lower number.
+ */
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("Dual BSD/GPL");
+#endif
+
+#ifdef CONFIG_IPSEC_DEBUG
+int debug_eroute = 0;
+int debug_spi = 0;
+int debug_netlink = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+int ipsec_device_event(struct notifier_block *dnot, unsigned long event, void *ptr);
+/*
+ * the following structure is required so that we receive
+ * event notifications when network devices are enabled and
+ * disabled (ifconfig up and down).
+ */
+static struct notifier_block ipsec_dev_notifier={
+	ipsec_device_event,
+	NULL,
+	0
+};
+
+#ifdef CONFIG_SYSCTL
+extern int ipsec_sysctl_register(void);
+extern void ipsec_sysctl_unregister(void);
+#endif
+
+/* void */
+int
+ipsec_init(void)
+{
+	int error = 0;
+#ifdef CONFIG_IPSEC_ENC_3DES
+	extern int des_check_key;
+
+	/* turn off checking of keys */
+	des_check_key=0;
+#endif /* CONFIG_IPSEC_ENC_3DES */
+
+	KLIPS_PRINT(1, "klips_info:ipsec_init: "
+		    "KLIPS startup, FreeS/WAN IPSec version: %s\n",
+		    ipsec_version_code());
+
+	error |= ipsec_proc_init();
+
+#ifndef SPINLOCK
+	tdb_lock.lock = 0;
+	eroute_lock.lock = 0;
+#endif /* !SPINLOCK */
+
+	error |= ipsec_sadb_init();
+	error |= ipsec_radijinit();
+
+	error |= pfkey_init();
+
+	error |= register_netdevice_notifier(&ipsec_dev_notifier);
+
+#ifdef CONFIG_IPSEC_ESP
+	inet_add_protocol(&esp_protocol);
+#endif /* CONFIG_IPSEC_ESP */
+
+#ifdef CONFIG_IPSEC_AH
+	inet_add_protocol(&ah_protocol);
+#endif /* CONFIG_IPSEC_AH */
+
+#if 0
+#ifdef CONFIG_IPSEC_IPCOMP
+	inet_add_protocol(&comp_protocol);
+#endif /* CONFIG_IPSEC_IPCOMP */
+#endif
+
+	error |= ipsec_tunnel_init_devices();
+
+#ifdef CONFIG_SYSCTL
+        error |= ipsec_sysctl_register();
+#endif                                                                          
+#ifdef CONFIG_IPSEC_ALG
+	ipsec_alg_init();
+#endif
+	return error;
+}	
+
+
+/* void */
+int
+ipsec_cleanup(void)
+{
+	int error = 0;
+
+#ifdef CONFIG_SYSCTL
+        ipsec_sysctl_unregister();
+#endif                                                                          
+	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
+		    "klips_debug:ipsec_cleanup: "
+		    "calling ipsec_tunnel_cleanup_devices.\n");
+	error |= ipsec_tunnel_cleanup_devices();
+
+#if 0
+#ifdef CONFIG_IPSEC_IPCOMP
+	if (inet_del_protocol(&comp_protocol) < 0)
+		printk(KERN_INFO "klips_debug:ipsec_cleanup: "
+		       "comp close: can't remove protocol\n");
+#endif /* CONFIG_IPSEC_IPCOMP */
+#endif /* 0 */
+#ifdef CONFIG_IPSEC_AH
+	if (inet_del_protocol(&ah_protocol) < 0)
+		printk(KERN_INFO "klips_debug:ipsec_cleanup: "
+		       "ah close: can't remove protocol\n");
+#endif /* CONFIG_IPSEC_AH */
+#ifdef CONFIG_IPSEC_ESP
+	if (inet_del_protocol(&esp_protocol) < 0)
+		printk(KERN_INFO "klips_debug:ipsec_cleanup: "
+		       "esp close: can't remove protocol\n");
+#endif /* CONFIG_IPSEC_ESP */
+
+	error |= unregister_netdevice_notifier(&ipsec_dev_notifier);
+
+	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
+		    "klips_debug:ipsec_cleanup: "
+		    "calling ipsec_tdbcleanup.\n");
+	error |= ipsec_sadb_cleanup(0);
+	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
+		    "klips_debug:ipsec_cleanup: "
+		    "calling ipsec_radijcleanup.\n");
+	error |= ipsec_radijcleanup();
+	
+	KLIPS_PRINT(debug_pfkey, /* debug_tunnel & DB_TN_INIT, */
+		    "klips_debug:ipsec_cleanup: "
+		    "calling pfkey_cleanup.\n");
+	error |= pfkey_cleanup();
+
+	ipsec_proc_cleanup();
+
+	return error;
+}
+
+#ifdef MODULE
+int
+init_module(void)
+{
+	int error = 0;
+
+	error |= ipsec_init();
+
+	return error;
+}
+
+int
+cleanup_module(void)
+{
+	int error = 0;
+
+	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
+		    "klips_debug:cleanup_module: "
+		    "calling ipsec_cleanup.\n");
+
+	error |= ipsec_cleanup();
+
+	KLIPS_PRINT(1, "klips_info:cleanup_module: "
+		    "ipsec module unloaded.\n");
+
+	return error;
+}
+#endif /* MODULE */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.2  2002/09/05 03:27:08  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.80  2002/03/24 07:34:08  rgb
+ * Sanity check for at least one of AH or ESP configured.
+ *
+ * Revision 1.79  2002/02/05 22:55:15  mcr
+ * 	added MODULE_LICENSE declaration.
+ * 	This macro does not appear in all kernel versions (see comment).
+ *
+ * Revision 1.78  2002/01/29 17:17:55  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.77  2002/01/29 04:00:51  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.76  2002/01/29 02:13:17  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.75  2001/11/26 09:23:48  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.74  2001/11/22 05:44:11  henry
+ * new version stuff
+ *
+ * Revision 1.71.2.2  2001/10/22 20:51:00  mcr
+ * 	explicitely set des_check_key.
+ *
+ * Revision 1.71.2.1  2001/09/25 02:19:39  mcr
+ * 	/proc manipulation code moved to new ipsec_proc.c
+ *
+ * Revision 1.73  2001/11/06 19:47:17  rgb
+ * Changed lifetime_packets to uint32 from uint64.
+ *
+ * Revision 1.72  2001/10/18 04:45:19  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.71  2001/09/20 15:32:45  rgb
+ * Minor pfkey lifetime fixes.
+ *
+ * Revision 1.70  2001/07/06 19:51:21  rgb
+ * Added inbound policy checking code for IPIP SAs.
+ *
+ * Revision 1.69  2001/06/14 19:33:26  rgb
+ * Silence startup message for console, but allow it to be logged.
+ * Update copyright date.
+ *
+ * Revision 1.68  2001/05/29 05:14:36  rgb
+ * Added PMTU to /proc/net/ipsec_tncfg output.  See 'man 5 ipsec_tncfg'.
+ *
+ * Revision 1.67  2001/05/04 16:34:52  rgb
+ * Rremove erroneous checking of return codes for proc_net_* in 2.4.
+ *
+ * Revision 1.66  2001/05/03 19:40:34  rgb
+ * Check error return codes in startup and shutdown.
+ *
+ * Revision 1.65  2001/02/28 05:03:27  rgb
+ * Clean up and rationalise startup messages.
+ *
+ * Revision 1.64  2001/02/27 22:24:53  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.63  2000/11/29 20:14:06  rgb
+ * Add src= to the output of /proc/net/ipsec_spi and delete dst from IPIP.
+ *
+ * Revision 1.62  2000/11/06 04:31:24  rgb
+ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
+ * Fixed longlong for pre-2.4 kernels (Svenning).
+ * Add Svenning's adaptive content compression.
+ * Disabled registration of ipcomp handler.
+ *
+ * Revision 1.61  2000/10/11 13:37:54  rgb
+ * #ifdef out debug print that causes proc/net/ipsec_version to oops.
+ *
+ * Revision 1.60  2000/09/20 03:59:01  rgb
+ * Change static info functions to DEBUG_NO_STATIC to reveal function names
+ * in oopsen.
+ *
+ * Revision 1.59  2000/09/16 01:06:26  rgb
+ * Added cast of var to silence compiler warning about long fed to int
+ * format.
+ *
+ * Revision 1.58  2000/09/15 11:37:01  rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.57  2000/09/12 03:21:50  rgb
+ * Moved radij_c_version printing to ipsec_version_get_info().
+ * Reformatted ipsec_version_get_info().
+ * Added sysctl_{,un}register() calls.
+ *
+ * Revision 1.56  2000/09/08 19:16:50  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Removed all references to CONFIG_IPSEC_PFKEYv2.
+ *
+ * Revision 1.55  2000/08/30 05:19:03  rgb
+ * Cleaned up no longer used spi_next, netlink register/unregister, other
+ * minor cleanup.
+ * Removed cruft replaced by TDB_XFORM_NAME.
+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst.
+ * Moved debug version strings to printk when /proc/net/ipsec_version is
+ * called.
+ *
+ * Revision 1.54  2000/08/20 18:31:05  rgb
+ * Changed cosmetic alignment in spi_info.
+ * Changed addtime and usetime to use actual value which is relative
+ * anyways, as intended. (Momchil)
+ *
+ * Revision 1.53  2000/08/18 17:37:03  rgb
+ * Added an (int) cast to shut up the compiler...
+ *
+ * Revision 1.52  2000/08/01 14:51:50  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.51  2000/07/25 20:41:22  rgb
+ * Removed duplicate parameter in spi_getinfo.
+ *
+ * Revision 1.50  2000/07/17 03:21:45  rgb
+ * Removed /proc/net/ipsec_spinew.
+ *
+ * Revision 1.49  2000/06/28 05:46:51  rgb
+ * Renamed ivlen to iv_bits for consistency.
+ * Changed output of add and use times to be relative to now.
+ *
+ * Revision 1.48  2000/05/11 18:26:10  rgb
+ * Commented out calls to netlink_attach/detach to avoid activating netlink
+ * in the kenrel config.
+ *
+ * Revision 1.47  2000/05/10 22:35:26  rgb
+ * Comment out most of the startup version information.
+ *
+ * Revision 1.46  2000/03/22 16:15:36  rgb
+ * Fixed renaming of dev_get (MB).
+ *
+ * Revision 1.45  2000/03/16 06:40:48  rgb
+ * Hardcode PF_KEYv2 support.
+ *
+ * Revision 1.44  2000/01/22 23:19:20  rgb
+ * Simplified code to use existing macro TDB_XFORM_NAME().
+ *
+ * Revision 1.43  2000/01/21 06:14:04  rgb
+ * Print individual stats only if non-zero.
+ * Removed 'bits' from each keylength for brevity.
+ * Shortened lifetimes legend for brevity.
+ * Changed wording from 'last_used' to the clearer 'idle'.
+ *
+ * Revision 1.42  1999/12/31 14:57:19  rgb
+ * MB fix for new dummy-less proc_get_info in 2.3.35.
+ *
+ * Revision 1.41  1999/11/23 23:04:03  rgb
+ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ *
+ * Revision 1.40  1999/11/18 18:47:01  rgb
+ * Added dynamic proc registration for 2.3.25+.
+ * Changed all device registrations for static linking to
+ * dynamic to reduce the number and size of patches.
+ * Changed all protocol registrations for static linking to
+ * dynamic to reduce the number and size of patches.
+ *
+ * Revision 1.39  1999/11/18 04:12:07  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ * Added Marc Boucher's 2.3.25 proc patches.
+ * Converted all PROC_FS entries to dynamic to reduce kernel patching.
+ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
+ *
+ * Revision 1.38  1999/11/17 15:53:38  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.37  1999/10/16 04:23:06  rgb
+ * Add stats for replaywin_errs, replaywin_max_sequence_difference,
+ * authentication errors, encryption size errors, encryption padding
+ * errors, and time since last packet.
+ *
+ * Revision 1.36  1999/10/16 00:30:47  rgb
+ * Added SA lifetime counting.
+ *
+ * Revision 1.35  1999/10/15 22:14:00  rgb
+ * Clean out cruft.
+ *
+ * Revision 1.34  1999/10/03 18:46:28  rgb
+ * Spinlock fixes for 2.0.xx and 2.3.xx.
+ *
+ * Revision 1.33  1999/10/01 17:08:10  rgb
+ * Disable spinlock init.
+ *
+ * Revision 1.32  1999/10/01 16:22:24  rgb
+ * Switch from assignment init. to functional init. of spinlocks.
+ *
+ * Revision 1.31  1999/10/01 15:44:52  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.30  1999/10/01 00:00:16  rgb
+ * Added eroute structure locking.
+ * Added tdb structure locking.
+ * Minor formatting changes.
+ * Add call to initialize tdb hash table.
+ *
+ * Revision 1.29  1999/09/23 20:22:40  rgb
+ * Enable, tidy and fix network notifier code.
+ *
+ * Revision 1.28  1999/09/18 11:39:56  rgb
+ * Start to add (disabled) netdevice notifier code.
+ *
+ * Revision 1.27  1999/08/28 08:24:47  rgb
+ * Add compiler directives to compile cleanly without debugging.
+ *
+ * Revision 1.26  1999/08/06 16:03:22  rgb
+ * Correct error messages on failure to unload /proc entries.
+ *
+ * Revision 1.25  1999/08/03 17:07:25  rgb
+ * Report device MTU, not private MTU.
+ *
+ * Revision 1.24  1999/05/25 22:24:37  rgb
+ * /PROC/NET/ipsec* init problem fix.
+ *
+ * Revision 1.23  1999/05/25 02:16:38  rgb
+ * Make modular proc_fs entries dynamic and fix for 2.2.x.
+ *
+ * Revision 1.22  1999/05/09 03:25:35  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.21  1999/05/05 22:02:30  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.20  1999/04/29 15:15:50  rgb
+ * Fix undetected iv_len reporting bug.
+ * Add sanity checking for null pointer to private data space.
+ * Add return values to init and cleanup functions.
+ *
+ * Revision 1.19  1999/04/27 19:24:44  rgb
+ * Added /proc/net/ipsec_klipsdebug support for reading the current debug
+ * settings.
+ * Instrument module load/init/unload.
+ *
+ * Revision 1.18  1999/04/15 15:37:24  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.15.2.3  1999/04/13 20:29:19  rgb
+ * /proc/net/ipsec_* cleanup.
+ *
+ * Revision 1.15.2.2  1999/04/02 04:28:23  rgb
+ * /proc/net/ipsec_* formatting enhancements.
+ *
+ * Revision 1.15.2.1  1999/03/30 17:08:33  rgb
+ * Add pfkey initialisation.
+ *
+ * Revision 1.17  1999/04/11 00:28:57  henry
+ * GPL boilerplate
+ *
+ * Revision 1.16  1999/04/06 04:54:25  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.15  1999/02/24 20:15:07  rgb
+ * Update output format.
+ *
+ * Revision 1.14  1999/02/17 16:49:39  rgb
+ * Convert DEBUG_IPSEC to KLIPS_PRINT
+ * Ditch NET_IPIP dependancy.
+ *
+ * Revision 1.13  1999/01/26 02:06:37  rgb
+ * Remove ah/esp switching on include files.
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ * Removed dead code.
+ * Remove references to INET_GET_PROTOCOL.
+ *
+ * Revision 1.12  1999/01/22 06:19:18  rgb
+ * Cruft clean-out.
+ * 64-bit clean-up.
+ * Added algorithm switch code.
+ *
+ * Revision 1.11  1998/12/01 05:54:53  rgb
+ * Cleanup and order debug version output.
+ *
+ * Revision 1.10  1998/11/30 13:22:54  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.9  1998/11/10 05:35:13  rgb
+ * Print direction in/out flag from /proc/net/ipsec_spi.
+ *
+ * Revision 1.8  1998/10/27 13:48:10  rgb
+ * Cleaned up /proc/net/ipsec_* filesystem for easy parsing by scripts.
+ * Fixed less(1) truncated output bug.
+ * Code clean-up.
+ *
+ * Revision 1.7  1998/10/22 06:43:16  rgb
+ * Convert to use satoa for printk.
+ *
+ * Revision 1.6  1998/10/19 14:24:35  rgb
+ * Added inclusion of freeswan.h.
+ *
+ * Revision 1.5  1998/10/09 04:43:35  rgb
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ *
+ * Revision 1.4  1998/07/27 21:50:22  rgb
+ * Not necessary to traverse mask tree for /proc/net/ipsec_eroute.
+ *
+ * Revision 1.3  1998/06/25 19:51:20  rgb
+ * Clean up #endif comments.
+ * Shift debugging comment control for procfs to debug_tunnel.
+ * Make proc_dir_entries visible to rest of kernel for static link.
+ * Replace hardwired fileperms with macros.
+ * Use macros for procfs inode numbers.
+ * Rearrange initialisations between ipsec_init and module_init as appropriate
+ * for static loading.
+ *
+ * Revision 1.2  1998/06/23 02:55:43  rgb
+ * Slightly quieted init-time messages.
+ * Re-introduced inet_add_protocol after it mysteriously disappeared...
+ * Check for and warn of absence of IPIP protocol on install of module.
+ * Move tdbcleanup to ipsec_xform.c.
+ *
+ * Revision 1.10  1998/06/18 21:29:04  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid kernel
+ * build scripts happier in presence of symbolic links
+ *
+ * Revision 1.9  1998/06/14 23:49:40  rgb
+ * Clarify version reporting on module loading.
+ *
+ * Revision 1.8  1998/06/11 05:54:23  rgb
+ * Added /proc/net/ipsec_version to report freeswan and transform versions.
+ * Added /proc/net/ipsec_spinew to generate new and unique spi's..
+ * Fixed /proc/net/ipsec_tncfg bug.
+ *
+ * Revision 1.7  1998/05/25 20:23:13  rgb
+ * proc_register changed to dynamic registration to avoid arbitrary inode
+ * numbers.
+ *
+ * Implement memory recovery from tdb and eroute tables.
+ *
+ * Revision 1.6  1998/05/21 13:08:58  rgb
+ * Rewrote procinfo subroutines to avoid *bad things* when more that 3k of
+ * information is available for printout.
+ *
+ * Revision 1.5  1998/05/18 21:29:48  rgb
+ * Cleaned up /proc/net/ipsec_* output, including a title line, algorithm
+ * names instead of numbers, standard format for numerical output base,
+ * whitespace for legibility, and the names themselves for consistency.
+ *
+ * Added /proc/net/ipsec_spigrp and /proc/net/ipsec_tncfg.
+ *
+ * Revision 1.4  1998/04/30 15:42:24  rgb
+ * Silencing attach for normal operations with #ifdef IPSEC_DEBUG.
+ *
+ * Revision 1.3  1998/04/21 21:28:58  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/12 22:03:22  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:06:05  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Fixed problem with node names of /proc/net entries.
+ * Other minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_ipe4.h linux-patched/net/ipsec/ipsec_ipe4.h
--- linux/net/ipsec/ipsec_ipe4.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_ipe4.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,65 @@
+/*
+ * IP-in-IP Header declarations
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/* The packet header is an IP header! */
+
+struct ipe4_xdata			/* transform table data */
+{
+	struct in_addr	i4_src;
+	struct in_addr	i4_dst;
+};
+
+#define EMT_IPE4_ULEN	8	/* coming from user mode */
+ 
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.4  2001/06/14 19:35:08  rgb
+ * Update copyright date.
+ *
+ * Revision 1.3  1999/04/11 00:28:57  henry
+ * GPL boilerplate
+ *
+ * Revision 1.2  1999/04/06 04:54:25  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.1  1998/06/18 21:27:47  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.1  1998/04/09 03:06:07  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:48:53  ji
+ * Release update only.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_kversion.h linux-patched/net/ipsec/ipsec_kversion.h
--- linux/net/ipsec/ipsec_kversion.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_kversion.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,190 @@
+#ifndef _FREESWAN_KVERSIONS_H
+/*
+ * header file for FreeS/WAN library functions
+ * Copyright (C) 1998, 1999, 2000  Henry Spencer.
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#define	_FREESWAN_KVERSIONS_H	/* seen it, no need to see it again */
+
+/*
+ * this file contains a series of atomic defines that depend upon
+ * kernel version numbers. The kernel versions are arranged
+ * in version-order number (which is often not chronological)
+ * and each clause enables or disables a feature.
+ */
+
+/*
+ * First, assorted kernel-version-dependent trickery.
+ */
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+#define HEADER_CACHE_BIND_21
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define SPINLOCK
+#define PROC_FS_21
+#define NETLINK_SOCK
+#define NET_21
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,19)
+#define net_device_stats enet_statistics
+#endif                                                                         
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#define SPINLOCK_23
+#define NETDEV_23
+#  ifndef CONFIG_IP_ALIAS
+#  define CONFIG_IP_ALIAS
+#  endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,25)
+#define PROC_FS_2325
+#undef  PROC_FS_21
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)
+#define PROC_NO_DUMMY
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,35)
+#define SKB_COPY_EXPAND
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,37)
+#define IP_SELECT_IDENT
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,50)) && defined(CONFIG_NETFILTER)
+#define SKB_RESET_NFCT
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,2)
+#define IP_SELECT_IDENT_NEW
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
+#define IPH_is_SKB_PULLED
+#define SKB_COW_NEW
+#define PROTO_HANDLER_SINGLE_PARM
+#define IP_FRAGMENT_LINEARIZE 1
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */
+#  ifdef REDHAT_BOGOSITY
+#  define IP_SELECT_IDENT_NEW
+#  define IPH_is_SKB_PULLED
+#  define SKB_COW_NEW
+#  define PROTO_HANDLER_SINGLE_PARM
+#  endif /* REDHAT_BOGOSITY */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
+#define MALLOC_SLAB
+#define LINUX_KERNEL_HAS_SNPRINTF
+#endif                                                                         
+
+#ifdef NET_21
+#  include <linux/in6.h>
+#else
+     /* old kernel in.h has some IPv6 stuff, but not quite enough */
+#  define	s6_addr16	s6_addr
+#  define	AF_INET6	10
+#  define uint8_t __u8
+#  define uint16_t __u16 
+#  define uint32_t __u32 
+#  define uint64_t __u64 
+#endif
+
+#ifndef SPINLOCK
+#  include <linux/bios32.h>
+     /* simulate spin locks and read/write locks */
+     typedef struct {
+       volatile char lock;
+     } spinlock_t;
+
+     typedef struct {
+       volatile unsigned int lock;
+     } rwlock_t;                                                                     
+
+#  define spin_lock_init(x) { (x)->lock = 0;}
+#  define rw_lock_init(x) { (x)->lock = 0; }
+
+#  define spin_lock(x) { while ((x)->lock) barrier(); (x)->lock=1;}
+#  define spin_lock_irq(x) { cli(); spin_lock(x);}
+#  define spin_lock_irqsave(x,flags) { save_flags(flags); spin_lock_irq(x);}
+
+#  define spin_unlock(x) { (x)->lock=0;}
+#  define spin_unlock_irq(x) { spin_unlock(x); sti();}
+#  define spin_unlock_irqrestore(x,flags) { spin_unlock(x); restore_flags(flags);}
+
+#  define read_lock(x) spin_lock(x)
+#  define read_lock_irq(x) spin_lock_irq(x)
+#  define read_lock_irqsave(x,flags) spin_lock_irqsave(x,flags)
+
+#  define read_unlock(x) spin_unlock(x)
+#  define read_unlock_irq(x) spin_unlock_irq(x)
+#  define read_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags)
+
+#  define write_lock(x) spin_lock(x)
+#  define write_lock_irq(x) spin_lock_irq(x)
+#  define write_lock_irqsave(x,flags) spin_lock_irqsave(x,flags)
+
+#  define write_unlock(x) spin_unlock(x)
+#  define write_unlock_irq(x) spin_unlock_irq(x)
+#  define write_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags)
+#endif /* !SPINLOCK */
+
+#ifndef SPINLOCK_23
+#  define spin_lock_bh(x)  spin_lock_irq(x)
+#  define spin_unlock_bh(x)  spin_unlock_irq(x)
+
+#  define read_lock_bh(x)  read_lock_irq(x)
+#  define read_unlock_bh(x)  read_unlock_irq(x)
+
+#  define write_lock_bh(x)  write_lock_irq(x)
+#  define write_unlock_bh(x)  write_unlock_irq(x)
+#endif /* !SPINLOCK_23 */
+
+#endif /* _FREESWAN_KVERSIONS_H */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.2.2.1  2002/04/12 03:21:43  mcr
+ *    fixes for compilation on RH 7.1
+ *
+ * Revision 1.3  2002/04/12 03:21:17  mcr
+ * 	three parameter version of ip_select_ident appears first
+ * 	in 2.4.2 (RH7.1) not 2.4.4.
+ *
+ * Revision 1.2  2002/03/08 21:35:22  rgb
+ * Defined LINUX_KERNEL_HAS_SNPRINTF to shut up compiler warnings after
+ * 2.4.9.  (Andreas Piesk).
+ *
+ * Revision 1.1  2002/01/29 02:11:42  mcr
+ * 	removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * 	updating of IPv6 structures to match latest in6.h version.
+ * 	removed dead code from freeswan.h that also duplicated kversions.h
+ * 	code.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_life.c linux-patched/net/ipsec/ipsec_life.c
--- linux/net/ipsec/ipsec_life.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_life.c	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,242 @@
+/*
+ * @(#) lifetime structure utilities
+ *
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ */
+
+/* 
+ * This provides series of utility functions for dealing with lifetime
+ * structures.
+ *
+ * ipsec_check_lifetime - returns -1    hard lifetime exceeded
+ *                                 0    soft lifetime exceeded
+ *                                 1    everything is okay
+ *                        based upon whether or not the count exceeds hard/soft
+ *
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/config.h>	/* for CONFIG_IP_FORWARD */
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#include <linux/netdevice.h>   /* struct device, struct net_device_stats and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+
+#include "radij.h"
+#include "ipsec_life.h"
+#include "ipsec_xform.h"
+#include "ipsec_eroute.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+
+#include "ipsec_netlink.h"
+#include "ipsec_sa.h"
+#include "ipsec_tunnel.h"
+#include "ipsec_ipe4.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+
+#ifdef CONFIG_IPSEC_IPCOMP
+#include "ipcomp.h"
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_proto.h"
+
+
+enum ipsec_life_alive
+ipsec_lifetime_check(struct ipsec_lifetime64 *il64,
+		     const char *lifename,
+		     const char *saname,
+		     enum ipsec_life_type ilt,
+		     enum ipsec_direction idir,
+		     struct ipsec_sa *ips)
+{
+	__u64 count;
+	const char *dir;
+
+	if(saname == NULL) {
+		saname = "unknown-SA";
+	}
+
+	if(idir == ipsec_incoming) {
+		dir = "incoming";
+	} else {
+		dir = "outgoing";
+	}
+		
+
+	if(ilt == ipsec_life_timebased) {
+		count = jiffies/HZ - il64->ipl_count;
+	} else {
+		count = il64->ipl_count;
+	}
+
+	if(il64->ipl_hard &&
+	   (count > il64->ipl_hard)) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "hard %s lifetime of SA:<%s%s%s> %s has been reached, SA expired, "
+			    "%s packet dropped.\n",
+			    lifename,
+			    IPS_XFORM_NAME(ips),
+			    saname,
+			    dir);
+
+		pfkey_expire(ips, 1);
+		return ipsec_life_harddied;
+	}
+
+	if(il64->ipl_soft &&
+	   (count > il64->ipl_soft)) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "soft %s lifetime of SA:<%s%s%s> %s has been reached, SA expiring, "
+			    "soft expire message sent up, %s packet still processed.\n",
+			    lifename,
+			    IPS_XFORM_NAME(ips),
+			    saname,
+			    dir);
+
+		if(ips->ips_state != SADB_SASTATE_DYING) {
+			pfkey_expire(ips, 0);
+		}
+		ips->ips_state = SADB_SASTATE_DYING;
+
+		return ipsec_life_softdied;
+	}
+	return ipsec_life_okay;
+}
+
+
+/*
+ * This function takes a buffer (with length), a lifetime name and type,
+ * and formats a string to represent the current values of the lifetime.
+ * 
+ * It returns the number of bytes that the format took.
+ * This is used in /proc routines and in debug output.
+ */
+int
+ipsec_lifetime_format(char *buffer,
+		      int   buflen,
+		      char *lifename,
+		      enum ipsec_life_type timebaselife,
+		      struct ipsec_lifetime64 *lifetime)
+{
+	int len = 0;
+	__u64 count;
+
+	if(timebaselife == ipsec_life_timebased) {
+		count = jiffies/HZ - lifetime->ipl_count;
+	} else {
+		count = lifetime->ipl_count;
+	}
+
+	if(lifetime->ipl_count > 1 || 
+	   lifetime->ipl_soft      ||
+	   lifetime->ipl_hard) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) 
+		len = snprintf(buffer, buflen,
+			       "%s(%Lu,%Lu,%Lu)",
+			       lifename,
+			       count,
+			       lifetime->ipl_soft,
+			       lifetime->ipl_hard);
+#else /* XXX high 32 bits are not displayed */
+		len = snprintf(buffer, buflen,
+				"%s(%lu,%lu,%lu)",
+				lifename,
+				(unsigned long)count,
+				(unsigned long)lifetime->ipl_soft,
+				(unsigned long)lifetime->ipl_hard);
+#endif
+	}
+
+	return len;
+}
+
+void
+ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime,
+			  __u64 newvalue)
+{
+	if(newvalue &&
+	   (!lifetime->ipl_hard ||
+	    (newvalue < lifetime->ipl_hard))) {
+		lifetime->ipl_hard = newvalue;
+
+		if(!lifetime->ipl_soft &&
+		   (lifetime->ipl_hard < lifetime->ipl_soft)) {
+			lifetime->ipl_soft = lifetime->ipl_hard;
+		}
+	}
+}	
+
+void
+ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime,
+			  __u64 newvalue)
+{
+	if(newvalue &&
+	   (!lifetime->ipl_soft ||
+	    (newvalue < lifetime->ipl_soft))) {
+		lifetime->ipl_soft = newvalue;
+
+		if(lifetime->ipl_hard &&
+		   (lifetime->ipl_hard < lifetime->ipl_soft)) {
+			lifetime->ipl_soft = lifetime->ipl_hard;
+		}
+	}
+}
+
+	
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.4.6.1  2002/05/31 00:19:05  mcr
+ * 	pullup of PR#72 fix from mainbranch-lifetime is relative.
+ *
+ * Revision 1.4  2002/01/29 17:17:55  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.3  2002/01/29 02:13:17  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.2  2001/11/26 09:16:14  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:25:57  mcr
+ * 	lifetime structure created and common functions created.
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_life.h linux-patched/net/ipsec/ipsec_life.h
--- linux/net/ipsec/ipsec_life.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_life.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,109 @@
+/*
+ * Definitions relevant to IPSEC lifetimes
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr.
+ *
+ */
+
+/* 
+ * This file describes the book keeping fields for the 
+ *   IPsec Security Association Structure. ("ipsec_sa")
+ *
+ * This structure is never allocated directly by kernel code,
+ * (it is always a static/auto or is part of a structure)
+ * so it does not have a reference count.
+ *
+ */
+
+#ifndef _IPSEC_LIFE_H_
+
+/*
+ *  _count is total count.
+ *  _hard is hard limit (kill SA after this number)
+ *  _soft is soft limit (try to renew SA after this number)
+ *  _last is used in some special cases.
+ *
+ */
+
+struct ipsec_lifetime64
+{
+	__u64           ipl_count;
+	__u64           ipl_soft;
+	__u64           ipl_hard;
+	__u64           ipl_last;  
+};
+
+struct ipsec_lifetimes
+{
+	/* number of bytes processed */
+	struct ipsec_lifetime64 ipl_bytes;
+
+	/* number of packets processed */
+	struct ipsec_lifetime64 ipl_packets;
+
+	/* time since SA was added */
+	struct ipsec_lifetime64 ipl_addtime;
+
+	/* time since SA was first used */
+	struct ipsec_lifetime64 ipl_usetime;
+
+	/* from rfc2367:  
+         *         For CURRENT, the number of different connections,
+         *         endpoints, or flows that the association has been
+         *          allocated towards. For HARD and SOFT, the number of
+         *          these the association may be allocated towards
+         *          before it expires. The concept of a connection,
+         *          flow, or endpoint is system specific.
+	 *
+	 * mcr(2001-9-18) it is unclear what purpose these serve for FreeSWAN.
+	 *          They are maintained for PF_KEY compatibility. 
+	 */
+	struct ipsec_lifetime64 ipl_allocations;
+};
+
+enum ipsec_life_alive {
+	ipsec_life_harddied = -1,
+	ipsec_life_softdied = 0,
+	ipsec_life_okay     = 1
+};
+
+enum ipsec_life_type {
+	ipsec_life_timebased = 1,
+	ipsec_life_countbased= 0
+};
+
+#define _IPSEC_LIFE_H_
+#endif /* _IPSEC_LIFE_H_ */
+
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.2  2001/11/26 09:16:14  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:25:58  mcr
+ * 	lifetime structure created and common functions created.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_md5c.c linux-patched/net/ipsec/ipsec_md5c.c
--- linux/net/ipsec/ipsec_md5c.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_md5c.c	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,433 @@
+/*
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic
+ * changes to accomodate it in the kernel by ji.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/string.h>
+
+#include "ipsec_md5h.h"
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/*
+ * Additions by JI
+ * 
+ * HAVEMEMCOPY is defined if mem* routines are available
+ *
+ * HAVEHTON is defined if htons() and htonl() can be used
+ * for big/little endian conversions
+ *
+ */
+
+#define HAVEMEMCOPY
+#ifdef __LITTLE_ENDIAN
+#define LITTLENDIAN
+#endif
+#ifdef __BIG_ENDIAN
+#define BIGENDIAN
+#endif
+
+/* Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+
+#ifdef LITTLEENDIAN
+#define Encode MD5_memcpy
+#define Decode MD5_memcpy
+#else
+static void Encode PROTO_LIST
+  ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+  ((UINT4 *, unsigned char *, unsigned int));
+#endif
+
+#ifdef HAVEMEMCOPY
+/* no need to include <memory.h> here; <linux/string.h> defines these */
+#define MD5_memcpy	memcpy
+#define MD5_memset	memset
+#else
+#ifdef HAVEBCOPY
+#define MD5_memcpy(_a,_b,_c) bcopy((_b),(_a),(_c))
+#define MD5_memset(_a,_b,_c) bzero((_a),(_c))
+#else
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+#endif
+#endif
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CTX *context;                                        /* context */
+{
+  context->count[0] = context->count[1] = 0;
+  /* Load magic initialization constants.
+*/
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+  operation, processing another message block, and updating the
+  context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CTX *context;                                        /* context */
+unsigned char *input;                                /* input block */
+__u32 inputLen;                     /* length of input block */
+{
+  __u32 i;
+  unsigned int index, partLen;
+
+  /* Compute number of bytes mod 64 */
+  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+  /* Update number of bits */
+  if ((context->count[0] += ((UINT4)inputLen << 3))
+   < ((UINT4)inputLen << 3))
+ context->count[1]++;
+  context->count[1] += ((UINT4)inputLen >> 29);
+
+  partLen = 64 - index;
+
+  /* Transform as many times as possible.
+*/
+  if (inputLen >= partLen) {
+ MD5_memcpy
+   ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+   MD5Transform (context->state, &input[i]);
+
+ index = 0;
+  }
+  else
+ i = 0;
+
+  /* Buffer remaining input */
+  MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+  inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+  the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16];                         /* message digest */
+MD5_CTX *context;                                       /* context */
+{
+  unsigned char bits[8];
+  unsigned int index, padLen;
+
+  /* Save number of bits */
+  Encode (bits, context->count, 8);
+
+  /* Pad out to 56 mod 64.
+*/
+  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (index < 56) ? (56 - index) : (120 - index);
+  MD5Update (context, PADDING, padLen);
+
+  /* Append length (before padding) */
+  MD5Update (context, bits, 8);
+
+  if (digest != NULL)			/* Bill Simpson's padding */
+  {
+	  /* store state in digest */
+	  Encode (digest, context->state, 16);
+
+	  /* Zeroize sensitive information.
+	   */
+	  MD5_memset ((POINTER)context, 0, sizeof (*context));
+  }
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+  Decode (x, block, 64);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information.
+*/
+  MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+#ifndef LITTLEENDIAN
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+  a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+  a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+   (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+#endif
+
+#ifndef HAVEMEMCOPY
+#ifndef HAVEBCOPY
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+  unsigned int i;
+
+  for (i = 0; i < len; i++)
+
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+  unsigned int i;
+
+  for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
+#endif
+#endif
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.4  1999/12/13 13:59:12  rgb
+ * Quick fix to argument size to Update bugs.
+ *
+ * Revision 1.3  1999/05/21 18:09:28  henry
+ * unnecessary <memory.h> include causes trouble in 2.2
+ *
+ * Revision 1.2  1999/04/06 04:54:26  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.1  1998/06/18 21:27:48  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2  1998/04/23 20:54:02  rgb
+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
+ * verified.
+ *
+ * Revision 1.1  1998/04/09 03:06:08  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.3  1996/11/20 14:48:53  ji
+ * Release update only.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_md5h.h linux-patched/net/ipsec/ipsec_md5h.h
--- linux/net/ipsec/ipsec_md5h.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_md5h.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,132 @@
+/*
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ * The rest of this file is Copyright RSA DSI. See the following comments
+ * for the full Copyright notice.
+ */
+
+#ifndef _IPSEC_MD5H_H_
+#define _IPSEC_MD5H_H_
+
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+     function argument prototyping.
+   The following makes PROTOTYPES default to 0 if it has not already
+     been defined with C compiler flags.
+ */
+#ifndef PROTOTYPES
+#define PROTOTYPES 1
+#endif /* !PROTOTYPES */
+
+/* POINTER defines a generic pointer type */
+typedef __u8 *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef __u16 UINT2;
+
+/* UINT4 defines a four byte word */
+typedef __u32 UINT4;
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+     returns an empty list.
+ */
+
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else /* PROTOTYPES */
+#define PROTO_LIST(list) ()
+#endif /* PROTOTYPES */
+
+
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* MD5 context. */
+typedef struct {
+  UINT4 state[4];                                   /* state (ABCD) */
+  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];                         /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((MD5_CTX *));
+void MD5Update PROTO_LIST
+  ((MD5_CTX *, unsigned char *, __u32));
+void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+ 
+#endif /* _IPSEC_MD5H_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.6  1999/12/13 13:59:13  rgb
+ * Quick fix to argument size to Update bugs.
+ *
+ * Revision 1.5  1999/12/07 18:16:23  rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.4  1999/04/06 04:54:26  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.3  1999/01/22 06:19:58  rgb
+ * 64-bit clean-up.
+ *
+ * Revision 1.2  1998/11/30 13:22:54  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.1  1998/06/18 21:27:48  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2  1998/04/23 20:54:03  rgb
+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
+ * verified.
+ *
+ * Revision 1.1  1998/04/09 03:04:21  henry
+ * sources moved up from linux/net/ipsec
+ * these two include files modified not to include others except in kernel
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:48:53  ji
+ * Release update only.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_netlink.c linux-patched/net/ipsec/ipsec_netlink.c
--- linux/net/ipsec/ipsec_netlink.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_netlink.c	Sun Jan 19 22:32:30 2003
@@ -0,0 +1,710 @@
+/*
+ * IPSEC <> netlink interface
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+char ipsec_netlink_c_version[] = "RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+#ifdef SPINLOCK
+# ifdef SPINLOCK_23
+#  include <linux/spinlock.h> /* *lock* */
+# else /* 23_SPINLOCK */
+#  include <asm/spinlock.h> /* *lock* */
+# endif /* 23_SPINLOCK */
+#endif /* SPINLOCK */
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+# define ip_chk_addr inet_addr_type
+# define IS_MYADDR RTN_LOCAL
+#endif
+#include <asm/checksum.h>
+#include <net/ip.h>
+#ifdef NETLINK_SOCK
+# include <linux/netlink.h>
+#else
+# include <net/netlink.h>
+#endif
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+
+#include "ipsec_rcv.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+
+#ifdef CONFIG_IPSEC_DEBUG
+# include "ipsec_tunnel.h"
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#ifdef CONFIG_IPSEC_DEBUG
+ int debug_netlink = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#define SENDERR(_x) do { len = -(_x); goto errlab; } while (0)
+
+#if 0
+int 
+#ifdef NETLINK_SOCK
+ipsec_callback(int proto, struct sk_buff *skb)
+#else /* NETLINK_SOCK */
+ipsec_callback(struct sk_buff *skb)
+#endif /* NETLINK_SOCK */
+{
+	/*
+	 * this happens when we write to /dev/ipsec (c 36 10)
+	 */
+	int len = skb->len;
+	u_char *dat = (u_char *)skb->data;
+	struct encap_msghdr *em	= (struct encap_msghdr *)dat;
+	struct tdb *tdbp, *tprev;
+	int i, nspis, error = 0;
+#ifdef CONFIG_IPSEC_DEBUG
+	struct eroute *eret;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	struct sk_buff *first, *last;
+
+
+	sa_len = satoa(em->em_said, 0, sa, SATOA_BUF);
+
+	if(debug_netlink) {
+		printk("klips_debug:ipsec_callback: "
+		       "skb=0x%p skblen=%ld em_magic=%d em_type=%d\n",
+		       skb,
+		       (unsigned long int)skb->len,
+		       em->em_magic,
+		       em->em_type);
+		switch(em->em_type) {
+		case EMT_SETDEBUG:
+			printk("klips_debug:ipsec_callback: "
+			       "set ipsec_debug level\n");
+			break;
+		case EMT_DELEROUTE:
+		case EMT_CLREROUTE:
+		case EMT_CLRSPIS:
+			break;
+		default:
+			printk("klips_debug:ipsec_callback: "
+			       "called for SA:%s\n",
+			       sa_len ? sa : " (error)");
+		}
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	/* XXXX Temporarily disable netlink I/F code until it gets permanantly
+	   ripped out in favour of PF_KEYv2 I/F. */
+	SENDERR(EPROTONOSUPPORT);
+
+	/*	em = (struct encap_msghdr *)dat; */
+	if (em->em_magic != EM_MAGIC) {
+		printk("klips_debug:ipsec_callback: "
+		       "bad magic=%d failed, should be %d\n",
+		       em->em_magic,
+		       EM_MAGIC);
+		SENDERR(EINVAL);
+	}
+	switch (em->em_type) {
+	case EMT_SETDEBUG:
+#ifdef CONFIG_IPSEC_DEBUG
+		if(em->em_db_nl >> (sizeof(em->em_db_nl) * 8 - 1)) {
+			em->em_db_nl &= ~(1 << (sizeof(em->em_db_nl) * 8 -1));
+			debug_tunnel  |= em->em_db_tn;
+			debug_netlink |= em->em_db_nl;
+			debug_xform   |= em->em_db_xf;
+			debug_eroute  |= em->em_db_er;
+			debug_spi     |= em->em_db_sp;
+			debug_radij   |= em->em_db_rj;
+			debug_esp     |= em->em_db_es;
+			debug_ah      |= em->em_db_ah;
+			debug_rcv     |= em->em_db_rx;
+			debug_pfkey   |= em->em_db_ky;
+			if(debug_netlink)
+				printk("klips_debug:ipsec_callback: set\n");
+		} else {
+			if(debug_netlink)
+				printk("klips_debug:ipsec_callback: unset\n");
+			debug_tunnel  &= em->em_db_tn;
+			debug_netlink &= em->em_db_nl;
+			debug_xform   &= em->em_db_xf;
+			debug_eroute  &= em->em_db_er;
+			debug_spi     &= em->em_db_sp;
+			debug_radij   &= em->em_db_rj;
+			debug_esp     &= em->em_db_es;
+			debug_ah      &= em->em_db_ah;
+			debug_rcv     &= em->em_db_rx;
+			debug_pfkey   &= em->em_db_ky;
+		}
+#else /* CONFIG_IPSEC_DEBUG */
+		printk("klips_debug:ipsec_callback: "
+		       "debugging not enabled\n");
+		SENDERR(EINVAL);
+#endif /* CONFIG_IPSEC_DEBUG */
+		break;
+
+	case EMT_SETEROUTE:
+		if ((error = ipsec_makeroute(&(em->em_eaddr), &(em->em_emask), em->em_ersaid, 0, NULL, NULL, NULL)))
+			SENDERR(-error);
+		break;
+
+	case EMT_REPLACEROUTE:
+		if ((error = ipsec_breakroute(&(em->em_eaddr), &(em->em_emask), &first, &last)) == EINVAL) {
+			kfree_skb(first);
+			kfree_skb(last);
+			SENDERR(-error);
+		}
+		if ((error = ipsec_makeroute(&(em->em_eaddr), &(em->em_emask), em->em_ersaid, NULL, NULL)))
+			SENDERR(-error);
+		break;
+
+	case EMT_DELEROUTE:
+		if ((error = ipsec_breakroute(&(em->em_eaddr), &(em->em_emask), &first, &last)))
+			kfree_skb(first);
+			kfree_skb(last);
+			SENDERR(-error);
+		break;
+
+	case EMT_CLREROUTE:
+		if ((error = ipsec_cleareroutes()))
+			SENDERR(-error);
+		break;
+
+	case EMT_SETSPI:
+		if (em->em_if >= 5)	/* XXX -- why 5? */
+			SENDERR(ENODEV);
+		
+		tdbp = gettdb(&(em->em_said));
+		if (tdbp == NULL) {
+			tdbp = (struct tdb *)kmalloc(sizeof (*tdbp), GFP_ATOMIC);
+
+			if (tdbp == NULL)
+				SENDERR(ENOBUFS);
+			
+			memset((caddr_t)tdbp, 0, sizeof(*tdbp));
+			
+			tdbp->tdb_said = em->em_said;
+			tdbp->tdb_flags = em->em_flags;
+			
+			if(ip_chk_addr((unsigned long)em->em_said.dst.s_addr) == IS_MYADDR) {
+				tdbp->tdb_flags |= EMT_INBOUND;
+			}
+			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
+				    "klips_debug:ipsec_callback: "
+				    "existing Tunnel Descriptor Block not found (this is good) for SA: %s, %s-bound, allocating.\n",
+				    sa_len ? sa : " (error)",
+				    (tdbp->tdb_flags & EMT_INBOUND) ? "in" : "out");
+
+/* XXX  		tdbp->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
+			tdbp->tdb_rcvif = NULL;
+		} else {
+			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
+				    "klips_debug:ipsec_callback: "
+				    "EMT_SETSPI found an old Tunnel Descriptor Block for SA: %s, delete it first.\n",
+				    sa_len ? sa : " (error)");
+			SENDERR(EEXIST);
+		}
+		
+		if ((error = tdb_init(tdbp, em))) {
+			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
+				    "klips_debug:ipsec_callback: "
+				    "EMT_SETSPI not successful for SA: %s, deleting.\n",
+				    sa_len ? sa : " (error)");
+			ipsec_tdbwipe(tdbp);
+			
+			SENDERR(-error);
+		}
+
+		tdbp->tdb_lifetime_addtime_c = jiffies/HZ;
+		tdbp->tdb_state = 1;
+		if(!tdbp->tdb_lifetime_allocations_c) {
+			tdbp->tdb_lifetime_allocations_c += 1;
+		}
+
+		puttdb(tdbp);
+		KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
+			    "klips_debug:ipsec_callback: "
+			    "EMT_SETSPI successful for SA: %s\n",
+			    sa_len ? sa : " (error)");
+		break;
+		
+	case EMT_DELSPI:
+		if (em->em_if >= 5)	/* XXX -- why 5? */
+			SENDERR(ENODEV);
+		
+		spin_lock_bh(&tdb_lock);
+		
+		tdbp = gettdb(&(em->em_said));
+		if (tdbp == NULL) {
+			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
+				    "klips_debug:ipsec_callback: "
+				    "EMT_DELSPI Tunnel Descriptor Block not found for SA%s, could not delete.\n",
+				    sa_len ? sa : " (error)");
+			spin_unlock_bh(&tdb_lock);
+			SENDERR(ENXIO);  /* XXX -- wrong error message... */
+		} else {
+			if((error = deltdbchain(tdbp))) {
+				spin_unlock_bh(&tdb_lock);
+				SENDERR(-error);
+			}
+		}
+		spin_unlock_bh(&tdb_lock);
+
+		break;
+		
+	case EMT_GRPSPIS:
+		nspis = (len - EMT_GRPSPIS_FLEN) / sizeof(em->em_rel[0]);
+		if ((nspis * (sizeof(em->em_rel[0]))) != (len - EMT_GRPSPIS_FLEN)) {
+			printk("klips_debug:ipsec_callback: "
+			       "EMT_GRPSPI message size incorrect, expected nspis(%d)*%d, got %d.\n",
+			       nspis,
+			       sizeof(em->em_rel[0]),
+			       (len - EMT_GRPSPIS_FLEN));
+			SENDERR(EINVAL);
+			break;
+		}
+		
+		spin_lock_bh(&tdb_lock);
+
+		for (i = 0; i < nspis; i++) {
+			KLIPS_PRINT(debug_netlink,
+				    "klips_debug:ipsec_callback: "
+				    "EMT_GRPSPI for SA(%d) %s,\n",
+				    i,
+				    sa_len ? sa : " (error)");
+			if ((tdbp = gettdb(&(em->em_rel[i].emr_said))) == NULL) {
+				KLIPS_PRINT(debug_netlink,
+					    "klips_debug:ipsec_callback: "
+					    "EMT_GRPSPI Tunnel Descriptor Block not found for SA%s, could not group.\n",
+					    sa_len ? sa : " (error)");
+				spin_unlock_bh(&tdb_lock);
+				SENDERR(ENXIO);
+			} else {
+				if(tdbp->tdb_inext || tdbp->tdb_onext) {
+					KLIPS_PRINT(debug_netlink,
+						    "klips_debug:ipsec_callback: "
+						    "EMT_GRPSPI Tunnel Descriptor Block already grouped for SA: %s, can't regroup.\n",
+						    sa_len ? sa : " (error)");
+					spin_unlock_bh(&tdb_lock);
+					SENDERR(EBUSY);
+				}
+				em->em_rel[i].emr_tdb = tdbp;
+			}
+		}
+		tprev = em->em_rel[0].emr_tdb;
+		tprev->tdb_inext = NULL;
+		for (i = 1; i < nspis; i++) {
+			tdbp = em->em_rel[i].emr_tdb;
+			tprev->tdb_onext = tdbp;
+			tdbp->tdb_inext = tprev;
+			tprev = tdbp;
+		}
+		tprev->tdb_onext = NULL;
+
+		spin_unlock_bh(&tdb_lock);
+
+		error = 0;
+		break;
+		
+	case EMT_UNGRPSPIS:
+		if (len != (8 + (sizeof(struct sa_id) + sizeof(struct tdb *)) /* 12 */) ) {
+			printk("klips_debug:ipsec_callback: "
+			       "EMT_UNGRPSPIS message size incorrect, expected %d, got %d.\n",
+			       8 + (sizeof(struct sa_id) + sizeof(struct tdb *)),
+				    len);
+			SENDERR(EINVAL);
+			break;
+		}
+		
+		spin_lock_bh(&tdb_lock);
+
+		if ((tdbp = gettdb(&(em->em_rel[0].emr_said))) == NULL) {
+			KLIPS_PRINT(debug_netlink,
+				    "klips_debug:ipsec_callback: "
+				    "EMT_UGRPSPI Tunnel Descriptor Block not found for SA%s, could not ungroup.\n",
+				    sa_len ? sa : " (error)");
+			spin_unlock_bh(&tdb_lock);
+			SENDERR(ENXIO);
+		}
+		while(tdbp->tdb_onext) {
+			tdbp = tdbp->tdb_onext;
+		}
+		while(tdbp->tdb_inext) {
+			tprev = tdbp;
+			tdbp = tdbp->tdb_inext;
+			tprev->tdb_inext = NULL;
+			tdbp->tdb_onext = NULL;
+		}
+
+		spin_unlock_bh(&tdb_lock);
+
+		break;
+		
+	case EMT_CLRSPIS:
+		KLIPS_PRINT(debug_netlink,
+			    "klips_debug:ipsec_callback: "
+			    "spi clear called.\n");
+		if (em->em_if >= 5)	/* XXX -- why 5? */
+			SENDERR(ENODEV);
+		ipsec_tdbcleanup(0);
+		break;
+	default:
+		KLIPS_PRINT(debug_netlink,
+			    "klips_debug:ipsec_callback: "
+			    "unknown message type\n");
+		SENDERR(EINVAL);
+	}
+ errlab:
+#ifdef NET_21
+	kfree_skb(skb);
+#else /* NET_21 */
+	kfree_skb(skb, FREE_WRITE);
+#endif /* NET_21 */
+	return len;
+}
+#endif
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.3  2003/01/19 22:32:30  ken
+ * X.509 0.9.19 -> 0.9.20
+ *
+ * Revision 1.2  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.56  2002/01/29 17:17:55  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.55  2002/01/29 04:00:51  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.54  2001/10/18 04:45:19  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.53  2001/09/15 16:24:04  rgb
+ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
+ *
+ * Revision 1.52  2001/09/14 16:58:36  rgb
+ * Added support for storing the first and last packets through a HOLD.
+ *
+ * Revision 1.51  2001/09/08 21:13:32  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.50  2001/07/06 19:49:00  rgb
+ * Renamed EMT_RPLACEROUTE to EMT_REPLACEROUTE for clarity and logical text
+ * searching.
+ *
+ * Revision 1.49  2001/06/14 19:35:08  rgb
+ * Update copyright date.
+ *
+ * Revision 1.48  2001/02/27 22:24:54  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.47  2000/11/06 04:32:08  rgb
+ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
+ *
+ * Revision 1.46  2000/09/08 19:16:50  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Removed all references to CONFIG_IPSEC_PFKEYv2.
+ *
+ * Revision 1.45  2000/08/30 05:23:55  rgb
+ * Compiler-define out ipsec_callback() function of ipsec_netlink.c.
+ * Nothing should be using it anyways.
+ *
+ * Revision 1.44  2000/03/16 14:01:26  rgb
+ * Indented headers for readability.
+ *
+ * Revision 1.43  2000/03/16 07:13:04  rgb
+ * Hardcode PF_KEYv2 support.
+ * Disable NET_LINK support.
+ *
+ * Revision 1.42  2000/01/21 06:14:27  rgb
+ * Moved debug message for expected output on set or clear.
+ *
+ * Revision 1.41  1999/12/01 22:14:37  rgb
+ * Added debugging message for bad netlink magic.
+ * Initialise tdb_sastate to MATURE (1).
+ * Added UNGRPSPIS bad length debugging message.
+ *
+ * Revision 1.40  1999/11/23 23:06:25  rgb
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ *
+ * Revision 1.39  1999/11/18 04:09:18  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.38  1999/11/17 15:53:39  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.37  1999/10/26 13:58:32  rgb
+ * Put spinlock flags variable declaration outside the debug compiler
+ * directive to enable compilation with debug shut off.
+ *
+ * Revision 1.36  1999/10/16 18:24:22  rgb
+ * Initialize lifetime_addtime_c and lifetime_allocations_c.
+ * Clean-up unused cruft.
+ *
+ * Revision 1.35  1999/10/08 18:37:34  rgb
+ * Fix end-of-line spacing to sate whining PHMs.
+ *
+ * Revision 1.34  1999/10/03 18:49:11  rgb
+ * Spinlock fixes for 2.0.xx and 2.3.xx.
+ *
+ * Revision 1.33  1999/10/01 15:44:53  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.32  1999/10/01 00:00:53  rgb
+ * Fix for proper netlink debugging operation.
+ * Added tdb structure locking.
+ * Minor formatting changes.
+ *
+ * Revision 1.31  1999/05/25 21:21:43  rgb
+ * Fix deltdbchain() error return code checking.
+ *
+ * Revision 1.30  1999/05/09 03:25:36  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.29  1999/05/08 21:23:27  rgb
+ * Simplify satoa() calling.
+ * Fix error return reporting.
+ * Add casting to silence the 2.2.x compile.
+ *
+ * Revision 1.28  1999/05/05 22:02:31  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.27  1999/04/29 15:16:24  rgb
+ * Add pfkey support to debugging.
+ * Change gettdb parameter to a pointer to reduce stack loading and
+ * facilitate
+ * parameter sanity checking.
+ * Add IS_MYADDR support obviating the necessity of doing this in user
+ * space.
+ * Fix undetected bug by moving puttdb in SETSPI until after initialisation
+ * to
+ * prevent tdb usage before it is ready and to save work if it does not
+ * initialise.
+ * Clean up deltdb/wipe code.
+ * Fix undetected bug of returning error as positive value.
+ * Add a parameter to tdbcleanup to be able to delete a class of SAs.
+ *
+ * Revision 1.26  1999/04/16 15:39:35  rgb
+ * Fix already fixed unbalanced #endif.
+ *
+ * Revision 1.25  1999/04/15 15:37:24  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.21.2.1  1999/04/13 20:30:26  rgb
+ * Add experimental 'getdebug'.
+ *
+ * Revision 1.24  1999/04/11 00:28:58  henry
+ * GPL boilerplate
+ *
+ * Revision 1.23  1999/04/07 17:44:21  rgb
+ * Fix ipsec_callback memory leak, skb not freed after use.
+ *
+ * Revision 1.22  1999/04/06 04:54:26  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.21  1999/02/17 16:50:11  rgb
+ * Consolidate satoa()s for space and speed efficiency.
+ * Convert DEBUG_IPSEC to KLIPS_PRINT
+ * Clean out unused cruft.
+ *
+ * Revision 1.20  1999/01/28 23:20:49  rgb
+ * Replace hard-coded numbers in macros and code with meaningful values
+ * automatically generated from sizeof() and offsetof() to further the
+ * goal of platform independance.
+ *
+ * Revision 1.19  1999/01/26 02:07:07  rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ * Remove ah/esp switching on include files.
+ * Removed dead code.
+ *
+ * Revision 1.18  1999/01/22 06:20:36  rgb
+ * Cruft clean-out.
+ * 64-bit clean-up.
+ * Added algorithm switch code.
+ *
+ * Revision 1.17  1998/12/02 03:09:39  rgb
+ * Clean up debug printing conditionals to compile with debugging off.
+ *
+ * Revision 1.16  1998/12/01 05:56:57  rgb
+ * Add support for debug printing of version info.
+ * Fail on unknown error for breakroute in replace command.
+ *
+ * Revision 1.15  1998/11/30 13:22:54  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.14  1998/11/10 05:36:14  rgb
+ * Clean up debug output.
+ * Add direction to spi setup debug code.
+ * Add support for SA direction flag.
+ *
+ * Revision 1.13  1998/10/31 06:51:56  rgb
+ * Get zeroize to return something useful.
+ * Clean up code to isolate 'spi --add/del' memory leak.
+ * Fixed up comments in #endif directives.
+ *
+ * Revision 1.12  1998/10/27 00:35:02  rgb
+ * Supressed debug output during normal operation.
+ *
+ * Revision 1.11  1998/10/25 02:40:21  rgb
+ * Selective debug printing, depending upon called service.
+ * Institute more precise error return codes from eroute commands.
+ * Fix bug in size of stucture passed in from user space for grpspi command.
+ *
+ * Revision 1.10  1998/10/22 06:44:58  rgb
+ * Convert to use satoa for printk.
+ * Moved break; in 'set debug level code to avoid undetected bug.
+ * Fixed run-on error message to fit 80 columns.
+ *
+ * Revision 1.9  1998/10/19 14:44:28  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.8  1998/10/09 04:29:51  rgb
+ * Added support for '-replace' option to eroute.
+ * Fixed spiungroup bug.
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ *
+ * Revision 1.7  1998/08/12 00:10:06  rgb
+ * Fixed minor error return code syntax.
+ *
+ * Revision 1.6  1998/07/29 20:22:57  rgb
+ * Cosmetic cleanup.
+ *
+ * Revision 1.5  1998/07/27 21:53:11  rgb
+ * Check for proper return code from eroute clear command.
+ * Use appropriate error return codes from kernel.
+ * Add an option to clear the SA table.
+ *
+ * Revision 1.4  1998/07/14 18:02:40  rgb
+ * Add a command to clear the eroute table.
+ * Clean up some error codes.
+ *
+ * Revision 1.3  1998/06/25 19:52:33  rgb
+ * Code cosmetic changes only.
+ *
+ * Revision 1.2  1998/06/23 02:57:58  rgb
+ * Clean up after an error condition in setspi.
+ *
+ * Revision 1.9  1998/06/18 21:29:06  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid kernel
+ * build scripts happier in presence of symbolic links
+ *
+ * Revision 1.8  1998/06/08 17:57:15  rgb
+ * Very minor spacing change.
+ *
+ * Revision 1.7  1998/05/18 21:46:45  rgb
+ * Clean up for numerical consistency of output.
+ *
+ * Added debugging switch output.
+ *
+ * SETSPI will refuse to overwrite a previous SA.  This is to make it
+ * consistent with the eroute command.
+ *
+ * spidel now deletes entire chain of spi's.
+ *
+ * spigrp can now ungroup a set of spi's.
+ *
+ * spigrp will not regroup a previously grouped spi.
+ *
+ * Key data is properly cleaned up, ie. zeroed.
+ *
+ * Revision 1.6  1998/05/07 20:36:27  rgb
+ * Fixed case where debugging not enabled that caused ipsec_netlink.c to
+ * not compile.
+ *
+ * Revision 1.5  1998/05/06 03:34:21  rgb
+ * Updated debugging output statements.
+ *
+ * Revision 1.4  1998/04/23 21:03:59  rgb
+ * Completed kernel development for userspace access to klips kernel debugging
+ * switches.
+ * Added detail to the kernel error message when trying to group non-existant
+ * spi's.
+ *
+ * Revision 1.3  1998/04/21 21:29:06  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/12 22:03:23  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:06:08  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_netlink.h linux-patched/net/ipsec/ipsec_netlink.h
--- linux/net/ipsec/ipsec_netlink.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_netlink.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,345 @@
+/*
+ * IPSEC <> netlink interface
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#include <linux/stddef.h>
+
+#ifndef NETLINK_IPSEC
+#define NETLINK_IPSEC          10      /* IPSEC */ 
+#endif /* !NETLINK_IPSEC */
+
+#define EM_MAXRELSPIS	4		/* at most five chained xforms */
+#define EM_MAGIC	0x5377616e	/* "Swan" */
+
+#define EMT_IFADDR	1	/* set enc if addr */
+#define EMT_SETSPI	2	/* Set SPI properties */
+#define EMT_DELSPI	3	/* Delete an SPI */
+#define EMT_GRPSPIS	4	/* Group SPIs (output order)  */
+#define EMT_SETEROUTE	5	/* set an extended route */
+#define EMT_DELEROUTE	6	/* del an extended route */
+#define EMT_TESTROUTE	7	/* try to find route, print to console */
+#define EMT_SETDEBUG	8	/* set debug level if active */
+#define EMT_UNGRPSPIS	9	/* UnGroup SPIs (output order)  */
+#define EMT_CLREROUTE	10	/* clear the extended route table */
+#define EMT_CLRSPIS	11	/* clear the spi table */
+#define EMT_REPLACEROUTE	12	/* set an extended route */
+#define EMT_GETDEBUG	13	/* get debug level if active */
+#define EMT_INEROUTE	14	/* set incoming policy for IPIP on a chain */
+
+#ifdef CONFIG_IPSEC_DEBUG
+#define DB_NL_TDBCB	0x0001
+#endif /* CONFIG_IPSEC_DEBUG */
+
+/* em_flags constants */
+/* be mindful that this flag conflicts with SADB_SAFLAGS_PFS in pfkeyv2 */
+/* perhaps it should be moved... */
+#define EMT_INBOUND	0x01	/* SA direction, 1=inbound */
+
+struct encap_msghdr
+{
+	__u32	em_magic;		/* EM_MAGIC */
+#if 0
+	__u16	em_msglen;		/* message length */
+#endif
+	__u8	em_msglen;		/* message length */
+	__u8	em_flags;		/* message flags */
+	__u8	em_version;		/* for future expansion */
+	__u8	em_type;		/* message type */
+	union
+	{
+		__u8	C;		/* Free-text */
+		
+		struct 
+		{
+			struct sa_id Said; /* SA ID */
+			struct sockaddr_encap Eaddr;
+			struct sockaddr_encap Emask;
+		} Ert;
+
+		struct
+		{
+			struct in_addr Ia;
+			__u8	Ifn;
+			__u8  xxx[3];	/* makes life a lot easier */
+		} Ifa;
+
+		struct
+		{
+			struct sa_id Said; /* SA ID */
+			int If;		/* enc i/f for input */
+			int Alg;	/* Algorithm to use */
+
+                        /* The following union is a surrogate for
+                         * algorithm-specific data.  To insure
+                         * proper alignment, worst-case fields
+                         * should be included.  It would be even
+                         * better to include the types that will
+                         * actually be used, but they may not be
+                         * defined for each use of this header.
+                         * The actual length is expected to be longer
+                         * than is declared here.  References are normally
+                         * made using the em_dat macro, as if it were a
+                         * field name.
+                         */
+                        union { /* Data */
+                                __u8 Dat[1];
+                                __u64 Datq[1];  /* maximal alignment (?) */
+                        } u;
+		} Xfm;
+		
+		struct
+		{
+			struct sa_id emr_said; /* SA ID */
+			struct ipsec_sa * emr_tdb; /* used internally! */
+			
+		} Rel[EM_MAXRELSPIS];
+		
+#ifdef CONFIG_IPSEC_DEBUG
+		struct
+		{
+			int debug_tunnel;
+			int debug_netlink;
+			int debug_xform;
+			int debug_eroute;
+			int debug_spi;
+			int debug_radij;
+			int debug_esp;
+			int debug_ah;
+			int debug_rcv;
+			int debug_pfkey;
+			int debug_ipcomp;
+			int debug_verbose;
+		} Dbg;
+#endif /* CONFIG_IPSEC_DEBUG */
+	} Eu;
+};
+
+#define EM_MINLEN	offsetof(struct encap_msghdr, Eu)
+#define EMT_SETSPI_FLEN	offsetof(struct encap_msghdr, em_dat)
+#define EMT_GRPSPIS_FLEN offsetof(struct encap_msghdr, Eu.Rel)
+#define EMT_SETDEBUG_FLEN (offsetof(struct encap_msghdr, Eu.Dbg + \
+			sizeof(((struct encap_msghdr*)0)->Eu.Dbg)))
+
+#define em_c	Eu.C
+#define em_eaddr Eu.Ert.Eaddr
+#define em_emask Eu.Ert.Emask
+#define em_ersaid Eu.Ert.Said
+#define em_erdst Eu.Ert.Said.dst
+#define em_erspi Eu.Ert.Said.spi
+#define em_erproto Eu.Ert.Said.proto
+
+#define em_ifa	Eu.Ifa.Ia
+#define em_ifn	Eu.Ifa.Ifn
+
+#define em_said	Eu.Xfm.Said
+#define em_spi	Eu.Xfm.Said.spi
+#define em_dst	Eu.Xfm.Said.dst
+#define em_proto	Eu.Xfm.Said.proto
+#define em_if	Eu.Xfm.If
+#define em_alg	Eu.Xfm.Alg
+#define em_dat	Eu.Xfm.u.Dat
+
+#define em_rel	Eu.Rel
+#define emr_dst emr_said.dst
+#define emr_spi emr_said.spi
+#define emr_proto emr_said.proto
+
+#ifdef CONFIG_IPSEC_DEBUG
+#define em_db_tn Eu.Dbg.debug_tunnel
+#define em_db_nl Eu.Dbg.debug_netlink
+#define em_db_xf Eu.Dbg.debug_xform
+#define em_db_er Eu.Dbg.debug_eroute
+#define em_db_sp Eu.Dbg.debug_spi
+#define em_db_rj Eu.Dbg.debug_radij
+#define em_db_es Eu.Dbg.debug_esp
+#define em_db_ah Eu.Dbg.debug_ah
+#define em_db_rx Eu.Dbg.debug_rcv
+#define em_db_ky Eu.Dbg.debug_pfkey
+#define em_db_gz Eu.Dbg.debug_ipcomp
+#define em_db_vb Eu.Dbg.debug_verbose
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#ifdef __KERNEL__
+extern char ipsec_netlink_c_version[];
+#ifndef KERNEL_VERSION
+#  include <linux/version.h>
+#endif
+#ifdef NETLINK_SOCK
+extern int ipsec_callback(int proto, struct sk_buff *skb);
+#else /* NETLINK_SOCK */
+extern int ipsec_callback(struct sk_buff *skb);
+#endif /* NETLINK_SOCK */
+extern void ipsec_print_ip(struct iphdr *ip);
+
+#ifdef CONFIG_IPSEC_DEBUG
+	#define KLIPS_PRINT(flag, format, args...) \
+		((flag) ? printk(KERN_INFO format , ## args) : 0)
+	#define KLIPS_PRINTMORE(flag, format, args...) \
+		((flag) ? printk(format , ## args) : 0)
+	#define KLIPS_IP_PRINT(flag, ip) \
+		((flag) ? ipsec_print_ip(ip) : 0)
+#else /* CONFIG_IPSEC_DEBUG */
+	#define KLIPS_PRINT(flag, format, args...) do ; while(0)
+	#define KLIPS_PRINTMORE(flag, format, args...) do ; while(0)
+	#define KLIPS_IP_PRINT(flag, ip) do ; while(0)
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_netlink;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* __KERNEL__ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.31  2001/11/26 09:23:48  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.30  2001/07/06 19:49:16  rgb
+ * Renamed EMT_RPLACEROUTE to EMT_REPLACEROUTE for clarity and logical text
+ * searching.
+ * Added EMT_INEROUTE for supporting incoming policy checks.
+ *
+ * Revision 1.29  2001/06/14 19:35:09  rgb
+ * Update copyright date.
+ *
+ * Revision 1.28  2000/10/10 20:10:18  rgb
+ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
+ *
+ * Revision 1.27  2000/09/12 03:20:28  rgb
+ * Cleared out now unused pfkeyv2 switch.
+ *
+ * Revision 1.26  2000/09/08 19:16:50  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Removed all references to CONFIG_IPSEC_PFKEYv2.
+ *
+ * Revision 1.25  2000/08/24 16:51:59  rgb
+ * Added KLIPS_PRINTMORE macro to continue lines without KERN_INFO level
+ * info.
+ *
+ * Revision 1.24  2000/08/09 20:43:34  rgb
+ * Fixed bitmask value for SADB_X_SAFLAGS_CLEAREROUTE.
+ *
+ * Revision 1.23  2000/03/16 14:01:48  rgb
+ * Hardwired CONFIG_IPSEC_PFKEYv2 on.
+ *
+ * Revision 1.22  1999/12/08 20:31:32  rgb
+ * Moved IPPROTO_COMP to lib/freeswan.h to simplify userspace includes.
+ *
+ * Revision 1.21  1999/11/18 18:47:41  rgb
+ * Added "#define NETLINK_IPSEC" in case kernel was not compiled with it.
+ *
+ * Revision 1.20  1999/11/18 04:09:18  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.19  1999/08/28 08:27:05  rgb
+ * Add a temporary kludge for 2.0.37-38 to compile even if one patch failed.
+ *
+ * Revision 1.18  1999/08/03 17:09:33  rgb
+ * Tidy up debug output, use KERN_INFO macro in printk's.
+ *
+ * Revision 1.17  1999/05/25 01:45:37  rgb
+ * Fix version macros for 2.0.x as a module.
+ *
+ * Revision 1.16  1999/05/05 22:02:31  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.15  1999/04/29 15:16:55  rgb
+ * Add pfkey support to debugging.
+ *
+ * Revision 1.14  1999/04/15 15:37:24  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.13  1999/04/11 00:28:58  henry
+ * GPL boilerplate
+ *
+ * Revision 1.12  1999/04/06 04:54:26  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.11  1999/02/12 21:13:17  rgb
+ * Moved KLIPS_PRINT into a more accessible place.
+ *
+ * Revision 1.10  1999/01/28 23:20:49  rgb
+ * Replace hard-coded numbers in macros and code with meaningful values
+ * automatically generated from sizeof() and offsetof() to further the
+ * goal of platform independance.
+ *
+ * Revision 1.9  1999/01/22 06:21:23  rgb
+ * Added algorithm switch code.
+ * Cruft clean-out.
+ * 64-bit clean-up.
+ *
+ * Revision 1.8  1998/12/01 05:57:42  rgb
+ * Add support for printing debug version info.
+ *
+ * Revision 1.7  1998/11/10 05:37:35  rgb
+ * Add support for SA direction flag.
+ *
+ * Revision 1.6  1998/10/25 02:40:45  rgb
+ * Fix bug in size of stucture passed in from user space for grpspi command.
+ *
+ * Revision 1.5  1998/10/19 14:44:29  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.4  1998/10/09 04:30:11  rgb
+ * Added support for '-replace' option to eroute.
+ *
+ * Revision 1.3  1998/07/27 21:54:22  rgb
+ * Rearrange structures for consistent alignment within a union.
+ * Add an option for clearing SA table.
+ *
+ * Revision 1.2  1998/07/14 18:05:51  rgb
+ * Added #ifdef __KERNEL__ directives to restrict scope of header.
+ *
+ * Revision 1.1  1998/06/18 21:27:49  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.4  1998/05/18 21:48:24  rgb
+ * Added switch for ungrouping spi's.
+ *
+ * Revision 1.3  1998/04/23 21:01:50  rgb
+ * Added a macro for userspace access to klips kernel debugging switches.
+ *
+ * Revision 1.2  1998/04/21 21:29:09  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1  1998/04/09 03:06:09  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_param.h linux-patched/net/ipsec/ipsec_param.h
--- linux/net/ipsec/ipsec_param.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_param.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,150 @@
+/*
+ * @(#) FreeSWAN tunable paramaters
+ *
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ */
+
+/* 
+ * This file provides a set of #define's which may be tuned by various
+ * people/configurations. It keeps all compile-time tunables in one place.
+ *
+ * This file should be included before all other IPsec kernel-only files.
+ *
+ */
+
+#ifndef _IPSEC_PARAM_H_
+
+#include "ipsec_kversion.h"
+
+#ifdef CONFIG_IPSEC_BIGGATE
+#define SADB_HASHMOD   8069
+#else
+#define SADB_HASHMOD	257
+#endif
+
+#ifndef PROC_NO_DUMMY
+#define IPSEC_PROC_LAST_ARG , int dummy
+#else
+#define IPSEC_PROC_LAST_ARG
+#endif /* !PROC_NO_DUMMY */
+
+#ifdef NETDEV_23
+
+#define device net_device
+#define ipsec_dev_get __dev_get_by_name
+
+#else
+
+#define ipsec_dev_get dev_get
+
+#endif /* NETDEV_23 */
+
+#ifndef PROC_FS_2325
+#define IPSEC_PROCFS_DEBUG_NO_STATIC DEBUG_NO_STATIC
+#else
+#define IPSEC_PROCFS_DEBUG_NO_STATIC
+#endif /* PROC_FS_2325 */
+
+#if !defined(LINUX_KERNEL_HAS_SNPRINTF)
+/* GNU CPP specific! */
+#define snprintf(buf, len, fmt...) sprintf(buf, ##fmt)
+#endif
+
+#ifdef SPINLOCK
+ #ifdef SPINLOCK_23
+  #include <linux/spinlock.h> /* *lock* */
+ #else /* SPINLOCK_23 */
+  #include <asm/spinlock.h> /* *lock* */
+ #endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+
+#ifndef KLIPS_FIXES_DES_PARITY
+#define KLIPS_FIXES_DES_PARITY 1
+#endif
+
+#ifndef KLIPS_DIVULGE_CYPHER_KEY
+#define KLIPS_DIVULGE_CYPHER_KEY 0
+#endif
+
+/* extra toggles for regression testing */
+#ifdef CONFIG_IPSEC_REGRESS
+
+/* 
+ * should pfkey_acquire() become 100% lossy?
+ *
+ */
+extern int sysctl_ipsec_regress_pfkey_lossage;
+#ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE
+#ifdef CONFIG_IPSEC_PFKEY_ACQUIRE_LOSSAGE
+#define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100
+#else
+/* not by default! */
+#define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0
+#endif
+#endif
+
+#endif
+
+/* IP_FRAGMENT_LINEARIZE is set in freeswan.h if Kernel > 2.4.4 */
+#ifndef IP_FRAGMENT_LINEARIZE
+#define IP_FRAGMENT_LINEARIZE 0
+#endif
+
+#define _IPSEC_PARAM_H_
+#endif
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.6  2002/01/29 02:11:42  mcr
+ * 	removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * 	updating of IPv6 structures to match latest in6.h version.
+ * 	removed dead code from freeswan.h that also duplicated kversions.h
+ * 	code.
+ *
+ * Revision 1.5  2002/01/28 19:22:01  mcr
+ * 	by default, turn off LINEARIZE option
+ * 	(let kversions.h turn it on)
+ *
+ * Revision 1.4  2002/01/20 20:19:36  mcr
+ * 	renamed option to IP_FRAGMENT_LINEARIZE.
+ *
+ * Revision 1.3  2002/01/12 02:57:25  mcr
+ * 	first regression test causes acquire messages to be lost
+ * 	100% of the time. This is to help testing of pluto.
+ *
+ * Revision 1.2  2001/11/26 09:16:14  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.3  2001/10/23 04:40:16  mcr
+ * 	added #define for DIVULGING session keys in debug output.
+ *
+ * Revision 1.1.2.2  2001/10/22 20:53:25  mcr
+ * 	added a define to control forcing of DES parity.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:20:19  mcr
+ * 	many common kernel configuration questions centralized.
+ * 	more things remain that should be moved from freeswan.h.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_proc.c linux-patched/net/ipsec/ipsec_proc.c
--- linux/net/ipsec/ipsec_proc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_proc.c	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,765 @@
+/*
+ * @(#) /proc file system interface code.
+ *
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
+ *                                 2001  Michael Richardson <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * Split out from ipsec_init.c version 1.70.
+ */
+
+char ipsec_proc_c_version[] = "RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+#include <linux/config.h>
+#include <linux/version.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/in.h>          /* struct sockaddr_in */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+#ifdef SPINLOCK
+#ifdef SPINLOCK_23
+#include <linux/spinlock.h> /* *lock* */
+#else /* SPINLOCK_23 */
+#include <asm/spinlock.h> /* *lock* */
+#endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+#ifdef NET_21
+#include <asm/uaccess.h>
+#include <linux/in6.h>
+#endif /* NET_21 */
+#include <asm/checksum.h>
+#include <net/ip.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+#ifdef NETLINK_SOCK
+#include <linux/netlink.h>
+#else
+#include <net/netlink.h>
+#endif
+
+#include "radij.h"
+
+#include "ipsec_life.h"
+#include "ipsec_stats.h"
+#include "ipsec_sa.h"
+
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_tunnel.h"
+
+#include "ipsec_rcv.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+
+#ifdef CONFIG_IPSEC_IPCOMP
+#include "ipcomp.h"
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#include "ipsec_proto.h"
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#ifdef CONFIG_PROC_FS
+
+#if 0
+static struct proc_dir_entry *proc_net_ipsec_dir;
+#endif
+
+IPSEC_PROCFS_DEBUG_NO_STATIC
+int
+ipsec_eroute_get_info(char *buffer, 
+		      char **start, 
+		      off_t offset, 
+		      int length        IPSEC_PROC_LAST_ARG)
+{
+	struct wsbuf w = {buffer, length, offset, 0, 0, 0, 0};
+
+#ifdef CONFIG_IPSEC_DEBUG
+	if (debug_radij & DB_RJ_DUMPTREES)
+	  rj_dumptrees();			/* XXXXXXXXX */
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_eroute_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
+
+	spin_lock_bh(&eroute_lock);
+
+	rj_walktree(rnh, ipsec_rj_walker_procprint, &w);
+/*	rj_walktree(mask_rjhead, ipsec_rj_walker_procprint, &w); */
+
+	spin_unlock_bh(&eroute_lock);
+
+	*start = buffer + (offset - w.begin);	/* Start of wanted data */
+	w.len -= (offset - w.begin);			/* Start slop */
+	if (w.len > length)
+		w.len = length;
+	return w.len;
+}
+
+IPSEC_PROCFS_DEBUG_NO_STATIC
+int
+ipsec_spi_get_info(char *buffer,
+		   char **start,
+		   off_t offset,
+		   int length    IPSEC_PROC_LAST_ARG)
+{
+	int len = 0;
+	off_t pos = 0, begin = 0;
+	int i;
+	struct ipsec_sa *sa_p;
+	char sa[SATOA_BUF];
+	char buf_s[SUBNETTOA_BUF];
+	char buf_d[SUBNETTOA_BUF];
+	size_t sa_len;
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_spi_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
+	
+	spin_lock_bh(&tdb_lock);
+
+
+	
+	for (i = 0; i < SADB_HASHMOD; i++) {
+		for (sa_p = ipsec_sadb_hash[i];
+		     sa_p;
+		     sa_p = sa_p->ips_hnext) {
+			sa_len = satoa(sa_p->ips_said, 0, sa, SATOA_BUF);
+			len += sprintf(buffer + len, "%s ",
+				       sa_len ? sa : " (error)");
+
+			len += sprintf(buffer + len, "%s%s%s",
+				       IPS_XFORM_NAME(sa_p));
+
+			len += sprintf(buffer + len, ": dir=%s",
+				       (sa_p->ips_flags & EMT_INBOUND) ?
+				       "in " : "out");
+
+			if(sa_p->ips_addr_s) {
+				addrtoa(((struct sockaddr_in*)(sa_p->ips_addr_s))->sin_addr,
+					0, buf_s, sizeof(buf_s));
+				len += sprintf(buffer + len, " src=%s",
+					       buf_s);
+			}
+
+			if((sa_p->ips_said.proto == IPPROTO_IPIP)
+			   && (sa_p->ips_flags & SADB_X_SAFLAGS_INFLOW)) {
+				subnettoa(sa_p->ips_flow_s.u.v4.sin_addr,
+					  sa_p->ips_mask_s.u.v4.sin_addr,
+					  0,
+					  buf_s,
+					  sizeof(buf_s));
+
+				subnettoa(sa_p->ips_flow_d.u.v4.sin_addr,
+					  sa_p->ips_mask_d.u.v4.sin_addr,
+					  0,
+					  buf_d,
+					  sizeof(buf_d));
+
+				len += sprintf(buffer + len, " policy=%s->%s",
+					       buf_s, buf_d);
+			}
+			
+			if(sa_p->ips_iv_bits) {
+				int j;
+				len += sprintf(buffer + len, " iv_bits=%dbits iv=0x",
+					       sa_p->ips_iv_bits);
+
+				for(j = 0; j < sa_p->ips_iv_bits / 8; j++) {
+					len += sprintf(buffer + len, "%02x",
+						       (__u32)((__u8*)(sa_p->ips_iv))[j]);
+				}
+			}
+
+			if(sa_p->ips_encalg || sa_p->ips_authalg) {
+				if(sa_p->ips_replaywin) {
+					len += sprintf(buffer + len, " ooowin=%d",
+						       sa_p->ips_replaywin);
+				}
+				if(sa_p->ips_errs.ips_replaywin_errs) {
+					len += sprintf(buffer + len, " ooo_errs=%d",
+						       sa_p->ips_errs.ips_replaywin_errs);
+				}
+				if(sa_p->ips_replaywin_lastseq) {
+                                       len += sprintf(buffer + len, " seq=%d",
+						      sa_p->ips_replaywin_lastseq);
+				}
+				if(sa_p->ips_replaywin_bitmap) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+					len += sprintf(buffer + len, " bit=0x%Lx",
+						       sa_p->ips_replaywin_bitmap);
+#else
+					len += sprintf(buffer + len, " bit=0x%x%08x",
+						       (__u32)(sa_p->ips_replaywin_bitmap >> 32),
+						       (__u32)sa_p->ips_replaywin_bitmap);
+#endif
+				}
+				if(sa_p->ips_replaywin_maxdiff) {
+					len += sprintf(buffer + len, " max_seq_diff=%d",
+						       sa_p->ips_replaywin_maxdiff);
+				}
+			}
+			if(sa_p->ips_flags & ~EMT_INBOUND) {
+				len += sprintf(buffer + len, " flags=0x%x",
+					       sa_p->ips_flags & ~EMT_INBOUND);
+				len += sprintf(buffer + len, "<");
+				/* flag printing goes here */
+				len += sprintf(buffer + len, ">");
+			}
+			if(sa_p->ips_auth_bits) {
+				len += sprintf(buffer + len, " alen=%d",
+					       sa_p->ips_auth_bits);
+			}
+			if(sa_p->ips_key_bits_a) {
+				len += sprintf(buffer + len, " aklen=%d",
+					       sa_p->ips_key_bits_a);
+			}
+			if(sa_p->ips_errs.ips_auth_errs) {
+				len += sprintf(buffer + len, " auth_errs=%d",
+					       sa_p->ips_errs.ips_auth_errs);
+			}
+			if(sa_p->ips_key_bits_e) {
+				len += sprintf(buffer + len, " eklen=%d",
+					       sa_p->ips_key_bits_e);
+			}
+			if(sa_p->ips_errs.ips_encsize_errs) {
+				len += sprintf(buffer + len, " encr_size_errs=%d",
+					       sa_p->ips_errs.ips_encsize_errs);
+			}
+			if(sa_p->ips_errs.ips_encpad_errs) {
+				len += sprintf(buffer + len, " encr_pad_errs=%d",
+					       sa_p->ips_errs.ips_encpad_errs);
+			}
+			
+			len += sprintf(buffer + len, " life(c,s,h)=");
+
+			len += ipsec_lifetime_format(buffer + len,
+						     length - len,
+						     "alloc", 
+						     ipsec_life_countbased,
+						     &sa_p->ips_life.ipl_allocations);
+
+			len += ipsec_lifetime_format(buffer + len,
+						     length - len,
+						     "bytes",
+						     ipsec_life_countbased,
+						     &sa_p->ips_life.ipl_bytes);
+
+			len += ipsec_lifetime_format(buffer + len,
+						     length - len,
+						     "addtime",
+						     ipsec_life_timebased,
+						     &sa_p->ips_life.ipl_addtime);
+
+			len += ipsec_lifetime_format(buffer + len,
+						     length - len,
+						     "usetime",
+						     ipsec_life_timebased,
+						     &sa_p->ips_life.ipl_usetime);
+			
+			len += ipsec_lifetime_format(buffer + len,
+						     length - len,
+						     "packets",
+						     ipsec_life_countbased,
+						     &sa_p->ips_life.ipl_packets);
+			
+			if(sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+				len += sprintf(buffer + len, " idle=%Ld",
+					       jiffies / HZ - sa_p->ips_life.ipl_usetime.ipl_last);
+#else
+				len += sprintf(buffer + len, " idle=%lu",
+					       jiffies / HZ - (unsigned long)sa_p->ips_life.ipl_usetime.ipl_last);
+#endif
+			}
+
+#ifdef CONFIG_IPSEC_IPCOMP
+			if(sa_p->ips_said.proto == IPPROTO_COMP &&
+			   (sa_p->ips_comp_ratio_dbytes ||
+			    sa_p->ips_comp_ratio_cbytes)) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+				len += sprintf(buffer + len, " ratio=%Ld:%Ld",
+					       sa_p->ips_comp_ratio_dbytes,
+					       sa_p->ips_comp_ratio_cbytes);
+#else
+				len += sprintf(buffer + len, " ratio=%lu:%lu",
+					       (unsigned long)sa_p->ips_comp_ratio_dbytes,
+					       (unsigned long)sa_p->ips_comp_ratio_cbytes);
+#endif
+			}
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+			len += sprintf(buffer + len, "\n");
+
+			pos = begin + len;
+			if(pos < offset) {
+				len = 0;
+				begin = pos;
+			}
+			if (pos > offset + length) {
+				goto done_spi_i;
+			}
+		}
+	}
+
+ done_spi_i:	
+	spin_unlock_bh(&tdb_lock);
+
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);			/* Start slop */
+	if (len > length)
+		len = length;
+	return len;
+}
+
+IPSEC_PROCFS_DEBUG_NO_STATIC
+int
+ipsec_spigrp_get_info(char *buffer,
+		      char **start,
+		      off_t offset,
+		      int length     IPSEC_PROC_LAST_ARG)
+{
+	int len = 0;
+	off_t pos = 0, begin = 0;
+	int i;
+	struct ipsec_sa *sa_p, *sa_p2;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_spigrp_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
+
+	spin_lock_bh(&tdb_lock);
+	
+	for (i = 0; i < SADB_HASHMOD; i++) {
+		for (sa_p = ipsec_sadb_hash[i];
+		     sa_p;
+		     sa_p = sa_p->ips_hnext)
+		{
+			if(!sa_p->ips_inext)
+			{
+				sa_p2 = sa_p;
+				while(sa_p2) {
+					sa_len = satoa(sa_p2->ips_said,
+						       0, sa, SATOA_BUF);
+					
+					len += sprintf(buffer + len, "%s ",
+						       sa_len ? sa : " (error)");
+					sa_p2 = sa_p2->ips_onext;
+				}
+				len += sprintf(buffer + len, "\n");
+				pos = begin + len;
+				if(pos < offset) {
+					len = 0;
+					begin = pos;
+				}
+				if (pos > offset + length) {
+					goto done_spigrp_i;
+				}
+			}
+		}
+	}
+
+ done_spigrp_i:	
+	spin_unlock_bh(&tdb_lock);
+
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);			/* Start slop */
+	if (len > length)
+		len = length;
+	return len;
+}
+
+IPSEC_PROCFS_DEBUG_NO_STATIC
+int
+ipsec_tncfg_get_info(char *buffer,
+		     char **start,
+		     off_t offset,
+		     int length     IPSEC_PROC_LAST_ARG)
+{
+	int len = 0;
+	off_t pos = 0, begin = 0;
+	int i;
+	char name[9];
+	struct device *dev, *privdev;
+	struct ipsecpriv *priv;
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_tncfg_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
+
+	for(i = 0; i < IPSEC_NUM_IF; i++) {
+		sprintf(name, "ipsec%d", i);
+		dev = ipsec_dev_get(name);
+		if(dev) {
+			priv = (struct ipsecpriv *)(dev->priv);
+			len += sprintf(buffer + len, "%s",
+				       dev->name);
+			if(priv) {
+				privdev = (struct device *)(priv->dev);
+				len += sprintf(buffer + len, " -> %s",
+					       privdev ? privdev->name : "NULL");
+				len += sprintf(buffer + len, " mtu=%d(%d) -> %d",
+					       dev->mtu,
+					       priv->mtu,
+					       privdev ? privdev->mtu : 0);
+			} else {
+				KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+					    "klips_debug:ipsec_tncfg_get_info: device '%s' has no private data space!\n",
+					    dev->name);
+			}
+			len += sprintf(buffer + len, "\n");
+
+			pos = begin + len;
+			if(pos < offset) {
+				len = 0;
+				begin = pos;
+			}
+			else if (pos > offset + length)	{
+				break;
+			}
+		}
+	}
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);			/* Start slop */
+	if (len > length)
+		len = length;
+	return len;
+}
+
+IPSEC_PROCFS_DEBUG_NO_STATIC
+int
+ipsec_version_get_info(char *buffer,
+		       char **start,
+		       off_t offset,
+		       int length  IPSEC_PROC_LAST_ARG)
+{
+	int len = 0;
+	off_t begin = 0;
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_version_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
+
+	len += sprintf(buffer + len, "FreeS/WAN version: %s\n",
+		       ipsec_version_code());
+#if 0
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_version_get_info: "
+		    "ipsec_init version: %s\n",
+		    ipsec_init_c_version);
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_version_get_info: "
+		    "ipsec_tunnel version: %s\n",
+		    ipsec_tunnel_c_version);
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_version_get_info: "
+		    "ipsec_netlink version: %s\n",
+		    ipsec_netlink_c_version);
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_version_get_info: "
+		    "radij_c_version: %s\n",
+		    radij_c_version);
+#endif
+
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);			/* Start slop */
+	if (len > length)
+		len = length;
+	return len;
+}
+
+#ifdef CONFIG_IPSEC_DEBUG
+IPSEC_PROCFS_DEBUG_NO_STATIC
+int
+ipsec_klipsdebug_get_info(char *buffer,
+			  char **start,
+			  off_t offset,
+			  int length      IPSEC_PROC_LAST_ARG)
+{
+	int len = 0;
+	off_t begin = 0;
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
+		    "klips_debug:ipsec_klipsdebug_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
+
+	len += sprintf(buffer + len, "debug_tunnel=%08x.\n", debug_tunnel);
+	len += sprintf(buffer + len, "debug_netlink=%08x.\n", debug_netlink);
+	len += sprintf(buffer + len, "debug_xform=%08x.\n", debug_xform);
+	len += sprintf(buffer + len, "debug_eroute=%08x.\n", debug_eroute);
+	len += sprintf(buffer + len, "debug_spi=%08x.\n", debug_spi);
+	len += sprintf(buffer + len, "debug_radij=%08x.\n", debug_radij);
+	len += sprintf(buffer + len, "debug_esp=%08x.\n", debug_esp);
+	len += sprintf(buffer + len, "debug_ah=%08x.\n", debug_ah);
+	len += sprintf(buffer + len, "debug_rcv=%08x.\n", debug_rcv);
+	len += sprintf(buffer + len, "debug_pfkey=%08x.\n", debug_pfkey);
+
+	*start = buffer + (offset - begin);	/* Start of wanted data */
+	len -= (offset - begin);			/* Start slop */
+	if (len > length)
+		len = length;
+	return len;
+}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#ifndef PROC_FS_2325
+struct proc_dir_entry ipsec_eroute =
+{
+	0,
+	12, "ipsec_eroute",
+	S_IFREG | S_IRUGO, 1, 0, 0, 0,
+	&proc_net_inode_operations,
+	ipsec_eroute_get_info,
+	NULL, NULL, NULL, NULL, NULL
+};
+
+struct proc_dir_entry ipsec_spi =
+{
+	0,
+	9, "ipsec_spi",
+	S_IFREG | S_IRUGO, 1, 0, 0, 0,
+	&proc_net_inode_operations,
+	ipsec_spi_get_info,
+	NULL, NULL, NULL, NULL, NULL
+};
+
+struct proc_dir_entry ipsec_spigrp =
+{
+	0,
+	12, "ipsec_spigrp",
+	S_IFREG | S_IRUGO, 1, 0, 0, 0,
+	&proc_net_inode_operations,
+	ipsec_spigrp_get_info,
+	NULL, NULL, NULL, NULL, NULL
+};
+
+struct proc_dir_entry ipsec_tncfg =
+{
+	0,
+	11, "ipsec_tncfg",
+	S_IFREG | S_IRUGO, 1, 0, 0, 0,
+	&proc_net_inode_operations,
+	ipsec_tncfg_get_info,
+	NULL, NULL, NULL, NULL, NULL
+};
+
+struct proc_dir_entry ipsec_version =
+{
+	0,
+	13, "ipsec_version",
+	S_IFREG | S_IRUGO, 1, 0, 0, 0,
+	&proc_net_inode_operations,
+	ipsec_version_get_info,
+	NULL, NULL, NULL, NULL, NULL
+};
+
+#ifdef CONFIG_IPSEC_DEBUG
+struct proc_dir_entry ipsec_klipsdebug =
+{
+	0,
+	16, "ipsec_klipsdebug",
+	S_IFREG | S_IRUGO, 1, 0, 0, 0,
+	&proc_net_inode_operations,
+	ipsec_klipsdebug_get_info,
+	NULL, NULL, NULL, NULL, NULL
+};
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* !PROC_FS_2325 */
+#endif /* CONFIG_PROC_FS */
+
+int
+ipsec_proc_init()
+{
+	int error = 0;
+
+	/* compile a dummy function if no /proc/-fs */
+
+	/* XXX-mcr probably should just complain because pluto won't
+	 * run without /proc!
+	 */
+
+#ifdef CONFIG_PROC_FS 
+#  ifndef PROC_FS_2325
+#    ifdef PROC_FS_21
+	error |= proc_register(proc_net, &ipsec_eroute);
+	error |= proc_register(proc_net, &ipsec_spi);
+	error |= proc_register(proc_net, &ipsec_spigrp);
+	error |= proc_register(proc_net, &ipsec_tncfg);
+	error |= proc_register(proc_net, &ipsec_version);
+#      ifdef CONFIG_IPSEC_DEBUG
+	error |= proc_register(proc_net, &ipsec_klipsdebug);
+#      endif /* CONFIG_IPSEC_DEBUG */
+#    else /* PROC_FS_21 */
+	error |= proc_register_dynamic(&proc_net, &ipsec_eroute);
+	error |= proc_register_dynamic(&proc_net, &ipsec_spi);
+	error |= proc_register_dynamic(&proc_net, &ipsec_spigrp);
+	error |= proc_register_dynamic(&proc_net, &ipsec_tncfg);
+	error |= proc_register_dynamic(&proc_net, &ipsec_version);
+#      ifdef CONFIG_IPSEC_DEBUG
+	error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug);
+#      endif /* CONFIG_IPSEC_DEBUG */
+#    endif /* PROC_FS_21 */
+#  else /* !PROC_FS_2325 */
+	/* create /proc/net/ipsec */
+#if 0
+	proc_net_ipsec_dir = proc_mkdir("ipsec", proc_net);
+	if(proc_net_ipsec_dir == NULL) {
+		error |= 1;
+	} else{
+		error |= proc_register();
+	}		
+#endif
+
+	proc_net_create ("ipsec_eroute", 0, ipsec_eroute_get_info);
+	proc_net_create ("ipsec_spi", 0, ipsec_spi_get_info);
+	proc_net_create ("ipsec_spigrp", 0, ipsec_spigrp_get_info);
+	proc_net_create ("ipsec_tncfg", 0, ipsec_tncfg_get_info);
+	proc_net_create ("ipsec_version", 0, ipsec_version_get_info);
+#    ifdef CONFIG_IPSEC_DEBUG
+	proc_net_create ("ipsec_klipsdebug", 0, ipsec_klipsdebug_get_info);
+#    endif /* CONFIG_IPSEC_DEBUG */
+#  endif /* !PROC_FS_2325 */
+#endif /* CONFIG_PROC_FS */
+
+	return error;
+}
+
+void
+ipsec_proc_cleanup()
+{
+#ifdef CONFIG_PROC_FS
+#  ifndef PROC_FS_2325
+#    ifdef CONFIG_IPSEC_DEBUG
+	if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0)
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_klipsdebug\n");
+#    endif /* CONFIG_IPSEC_DEBUG */
+	if (proc_net_unregister(ipsec_version.low_ino) != 0)
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_version\n");
+	if (proc_net_unregister(ipsec_eroute.low_ino) != 0)
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_eroute\n");
+	if (proc_net_unregister(ipsec_spi.low_ino) != 0)
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_spi\n");
+	if (proc_net_unregister(ipsec_spigrp.low_ino) != 0)
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_spigrp\n");
+	if (proc_net_unregister(ipsec_tncfg.low_ino) != 0)
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_tncfg\n");
+#  else /* !PROC_FS_2325 */
+#    ifdef CONFIG_IPSEC_DEBUG
+	proc_net_remove ("ipsec_klipsdebug");
+#    endif /* CONFIG_IPSEC_DEBUG */
+	proc_net_remove ("ipsec_eroute");
+	proc_net_remove ("ipsec_spi");
+	proc_net_remove ("ipsec_spigrp");
+	proc_net_remove ("ipsec_tncfg");
+	proc_net_remove ("ipsec_version");
+#  endif /* !PROC_FS_2325 */
+#endif          /* CONFIG_PROC_FS */
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.8  2002/01/29 17:17:55  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.7  2002/01/29 04:00:52  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.6  2002/01/29 02:13:17  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.5  2002/01/12 02:54:30  mcr
+ * 	beginnings of /proc/net/ipsec dir.
+ *
+ * Revision 1.4  2001/12/11 02:21:05  rgb
+ * Don't include module version here, fixing 2.2 compile bug.
+ *
+ * Revision 1.3  2001/12/05 07:19:44  rgb
+ * Fixed extraneous #include "version.c" bug causing modular KLIPS failure.
+ *
+ * Revision 1.2  2001/11/26 09:16:14  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.74  2001/11/22 05:44:11  henry
+ * new version stuff
+ *
+ * Revision 1.1.2.1  2001/09/25 02:19:40  mcr
+ * 	/proc manipulation code moved to new ipsec_proc.c
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_proto.h linux-patched/net/ipsec/ipsec_proto.h
--- linux/net/ipsec/ipsec_proto.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_proto.h	Sun Jan 19 22:32:30 2003
@@ -0,0 +1,134 @@
+/*
+ * @(#) prototypes for FreeSWAN functions 
+ *
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ */
+
+#ifndef _IPSEC_PROTO_H_
+
+#include "ipsec_param.h"
+
+/* 
+ * This file is a kernel only file that declares prototypes for
+ * all intra-module function calls and global data structures.
+ *
+ * Include this file last.
+ *
+ */
+
+/* ipsec_sa.c */
+extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];
+extern spinlock_t       tdb_lock;
+extern int ipsec_sadb_init(void);
+
+extern struct ipsec_sa *ipsec_sa_getbyid(struct sa_id*);
+extern /* void */ int ipsec_sa_del(struct ipsec_sa *);
+extern /* void */ int ipsec_sa_delchain(struct ipsec_sa *);
+extern /* void */ int ipsec_sa_put(struct ipsec_sa *);
+
+extern int ipsec_sa_init(struct ipsec_sa *, struct encap_msghdr *);
+extern int ipsec_sadb_cleanup(__u8);
+extern int ipsec_sa_wipe(struct ipsec_sa *);
+
+/* debug declarations */
+
+/* ipsec_proc.c */
+extern int  ipsec_proc_init(void);
+extern void ipsec_proc_cleanup(void);
+
+/* ipsec_radij.c */
+extern int ipsec_makeroute(struct sockaddr_encap *ea,
+			   struct sockaddr_encap *em,
+			   struct sa_id said,
+			   uint32_t pid,
+			   struct sk_buff *skb,
+			   struct ident *ident_s,
+			   struct ident *ident_d);
+
+extern int ipsec_breakroute(struct sockaddr_encap *ea,
+			    struct sockaddr_encap *em,
+			    struct sk_buff **first,
+			    struct sk_buff **last);
+
+int ipsec_radijinit(void);
+int ipsec_cleareroutes(void);
+int ipsec_radijcleanup(void);
+
+/* ipsec_life.c */
+extern enum ipsec_life_alive ipsec_lifetime_check(struct ipsec_lifetime64 *il64,
+						  const char *lifename,
+						  const char *saname,
+						  enum ipsec_life_type ilt,
+						  enum ipsec_direction idir,
+						  struct ipsec_sa *ips);
+
+
+extern int ipsec_lifetime_format(char *buffer,
+				 int   buflen,
+				 char *lifename,
+				 enum ipsec_life_type timebaselife,
+				 struct ipsec_lifetime64 *lifetime);
+
+extern void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime,
+				       __u64 newvalue);
+
+extern void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime,
+				       __u64 newvalue);
+
+
+
+
+#ifdef CONFIG_IPSEC_DEBUG
+
+extern int debug_xform;
+extern int debug_eroute;
+extern int debug_spi;
+
+#endif /* CONFIG_IPSEC_DEBUG */
+
+
+
+
+#define _IPSEC_PROTO_H
+#endif /* _IPSEC_PROTO_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.3  2003/01/19 22:32:30  ken
+ * X.509 0.9.19 -> 0.9.20
+ *
+ * Revision 1.2  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.2  2001/11/26 09:16:15  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:21:01  mcr
+ * 	ipsec_proto.h created to keep prototypes rather than deal with
+ * 	cyclic dependancies of structures and prototypes in .h files.
+ *
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_radij.c linux-patched/net/ipsec/ipsec_radij.c
--- linux/net/ipsec/ipsec_radij.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_radij.c	Sun Jan 19 22:32:30 2003
@@ -0,0 +1,810 @@
+/*
+ * Interface between the IPSEC code and the radix (radij) tree code
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, struct net_device_stats and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+#ifdef SPINLOCK
+# ifdef SPINLOCK_23
+#  include <linux/spinlock.h> /* *lock* */
+# else /* 23_SPINLOCK */
+#  include <asm/spinlock.h> /* *lock* */
+# endif /* 23_SPINLOCK */
+#endif /* SPINLOCK */
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+#endif
+#include <asm/checksum.h>
+#include <net/ip.h>
+
+#include "ipsec_eroute.h"
+#include "ipsec_sa.h"
+ 
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_tunnel.h"	/* struct ipsecpriv */
+#include "ipsec_xform.h"
+ 
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_proto.h"
+
+#ifdef CONFIG_IPSEC_DEBUG
+int debug_radij = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+struct radij_node_head *rnh = NULL;
+#ifdef SPINLOCK
+spinlock_t eroute_lock = SPIN_LOCK_UNLOCKED;
+#else /* SPINLOCK */
+spinlock_t eroute_lock;
+#endif /* SPINLOCK */
+
+int
+ipsec_radijinit(void)
+{
+	maj_keylen = sizeof (struct sockaddr_encap);
+
+	rj_init();
+	
+	if (rj_inithead((void **)&rnh, /*16*/offsetof(struct sockaddr_encap, sen_type) * sizeof(__u8)) == 0) /* 16 is bit offset of sen_type */
+		return -1;
+	return 0;
+}
+
+int
+ipsec_radijcleanup(void)
+{
+	int error;
+
+	spin_lock_bh(&eroute_lock);
+
+	error = radijcleanup();
+
+	spin_unlock_bh(&eroute_lock);
+
+	return error;
+}
+
+int
+ipsec_cleareroutes(void)
+{
+	int error = 0;
+
+	spin_lock_bh(&eroute_lock);
+
+	error = radijcleartree();
+
+	spin_unlock_bh(&eroute_lock);
+
+	return error;
+}
+
+int
+ipsec_breakroute(struct sockaddr_encap *eaddr,
+		 struct sockaddr_encap *emask,
+		 struct sk_buff **first,
+		 struct sk_buff **last)
+{
+	struct eroute *ro;
+	struct radij_node *rn;
+	int error = 0;
+#ifdef CONFIG_IPSEC_DEBUG
+	char buf1[64], buf2[64];
+	
+	if (debug_eroute) {
+		subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
+		KLIPS_PRINT(debug_eroute, 
+			    "klips_debug:ipsec_breakroute: "
+			    "attempting to delete eroute for %s:%d->%s:%d %d\n",
+			    buf1, ntohs(eaddr->sen_sport),
+			    buf2, ntohs(eaddr->sen_dport), eaddr->sen_proto);
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	spin_lock_bh(&eroute_lock);
+
+	if ((error = rj_delete(eaddr, emask, rnh, &rn)) != 0) {
+		spin_unlock_bh(&eroute_lock);
+		KLIPS_PRINT(debug_eroute,
+			    "klips_debug:ipsec_breakroute: "
+			    "node not found, eroute delete failed.\n");
+		return error;
+	}
+
+	spin_unlock_bh(&eroute_lock);
+	
+	ro = (struct eroute *)rn;
+	
+	KLIPS_PRINT(debug_eroute, 
+		    "klips_debug:ipsec_breakroute: "
+		    "deleted eroute=%p, ident=%p->%p, first=%p, last=%p\n",
+		    ro,
+		    ro->er_ident_s.data,
+		    ro->er_ident_d.data,
+		    ro->er_first,
+		    ro->er_last);
+	
+	if (ro->er_ident_s.data != NULL) {
+		kfree(ro->er_ident_s.data);
+	}
+	if (ro->er_ident_d.data != NULL) {
+		kfree(ro->er_ident_d.data);
+	}
+	if (ro->er_first != NULL) {
+#if 0
+		struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_first->dev->priv))->mystats);
+		stats->tx_dropped--;
+#endif
+		*first = ro->er_first;
+	}
+	if (ro->er_last != NULL) {
+#if 0
+		struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_last->dev->priv))->mystats);
+		stats->tx_dropped--;
+#endif
+		*last = ro->er_last;
+	}
+	
+	if (rn->rj_flags & (RJF_ACTIVE | RJF_ROOT))
+		panic ("ipsec_breakroute RMT_DELEROUTE root or active node\n");
+	memset((caddr_t)rn, 0, sizeof (struct eroute));
+	kfree(rn);
+	
+	return 0;
+}
+
+int
+ipsec_makeroute(struct sockaddr_encap *eaddr,
+		struct sockaddr_encap *emask,
+		struct sa_id said,
+		uint32_t pid,
+		struct sk_buff *skb,
+		struct ident *ident_s,
+		struct ident *ident_d)
+{
+	struct eroute *retrt;
+	int error = 0;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+#ifdef CONFIG_IPSEC_DEBUG
+	char buf1[64], buf2[64];
+	
+	if (debug_eroute) {
+		subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
+		sa_len = satoa(said, 0, sa, SATOA_BUF);
+		KLIPS_PRINT(debug_eroute, 
+			    "klips_debug:ipsec_makeroute: "
+			    "attempting to insert eroute for %s:%d->%s:%d %d, SA: %s, PID:%d, skb=%p, ident:%s->%s\n",
+			    buf1, ntohs(eaddr->sen_sport),
+			    buf2, ntohs(eaddr->sen_dport),
+			    eaddr->sen_proto,
+			    sa_len ? sa : " (error)",
+			    pid,
+			    skb,
+			    (ident_s ? (ident_s->data ? ident_s->data : "NULL") : "NULL"),
+			    (ident_d ? (ident_d->data ? ident_d->data : "NULL") : "NULL"));
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	retrt = (struct eroute *)kmalloc(sizeof (struct eroute), GFP_ATOMIC);
+	if (retrt == NULL) {
+		printk("klips_error:ipsec_makeroute: "
+		       "not able to allocate kernel memory");
+		return -ENOMEM;
+	}
+	memset((caddr_t)retrt, 0, sizeof (struct eroute));
+
+	retrt->er_eaddr = *eaddr;
+	retrt->er_emask = *emask;
+	retrt->er_said = said;
+	retrt->er_pid = pid;
+	retrt->er_count = 0;
+	retrt->er_lasttime = jiffies/HZ;
+	rd_key((&(retrt->er_rjt))) = &(retrt->er_eaddr);
+	
+	if (ident_s && ident_s->type != SADB_IDENTTYPE_RESERVED) {
+		int data_len = ident_s->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+		
+		retrt->er_ident_s.type = ident_s->type;
+		retrt->er_ident_s.id = ident_s->id;
+		retrt->er_ident_s.len = ident_s->len;
+		if(data_len) {
+			if(!(retrt->er_ident_s.data = kmalloc(data_len, GFP_KERNEL))) {
+				kfree(retrt);
+				printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len);
+				return ENOMEM;
+			}
+			memcpy(retrt->er_ident_s.data, ident_s->data, data_len);
+		} else {
+			retrt->er_ident_s.data = NULL;
+		}
+	}
+	
+	if (ident_d && ident_d->type != SADB_IDENTTYPE_RESERVED) {
+		int data_len = ident_d->len  * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+		
+		retrt->er_ident_d.type = ident_d->type;
+		retrt->er_ident_d.id = ident_d->id;
+		retrt->er_ident_d.len = ident_d->len;
+		if(data_len) {
+			if(!(retrt->er_ident_d.data = kmalloc(data_len, GFP_KERNEL))) {
+				if (retrt->er_ident_s.data)
+					kfree(retrt->er_ident_s.data);
+				kfree(retrt);
+				printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len);
+				return ENOMEM;
+			}
+			memcpy(retrt->er_ident_d.data, ident_d->data, data_len);
+		} else {
+			retrt->er_ident_d.data = NULL;
+		}
+	}
+	retrt->er_first = skb;
+	retrt->er_last = NULL;
+	
+	spin_lock_bh(&eroute_lock);
+	
+	error = rj_addroute(&(retrt->er_eaddr), &(retrt->er_emask), 
+			 rnh, retrt->er_rjt.rd_nodes);
+
+	spin_unlock_bh(&eroute_lock);
+	
+	if(error) {
+		sa_len = satoa(said, 0, sa, SATOA_BUF);
+		KLIPS_PRINT(debug_eroute, 
+			    "klips_debug:ipsec_makeroute: "
+			    "rj_addroute not able to insert eroute for SA:%s\n",
+			    sa_len ? sa : " (error)");
+		if (retrt->er_ident_s.data)
+			kfree(retrt->er_ident_s.data);
+		if (retrt->er_ident_d.data)
+			kfree(retrt->er_ident_d.data);
+		
+		kfree(retrt);
+		
+		return error;
+	}
+
+#ifdef CONFIG_IPSEC_DEBUG
+	if (debug_eroute && 0) {
+/*
+		subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
+*/
+		subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_src, rd_mask((&(retrt->er_rjt)))->sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_dst, rd_mask((&(retrt->er_rjt)))->sen_ip_dst, 0, buf2, sizeof(buf2));
+		sa_len = satoa(retrt->er_said, 0, sa, SATOA_BUF);
+		
+		KLIPS_PRINT(debug_eroute,
+			    "klips_debug:ipsec_makeroute: "
+			    "pid=%05d "
+			    "count=%10d "
+			    "lasttime=%6d "
+			    "%-18s -> %-18s => %s\n",
+			    retrt->er_pid,
+			    retrt->er_count,
+			    (int)(jiffies/HZ - retrt->er_lasttime),
+			    buf1,
+			    buf2,
+			    sa_len ? sa : " (error)");
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+	KLIPS_PRINT(debug_eroute,
+		    "klips_debug:ipsec_makeroute: "
+		    "succeeded, I think...\n");
+	return 0;
+}
+
+struct eroute *
+ipsec_findroute(struct sockaddr_encap *eaddr)
+{
+	struct radij_node *rn;
+#ifdef CONFIG_IPSEC_DEBUG
+	char buf1[ADDRTOA_BUF], buf2[ADDRTOA_BUF];
+	
+	if (debug_radij & DB_RJ_FINDROUTE) {
+		addrtoa(eaddr->sen_ip_src, 0, buf1, sizeof(buf1));
+		addrtoa(eaddr->sen_ip_dst, 0, buf2, sizeof(buf2));
+		KLIPS_PRINT(debug_eroute,
+			    "klips_debug:ipsec_findroute: "
+			    "%s:%d->%s:%d %d\n",
+			    buf1, ntohs(eaddr->sen_sport),
+			    buf2, ntohs(eaddr->sen_dport),
+			    eaddr->sen_proto);
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+	rn = rj_match((caddr_t)eaddr, rnh);
+	if(rn) {
+		KLIPS_PRINT(debug_eroute,
+			    "klips_debug:ipsec_findroute: "
+			    "found, points to proto=%d, spi=%x, dst=%x.\n",
+			    ((struct eroute*)rn)->er_said.proto,
+			    ntohl(((struct eroute*)rn)->er_said.spi),
+			    ntohl(((struct eroute*)rn)->er_said.dst.s_addr));
+	}
+	return (struct eroute *)rn;
+}
+		
+#ifdef CONFIG_PROC_FS
+int
+ipsec_rj_walker_procprint(struct radij_node *rn, void *w0)
+{
+	struct eroute *ro = (struct eroute *)rn;
+	struct rjtentry *rd = (struct rjtentry *)rn;
+	struct wsbuf *w = (struct wsbuf *)w0;
+	char buf1[64], buf2[64];
+	char sa[SATOA_BUF];
+	size_t sa_len, buf_len;
+	struct sockaddr_encap *key, *mask;
+	
+	KLIPS_PRINT(debug_radij,
+		    "klips_debug:ipsec_rj_walker_procprint: "
+		    "rn=%p, w0=%p\n",
+		    rn,
+		    w0);
+	if (rn == NULL)	{
+		return 120;
+	}
+	
+	if (rn->rj_b >= 0) {
+		return 0;
+	}
+	
+	key = rd_key(rd);
+	mask = rd_mask(rd);
+	
+	if ((key == 0) || (mask == 0)) {
+		return 0;
+	}
+
+	buf_len = subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1));
+	sprintf(buf1+buf_len-1, ":%d", ntohs(key->sen_sport));
+	buf_len = subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2));
+	sprintf(buf2+buf_len-1, ":%d", ntohs(key->sen_dport));
+	sa_len = satoa(ro->er_said, 0, sa, SATOA_BUF);
+#define IPSEC_EROUTE_IDENT_
+#ifndef IPSEC_EROUTE_IDENT
+	w->len += sprintf(w->buffer + w->len,
+/*
+			  "%05d "
+*/
+			  "%-10d "
+/*
+			  "%6d "
+*/
+			  "%-18s -> %-18s => %s:%d\n",
+/*
+			  ro->er_pid,
+*/
+			  ro->er_count,
+/*
+			  jiffies / HZ - ro->er_lasttime,
+*/
+			  buf1,
+			  buf2,
+			  sa_len ? sa : " (error)",
+			  key->sen_proto);
+#else /* IPSEC_EROUTE_IDENT */
+	w->len += sprintf(w->buffer + w->len,
+/*
+			  "%05d "
+*/
+			  "%-10d "
+/*
+			  "%6d "
+*/
+			  "%-18s -> %-18s => %s:%d (%s) (%s)\n",
+/*
+			  ro->er_pid,
+*/
+			  ro->er_count,
+/*
+			  jiffies / HZ - ro->er_lasttime,
+*/
+			  buf1,
+			  buf2,
+			  sa_len ? sa : " (error)",
+			  key->sen_proto,
+			  (ro->er_ident_s.data ? ro->er_ident_s.data : ""),
+			  (ro->er_ident_d.data ? ro->er_ident_d.data : ""));
+#endif /* IPSEC_EROUTE_IDENT */
+	
+	w->pos = w->begin + w->len;
+	if(w->pos < w->offset) {
+		w->len = 0;
+		w->begin = w->pos;
+	}
+	if (w->pos > w->offset + w->length) {
+		return -ENOBUFS;
+	}
+	return 0;
+}
+#endif          /* CONFIG_PROC_FS */
+
+int
+ipsec_rj_walker_delete(struct radij_node *rn, void *w0)
+{
+	struct eroute *ro;
+	struct rjtentry *rd = (struct rjtentry *)rn;
+	struct radij_node *rn2;
+	int error = 0;
+	struct sockaddr_encap *key, *mask;
+#ifdef CONFIG_IPSEC_DEBUG
+	char buf1[64] = { 0 }, buf2[64] = { 0 };
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	if (rn == NULL)	{
+		return 120;
+	}
+	
+	key = rd_key(rd);
+	mask = rd_mask(rd);
+	
+	if(!key || !mask) {
+		return -ENODATA;
+	}
+#ifdef CONFIG_IPSEC_DEBUG
+	if(debug_radij)	{
+		subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2));
+		KLIPS_PRINT(debug_radij, 
+			    "klips_debug:ipsec_rj_walker_delete: "
+			    "deleting: %s -> %s\n",
+			    buf1,
+			    buf2);
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	if((error = rj_delete(key, mask, rnh, &rn2))) {
+		KLIPS_PRINT(debug_radij,
+			    "klips_debug:ipsec_rj_walker_delete: "
+			    "rj_delete failed with error=%d.\n", error);
+		return error;
+	}
+
+	if(rn2 != rn) {
+		printk("klips_debug:ipsec_rj_walker_delete: "
+		       "tried to delete a different node?!?  This should never happen!\n");
+	}
+ 
+	ro = (struct eroute *)rn;
+	
+	if (ro->er_ident_s.data)
+		kfree(ro->er_ident_s.data);
+	if (ro->er_ident_d.data)
+		kfree(ro->er_ident_d.data);
+	
+	memset((caddr_t)rn, 0, sizeof (struct eroute));
+	kfree(rn);
+	
+	return 0;
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.3  2003/01/19 22:32:30  ken
+ * X.509 0.9.19 -> 0.9.20
+ *
+ * Revision 1.2  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.60  2002/02/19 23:59:45  rgb
+ * Removed redundant compiler directives.
+ *
+ * Revision 1.59  2002/02/06 04:13:47  mcr
+ * 	missing #ifdef CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.58  2002/01/29 17:17:56  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.57  2002/01/29 04:00:52  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.56  2002/01/29 02:13:17  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.55  2001/11/26 09:23:48  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.53.2.1  2001/09/25 02:26:32  mcr
+ * 	headers adjusted for new usage.
+ *
+ * Revision 1.54  2001/10/18 04:45:20  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.53  2001/09/19 17:19:40  rgb
+ * Debug output bugfix for NetCelo's PF_KEY ident patch.
+ *
+ * Revision 1.52  2001/09/19 16:33:37  rgb
+ * Temporarily disable ident fields to /proc/net/ipsec_eroute.
+ *
+ * Revision 1.51  2001/09/15 16:24:04  rgb
+ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
+ *
+ * Revision 1.50  2001/09/14 16:58:36  rgb
+ * Added support for storing the first and last packets through a HOLD.
+ *
+ * Revision 1.49  2001/09/08 21:13:32  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.48  2001/06/15 04:12:56  rgb
+ * Fixed kernel memory allocation error return code polarity bug.
+ *
+ * Revision 1.47  2001/06/14 19:35:09  rgb
+ * Update copyright date.
+ *
+ * Revision 1.46  2001/06/08 08:47:18  rgb
+ * Fixed for debug disabled.
+ *
+ * Revision 1.45  2001/05/27 06:12:11  rgb
+ * Added structures for pid, packet count and last access time to eroute.
+ * Added packet count to beginning of /proc/net/ipsec_eroute.
+ *
+ * Revision 1.44  2001/05/03 19:41:01  rgb
+ * Initialise error return variable.
+ * Use more appropriate return value for ipsec_rj_walker_delete().
+ *
+ * Revision 1.43  2001/02/27 22:24:54  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.42  2001/02/27 06:21:57  rgb
+ * Added findroute success instrumentation.
+ *
+ * Revision 1.41  2000/11/06 04:32:08  rgb
+ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
+ *
+ * Revision 1.40  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.39  2000/08/30 05:25:20  rgb
+ * Correct debug text in ipsec_breakroute() from incorrect
+ * "ipsec_callback".
+ *
+ * Revision 1.38  2000/07/28 14:58:31  rgb
+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
+ *
+ * Revision 1.37  2000/03/16 14:02:50  rgb
+ * Fixed debug scope to enable compilation with debug off.
+ *
+ * Revision 1.36  2000/01/21 06:14:46  rgb
+ * Added debugging text to ipsec_rj_walker_delete().
+ * Set return code to negative for consistency.
+ *
+ * Revision 1.35  1999/11/23 23:05:24  rgb
+ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
+ *
+ * Revision 1.34  1999/11/18 04:13:56  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
+ *
+ * Revision 1.33  1999/11/17 15:53:39  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.32  1999/10/26 13:58:33  rgb
+ * Put spinlock flags variable declaration outside the debug compiler
+ * directive to enable compilation with debug shut off.
+ *
+ * Revision 1.31  1999/10/15 22:13:29  rgb
+ * Clean out cruft.
+ * Align /proc/net/ipsec_eroute output for easier readability.
+ * Fix double linefeed in radij debug output.
+ * Fix double locking bug that locks up 2.0.36 but not 2.0.38.
+ *
+ * Revision 1.30  1999/10/08 18:37:33  rgb
+ * Fix end-of-line spacing to sate whining PHMs.
+ *
+ * Revision 1.29  1999/10/03 18:52:45  rgb
+ * Spinlock support for 2.0.xx.
+ * Dumb return code spin_unlock fix.
+ *
+ * Revision 1.28  1999/10/01 16:22:24  rgb
+ * Switch from assignment init. to functional init. of spinlocks.
+ *
+ * Revision 1.27  1999/10/01 15:44:53  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.26  1999/10/01 00:01:23  rgb
+ * Added eroute structure locking.
+ *
+ * Revision 1.25  1999/06/10 16:07:30  rgb
+ * Silence delete eroute on no debug.
+ *
+ * Revision 1.24  1999/05/09 03:25:36  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.23  1999/05/05 22:02:31  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.22  1999/04/29 15:17:23  rgb
+ * Add return values to init and cleanup functions.
+ * Add sanity checking for null pointer arguments.
+ *
+ * Revision 1.21  1999/04/11 00:28:58  henry
+ * GPL boilerplate
+ *
+ * Revision 1.20  1999/04/06 04:54:26  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.19  1999/02/17 16:50:35  rgb
+ * Clean out unused cruft.
+ * Consolidate for space and speed efficiency.
+ * Convert DEBUG_IPSEC to KLIPS_PRINT
+ *
+ * Revision 1.18  1999/01/22 06:22:06  rgb
+ * Cruft clean-out.
+ * 64-bit clean-up.
+ *
+ * Revision 1.17  1998/12/02 03:09:39  rgb
+ * Clean up debug printing conditionals to compile with debugging off.
+ *
+ * Revision 1.16  1998/12/01 13:49:39  rgb
+ * Wrap version info printing in debug switches.
+ *
+ * Revision 1.15  1998/11/30 13:22:54  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.14  1998/10/31 06:48:17  rgb
+ * Fixed up comments in #endif directives.
+ *
+ * Revision 1.13  1998/10/27 13:48:09  rgb
+ * Cleaned up /proc/net/ipsec_* filesystem for easy parsing by scripts.
+ * Fixed less(1) truncated output bug.
+ * Code clean-up.
+ *
+ * Revision 1.12  1998/10/25 02:41:36  rgb
+ * Change return type on ipsec_breakroute and ipsec_makeroute and add an
+ * argument to be able to transmit more infomation about errors.
+ * Fix cut-and-paste debug statement identifier.
+ *
+ * Revision 1.11  1998/10/22 06:45:39  rgb
+ * Cleaned up cruft.
+ * Convert to use satoa for printk.
+ *
+ * Revision 1.10  1998/10/19 14:44:28  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.9  1998/10/09 04:30:52  rgb
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ * Deleted old commented out cruft.
+ *
+ * Revision 1.8  1998/08/06 17:24:23  rgb
+ * Fix addrtoa return code bug from stale manpage advice preventing packets
+ * from being erouted.
+ *
+ * Revision 1.7  1998/08/06 07:44:59  rgb
+ * Fixed /proc/net/ipsec_eroute subnettoa and addrtoa return value bug that
+ * ended up in nothing being printed.
+ *
+ * Revision 1.6  1998/08/05 22:16:41  rgb
+ * Cleanup to prevent cosmetic errors (ie. debug output) from being fatal.
+ *
+ * Revision 1.5  1998/07/29 20:38:44  rgb
+ * Debug and fix subnettoa and addrtoa output.
+ *
+ * Revision 1.4  1998/07/28 00:02:39  rgb
+ * Converting to exclusive use of addrtoa.
+ * Fix eroute delete.
+ *
+ * Revision 1.3  1998/07/14 18:21:26  rgb
+ * Add function to clear the eroute table.
+ *
+ * Revision 1.2  1998/06/23 02:59:14  rgb
+ * Added debugging output to eroute add/delete routines.
+ *
+ * Revision 1.9  1998/06/18 21:29:06  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid kernel
+ * build scripts happier in presence of symbolic links
+ *
+ * Revision 1.8  1998/06/05 02:32:26  rgb
+ * Fix spi ntoh kernel debug output.
+ *
+ * Revision 1.7  1998/05/25 20:30:37  rgb
+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
+ *
+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
+ * add ipsec_rj_walker_delete.
+ *
+ * Revision 1.6  1998/05/21 13:08:57  rgb
+ * Rewrote procinfo subroutines to avoid *bad things* when more that 3k of
+ * information is available for printout.
+ *
+ * Revision 1.5  1998/05/18 21:35:55  rgb
+ * Clean up output for numerical consistency and readability.  Zero freed
+ * eroute memory.
+ *
+ * Revision 1.4  1998/04/21 21:28:58  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.3  1998/04/14 17:30:39  rgb
+ * Fix up compiling errors for radij tree memory reclamation.
+ *
+ * Revision 1.2  1998/04/12 22:03:23  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:06:10  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_radij.h linux-patched/net/ipsec/ipsec_radij.h
--- linux/net/ipsec/ipsec_radij.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_radij.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,163 @@
+/*
+ * @(#) Definitions relevant to the IPSEC <> radij tree interfacing
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#ifndef _IPSEC_RADIJ_H
+
+#include <freeswan.h>
+
+int ipsec_walk(char *);
+
+int ipsec_rj_walker_procprint(struct radij_node *, void *);
+int ipsec_rj_walker_delete(struct radij_node *, void *);
+
+struct wsbuf
+{
+	char *buffer;
+	int length;
+	off_t offset;
+	int len;
+	int prev_len;
+	off_t begin;
+	off_t pos;
+};
+
+extern struct radij_node_head *rnh;
+extern spinlock_t eroute_lock;
+
+struct eroute * ipsec_findroute(struct sockaddr_encap *);
+
+#define O1(x) (int)(((x)>>24)&0xff)
+#define O2(x) (int)(((x)>>16)&0xff)
+#define O3(x) (int)(((x)>>8)&0xff)
+#define O4(x) (int)(((x))&0xff)
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_radij;
+void rj_dumptrees(void);
+
+#define DB_RJ_DUMPTREES	0x0001
+#define DB_RJ_FINDROUTE 0x0002
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#define _IPSEC_RADIJ_H
+#endif
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.17  2001/11/26 09:23:49  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.16.2.1  2001/09/25 02:21:17  mcr
+ * 	ipsec_proto.h created to keep prototypes rather than deal with
+ * 	cyclic dependancies of structures and prototypes in .h files.
+ *
+ * Revision 1.16  2001/09/15 16:24:04  rgb
+ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
+ *
+ * Revision 1.15  2001/09/14 16:58:37  rgb
+ * Added support for storing the first and last packets through a HOLD.
+ *
+ * Revision 1.14  2001/09/08 21:13:32  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.13  2001/06/14 19:35:09  rgb
+ * Update copyright date.
+ *
+ * Revision 1.12  2001/05/27 06:12:11  rgb
+ * Added structures for pid, packet count and last access time to eroute.
+ * Added packet count to beginning of /proc/net/ipsec_eroute.
+ *
+ * Revision 1.11  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.10  1999/11/17 15:53:39  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.9  1999/10/01 00:01:23  rgb
+ * Added eroute structure locking.
+ *
+ * Revision 1.8  1999/04/11 00:28:59  henry
+ * GPL boilerplate
+ *
+ * Revision 1.7  1999/04/06 04:54:26  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.6  1999/01/22 06:23:26  rgb
+ * Cruft clean-out.
+ *
+ * Revision 1.5  1998/10/25 02:42:08  rgb
+ * Change return type on ipsec_breakroute and ipsec_makeroute and add an
+ * argument to be able to transmit more infomation about errors.
+ *
+ * Revision 1.4  1998/10/19 14:44:29  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.3  1998/07/28 00:03:31  rgb
+ * Comment out temporary inet_nto4u() kluge.
+ *
+ * Revision 1.2  1998/07/14 18:22:00  rgb
+ * Add function to clear the eroute table.
+ *
+ * Revision 1.1  1998/06/18 21:27:49  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.5  1998/05/25 20:30:38  rgb
+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
+ *
+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
+ * add ipsec_rj_walker_delete.
+ *
+ * Revision 1.4  1998/05/21 13:02:56  rgb
+ * Imported definitions from ipsec_radij.c and radij.c to support /proc 3k
+ * limit fix.
+ *
+ * Revision 1.3  1998/04/21 21:29:09  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/14 17:30:39  rgb
+ * Fix up compiling errors for radij tree memory reclamation.
+ *
+ * Revision 1.1  1998/04/09 03:06:10  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_rcv.c linux-patched/net/ipsec/ipsec_rcv.c
--- linux/net/ipsec/ipsec_rcv.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_rcv.c	Fri Jul  4 20:07:34 2003
@@ -0,0 +1,2595 @@
+/*
+ * receive code
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+char ipsec_rcv_c_version[] = "RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/kernel.h> /* printk() */
+
+#define IPSEC_KLIPS1_COMPAT 1
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+#ifdef SPINLOCK
+# ifdef SPINLOCK_23
+#  include <linux/spinlock.h> /* *lock* */
+# else /* SPINLOCK_23 */
+#  include <asm/spinlock.h> /* *lock* */
+# endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+# define proto_priv cb
+#endif /* NET21 */
+#include <asm/checksum.h>
+#include <net/ip.h>
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_sa.h"
+
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_tunnel.h"
+#include "ipsec_rcv.h"
+#if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH)
+# include "ipsec_ah.h"
+#endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */
+#ifdef CONFIG_IPSEC_ESP
+# include "ipsec_esp.h"
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_IPCOMP
+# include "ipcomp.h"
+#endif /* CONFIG_IPSEC_COMP */
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_proto.h"
+
+#include "ipsec_alg.h"
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+#include <linux/udp.h>
+#endif
+
+#ifdef CONFIG_IPSEC_DEBUG
+int debug_ah = 0;
+int debug_esp = 0;
+int debug_rcv = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+int sysctl_ipsec_inbound_policy_check = 1;
+
+#if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH)
+__u32 zeroes[AH_AMAX];
+#endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */
+
+/*
+ * Check-replay-window routine, adapted from the original 
+ * by J. Hughes, from draft-ietf-ipsec-esp-des-md5-03.txt
+ *
+ *  This is a routine that implements a 64 packet window. This is intend-
+ *  ed on being an implementation sample.
+ */
+
+DEBUG_NO_STATIC int
+ipsec_checkreplaywindow(struct ipsec_sa*tdbp, __u32 seq)
+{
+	__u32 diff;
+	
+	if (tdbp->tdb_replaywin == 0)	/* replay shut off */
+		return 1;
+	if (seq == 0) 
+		return 0;		/* first == 0 or wrapped */
+
+	/* new larger sequence number */
+	if (seq > tdbp->tdb_replaywin_lastseq) {
+		return 1;		/* larger is good */
+	}
+	diff = tdbp->tdb_replaywin_lastseq - seq;
+
+	/* too old or wrapped */ /* if wrapped, kill off SA? */
+	if (diff >= tdbp->tdb_replaywin) {
+		return 0;
+	}
+	/* this packet already seen */
+	if (tdbp->tdb_replaywin_bitmap & (1 << diff))
+		return 0;
+	return 1;			/* out of order but good */
+}
+
+DEBUG_NO_STATIC int
+ipsec_updatereplaywindow(struct ipsec_sa*tdbp, __u32 seq)
+{
+	__u32 diff;
+	
+	if (tdbp->tdb_replaywin == 0)	/* replay shut off */
+		return 1;
+	if (seq == 0) 
+		return 0;		/* first == 0 or wrapped */
+
+	/* new larger sequence number */
+	if (seq > tdbp->tdb_replaywin_lastseq) {
+		diff = seq - tdbp->tdb_replaywin_lastseq;
+
+		/* In win, set bit for this pkt */
+		if (diff < tdbp->tdb_replaywin)
+			tdbp->tdb_replaywin_bitmap =
+				(tdbp->tdb_replaywin_bitmap << diff) | 1;
+		else
+			/* This packet has way larger seq num */
+			tdbp->tdb_replaywin_bitmap = 1;
+
+		if(seq - tdbp->tdb_replaywin_lastseq - 1 > tdbp->tdb_replaywin_maxdiff) {
+			tdbp->tdb_replaywin_maxdiff = seq - tdbp->tdb_replaywin_lastseq - 1;
+		}
+		tdbp->tdb_replaywin_lastseq = seq;
+		return 1;		/* larger is good */
+	}
+	diff = tdbp->tdb_replaywin_lastseq - seq;
+
+	/* too old or wrapped */ /* if wrapped, kill off SA? */
+	if (diff >= tdbp->tdb_replaywin) {
+/*
+		if(seq < 0.25*max && tdbp->tdb_replaywin_lastseq > 0.75*max) {
+			deltdbchain(tdbp);
+		}
+*/	
+		return 0;
+	}
+	/* this packet already seen */
+	if (tdbp->tdb_replaywin_bitmap & (1 << diff))
+		return 0;
+	tdbp->tdb_replaywin_bitmap |= (1 << diff);	/* mark as seen */
+	return 1;			/* out of order but good */
+}
+
+int
+#ifdef PROTO_HANDLER_SINGLE_PARM
+ipsec_rcv(struct sk_buff *skb)
+#else /* PROTO_HANDLER_SINGLE_PARM */
+#ifdef NET_21
+ipsec_rcv(struct sk_buff *skb, unsigned short xlen)
+#else /* NET_21 */
+ipsec_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, 
+		__u32 daddr_unused, unsigned short xlen, __u32 saddr,
+                                   int redo, struct inet_protocol *protocol)
+#endif /* NET_21 */
+#endif /* PROTO_HANDLER_SINGLE_PARM */
+{
+#ifdef NET_21
+#ifdef CONFIG_IPSEC_DEBUG
+	struct device *dev = skb->dev;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* NET_21 */
+	unsigned char protoc;
+	struct iphdr *ipp;
+	int authlen = 0;
+#ifdef CONFIG_IPSEC_ESP
+	struct esp *espp = NULL;
+	int esphlen = 0;
+#ifdef CONFIG_IPSEC_ENC_3DES
+	__u32 iv[ESP_IV_MAXSZ_INT];
+#endif /* !CONFIG_IPSEC_ENC_3DES */
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+	struct ah *ahp = NULL;
+	int ahhlen = 0;
+#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1)
+	struct iphdr ipo;
+#endif
+#endif /* CONFIG_IPSEC_AH */
+	unsigned char *authenticator = NULL;
+	union {
+		MD5_CTX		md5;
+		SHA1_CTX	sha1;
+	} tctx;
+	__u8 hash[AH_AMAX];
+#if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH)
+#endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */
+#ifdef CONFIG_IPSEC_IPCOMP
+	struct ipcomphdr*compp = NULL;
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+	int hard_header_len;
+	int iphlen;
+	unsigned char *dat;
+	struct ipsec_sa *tdbp = NULL;
+	struct sa_id said;
+	struct net_device_stats *stats = NULL;		/* This device's statistics */
+	struct device *ipsecdev = NULL, *prvdev;
+	struct ipsecpriv *prv;
+	char name[9];
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	char ipaddr_txt[ADDRTOA_BUF];
+	int i;
+	struct in_addr ipaddr;
+	__u8 next_header = 0;
+	__u8 proto;
+	
+#ifdef CONFIG_IPSEC_ESP
+	int pad = 0, padlen;
+#endif /* CONFIG_IPSEC_ESP */
+	int ilen;	/* content to be decrypted/authenticated */
+	int len;	/* packet length */
+	int replay = 0;	/* replay value in AH or ESP packet */
+	__u8 *idat;	/* pointer to content to be decrypted/authenticated */
+	struct ipsec_sa* tdbprev = NULL;	/* previous SA from outside of packet */
+	struct ipsec_sa* tdbnext = NULL;	/* next SA towards inside of packet */
+#ifdef INBOUND_POLICY_CHECK_eroute
+	struct sockaddr_encap matcher;	/* eroute search key */
+	struct eroute *er;
+	struct ipsec_sa* policy_tdb = NULL;
+	struct sa_id policy_said;
+	struct sockaddr_encap policy_eaddr;
+	struct sockaddr_encap policy_emask;
+#endif /* INBOUND_POLICY_CHECK_eroute */
+#ifdef CONFIG_IPSEC_ALG
+	struct ipsec_alg_enc *ixt_e=NULL;
+	struct ipsec_alg_auth *ixt_a=NULL;
+#endif /* CONFIG_IPSEC_ALG */
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	__u16 natt_len = 0, natt_sport = 0, natt_dport = 0;
+	__u8 natt_type = 0;
+#endif
+
+	/* Don't unlink in the middle of a turnaround */
+	MOD_INC_USE_COUNT;
+	
+	if (skb == NULL) {
+		KLIPS_PRINT(debug_rcv, 
+			    "klips_debug:ipsec_rcv: "
+			    "NULL skb passed in.\n");
+		goto rcvleave;
+	}
+		
+	if (skb->data == NULL) {
+		KLIPS_PRINT(debug_rcv,
+			    "klips_debug:ipsec_rcv: "
+			    "NULL skb->data passed in, packet is bogus, dropping.\n");
+		goto rcvleave;
+	}
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	if (skb->sk && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_UDP) {
+		/**
+		 * Packet comes from udp_queue_rcv_skb so it is already defrag,
+		 * checksum verified, ... (ie safe to use)
+		 *
+		 * If the packet is not for us, return -1 and udp_queue_rcv_skb
+		 * will continue to handle it (do not kfree skb !!).
+		 */
+		struct udp_opt *tp =  &(skb->sk->tp_pinfo.af_udp);
+		struct iphdr *ip = (struct iphdr *)skb->nh.iph;
+		struct udphdr *udp = (struct udphdr *)((__u32 *)ip+ip->ihl);
+		__u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr);
+		__u32 *udpdata32 = (__u32 *)udpdata;
+
+		natt_sport = ntohs(udp->source);
+		natt_dport = ntohs(udp->dest);
+
+		KLIPS_PRINT(debug_rcv,
+		    "klips_debug:ipsec_rcv: "
+		    "suspected ESPinUDP packet (NAT-Traversal) [%d].\n",
+			tp->esp_in_udp);
+		KLIPS_IP_PRINT(debug_rcv, ip);
+
+		if (udpdata < skb->tail) {
+			unsigned int len = skb->tail - udpdata;
+			if ((len==1) && (udpdata[0]==0xff)) {
+				KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+					/* not IPv6 compliant message */
+				    "NAT-keepalive from %d.%d.%d.%d.\n", NIPQUAD(ip->saddr));
+				goto rcvleave;
+			}
+			else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_IKE) &&
+				(len > (2*sizeof(__u32) + sizeof(struct esp))) &&
+				(udpdata32[0]==0) && (udpdata32[1]==0) ) {
+				/* ESP Packet with Non-IKE header */
+				KLIPS_PRINT(debug_rcv, 
+					"klips_debug:ipsec_rcv: "
+					"ESPinUDP pkt with Non-IKE - spi=0x%x\n",
+					udpdata32[2]);
+				natt_type = ESPINUDP_WITH_NON_IKE;
+				natt_len = sizeof(struct udphdr)+(2*sizeof(__u32));
+			}
+			else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP) &&
+				(len > sizeof(struct esp)) &&
+				(udpdata32[0]!=0) ) {
+				/* ESP Packet without Non-ESP header */
+				natt_type = ESPINUDP_WITH_NON_ESP;
+				natt_len = sizeof(struct udphdr);
+				KLIPS_PRINT(debug_rcv, 
+					"klips_debug:ipsec_rcv: "
+                                        "ESPinUDP pkt without Non-ESP - spi=0x%x\n",
+					udpdata32[0]);
+			}
+			else {
+				KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+					"IKE packet - not handled here\n");
+				MOD_DEC_USE_COUNT;
+				return -1;
+			}
+		}
+		else {
+			MOD_DEC_USE_COUNT;
+			return -1;
+		}
+	}
+#endif
+		
+#ifdef IPH_is_SKB_PULLED
+	/* In Linux 2.4.4, the IP header has been skb_pull()ed before the
+	   packet is passed to us. So we'll skb_push() to get back to it. */
+	if (skb->data == skb->h.raw) {
+		skb_push(skb, skb->h.raw - skb->nh.raw);
+	}
+#endif /* IPH_is_SKB_PULLED */
+
+	ipp = (struct iphdr *)skb->data;
+	iphlen = ipp->ihl << 2;
+	/* dev->hard_header_len is unreliable and should not be used */
+	hard_header_len = skb->mac.raw ? (skb->data - skb->mac.raw) : 0;
+	if((hard_header_len < 0) || (hard_header_len > skb_headroom(skb)))
+		hard_header_len = 0;
+
+#ifdef NET_21
+	/* if skb was cloned (most likely due to a packet sniffer such as
+	   tcpdump being momentarily attached to the interface), make
+	   a copy of our own to modify */
+	if(skb_cloned(skb)) {
+		/* include any mac header while copying.. */
+		if(skb_headroom(skb) < hard_header_len) {
+			printk(KERN_WARNING "klips_error:ipsec_rcv: "
+			       "tried to skb_push hhlen=%d, %d available.  This should never happen, please report.\n",
+			       hard_header_len,
+			       skb_headroom(skb));
+			goto rcvleave;
+		}
+		skb_push(skb, hard_header_len);
+		if
+#ifdef SKB_COW_NEW
+               (skb_cow(skb, skb_headroom(skb)) != 0)
+#else /* SKB_COW_NEW */
+               ((skb = skb_cow(skb, skb_headroom(skb))) == NULL)
+#endif /* SKB_COW_NEW */
+		{
+			goto rcvleave;
+		}
+		if(skb->len < hard_header_len) {
+			printk(KERN_WARNING "klips_error:ipsec_rcv: "
+			       "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",
+			       hard_header_len,
+			       skb->len);
+			goto rcvleave;
+		}
+		skb_pull(skb, hard_header_len);
+	}
+	
+#endif /* NET_21 */
+		
+#if IP_FRAGMENT_LINEARIZE
+	/* In Linux 2.4.4, we may have to reassemble fragments. They are
+	   not assembled automatically to save TCP from having to copy
+	   twice.
+	*/
+      if (skb_is_nonlinear(skb)) {
+	if (skb_linearize(skb, GFP_ATOMIC) != 0) {
+	  goto rcvleave;
+	}
+      }
+      ipp = (struct iphdr *)skb->nh.iph;
+      iphlen = ipp->ihl << 2;
+#endif
+	
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	if (natt_len) {
+		/**
+		 * Now, we are sure packet is ESPinUDP. Remove natt_len bytes from
+		 * packet and modify protocol to ESP.
+		 */
+		if (((unsigned char *)skb->data > (unsigned char *)skb->nh.iph) &&
+			((unsigned char *)skb->nh.iph > (unsigned char *)skb->head)) {
+			unsigned int _len = (unsigned char *)skb->data -
+				(unsigned char *)skb->nh.iph;
+			KLIPS_PRINT(debug_rcv,
+				"klips_debug:ipsec_rcv: adjusting skb: skb_push(%u)\n",
+				_len);
+			skb_push(skb, _len);
+		}
+		KLIPS_PRINT(debug_rcv,
+		    "klips_debug:ipsec_rcv: "
+			"removing %d bytes from ESPinUDP packet\n", natt_len);
+		ipp = (struct iphdr *)skb->data;
+		iphlen = ipp->ihl << 2;
+		ipp->tot_len = htons(ntohs(ipp->tot_len) - natt_len);
+		if (skb->len < iphlen + natt_len) {
+			printk(KERN_WARNING
+		       "klips_error:ipsec_rcv: "
+		       "ESPinUDP packet is too small (%d < %d+%d). "
+			   "This should never happen, please report.\n",
+		       (int)(skb->len), iphlen, natt_len);
+			goto rcvleave;
+		}
+		memmove(skb->data + natt_len, skb->data, iphlen);
+		skb_pull(skb, natt_len);
+
+		/* update nh.iph */
+		ipp = skb->nh.iph = (struct iphdr *)skb->data;
+
+		/* modify protocol */
+		ipp->protocol = IPPROTO_ESP;
+
+		skb->sk = NULL;
+
+		KLIPS_IP_PRINT(debug_rcv, skb->nh.iph);
+	}
+#endif
+
+	KLIPS_PRINT(debug_rcv, 
+		    "klips_debug:ipsec_rcv: "
+		    "<<< Info -- ");
+	KLIPS_PRINTMORE(debug_rcv && skb->dev, "skb->dev=%s ",
+		    skb->dev->name ? skb->dev->name : "NULL");
+	KLIPS_PRINTMORE(debug_rcv && dev, "dev=%s ",
+		    dev->name ? dev->name : "NULL");
+	KLIPS_PRINTMORE(debug_rcv, "\n");
+
+	KLIPS_PRINT(debug_rcv && !(skb->dev && dev && (skb->dev == dev)),
+		    "klips_debug:ipsec_rcv: "
+		    "Informational -- **if this happens, find out why** skb->dev:%s is not equal to dev:%s\n",
+		    skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL",
+		    dev ? (dev->name ? dev->name : "NULL") : "NULL");
+
+	protoc = ipp->protocol;
+#ifndef NET_21
+	if((!protocol) || (protocol->protocol != protoc)) {
+		KLIPS_PRINT(debug_rcv & DB_RX_TDB,
+			    "klips_debug:ipsec_rcv: "
+			    "protocol arg is NULL or unequal to the packet contents, this is odd, using value in packet.\n");
+	}
+#endif /* !NET_21 */
+
+	if( (protoc != IPPROTO_AH) &&
+#ifdef CONFIG_IPSEC_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER
+	    (protoc != IPPROTO_COMP) &&
+#endif /* CONFIG_IPSEC_IPCOMP */
+	    (protoc != IPPROTO_ESP) ) {
+		KLIPS_PRINT(debug_rcv & DB_RX_TDB,
+			    "klips_debug:ipsec_rcv: Why the hell is someone "
+			    "passing me a non-ipsec protocol = %d packet? -- dropped.\n",
+			    protoc);
+		goto rcvleave;
+	}
+
+	if(skb->dev) {
+		for(i = 0; i < IPSEC_NUM_IF; i++) {
+			sprintf(name, "ipsec%d", i);
+			if(!strcmp(name, skb->dev->name)) {
+				prv = (struct ipsecpriv *)(skb->dev->priv);
+				if(prv) {
+					stats = (struct net_device_stats *) &(prv->mystats);
+				}
+				ipsecdev = skb->dev;
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "Info -- pkt already proc'ed a group of ipsec headers, processing next group of ipsec headers.\n");
+				break;
+			}
+			if((ipsecdev = ipsec_dev_get(name)) == NULL) {
+				KLIPS_PRINT(debug_rcv,
+					    "klips_error:ipsec_rcv: "
+					    "device %s does not exist\n",
+					    name);
+			}
+			prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL;
+			prvdev = prv ? (struct device *)(prv->dev) : NULL;
+			
+#if 0
+			KLIPS_PRINT(debug_rcv && prvdev, 
+				    "klips_debug:ipsec_rcv: "
+				    "physical device for device %s is %s\n",
+				    name,
+				    prvdev->name);
+#endif
+			if(prvdev && skb->dev &&
+			   !strcmp(prvdev->name, skb->dev->name)) {
+				stats = prv ? ((struct net_device_stats *) &(prv->mystats)) : NULL;
+				skb->dev = ipsecdev;
+				KLIPS_PRINT(debug_rcv && prvdev, 
+					    "klips_debug:ipsec_rcv: "
+					    "assigning packet ownership to virtual device %s from physical device %s.\n",
+					    name, prvdev->name);
+				if(stats) {
+					stats->rx_packets++;
+				}
+				break;
+			}
+		}
+	} else {
+		KLIPS_PRINT(debug_rcv, 
+			    "klips_debug:ipsec_rcv: "
+			    "device supplied with skb is NULL\n");
+	}
+			
+	if(!stats) {
+		ipsecdev = NULL;
+	}
+	KLIPS_PRINT((debug_rcv && !stats),
+		    "klips_error:ipsec_rcv: "
+		    "packet received from physical I/F (%s) not connected to ipsec I/F.  Cannot record stats.  May not have SA for decoding.  Is IPSEC traffic expected on this I/F?  Check routing.\n",
+		    skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL");
+
+	KLIPS_IP_PRINT(debug_rcv, ipp);
+
+	/* begin decapsulating loop here */
+	do {
+		authlen = 0;
+#ifdef CONFIG_IPSEC_ESP
+		espp = NULL;
+		esphlen = 0;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+		ahp = NULL;
+		ahhlen = 0;
+#endif /* CONFIG_IPSEC_AH */
+#ifdef CONFIG_IPSEC_IPCOMP
+		compp = NULL;
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+		len = skb->len;
+		dat = skb->data;
+		ipp = (struct iphdr *)skb->data;
+		proto = ipp->protocol;
+		ipaddr.s_addr = ipp->saddr;
+		addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));
+		
+		iphlen = ipp->ihl << 2;
+		ipp->check = 0;			/* we know the sum is good */
+		
+#ifdef CONFIG_IPSEC_ESP
+		/* XXX this will need to be 8 for IPv6 */
+		if ((proto == IPPROTO_ESP) && ((len - iphlen) % 4)) {
+			printk("klips_error:ipsec_rcv: "
+			       "got packet with content length = %d from %s -- should be on 4 octet boundary, packet dropped\n",
+			       len - iphlen,
+			       ipaddr_txt);
+			if(stats) {
+				stats->rx_errors++;
+			}
+			goto rcvleave;
+		}
+#endif /* !CONFIG_IPSEC_ESP */
+		
+		/*
+		 * Find tunnel control block and (indirectly) call the
+		 * appropriate tranform routine. The resulting sk_buf
+		 * is a valid IP packet ready to go through input processing.
+		 */
+		
+		said.dst.s_addr = ipp->daddr;
+		switch(proto) {
+#ifdef CONFIG_IPSEC_ESP
+		case IPPROTO_ESP:
+			if(skb->len < (hard_header_len + sizeof(struct iphdr) + sizeof(struct esp))) {
+				KLIPS_PRINT(debug_rcv & DB_RX_INAU,
+					    "klips_debug:ipsec_rcv: "
+					    "runt esp packet of skb->len=%d received from %s, dropped.\n",
+					    skb->len,
+					    ipaddr_txt);
+				if(stats) {
+					stats->rx_errors++;
+				}
+				goto rcvleave;
+			}
+		       
+			espp = (struct esp *)(skb->data + iphlen);
+			said.spi = espp->esp_spi;
+			break;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+		case IPPROTO_AH:
+			if((skb->len 
+			    < (hard_header_len + sizeof(struct iphdr) + sizeof(struct ah)))
+			   || (skb->len 
+			       < (hard_header_len + sizeof(struct iphdr) 
+				  + ((ahp = (struct ah *) (skb->data + iphlen))->ah_hl << 2)))) {
+				KLIPS_PRINT(debug_rcv & DB_RX_INAU,
+					    "klips_debug:ipsec_rcv: "
+					    "runt ah packet of skb->len=%d received from %s, dropped.\n",
+					    skb->len,
+					    ipaddr_txt);
+				if(stats) {
+					stats->rx_errors++;
+				}
+				goto rcvleave;
+			}
+		       
+			said.spi = ahp->ah_spi;
+			break;
+#endif /* CONFIG_IPSEC_AH */
+#ifdef CONFIG_IPSEC_IPCOMP
+		case IPPROTO_COMP:
+			if(skb->len < (hard_header_len + sizeof(struct iphdr) + sizeof(struct ipcomphdr))) {
+				KLIPS_PRINT(debug_rcv & DB_RX_INAU,
+					    "klips_debug:ipsec_rcv: "
+					    "runt comp packet of skb->len=%d received from %s, dropped.\n",
+					    skb->len,
+					    ipaddr_txt);
+				if(stats) {
+					stats->rx_errors++;
+				}
+				goto rcvleave;
+			}
+		       
+			compp = (struct ipcomphdr *)(skb->data + iphlen);
+			said.spi = htonl((__u32)ntohs(compp->ipcomp_cpi));
+			break;
+#endif /* CONFIG_IPSEC_IPCOMP */
+		default:
+			if(stats) {
+				stats->rx_errors++;
+			}
+			goto rcvleave;
+		}
+		said.proto = proto;
+		sa_len = satoa(said, 0, sa, SATOA_BUF);
+		if(sa_len == 0) {
+		  strcpy(sa, "(error)");
+		}
+		
+#ifdef CONFIG_IPSEC_AH
+		if(proto == IPPROTO_AH) {
+			ahhlen = (ahp->ah_hl << 2) +
+				((caddr_t)&(ahp->ah_rpl) - (caddr_t)ahp);
+			next_header = ahp->ah_nh;
+			if (ahhlen != sizeof(struct ah)) {
+				KLIPS_PRINT(debug_rcv & DB_RX_INAU,
+					    "klips_debug:ipsec_rcv: "
+					    "bad authenticator length %d, expected %d from %s.\n",
+					    ahhlen - ((caddr_t)(ahp->ah_data) - (caddr_t)ahp),
+					    AHHMAC_HASHLEN,
+					    ipaddr_txt);
+				if(stats) {
+					stats->rx_errors++;
+				}
+				goto rcvleave;
+			}
+			
+		}
+#endif /* CONFIG_IPSEC_AH */
+		
+		/*
+		  The spinlock is to prevent any other process from
+		  accessing or deleting the TDB hash table or any of the
+		  TDBs while we are using and updating them.
+		  
+		  This is not optimal, but was relatively straightforward
+		  at the time.  A better way to do it has been planned for
+		  more than a year, to lock the hash table and put reference
+		  counts on each TDB instead.  This is not likely to happen
+		  in KLIPS1 unless a volunteer contributes it, but will be
+		  designed into KLIPS2.
+		*/
+		if(tdbprev == NULL) {
+			spin_lock(&tdb_lock);
+		}
+		
+#ifdef CONFIG_IPSEC_IPCOMP
+		if (proto == IPPROTO_COMP) {
+			unsigned int flags = 0;
+			if (tdbp == NULL) {
+				spin_unlock(&tdb_lock);
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "Incoming packet with outer IPCOMP header SA:%s: not yet supported by KLIPS, dropped\n",
+					    sa_len ? sa : " (error)");
+				if(stats) {
+					stats->rx_dropped++;
+				}
+
+				goto rcvleave;
+			}
+
+			tdbprev = tdbp;
+			tdbp = tdbnext;
+
+			if(sysctl_ipsec_inbound_policy_check
+			   && ((tdbp == NULL)
+			       || (((ntohl(tdbp->tdb_said.spi) & 0x0000ffff)
+				    != ntohl(said.spi))
+				/* next line is a workaround for peer
+				   non-compliance with rfc2393 */
+				   && (tdbp->tdb_encalg != ntohl(said.spi)) 
+				       ))) {
+				char sa2[SATOA_BUF];
+				size_t sa_len2 = 0;
+
+				if(tdbp) {
+					sa_len2 = satoa(tdbp->tdb_said, 0, sa2, SATOA_BUF);
+				}
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n",
+					    sa_len ? sa : " (error)",
+					    tdbp ? (sa_len2 ? sa2 : " (error)") : "NULL",
+					    ntohs(compp->ipcomp_cpi),
+					    (__u32)ntohl(said.spi),
+					    tdbp ? (__u32)ntohl((tdbp->tdb_said.spi)) : 0,
+					    tdbp ? (__u16)(ntohl(tdbp->tdb_said.spi) & 0x0000ffff) : 0);
+				spin_unlock(&tdb_lock);
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+
+			if (tdbp) {
+				tdbp->tdb_comp_ratio_cbytes += ntohs(ipp->tot_len);
+				tdbnext = tdbp->tdb_inext;
+			}
+			next_header = compp->ipcomp_nh;
+
+			skb = skb_decompress(skb, tdbp, &flags);
+			if (!skb || flags) {
+				spin_unlock(&tdb_lock);
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "skb_decompress() returned error flags=%x, dropped.\n",
+					    flags);
+				if (stats) {
+				    if (flags)
+					stats->rx_errors++;
+				    else
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+#ifdef NET_21
+			ipp = skb->nh.iph;
+#else /* NET_21 */
+			ipp = skb->ip_hdr;
+#endif /* NET_21 */
+
+			if (tdbp) {
+				tdbp->tdb_comp_ratio_dbytes += ntohs(ipp->tot_len);
+			}
+
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n",
+				    sa_len ? sa : " (error)",
+				    (__u32)ntohl(said.spi),
+				    tdbp ? (__u32)ntohl((tdbp->tdb_said.spi)) : 0,
+				    tdbp ? (__u16)(ntohl(tdbp->tdb_said.spi) & 0x0000ffff) : 0,
+				    next_header);
+			KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);
+
+			continue;
+			/* Skip rest of stuff and decapsulate next inner
+			   packet, if any */
+		}
+#endif /* CONFIG_IPSEC_IPCOMP */
+		
+		tdbp = ipsec_sa_getbyid(&said);
+		if (tdbp == NULL) {
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "no Tunnel Descriptor Block for SA:%s: incoming packet with no SA dropped\n",
+				    sa_len ? sa : " (error)");
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+		if ((natt_type) &&
+			( (ipp->saddr != (((struct sockaddr_in*)(tdbp->tdb_addr_s))->sin_addr.s_addr)) ||
+			  (natt_sport != tdbp->ips_natt_sport)
+			)) {
+			struct sockaddr sipaddr;
+			/** Advertise NAT-T addr change to pluto **/
+			sipaddr.sa_family = AF_INET;
+			((struct sockaddr_in*)&sipaddr)->sin_addr.s_addr = ipp->saddr;
+			((struct sockaddr_in*)&sipaddr)->sin_port = htons(natt_sport);
+			pfkey_nat_t_new_mapping(tdbp, &sipaddr, natt_sport);
+			/**
+			 * Then allow or block packet depending on
+			 * sysctl_ipsec_inbound_policy_check.
+			 *
+			 * In all cases, pluto will update SA if new mapping is
+			 * accepted.
+			 */
+			if (sysctl_ipsec_inbound_policy_check) {
+				spin_unlock(&tdb_lock);
+				ipaddr.s_addr = ipp->saddr;
+				addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));
+				KLIPS_PRINT(debug_rcv,
+					"klips_debug:ipsec_rcv: "
+					"SA:%s, src=%s:%u of pkt does not agree with expected "
+					"SA source address policy (pluto has been informed).\n",
+					sa_len ? sa : " (error)",
+					ipaddr_txt, natt_sport);
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+		}
+#endif
+
+		if(sysctl_ipsec_inbound_policy_check) {
+			if(ipp->saddr != ((struct sockaddr_in*)(tdbp->tdb_addr_s))->sin_addr.s_addr) {
+				spin_unlock(&tdb_lock);
+				ipaddr.s_addr = ipp->saddr;
+				addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n",
+					    sa_len ? sa : " (error)",
+					    ipaddr_txt);
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+			ipaddr.s_addr = ipp->saddr;
+			addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n",
+				    sa_len ? sa : " (error)",
+				    ipaddr_txt);
+			if(tdbnext) {
+				if(tdbnext != tdbp) {
+					spin_unlock(&tdb_lock);
+					KLIPS_PRINT(debug_rcv,
+						    "klips_debug:ipsec_rcv: "
+						    "unexpected SA:%s: does not agree with tdb->inext policy, dropped\n",
+						    sa_len ? sa : " (error)");
+					if(stats) {
+						stats->rx_dropped++;
+					}
+					goto rcvleave;
+				}
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s grouping from previous SA is OK.\n",
+					    sa_len ? sa : " (error)");
+			} else {
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s First SA in group.\n",
+					    sa_len ? sa : " (error)");
+			}
+			
+			if(tdbp->tdb_onext) {
+				if(tdbprev != tdbp->tdb_onext) {
+					spin_unlock(&tdb_lock);
+					KLIPS_PRINT(debug_rcv,
+						    "klips_debug:ipsec_rcv: "
+						    "unexpected SA:%s: does not agree with tdb->onext policy, dropped.\n",
+						    sa_len ? sa : " (error)");
+					if(stats) {
+						stats->rx_dropped++;
+					}
+					goto rcvleave;
+				} else {
+					KLIPS_PRINT(debug_rcv,
+						    "klips_debug:ipsec_rcv: "
+						    "SA:%s grouping to previous SA is OK.\n",
+						    sa_len ? sa : " (error)");
+				}
+			} else {
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s No previous backlink in group.\n",
+					    sa_len ? sa : " (error)");
+			}
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+			KLIPS_PRINT(debug_rcv,
+				"klips_debug:ipsec_rcv: "
+				"natt_type=%u tdbp->ips_natt_type=%u : %s\n",
+				natt_type, tdbp->ips_natt_type,
+				(natt_type==tdbp->ips_natt_type)?"ok":"bad");
+			if (natt_type != tdbp->ips_natt_type) {
+				spin_unlock(&tdb_lock);
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s does not agree with expected NAT-T policy.\n",
+					    sa_len ? sa : " (error)");
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+#endif
+		}
+		
+		/* If it is in larval state, drop the packet, we cannot process yet. */
+		if(tdbp->tdb_state == SADB_SASTATE_LARVAL) {
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "TDB in larval state, cannot be used yet, dropping packet.\n");
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+		
+		if(tdbp->tdb_state == SADB_SASTATE_DEAD) {
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "TDB in dead state, cannot be used any more, dropping packet.\n");
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+		
+		if(ipsec_lifetime_check(&tdbp->ips_life.ipl_bytes,   "bytes", sa,
+					ipsec_life_countbased, ipsec_incoming, tdbp) == ipsec_life_harddied ||
+		   ipsec_lifetime_check(&tdbp->ips_life.ipl_addtime, "addtime",sa,
+					ipsec_life_timebased,  ipsec_incoming, tdbp) == ipsec_life_harddied ||
+		   ipsec_lifetime_check(&tdbp->ips_life.ipl_addtime, "usetime",sa,
+					ipsec_life_timebased,  ipsec_incoming, tdbp) == ipsec_life_harddied ||
+		   ipsec_lifetime_check(&tdbp->ips_life.ipl_packets, "packets",sa, 
+					ipsec_life_countbased, ipsec_incoming, tdbp) == ipsec_life_harddied) {
+			ipsec_sa_delchain(tdbp);
+			spin_unlock(&tdb_lock);
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+
+		/* authenticate, if required */
+		idat = dat + iphlen;
+#ifdef CONFIG_IPSEC_ALG
+		if ((ixt_a=IPSEC_ALG_SA_ESP_AUTH(tdbp))) {
+			authlen = AHHMAC_HASHLEN;
+			KLIPS_PRINT(debug_rcv,
+					"klips_debug:ipsec_rcv: "
+					"authalg=%d authlen=%d\n",
+					tdbp->tdb_authalg, authlen);
+		} else
+#endif /* CONFIG_IPSEC_ALG */
+		switch(tdbp->tdb_authalg) {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+		case AH_MD5:
+			authlen = AHHMAC_HASHLEN;
+			break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+		case AH_SHA:
+			authlen = AHHMAC_HASHLEN;
+			break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+		case AH_NONE:
+			authlen = 0;
+			break;
+		default:
+			tdbp->tdb_alg_errs += 1;
+			spin_unlock(&tdb_lock);
+			if(stats) {
+				stats->rx_errors++;
+			}
+			goto rcvleave;
+		}
+		ilen = len - iphlen - authlen;
+		if(ilen <= 0) {
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "runt AH packet with no data, dropping.\n");
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+		
+#ifdef CONFIG_IPSEC_ESP
+		KLIPS_PRINT(proto == IPPROTO_ESP && debug_rcv, 
+			    "klips_debug:ipsec_rcv: "
+			    "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n",
+			    ipaddr_txt,
+			    (__u32)ntohl(espp->esp_rpl),
+			    (__u32)ntohl(*((__u32 *)(espp->esp_iv)    )),
+			    (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)),
+			    len,
+			    ilen,
+			    sa_len ? sa : " (error)");
+#endif /* !CONFIG_IPSEC_ESP */
+		
+		switch(proto) {
+#ifdef CONFIG_IPSEC_ESP
+		case IPPROTO_ESP:
+			replay = ntohl(espp->esp_rpl);
+			authenticator = &(dat[len - authlen]);
+			break;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+		case IPPROTO_AH:
+			replay = ntohl(ahp->ah_rpl);
+			authenticator = ahp->ah_data;
+			break;
+#endif /* CONFIG_IPSEC_AH */
+		}
+
+		if (!ipsec_checkreplaywindow(tdbp, replay)) {
+			tdbp->tdb_replaywin_errs += 1;
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,
+				    "klips_debug:ipsec_rcv: "
+				    "duplicate frame from %s, packet dropped\n",
+				    ipaddr_txt);
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+		
+		/*
+		 * verify authenticator
+		 */
+		
+		KLIPS_PRINT(debug_rcv,
+			    "klips_debug:ipsec_rcv: "
+			    "encalg = %d, authalg = %d.\n",
+			    tdbp->tdb_encalg,
+			    tdbp->tdb_authalg);
+		
+#ifdef CONFIG_IPSEC_ALG
+		if (ixt_a) {
+			KLIPS_PRINT(debug_rcv,
+					"klips_debug:ipsec_rcv: "
+					"ipsec_alg hashing ... ");
+			if(proto == IPPROTO_ESP) {
+				ipsec_alg_sa_esp_hash(tdbp,
+						(caddr_t)espp, ilen,
+						hash, AHHMAC_HASHLEN);
+#ifdef CONFIG_IPSEC_AH
+#ifdef IPSEC_ALG_WHEN_AH_IS_READY
+			} else {
+				ipo = *ipp;
+				ipo.tos = 0;
+				ipo.frag_off = 0;
+				ipo.ttl = 0;
+				ipo.check = 0;
+
+				ipsec_alg_hmac_update(tdbp->tdb_key_a,
+						(caddr_t)&ipo, 
+						sizeof(struct iphdr));
+				ipsec_alg_hmac_update(tdbp->tdb_key_a,
+						(caddr_t)ahp,
+						ahhlen - AHHMAC_HASHLEN);
+				ipsec_alg_hmac_update(tdbp->tdb_key_a,
+						(caddr_t)zeroes,
+						AHHMAC_HASHLEN);
+				ipsec_alg_hmac_hash(tdbp->tdb_key_a,
+						(caddr_t)dat + iphlen + ahhlen,
+						len - iphlen - ahhlen,
+						hash, AHHMAC_HASHLEN);
+#endif
+#endif /* CONFIG_IPSEC_AH */
+			}
+		} else
+#endif /* CONFIG_IPSEC_ALG */
+		if(tdbp->tdb_authalg) {
+			switch(tdbp->tdb_authalg) {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+			case AH_MD5:
+				tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx;
+				if(proto == IPPROTO_ESP) {
+					MD5Update(&tctx.md5, (caddr_t)espp, ilen);
+#ifdef CONFIG_IPSEC_AH
+				} else {
+					ipo = *ipp;
+					ipo.tos = 0;	/* mutable RFC 2402 3.3.3.1.1.1 */
+					ipo.frag_off = 0;
+					ipo.ttl = 0;
+					ipo.check = 0;
+					
+					MD5Update(&tctx.md5, (caddr_t)&ipo,
+						  sizeof(struct iphdr));
+					MD5Update(&tctx.md5, (caddr_t)ahp,
+						  ahhlen - AHHMAC_HASHLEN);
+					MD5Update(&tctx.md5, (caddr_t)zeroes,
+						  AHHMAC_HASHLEN);
+					MD5Update(&tctx.md5,
+						  (caddr_t)dat + iphlen + ahhlen,
+						  len - iphlen - ahhlen);
+#endif /* CONFIG_IPSEC_AH */
+				}
+				MD5Final(hash, &tctx.md5);
+				tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx;
+				MD5Update(&tctx.md5, hash, AHMD596_ALEN);
+				MD5Final(hash, &tctx.md5);
+				break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+			case AH_SHA:
+				tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx;
+				if(proto == IPPROTO_ESP) {
+					SHA1Update(&tctx.sha1, (caddr_t)espp, ilen);
+#ifdef CONFIG_IPSEC_AH
+				} else {
+					ipo = *ipp;
+					ipo.tos = 0;
+					ipo.frag_off = 0;
+					ipo.ttl = 0;
+					ipo.check = 0;
+					
+					SHA1Update(&tctx.sha1, (caddr_t)&ipo,
+						   sizeof(struct iphdr));
+					SHA1Update(&tctx.sha1, (caddr_t)ahp,
+						   ahhlen - AHHMAC_HASHLEN);
+					SHA1Update(&tctx.sha1, (caddr_t)zeroes,
+						   AHHMAC_HASHLEN);
+					SHA1Update(&tctx.sha1,
+						   (caddr_t)dat + iphlen + ahhlen,
+						   len - iphlen - ahhlen);
+#endif /* CONFIG_IPSEC_AH */
+				}
+				SHA1Final(hash, &tctx.sha1);
+				tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx;
+				SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);
+				SHA1Final(hash, &tctx.sha1);
+				break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+			case AH_NONE:
+				break;
+			}
+		
+			if(!authenticator) {
+				tdbp->tdb_auth_errs += 1;
+				spin_unlock(&tdb_lock);
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+
+			if (memcmp(hash, authenticator, authlen)) {
+				tdbp->tdb_auth_errs += 1;
+				spin_unlock(&tdb_lock);
+				KLIPS_PRINT(debug_rcv & DB_RX_INAU,
+					    "klips_debug:ipsec_rcv: "
+					    "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n",
+					    ipaddr_txt,
+					    *(__u32*)&hash[0],
+					    *(__u32*)&hash[4],
+					    *(__u32*)&hash[8],
+					    *(__u32*)authenticator,
+					    *((__u32*)authenticator + 1),
+					    *((__u32*)authenticator + 2));
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			} else {
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "authentication successful.\n");
+			}
+			
+			memset((caddr_t)&tctx, 0, sizeof(tctx));
+			memset(hash, 0, sizeof(hash));
+		}
+
+		/* If the sequence number == 0, expire SA, it had rolled */
+		if(tdbp->tdb_replaywin && !replay /* !tdbp->tdb_replaywin_lastseq */) {
+			ipsec_sa_delchain(tdbp);
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "replay window counter rolled, expiring SA.\n");
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+
+		if (!ipsec_updatereplaywindow(tdbp, replay)) {
+			tdbp->tdb_replaywin_errs += 1;
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,
+				    "klips_debug:ipsec_rcv: "
+				    "duplicate frame from %s, packet dropped\n",
+				    ipaddr_txt);
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+		
+		switch(proto) {
+#ifdef CONFIG_IPSEC_ESP
+		case IPPROTO_ESP:
+#ifdef CONFIG_IPSEC_ALG
+			if ((ixt_e=IPSEC_ALG_SA_ESP_ENC(tdbp))) {
+				esphlen = ESP_HEADER_LEN + ixt_e->ixt_ivlen/8;
+				KLIPS_PRINT(debug_rcv,
+						"klips_debug:ipsec_rcv: "
+						"encalg=%d esphlen=%d\n",
+						tdbp->tdb_encalg, esphlen);
+			} else
+#endif /* CONFIG_IPSEC_ALG */
+			switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_3DES
+			case ESP_3DES:
+				iv[0] = *((__u32 *)(espp->esp_iv)    );
+				iv[1] = *((__u32 *)(espp->esp_iv) + 1);
+				esphlen = sizeof(struct esp);
+				break;
+#endif /* CONFIG_IPSEC_ENC_3DES */
+			default:
+				tdbp->tdb_alg_errs += 1;
+				spin_unlock(&tdb_lock);
+				if(stats) {
+					stats->rx_errors++;
+				}
+				goto rcvleave;
+			}
+			idat += esphlen;
+			ilen -= esphlen;
+			
+#ifdef CONFIG_IPSEC_ALG
+			if (ixt_e)
+			{
+				if (ipsec_alg_esp_encrypt(tdbp, 
+					idat, ilen, espp->esp_iv, 
+					IPSEC_ALG_DECRYPT) <= 0)
+				{
+					spin_unlock(&tdb_lock);
+					printk("klips_error:ipsec_rcv: "
+						"got packet with esplen = %d "
+						"from %s -- should be on "
+						"ENC(%d) octet boundary, "
+						"packet dropped\n",
+							ilen,
+							ipaddr_txt,
+							tdbp->tdb_encalg);
+					stats->rx_errors++;
+					goto rcvleave;
+				}
+			} else
+#endif /* CONFIG_IPSEC_ALG */
+			switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_3DES
+			case ESP_3DES:
+				if ((ilen) % 8) {
+					tdbp->tdb_encsize_errs += 1;
+					spin_unlock(&tdb_lock);
+					printk("klips_error:ipsec_rcv: "
+					       "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n",
+					       ilen,
+					       ipaddr_txt);
+					if(stats) {
+						stats->rx_errors++;
+					}
+					goto rcvleave;
+				}
+				des_ede3_cbc_encrypt((des_cblock *)idat,
+						     (des_cblock *)idat,
+						     ilen,
+						     ((struct des_eks *)(tdbp->tdb_key_e))[0].ks,
+						     ((struct des_eks *)(tdbp->tdb_key_e))[1].ks,
+						     ((struct des_eks *)(tdbp->tdb_key_e))[2].ks,
+						     (des_cblock *)iv, 0);
+				break;
+#endif /* CONFIG_IPSEC_ENC_3DES */
+			default:
+			}
+			next_header = idat[ilen - 1];
+			padlen = idat[ilen - 2];
+			pad = padlen + 2 + authlen;
+			{
+			        int badpad = 0;
+				
+				KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
+					    "klips_debug:ipsec_rcv: "
+					    "padlen=%d, contents: 0x<offset>: 0x<value> 0x<value> ...\n",
+					    padlen);
+				
+				for (i = 1; i <= padlen; i++) {
+					if((i % 16) == 1) {
+						KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
+							    "klips_debug:           %02x:",
+							    i - 1);
+					}
+					KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,
+						    " %02x",
+						    idat[ilen - 2 - padlen + i - 1]);
+					if(i != idat[ilen - 2 - padlen + i - 1]) {
+					        badpad = 1;
+					} 
+					if((i % 16) == 0) {
+						KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,
+							    "\n");
+					}
+				}
+				if((i % 16) != 1) {
+					KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,
+							"\n");
+				}
+				if(badpad) {
+					KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
+						    "klips_debug:ipsec_rcv: "
+						    "warning, decrypted packet from %s has bad padding\n",
+						    ipaddr_txt);
+					KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
+						    "klips_debug:ipsec_rcv: "
+						    "...may be bad decryption -- not dropped\n");
+					tdbp->tdb_encpad_errs += 1;
+				}
+				
+				KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
+					    "klips_debug:ipsec_rcv: "
+					    "packet decrypted from %s: next_header = %d, padding = %d\n",
+					    ipaddr_txt,
+					    next_header,
+					    pad - 2 - authlen);
+			}
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+		case IPPROTO_AH:
+			break;
+#endif /* CONFIG_IPSEC_AH */
+		}
+	       
+		/*
+		 *	Discard the original ESP/AH header
+		 */
+		
+		ipp->protocol = next_header;
+		
+		switch(proto) {
+#ifdef CONFIG_IPSEC_ESP
+		case IPPROTO_ESP:
+			ipp->tot_len = htons(ntohs(ipp->tot_len) - (esphlen + pad));
+			memmove((void *)(skb->data + esphlen),
+				(void *)(skb->data), iphlen);
+			if(skb->len < esphlen) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING
+				       "klips_error:ipsec_rcv: "
+				       "tried to skb_pull esphlen=%d, %d available.  This should never happen, please report.\n",
+				       esphlen, (int)(skb->len));
+				goto rcvleave;
+			}
+			skb_pull(skb, esphlen);
+
+			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
+				    "klips_debug:ipsec_rcv: "
+				    "trimming to %d.\n",
+				    len - esphlen - pad);
+			if(pad + esphlen <= len) {
+			        skb_trim(skb, len - esphlen - pad);
+			} else {
+				spin_unlock(&tdb_lock);
+			        KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
+				            "klips_debug:ipsec_rcv: "
+					    "bogus packet, size is zero or negative, dropping.\n");
+				goto rcvleave;
+			}
+		break;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+		case IPPROTO_AH:
+			ipp->tot_len = htons(ntohs(ipp->tot_len) - ahhlen);
+			memmove((void *)(skb->data + ahhlen),
+				(void *)(skb->data), iphlen);
+			if(skb->len < ahhlen) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING
+				       "klips_error:ipsec_rcv: "
+				       "tried to skb_pull ahhlen=%d, %d available.  This should never happen, please report.\n",
+				       ahhlen,
+				       (int)(skb->len));
+				goto rcvleave;
+			}
+			skb_pull(skb, ahhlen);
+			break;
+#endif /* CONFIG_IPSEC_AH */
+		}
+
+
+		/*
+		 *	Adjust pointers
+		 */
+		
+		len = skb->len;
+		dat = skb->data;
+		
+#ifdef NET_21
+/*		skb->h.ipiph=(struct iphdr *)skb->data; */
+		skb->nh.raw = skb->data;
+		skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2);
+		
+		memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+#else /* NET_21 */
+		skb->h.iph=(struct iphdr *)skb->data;
+		skb->ip_hdr=(struct iphdr *)skb->data;
+		memset(skb->proto_priv, 0, sizeof(struct options));
+#endif /* NET_21 */
+		
+		ipp = (struct iphdr *)dat;
+		ipp->check = 0;
+		ipp->check = ip_fast_csum((unsigned char *)dat, iphlen >> 2);
+		
+		KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
+			    "klips_debug:ipsec_rcv: "
+			    "after <%s%s%s>, SA:%s:\n",
+			    IPS_XFORM_NAME(tdbp),
+			    sa_len ? sa : " (error)");
+		KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);
+		
+		skb->protocol = htons(ETH_P_IP);
+		skb->ip_summed = 0;
+
+		tdbprev = tdbp;
+		tdbnext = tdbp->tdb_inext;
+		if(sysctl_ipsec_inbound_policy_check) {
+			if(tdbnext) {
+				if(tdbnext->tdb_onext != tdbp) {
+					spin_unlock(&tdb_lock);
+					KLIPS_PRINT(debug_rcv,
+						    "klips_debug:ipsec_rcv: "
+						    "SA:%s, backpolicy does not agree with fwdpolicy.\n",
+						    sa_len ? sa : " (error)");
+					if(stats) {
+						stats->rx_dropped++;
+					}
+					goto rcvleave;
+				}
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s, backpolicy agrees with fwdpolicy.\n",
+					    sa_len ? sa : " (error)");
+				if(
+					ipp->protocol != IPPROTO_AH  
+					&& ipp->protocol != IPPROTO_ESP 
+#ifdef CONFIG_IPSEC_IPCOMP
+					&& ipp->protocol != IPPROTO_COMP
+					&& (tdbnext->tdb_said.proto != IPPROTO_COMP
+					    || (tdbnext->tdb_said.proto == IPPROTO_COMP
+						&& tdbnext->tdb_inext))
+#endif /* CONFIG_IPSEC_IPCOMP */
+					&& ipp->protocol != IPPROTO_IPIP
+					&& ipp->protocol != 0xFE  // added to support heartbeats to AT&T SIG/GIG
+					) {
+					spin_unlock(&tdb_lock);
+					KLIPS_PRINT(debug_rcv,
+						    "klips_debug:ipsec_rcv: "
+						    "packet with incomplete policy dropped, last successful SA:%s.\n",
+						    sa_len ? sa : " (error)");
+					if(stats) {
+						stats->rx_dropped++;
+					}
+					goto rcvleave;
+				}
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s, Another IPSEC header to process.\n",
+					    sa_len ? sa : " (error)");
+			} else {
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "No tdb_inext from this SA:%s.\n",
+					    sa_len ? sa : " (error)");
+			}
+		}
+
+#ifdef CONFIG_IPSEC_IPCOMP
+		/* update ipcomp ratio counters, even if no ipcomp packet is present */
+		if (tdbnext
+		  && tdbnext->tdb_said.proto == IPPROTO_COMP
+		  && ipp->protocol != IPPROTO_COMP) {
+			tdbnext->tdb_comp_ratio_cbytes += ntohs(ipp->tot_len);
+			tdbnext->tdb_comp_ratio_dbytes += ntohs(ipp->tot_len);
+		}
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+		tdbp->ips_life.ipl_bytes.ipl_count += len;
+		tdbp->ips_life.ipl_bytes.ipl_last   = len;
+
+		if(!tdbp->ips_life.ipl_usetime.ipl_count) {
+			tdbp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;
+		}
+		tdbp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;
+		tdbp->ips_life.ipl_packets.ipl_count += 1;
+		
+	/* end decapsulation loop here */
+	} while(   (ipp->protocol == IPPROTO_ESP )
+		|| (ipp->protocol == IPPROTO_AH  )
+#ifdef CONFIG_IPSEC_IPCOMP
+		|| (ipp->protocol == IPPROTO_COMP)
+#endif /* CONFIG_IPSEC_IPCOMP */
+		);
+	
+#ifdef CONFIG_IPSEC_IPCOMP
+	if(tdbnext && tdbnext->tdb_said.proto == IPPROTO_COMP) {
+		tdbprev = tdbp;
+		tdbp = tdbnext;
+		tdbnext = tdbp->tdb_inext;
+	}
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	if ((natt_type) && (ipp->protocol != IPPROTO_IPIP)) {
+		/**
+		 * NAT-Traversal and Transport Mode:
+		 *   we need to correct TCP/UDP checksum
+		 *
+		 * If we've got NAT-OA, we can fix checksum without recalculation.
+		 */
+		__u32 natt_oa = tdbp->ips_natt_oa ?
+			((struct sockaddr_in*)(tdbp->ips_natt_oa))->sin_addr.s_addr : 0;
+		__u16 pkt_len = skb->tail - (unsigned char *)ipp;
+		__u16 data_len = pkt_len - (ipp->ihl << 2);
+
+		switch (ipp->protocol) {
+			case IPPROTO_TCP:
+				if (data_len >= sizeof(struct tcphdr)) {
+					struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ipp+ipp->ihl);
+					if (natt_oa) {
+						__u32 buff[2] = { ~natt_oa, ipp->saddr };
+						KLIPS_PRINT(debug_rcv,
+				    		"klips_debug:ipsec_rcv: "
+							"NAT-T & TRANSPORT: "
+							"fix TCP checksum using NAT-OA\n");
+						tcp->check = csum_fold(
+							csum_partial((unsigned char *)buff, sizeof(buff),
+							tcp->check^0xffff));
+					}
+					else {
+						KLIPS_PRINT(debug_rcv,
+			    			"klips_debug:ipsec_rcv: "
+							"NAT-T & TRANSPORT: recalc TCP checksum\n");
+						if (pkt_len > (ntohs(ipp->tot_len)))
+							data_len -= (pkt_len - ntohs(ipp->tot_len));
+						tcp->check = 0;
+						tcp->check = csum_tcpudp_magic(ipp->saddr, ipp->daddr,
+							data_len, IPPROTO_TCP,
+							csum_partial((unsigned char *)tcp, data_len, 0));
+					}
+				}
+				else {
+					KLIPS_PRINT(debug_rcv,
+			    		"klips_debug:ipsec_rcv: "
+						"NAT-T & TRANSPORT: can't fix TCP checksum\n");
+				}
+				break;
+			case IPPROTO_UDP:
+				if (data_len >= sizeof(struct udphdr)) {
+					struct udphdr *udp = (struct udphdr *)((__u32 *)ipp+ipp->ihl);
+					if (udp->check == 0) {
+						KLIPS_PRINT(debug_rcv,
+				    		"klips_debug:ipsec_rcv: "
+							"NAT-T & TRANSPORT: UDP checksum already 0\n");
+					}
+					else if (natt_oa) {
+						__u32 buff[2] = { ~natt_oa, ipp->saddr };
+						KLIPS_PRINT(debug_rcv,
+				    		"klips_debug:ipsec_rcv: "
+							"NAT-T & TRANSPORT: "
+							"fix UDP checksum using NAT-OA\n");
+						udp->check = csum_fold(
+							csum_partial((unsigned char *)buff, sizeof(buff),
+							udp->check^0xffff));
+					}
+					else {
+						KLIPS_PRINT(debug_rcv,
+				    		"klips_debug:ipsec_rcv: "
+							"NAT-T & TRANSPORT: zero UDP checksum\n");
+						udp->check = 0;
+					}
+				}
+				else {
+					KLIPS_PRINT(debug_rcv,
+			    		"klips_debug:ipsec_rcv: "
+						"NAT-T & TRANSPORT: can't fix UDP checksum\n");
+				}
+				break;
+			default:
+				KLIPS_PRINT(debug_rcv,
+			    	"klips_debug:ipsec_rcv: "
+					"NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n");
+				break;
+		}
+	}
+#endif
+
+	/*
+	 * XXX this needs to be locked from when it was first looked
+	 * up in the decapsulation loop.  Perhaps it is better to put
+	 * the IPIP decap inside the loop.
+	 */
+	if(tdbnext) {
+		tdbp = tdbnext;
+		sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+		if((ipp->protocol != IPPROTO_IPIP) && 
+                   ( 0xFE != ipp->protocol))          // added to support AT&T heartbeats to SIG/GIG
+                { 
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "SA:%s, Hey!  How did this get through?  Dropped.\n",
+				    sa_len ? sa : " (error)");
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+		if(sysctl_ipsec_inbound_policy_check) {
+			if((tdbnext = tdbp->tdb_inext)) {
+				char sa2[SATOA_BUF];
+				size_t sa_len2;
+				sa_len2 = satoa(tdbnext->tdb_said, 0, sa2, SATOA_BUF);
+				spin_unlock(&tdb_lock);
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "unexpected SA:%s after IPIP SA:%s\n",
+					    sa_len2 ? sa2 : " (error)",
+					    sa_len ? sa : " (error)");
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+			if(ipp->saddr != ((struct sockaddr_in*)(tdbp->tdb_addr_s))->sin_addr.s_addr) {
+				spin_unlock(&tdb_lock);
+				ipaddr.s_addr = ipp->saddr;
+				addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));
+				KLIPS_PRINT(debug_rcv,
+					    "klips_debug:ipsec_rcv: "
+					    "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n",
+					    sa_len ? sa : " (error)",
+					    ipaddr_txt);
+				if(stats) {
+					stats->rx_dropped++;
+				}
+				goto rcvleave;
+			}
+		}
+
+  if(ipp->protocol == IPPROTO_IPIP)  // added to support AT&T heartbeats to SIG/GIG
+  {  
+		/*
+		 * XXX this needs to be locked from when it was first looked
+		 * up in the decapsulation loop.  Perhaps it is better to put
+		 * the IPIP decap inside the loop.
+		 */
+		tdbp->ips_life.ipl_bytes.ipl_count += len;
+		tdbp->ips_life.ipl_bytes.ipl_last   = len;
+
+		if(!tdbp->ips_life.ipl_usetime.ipl_count) {
+			tdbp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;
+		}
+		tdbp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;
+		tdbp->ips_life.ipl_packets.ipl_count += 1;
+		
+		if(skb->len < iphlen) {
+			spin_unlock(&tdb_lock);
+			printk(KERN_WARNING "klips_debug:ipsec_rcv: "
+			       "tried to skb_pull iphlen=%d, %d available.  This should never happen, please report.\n",
+			       iphlen,
+			       (int)(skb->len));
+
+			goto rcvleave;
+		}
+		skb_pull(skb, iphlen);
+
+#ifdef NET_21
+		ipp = (struct iphdr *)skb->nh.raw = skb->data;
+		skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2);
+		
+		memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+#else /* NET_21 */
+		ipp = skb->ip_hdr = skb->h.iph = (struct iphdr *)skb->data;
+
+		memset(skb->proto_priv, 0, sizeof(struct options));
+#endif /* NET_21 */
+
+		skb->protocol = htons(ETH_P_IP);
+		skb->ip_summed = 0;
+		KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
+			    "klips_debug:ipsec_rcv: "
+			    "IPIP tunnel stripped.\n");
+		KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);
+  }
+
+		if(sysctl_ipsec_inbound_policy_check
+		   /* 
+		      Note: "xor" (^) logically replaces "not equal"
+		      (!=) and "bitwise or" (|) logically replaces
+		      "boolean or" (||).  This is done to speed up
+		      execution by doing only bitwise operations and
+		      no branch operations
+		   */
+		   && (((ipp->saddr & tdbp->tdb_mask_s.u.v4.sin_addr.s_addr)
+			            ^ tdbp->tdb_flow_s.u.v4.sin_addr.s_addr)
+		       | ((ipp->daddr & tdbp->tdb_mask_d.u.v4.sin_addr.s_addr)
+			              ^ tdbp->tdb_flow_d.u.v4.sin_addr.s_addr)) )
+		{
+			struct in_addr daddr, saddr;
+			char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF];
+			char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF];
+			
+			subnettoa(tdbp->tdb_flow_s.u.v4.sin_addr,
+				tdbp->tdb_mask_s.u.v4.sin_addr,
+				0, sflow_txt, sizeof(sflow_txt));
+			subnettoa(tdbp->tdb_flow_d.u.v4.sin_addr,
+				tdbp->tdb_mask_d.u.v4.sin_addr,
+				0, dflow_txt, sizeof(dflow_txt));
+			spin_unlock(&tdb_lock);
+			saddr.s_addr = ipp->saddr;
+			daddr.s_addr = ipp->daddr;
+			addrtoa(saddr, 0, saddr_txt, sizeof(saddr_txt));
+			addrtoa(daddr, 0, daddr_txt, sizeof(daddr_txt));
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n",
+				    sa_len ? sa : " (error)",
+				    sflow_txt,
+				    dflow_txt,
+				    saddr_txt,
+				    daddr_txt);
+			if(stats) {
+				stats->rx_dropped++;
+			}
+			goto rcvleave;
+		}
+	}
+
+#ifdef INBOUND_POLICY_CHECK_eroute
+	/*
+	  Do *not* enable this without thoroughly checking spinlock issues
+	  first.  In particular, nesting an eroute spinlock within a tdb
+	  spinlock could result in a deadlock.  (Well, only on a SMP machine
+	  under 2.4?)
+	*/
+
+	/*
+	 * First things first -- look us up in the erouting tables.
+	 */
+	matcher.sen_len = sizeof (struct sockaddr_encap);
+	matcher.sen_family = AF_ENCAP;
+	matcher.sen_type = SENT_IP4;
+	if(ipp->protocol == IPPROTO_IPIP) {
+		struct iphdr *ipp2;
+
+		ipp2 = (struct iphdr*) (((char*)ipp) + (ipp->ihl << 2));
+		matcher.sen_ip_src.s_addr = ipp2->saddr;
+		matcher.sen_ip_dst.s_addr = ipp2->daddr;
+	} else {
+		matcher.sen_ip_src.s_addr = ipp->saddr;
+		matcher.sen_ip_dst.s_addr = ipp->daddr;
+	}
+	
+	/*
+	 * The spinlock is to prevent any other process from accessing or
+	 * deleting the eroute while we are using and updating it.
+	 */
+	spin_lock(&eroute_lock);
+	
+	er = ipsec_findroute(&matcher);
+	if(er) {
+		policy_said = er->er_said;
+		policy_eaddr = er->er_eaddr;
+		policy_emask = er->er_emask;
+		er->er_count++;
+		er->er_lasttime = jiffies/HZ;
+	}
+	
+	spin_unlock(&eroute_lock);
+
+	if(er) {
+		/*
+		 * The spinlock is to prevent any other process from
+		 * accessing or deleting the tdb while we are using and
+		 * updating it.
+		 */
+		spin_lock(&tdb_lock);
+
+		policy_tdb = gettdb(&policy_said);
+		if (policy_tdb == NULL) {
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "no Tunnel Descriptor Block for SA%s: incoming packet with no policy SA, dropped.\n",
+				    sa_len ? sa : " (error)");
+			goto rcvleave;
+		}
+		
+		sa_len = satoa(policy_said, 0, sa, SATOA_BUF);
+
+		KLIPS_PRINT(debug_rcv,
+			    "klips_debug:ipsec_rcv: "
+			    "found policy Tunnel Descriptor Block -- SA:%s\n",
+			    sa_len ? sa : " (error)");
+		while(1) {
+			if(policy_tdb->tdb_inext) {
+				policy_tdb = policy_tdb->tdb_inext;
+			} else {
+				break;
+			}
+		}
+		if(policy_tdb != tdbp) {
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "Tunnel Descriptor Block for SA%s: incoming packet with different policy SA, dropped.\n",
+				    sa_len ? sa : " (error)");
+			goto rcvleave;
+		}
+
+		/* spin_unlock(&tdb_lock); */
+	}
+#endif /* INBOUND_POLICY_CHECK_eroute */
+
+	spin_unlock(&tdb_lock);
+
+#ifdef NET_21
+	if(stats) {
+		stats->rx_bytes += skb->len;
+	}
+	if(skb->dst) {
+		dst_release(skb->dst);
+		skb->dst = NULL;
+	}
+	skb->pkt_type = PACKET_HOST;
+	if(hard_header_len &&
+	   (skb->mac.raw != (skb->data - hard_header_len)) &&
+	   (hard_header_len <= skb_headroom(skb))) {
+		/* copy back original MAC header */
+		memmove(skb->data - hard_header_len, skb->mac.raw, hard_header_len);
+		skb->mac.raw = skb->data - hard_header_len;
+	}
+#endif /* NET_21 */
+
+#ifdef CONFIG_IPSEC_IPCOMP
+	if(ipp->protocol == IPPROTO_COMP) {
+		unsigned int flags = 0;
+
+		if(sysctl_ipsec_inbound_policy_check) {
+			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
+				"klips_debug:ipsec_rcv: "
+				"inbound policy checking enabled, IPCOMP follows IPIP, dropped.\n");
+			if (stats) {
+				stats->rx_errors++;
+			}
+			goto rcvleave;
+		}
+		/*
+		  XXX need a TDB for updating ratio counters but it is not
+		  following policy anyways so it is not a priority
+		*/
+		skb = skb_decompress(skb, NULL, &flags);
+		if (!skb || flags) {
+			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
+				"klips_debug:ipsec_rcv: "
+				"skb_decompress() returned error flags: %d, dropped.\n",
+			       flags);
+			if (stats) {
+				stats->rx_errors++;
+			}
+			goto rcvleave;
+		}
+	}
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#ifdef SKB_RESET_NFCT
+        nf_conntrack_put(skb->nfct);
+        skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif /* CONFIG_NETFILTER_DEBUG */
+#endif /* SKB_RESET_NFCT */
+	KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
+		    "klips_debug:ipsec_rcv: "
+		    "netif_rx() called.\n");
+	netif_rx(skb);
+
+	MOD_DEC_USE_COUNT;
+	return(0);
+	
+ rcvleave:
+ 	if(skb) {
+#ifdef NET_21
+                kfree_skb(skb);
+#else /* NET_21 */
+                kfree_skb(skb, FREE_WRITE);
+#endif /* NET_21 */
+	}
+
+	MOD_DEC_USE_COUNT;
+	return(0);
+}
+
+struct inet_protocol ah_protocol =
+{
+	ipsec_rcv,				/* AH handler */
+	NULL,				/* TUNNEL error control */
+	0,				/* next */
+	IPPROTO_AH,			/* protocol ID */
+	0,				/* copy */
+	NULL,				/* data */
+	"AH"				/* name */
+};
+
+struct inet_protocol esp_protocol = 
+{
+	ipsec_rcv,			/* ESP handler          */
+	NULL,				/* TUNNEL error control */
+	0,				/* next */
+	IPPROTO_ESP,			/* protocol ID */
+	0,				/* copy */
+	NULL,				/* data */
+	"ESP"				/* name */
+};
+
+#if 0
+/* We probably don't want to install a pure IPCOMP protocol handler, but
+   only want to handle IPCOMP if it is encapsulated inside an ESP payload
+   (which is already handled) */
+#ifdef CONFIG_IPSEC_IPCOMP
+struct inet_protocol comp_protocol =
+{
+	ipsec_rcv,			/* COMP handler		*/
+	NULL,				/* COMP error control	*/
+	0,				/* next */
+	IPPROTO_COMP,			/* protocol ID */
+	0,				/* copy */
+	NULL,				/* data */
+	"COMP"				/* name */
+};
+#endif /* CONFIG_IPSEC_IPCOMP */
+#endif
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.15  2003/07/04 19:07:34  ken
+ * Added NAT-T 0.6 diff/patch from Tuomo
+ *
+ * Revision 1.14  2003/02/07 13:14:24  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.13.2.1  2003/02/06 22:09:49  jjo
+ * sync to alg-0.8.1-rc4
+ *
+ * Revision 1.13  2003/01/19 23:06:27  ken
+ * Added MTS Patch (fix broken AT&T VPN System for IBM Users) - amcedwards
+ *
+ * Revision 1.12  2003/01/02 21:47:45  ken
+ * NAT-T 0.5
+ *
+ * Revision 1.11  2002/11/05 01:41:46  ken
+ * Pulled  from 1.99
+ *
+ * Revision 1.102.6.6  2002/10/30 17:39:07  rgb
+ * Fixed cut-and-paste error mis-identifying comp runt as ah.
+ *
+ * Revision 1.102.6.5  2002/10/30 05:45:19  rgb
+ * Make sure partial esp/ah/comp headers don't cause oops.
+ *
+ * Revision 1.102.6.4  2002/10/28 19:54:56  sam
+ * Fix scope of shift in AH header length check.
+ *
+ * Revision 1.10  2002/11/05 01:35:58  ken
+ * 1.99cand -> 1.99 Final Code changes
+ *
+ * Revision 1.9  2002/10/26 19:18:48  ken
+ * fixed bad patch of ipsec_rcv.c
+ *
+ * Revision 1.102.6.3  2002/10/25 17:26:40  sam
+ * runt patch applied for DOS
+ *
+ * Revision 1.102.6.2  2002/10/18 05:20:36  sam
+ * Patched with RGB's fix from ipsec_rcv.c v1.109:
+ *
+ * Fixed ESP short packet DOS (and AH and IPCOMP)
+ *
+ * Revision 1.8  2002/10/26 14:32:44  ken
+ * Patch in code from 1.99 for ESP DOS Fix, and RPM build fixes.
+ * patch -p1 -F 3 < ../_kb9-DOSFIX.diff
+ *
+ * Revision 1.7  2002/10/16 00:21:46  ken
+ * Applied JuanJo's NULL Patch
+ *
+ * Revision 1.6  2002/10/16 00:16:50  ken
+ * Backed out David patch in prep for JuanJo's
+ *
+ * Revision 1.5  2002/10/15 18:35:24  ken
+ * Updated README/CHANGES for _kb8
+ *
+ * Revision 1.4  2002/10/15 17:52:47  ken
+ * Added David De Reu's NULL ALG Bugfix
+ *
+ * Revision 1.3  2002/09/05 03:53:52  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.2  2002/09/05 03:27:08  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.102  2002/01/29 17:17:56  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.101  2002/01/29 04:00:52  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.100  2002/01/29 02:13:17  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.99  2002/01/28 21:40:59  mcr
+ * 	should use #if to test boolean option rather than #ifdef.
+ *
+ * Revision 1.98  2002/01/20 20:19:36  mcr
+ * 	renamed option to IP_FRAGMENT_LINEARIZE.
+ *
+ * Revision 1.97  2002/01/12 02:55:36  mcr
+ * 	fix for post-2.4.4 to linearize skb's when ESP packet
+ * 	was assembled from fragments.
+ *
+ * Revision 1.96  2001/11/26 09:23:49  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.93.2.2  2001/10/22 20:54:07  mcr
+ * 	include des.h, removed phony prototypes and fixed calling
+ * 	conventions to match real prototypes.
+ *
+ * Revision 1.93.2.1  2001/09/25 02:22:22  mcr
+ * 	struct tdb -> struct ipsec_sa.
+ * 	lifetime checks moved to ipsec_life.c
+ * 	some sa(tdb) manipulation functions renamed.
+ *
+ * Revision 1.95  2001/11/06 19:49:07  rgb
+ * Added variable descriptions.
+ * Removed unauthenticated sequence==0 check to prevent DoS.
+ *
+ * Revision 1.94  2001/10/18 04:45:20  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.93  2001/09/07 22:17:24  rgb
+ * Fix for removal of transport layer protocol handler arg in 2.4.4.
+ * Fix to accomodate peer non-conformance to IPCOMP rfc2393.
+ *
+ * Revision 1.92  2001/08/27 19:44:41  rgb
+ * Fix error in comment.
+ *
+ * Revision 1.91  2001/07/20 19:31:48  dhr
+ * [DHR] fix source and destination subnets of policy in diagnostic
+ *
+ * Revision 1.90  2001/07/06 19:51:09  rgb
+ * Added inbound policy checking code for IPIP SAs.
+ * Renamed unused function argument for ease and intuitive naming.
+ *
+ * Revision 1.89  2001/06/22 19:35:23  rgb
+ * Disable ipcomp processing if we are handed a ipcomp packet with no esp
+ * or ah header.
+ * Print protocol if we are handed a non-ipsec packet.
+ *
+ * Revision 1.88  2001/06/20 06:30:47  rgb
+ * Fixed transport mode IPCOMP policy check bug.
+ *
+ * Revision 1.87  2001/06/13 20:58:40  rgb
+ * Added parentheses around assignment used as truth value to silence
+ * compiler.
+ *
+ * Revision 1.86  2001/06/07 22:25:23  rgb
+ * Added a source address policy check for tunnel mode.  It still does
+ * not check client addresses and masks.
+ * Only decapsulate IPIP if it is expected.
+ *
+ * Revision 1.85  2001/05/30 08:14:02  rgb
+ * Removed vestiges of esp-null transforms.
+ *
+ * Revision 1.84  2001/05/27 06:12:11  rgb
+ * Added structures for pid, packet count and last access time to eroute.
+ * Added packet count to beginning of /proc/net/ipsec_eroute.
+ *
+ * Revision 1.83  2001/05/04 16:45:47  rgb
+ * Remove unneeded code.  ipp is not used after this point.
+ *
+ * Revision 1.82  2001/05/04 16:36:00  rgb
+ * Fix skb_cow() call for 2.4.4. (SS)
+ *
+ * Revision 1.81  2001/05/02 14:46:53  rgb
+ * Fix typo for compiler directive to pull IPH back.
+ *
+ * Revision 1.80  2001/04/30 19:46:34  rgb
+ * Update for 2.4.4.  We now receive the skb with skb->data pointing to
+ * h.raw.
+ *
+ * Revision 1.79  2001/04/23 15:01:15  rgb
+ * Added spin_lock() check to prevent double-locking for multiple
+ * transforms and hence kernel lock-ups with SMP kernels.
+ * Minor spin_unlock() adjustments to unlock before non-dependant prints
+ * and IPSEC device stats updates.
+ *
+ * Revision 1.78  2001/04/21 23:04:24  rgb
+ * Check if soft expire has already been sent before sending another to
+ * prevent ACQUIRE flooding.
+ *
+ * Revision 1.77  2001/03/16 07:35:20  rgb
+ * Ditch extra #if 1 around now permanent policy checking code.
+ *
+ * Revision 1.76  2001/02/27 22:24:54  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.75  2001/02/19 22:28:30  rgb
+ * Minor change to virtual device discovery code to assert which I/F has
+ * been found.
+ *
+ * Revision 1.74  2000/11/25 03:50:36  rgb
+ * Oops fix by minor re-arrangement of code to avoid accessing a freed tdb.
+ *
+ * Revision 1.73  2000/11/09 20:52:15  rgb
+ * More spinlock shuffling, locking earlier and unlocking later in rcv to
+ * include ipcomp and prevent races, renaming some tdb variables that got
+ * forgotten, moving some unlocks to include tdbs and adding a missing
+ * unlock.  Thanks to Svenning for some of these.
+ *
+ * Revision 1.72  2000/11/09 20:11:22  rgb
+ * Minor shuffles to fix non-standard kernel config option selection.
+ *
+ * Revision 1.71  2000/11/06 04:36:18  rgb
+ * Ditched spin_lock_irqsave in favour of spin_lock.
+ * Minor initial protocol check rewrite.
+ * Clean up debug printing.
+ * Clean up tdb handling on ipcomp.
+ * Fixed transport mode null pointer de-reference without ipcomp.
+ * Add Svenning's adaptive content compression.
+ * Disabled registration of ipcomp handler.
+ *
+ * Revision 1.70  2000/10/30 23:41:43  henry
+ * Hans-Joerg Hoexer's null-pointer fix
+ *
+ * Revision 1.69  2000/10/10 18:54:16  rgb
+ * Added a fix for incoming policy check with ipcomp enabled but
+ * uncompressible.
+ *
+ * Revision 1.68  2000/09/22 17:53:12  rgb
+ * Fixed ipcomp tdb pointers update for policy checking.
+ *
+ * Revision 1.67  2000/09/21 03:40:58  rgb
+ * Added more debugging to try and track down the cpi outward copy problem.
+ *
+ * Revision 1.66  2000/09/20 04:00:10  rgb
+ * Changed static functions to DEBUG_NO_STATIC to reveal function names for
+ * debugging oopsen.
+ *
+ * Revision 1.65  2000/09/19 07:07:16  rgb
+ * Added debugging to inbound policy check for ipcomp.
+ * Added missing spin_unlocks (thanks Svenning!).
+ * Fixed misplaced tdbnext pointers causing mismatched ipip policy check.
+ * Protect ipcomp policy check following ipip decap with sysctl switch.
+ *
+ * Revision 1.64  2000/09/18 21:27:29  rgb
+ * 2.0 fixes.
+ *
+ * Revision 1.63  2000/09/18 02:35:50  rgb
+ * Added policy checking to ipcomp and re-enabled policy checking by
+ * default.
+ * Optimised satoa calls.
+ *
+ * Revision 1.62  2000/09/17 21:02:32  rgb
+ * Clean up debugging, removing slow timestamp debug code.
+ *
+ * Revision 1.61  2000/09/16 01:07:55  rgb
+ * Fixed erroneous ref from struct ipcomp to struct ipcomphdr.
+ *
+ * Revision 1.60  2000/09/15 11:37:01  rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.59  2000/09/15 04:56:20  rgb
+ * Remove redundant satoa() call, reformat comment.
+ *
+ * Revision 1.58  2000/09/13 08:00:52  rgb
+ * Flick on inbound policy checking.
+ *
+ * Revision 1.57  2000/09/12 03:22:19  rgb
+ * Converted inbound_policy_check to sysctl.
+ * Re-enabled policy backcheck.
+ * Moved policy checks to top and within tdb lock.
+ *
+ * Revision 1.56  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.55  2000/08/28 18:15:46  rgb
+ * Added MB's nf-debug reset patch.
+ *
+ * Revision 1.54  2000/08/27 01:41:26  rgb
+ * More minor tweaks to the bad padding debug code.
+ *
+ * Revision 1.53  2000/08/24 16:54:16  rgb
+ * Added KLIPS_PRINTMORE macro to continue lines without KERN_INFO level
+ * info.
+ * Tidied up device reporting at the start of ipsec_rcv.
+ * Tidied up bad padding debugging and processing.
+ *
+ * Revision 1.52  2000/08/20 21:36:03  rgb
+ * Activated pfkey_expire() calls.
+ * Added a hard/soft expiry parameter to pfkey_expire().
+ * Added sanity checking to avoid propagating zero or smaller-length skbs
+ * from a bogus decryption.
+ * Re-arranged the order of soft and hard expiry to conform to RFC2367.
+ * Clean up references to CONFIG_IPSEC_PFKEYv2.
+ *
+ * Revision 1.51  2000/08/18 21:23:30  rgb
+ * Improve bad padding warning so that the printk buffer doesn't get
+ * trampled.
+ *
+ * Revision 1.50  2000/08/01 14:51:51  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.49  2000/07/28 13:50:53  rgb
+ * Changed enet_statistics to net_device_stats and added back compatibility
+ * for pre-2.1.19.
+ *
+ * Revision 1.48  2000/05/10 19:14:40  rgb
+ * Only check usetime against soft and hard limits if the tdb has been
+ * used.
+ * Cast output of ntohl so that the broken prototype doesn't make our
+ * compile noisy.
+ *
+ * Revision 1.47  2000/05/09 17:45:43  rgb
+ * Fix replay bitmap corruption bug upon receipt of bogus packet
+ * with correct SPI.  This was a DoS.
+ *
+ * Revision 1.46  2000/03/27 02:31:58  rgb
+ * Fixed authentication failure printout bug.
+ *
+ * Revision 1.45  2000/03/22 16:15:37  rgb
+ * Fixed renaming of dev_get (MB).
+ *
+ * Revision 1.44  2000/03/16 08:17:24  rgb
+ * Hardcode PF_KEYv2 support.
+ * Fixed minor bug checking AH header length.
+ *
+ * Revision 1.43  2000/03/14 12:26:59  rgb
+ * Added skb->nfct support for clearing netfilter conntrack bits (MB).
+ *
+ * Revision 1.42  2000/01/26 10:04:04  rgb
+ * Fixed inbound policy checking on transport mode bug.
+ * Fixed noisy 2.0 printk arguments.
+ *
+ * Revision 1.41  2000/01/24 20:58:02  rgb
+ * Improve debugging/reporting support for (disabled) inbound
+ * policy checking.
+ *
+ * Revision 1.40  2000/01/22 23:20:10  rgb
+ * Fixed up inboud policy checking code.
+ * Cleaned out unused crud.
+ *
+ * Revision 1.39  2000/01/21 06:15:29  rgb
+ * Added sanity checks on skb_push(), skb_pull() to prevent panics.
+ * Fixed cut-and-paste debug_tunnel to debug_rcv.
+ * Added inbound policy checking code, disabled.
+ * Simplified output code by updating ipp to post-IPIP decapsulation.
+ *
+ * Revision 1.38  1999/12/22 05:08:36  rgb
+ * Checked for null skb, skb->dev, skb->data, skb->dev->name, dev->name,
+ * protocol and take appropriate action for sanity.
+ * Set ipsecdev to NULL if device could not be determined.
+ * Fixed NULL stats access bug if device could not be determined.
+ *
+ * Revision 1.37  1999/12/14 20:07:59  rgb
+ * Added a default switch case to catch bogus encalg values.
+ *
+ * Revision 1.36  1999/12/07 18:57:57  rgb
+ * Fix PFKEY symbol compile error (SADB_*) without pfkey enabled.
+ *
+ * Revision 1.35  1999/12/01 22:15:35  rgb
+ * Add checks for LARVAL and DEAD SAs.
+ * Change state of SA from MATURE to DYING when a soft lifetime is
+ * reached and print debug warning.
+ *
+ * Revision 1.34  1999/11/23 23:04:03  rgb
+ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ *
+ * Revision 1.33  1999/11/19 01:10:06  rgb
+ * Enable protocol handler structures for static linking.
+ *
+ * Revision 1.32  1999/11/18 04:09:19  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.31  1999/11/17 15:53:39  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.30  1999/10/26 15:09:07  rgb
+ * Used debug compiler directives to shut up compiler for decl/assign
+ * statement.
+ *
+ * Revision 1.29  1999/10/16 18:25:37  rgb
+ * Moved SA lifetime expiry checks before packet processing.
+ * Expire SA on replay counter rollover.
+ *
+ * Revision 1.28  1999/10/16 04:23:07  rgb
+ * Add stats for replaywin_errs, replaywin_max_sequence_difference,
+ * authentication errors, encryption size errors, encryption padding
+ * errors, and time since last packet.
+ *
+ * Revision 1.27  1999/10/16 00:30:47  rgb
+ * Added SA lifetime counting.
+ *
+ * Revision 1.26  1999/10/15 22:14:37  rgb
+ * Add debugging.
+ *
+ * Revision 1.25  1999/10/08 18:37:34  rgb
+ * Fix end-of-line spacing to sate whining PHMs.
+ *
+ * Revision 1.24  1999/10/03 18:54:51  rgb
+ * Spinlock support for 2.3.xx.
+ * Don't forget to undo spinlocks on error!
+ *
+ * Revision 1.23  1999/10/01 15:44:53  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.22  1999/10/01 00:01:54  rgb
+ * Added tdb structure locking.
+ *
+ * Revision 1.21  1999/09/18 11:42:12  rgb
+ * Add Marc Boucher's tcpdump cloned packet fix.
+ *
+ * Revision 1.20  1999/09/17 23:50:25  rgb
+ * Add Marc Boucher's hard_header_len patches.
+ *
+ * Revision 1.19  1999/09/10 05:31:36  henry
+ * tentative fix for 2.0.38-crash bug (move chunk of new code into 2.2 #ifdef)
+ *
+ * Revision 1.18  1999/08/28 08:28:06  rgb
+ * Delete redundant sanity check.
+ *
+ * Revision 1.17  1999/08/28 02:00:58  rgb
+ * Add an extra sanity check for null skbs.
+ *
+ * Revision 1.16  1999/08/27 05:21:38  rgb
+ * Clean up skb->data/raw/nh/h manipulation.
+ * Add Marc Boucher's mods to aid tcpdump.
+ *
+ * Revision 1.15  1999/08/25 14:22:40  rgb
+ * Require 4-octet boundary check only for ESP.
+ *
+ * Revision 1.14  1999/08/11 08:36:44  rgb
+ * Add compiler directives to allow configuring out AH, ESP or transforms.
+ *
+ * Revision 1.13  1999/08/03 17:10:49  rgb
+ * Cosmetic fixes and clarification to debug output.
+ *
+ * Revision 1.12  1999/05/09 03:25:36  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.11  1999/05/08 21:23:57  rgb
+ * Add casting to silence the 2.2.x compile.
+ *
+ * Revision 1.10  1999/05/05 22:02:31  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.9  1999/04/29 15:18:01  rgb
+ * hange debugging to respond only to debug_rcv.
+ * Change gettdb parameter to a pointer to reduce stack loading and
+ * facilitate parameter sanity checking.
+ *
+ * Revision 1.8  1999/04/15 15:37:24  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.4.2.2  1999/04/13 20:32:45  rgb
+ * Move null skb sanity check.
+ * Silence debug a bit more when off.
+ * Use stats more effectively.
+ *
+ * Revision 1.4.2.1  1999/03/30 17:10:32  rgb
+ * Update AH+ESP bugfix.
+ *
+ * Revision 1.7  1999/04/11 00:28:59  henry
+ * GPL boilerplate
+ *
+ * Revision 1.6  1999/04/06 04:54:27  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.5  1999/03/17 15:39:23  rgb
+ * Code clean-up.
+ * Bundling bug fix.
+ * ESP_NULL esphlen and IV bug fix.
+ *
+ * Revision 1.4  1999/02/17 16:51:02  rgb
+ * Ditch NET_IPIP dependancy.
+ * Decapsulate recursively for an entire bundle.
+ *
+ * Revision 1.3  1999/02/12 21:22:47  rgb
+ * Convert debugging printks to KLIPS_PRINT macro.
+ * Clean-up cruft.
+ * Process IPIP tunnels internally.
+ *
+ * Revision 1.2  1999/01/26 02:07:36  rgb
+ * Clean up debug code when switched off.
+ * Remove references to INET_GET_PROTOCOL.
+ *
+ * Revision 1.1  1999/01/21 20:29:11  rgb
+ * Converted from transform switching to algorithm switching.
+ *
+ *
+ * Id: ipsec_esp.c,v 1.16 1998/12/02 03:08:11 rgb Exp $
+ *
+ * Log: ipsec_esp.c,v $
+ * Revision 1.16  1998/12/02 03:08:11  rgb
+ * Fix incoming I/F bug in AH and clean up inconsistencies in the I/F
+ * discovery routine in both AH and ESP.
+ *
+ * Revision 1.15  1998/11/30 13:22:51  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.14  1998/11/10 05:55:37  rgb
+ * Add even more detail to 'wrong I/F' debug statement.
+ *
+ * Revision 1.13  1998/11/10 05:01:30  rgb
+ * Clean up debug output to be quiet when disabled.
+ * Add more detail to 'wrong I/F' debug statement.
+ *
+ * Revision 1.12  1998/10/31 06:39:32  rgb
+ * Fixed up comments in #endif directives.
+ * Tidied up debug printk output.
+ * Convert to addrtoa and satoa where possible.
+ *
+ * Revision 1.11  1998/10/27 00:49:30  rgb
+ * AH+ESP bundling bug has been squished.
+ * Cosmetic brace fixing in code.
+ * Newlines added before calls to ipsec_print_ip.
+ * Fix debug output function ID's.
+ *
+ * Revision 1.10  1998/10/22 06:37:22  rgb
+ * Fixed run-on error message to fit 80 columns.
+ *
+ * Revision 1.9  1998/10/20 02:41:04  rgb
+ * Fixed a replay window size sanity test bug.
+ *
+ * Revision 1.8  1998/10/19 18:55:27  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ * \n bugfix to printk debug message.
+ *
+ * Revision 1.7  1998/10/09 04:23:03  rgb
+ * Fixed possible DoS caused by invalid transform called from an ESP
+ * packet.  This should not be a problem when protocol is added to the SA.
+ * Sanity check added for null xf_input routine.  Sanity check added for null
+ * socket buffer returned from xf_input routine.
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ *
+ * Revision 1.6  1998/07/14 15:56:04  rgb
+ * Set sdb->dev to virtual ipsec I/F.
+ *
+ * Revision 1.5  1998/06/30 18:07:46  rgb
+ * Change for ah/esp_protocol stuct visible only if module.
+ *
+ * Revision 1.4  1998/06/30 00:12:46  rgb
+ * Clean up a module compile error.
+ *
+ * Revision 1.3  1998/06/25 19:28:06  rgb
+ * Readjust premature unloading of module on packet receipt.
+ * Make protocol structure abailable to rest of kernel.
+ * Use macro for protocol number.
+ *
+ * Revision 1.2  1998/06/23 02:49:34  rgb
+ * Fix minor #include bug that prevented compiling without debugging.
+ * Added code to check for presence of IPIP protocol if an incoming packet
+ * is IPIP encapped.
+ *
+ * Revision 1.1  1998/06/18 21:27:44  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.9  1998/06/14 23:48:42  rgb
+ * Fix I/F name comparison oops bug.
+ *
+ * Revision 1.8  1998/06/11 07:20:04  rgb
+ * Stats fixed for rx_packets.
+ *
+ * Revision 1.7  1998/06/11 05:53:34  rgb
+ * Added stats for rx error and good packet reporting.
+ *
+ * Revision 1.6  1998/06/05 02:27:28  rgb
+ * Add rx_errors stats.
+ * Fix DoS bug:  skb's not being freed on dropped packets.
+ *
+ * Revision 1.5  1998/05/27 21:21:29  rgb
+ * Fix DoS potential bug.  skb was not being freed if the packet was bad.
+ *
+ * Revision 1.4  1998/05/18 22:31:37  rgb
+ * Minor change in debug output and comments.
+ *
+ * Revision 1.3  1998/04/21 21:29:02  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/12 22:03:19  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:05:59  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Minor cosmetic changes.
+ *
+ * Revision 0.3  1996/11/20 14:35:48  ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_rcv.h linux-patched/net/ipsec/ipsec_rcv.h
--- linux/net/ipsec/ipsec_rcv.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_rcv.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,177 @@
+/*
+ * 
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#define DB_RX_PKTRX	0x0001
+#define DB_RX_PKTRX2	0x0002
+#define DB_RX_DMP	0x0004
+#define DB_RX_TDB	0x0010
+#define DB_RX_XF	0x0020
+#define DB_RX_IPAD	0x0040
+#define DB_RX_INAU	0x0080
+#define DB_RX_OINFO	0x0100
+#define DB_RX_OINFO2	0x0200
+#define DB_RX_OH	0x0400
+#define DB_RX_REPLAY	0x0800
+
+#ifdef __KERNEL__
+/* struct options; */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/config.h>	/* for CONFIG_IP_FORWARD */
+#include <linux/version.h>
+#include <freeswan.h>
+
+extern int
+#ifdef PROTO_HANDLER_SINGLE_PARM
+ipsec_rcv(struct sk_buff *skb);
+#else /* PROTO_HANDLER_SINGLE_PARM */
+ipsec_rcv(struct sk_buff *skb,
+#ifdef NET_21
+	  unsigned short xlen);
+#else /* NET_21 */
+	  struct device *dev,
+	  struct options *opt, 
+	  __u32 daddr,
+	  unsigned short len,
+	  __u32 saddr,
+	  int redo,
+	  struct inet_protocol *protocol);
+#endif /* NET_21 */
+#endif /* PROTO_HANDLER_SINGLE_PARM */
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_rcv;
+#endif /* CONFIG_IPSEC_DEBUG */
+extern int sysctl_ipsec_inbound_policy_check;
+#endif /* __KERNEL__ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.14  2001/09/07 22:15:48  rgb
+ * Fix for removal of transport layer protocol handler arg in 2.4.4.
+ *
+ * Revision 1.13  2001/06/14 19:35:09  rgb
+ * Update copyright date.
+ *
+ * Revision 1.12  2001/03/16 07:36:44  rgb
+ * Fixed #endif comment to sate compiler.
+ *
+ * Revision 1.11  2000/09/21 04:34:21  rgb
+ * Moved declaration of sysctl_ipsec_inbound_policy_check outside
+ * CONFIG_IPSEC_DEBUG. (MB)
+ *
+ * Revision 1.10  2000/09/18 02:36:10  rgb
+ * Exported sysctl_ipsec_inbound_policy_check for skb_decompress().
+ *
+ * Revision 1.9  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.8  1999/11/18 04:09:19  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.7  1999/05/25 01:45:37  rgb
+ * Fix version macros for 2.0.x as a module.
+ *
+ * Revision 1.6  1999/05/08 21:24:27  rgb
+ * Add includes for 2.2.x include into net/ipv4/protocol.c
+ *
+ * Revision 1.5  1999/05/05 22:02:32  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.4  1999/04/11 00:28:59  henry
+ * GPL boilerplate
+ *
+ * Revision 1.3  1999/04/06 04:54:27  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.2  1999/01/22 20:06:59  rgb
+ * Fixed cut-and-paste error from ipsec_esp.h.
+ *
+ * Revision 1.1  1999/01/21 20:29:12  rgb
+ * Converted from transform switching to algorithm switching.
+ *
+ * Log: ipsec_esp.h,v 
+ * Revision 1.4  1998/08/12 00:07:32  rgb
+ * Added data structures for new xforms: null, {,3}dessha1.
+ *
+ * Revision 1.3  1998/07/14 15:57:01  rgb
+ * Add #ifdef __KERNEL__ to protect kernel-only structures.
+ *
+ * Revision 1.2  1998/06/25 19:33:46  rgb
+ * Add prototype for protocol receive function.
+ * Rearrange for more logical layout.
+ *
+ * Revision 1.1  1998/06/18 21:27:45  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.6  1998/06/05 02:28:08  rgb
+ * Minor comment fix.
+ *
+ * Revision 1.5  1998/05/27 22:34:00  rgb
+ * Changed structures to accomodate key separation.
+ *
+ * Revision 1.4  1998/05/18 22:28:43  rgb
+ * Disable key printing facilities from /proc/net/ipsec_*.
+ *
+ * Revision 1.3  1998/04/21 21:29:07  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/12 22:03:20  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:06:00  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5  1997/06/03 04:24:48  ji
+ * Added ESP-3DES-MD5-96 transform.
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Added definitions for new ESP transforms.
+ *
+ * Revision 0.3  1996/11/20 14:35:48  ji
+ * Minor Cleanup.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
+
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_sa.c linux-patched/net/ipsec/ipsec_sa.c
--- linux/net/ipsec/ipsec_sa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_sa.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,786 @@
+/*
+ * Common routines for IPsec SA maintenance routines.
+ *
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ * This is the file formerly known as "ipsec_xform.h"
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#include <linux/random.h>	/* get_random_bytes() */
+#include <freeswan.h>
+#ifdef SPINLOCK
+#ifdef SPINLOCK_23
+#include <linux/spinlock.h> /* *lock* */
+#else /* SPINLOCK_23 */
+#include <asm/spinlock.h> /* *lock* */
+#endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+#ifdef NET_21
+#include <asm/uaccess.h>
+#include <linux/in6.h>
+#endif
+#include <asm/checksum.h>
+#include <net/ip.h>
+
+#include "radij.h"
+
+#include "ipsec_stats.h"
+#include "ipsec_life.h"
+#include "ipsec_sa.h"
+#include "ipsec_xform.h"
+
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_ipe4.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_proto.h"
+#include "ipsec_alg.h"
+
+
+#ifdef CONFIG_IPSEC_DEBUG
+int debug_xform = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];
+#ifdef SPINLOCK
+spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED;
+#else /* SPINLOCK */
+spinlock_t tdb_lock;
+#endif /* SPINLOCK */
+
+int
+ipsec_sadb_init(void)
+{
+	int i;
+
+	for(i = 1; i < SADB_HASHMOD; i++) {
+		ipsec_sadb_hash[i] = NULL;
+	}
+	return 0;
+}
+
+struct ipsec_sa *
+ipsec_sa_getbyid(struct sa_id *said)
+{
+	int hashval;
+	struct ipsec_sa *ips;
+        char sa[SATOA_BUF];
+	size_t sa_len;
+
+	if(!said) {
+		KLIPS_PRINT(debug_xform,
+			    "klips_error:gettdb: "
+			    "null pointer passed in!\n");
+		return NULL;
+	}
+
+	sa_len = satoa(*said, 0, sa, SATOA_BUF);
+
+	hashval = (said->spi+said->dst.s_addr+said->proto) % SADB_HASHMOD;
+	
+	KLIPS_PRINT(debug_xform,
+		    "klips_debug:gettdb: "
+		    "linked entry in tdb table for hash=%d of SA:%s requested.\n",
+		    hashval,
+		    sa_len ? sa : " (error)");
+
+	if(!(ips = ipsec_sadb_hash[hashval])) {
+		KLIPS_PRINT(debug_xform,
+			    "klips_debug:gettdb: "
+			    "no entries in tdb table for hash=%d of SA:%s.\n",
+			    hashval,
+			    sa_len ? sa : " (error)");
+		return NULL;
+	}
+
+	for (; ips; ips = ips->ips_hnext) {
+		if ((ips->ips_said.spi == said->spi) &&
+		    (ips->ips_said.dst.s_addr == said->dst.s_addr) &&
+		    (ips->ips_said.proto == said->proto)) {
+			return ips;
+		}
+	}
+	
+	KLIPS_PRINT(debug_xform,
+		    "klips_debug:gettdb: "
+		    "no entry in linked list for hash=%d of SA:%s.\n",
+		    hashval,
+		    sa_len ? sa : " (error)");
+	return NULL;
+}
+
+/*
+  The tdb table better *NOT* be locked before it is handed in, or SMP locks will happen
+*/
+int
+ipsec_sa_put(struct ipsec_sa *ips)
+{
+	int error = 0;
+	unsigned int hashval;
+
+	if(!ips) {
+		KLIPS_PRINT(debug_xform,
+			    "klips_error:puttdb: "
+			    "null pointer passed in!\n");
+		return -ENODATA;
+	}
+	hashval = ((ips->ips_said.spi + ips->ips_said.dst.s_addr + ips->ips_said.proto) % SADB_HASHMOD);
+
+	spin_lock_bh(&tdb_lock);
+	
+	ips->ips_hnext = ipsec_sadb_hash[hashval];
+	ipsec_sadb_hash[hashval] = ips;
+	
+	spin_unlock_bh(&tdb_lock);
+
+	return error;
+}
+
+/*
+  The tdb table better be locked before it is handed in, or races might happen
+*/
+int
+ipsec_sa_del(struct ipsec_sa *ips)
+{
+	unsigned int hashval;
+	struct ipsec_sa *tdbtp;
+        char sa[SATOA_BUF];
+	size_t sa_len;
+
+	if(!ips) {
+		KLIPS_PRINT(debug_xform,
+			    "klips_error:deltdb: "
+			    "null pointer passed in!\n");
+		return -ENODATA;
+	}
+	
+	sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF);
+	if(ips->ips_inext || ips->ips_onext) {
+		KLIPS_PRINT(debug_xform,
+			    "klips_error:deltdb: "
+			    "SA:%s still linked!\n",
+			    sa_len ? sa : " (error)");
+		return -EMLINK;
+	}
+	
+	hashval = ((ips->ips_said.spi + ips->ips_said.dst.s_addr + ips->ips_said.proto) % SADB_HASHMOD);
+	
+	KLIPS_PRINT(debug_xform,
+		    "klips_debug:deltdb: "
+		    "deleting SA:%s, hashval=%d.\n",
+		    sa_len ? sa : " (error)",
+		    hashval);
+	if(!ipsec_sadb_hash[hashval]) {
+		KLIPS_PRINT(debug_xform,
+			    "klips_debug:deltdb: "
+			    "no entries in tdb table for hash=%d of SA:%s.\n",
+			    hashval,
+			    sa_len ? sa : " (error)");
+		return -ENOENT;
+	}
+	
+	if (ips == ipsec_sadb_hash[hashval]) {
+		ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext;
+		ips->ips_hnext = NULL;
+		KLIPS_PRINT(debug_xform,
+			    "klips_debug:deltdb: "
+			    "successfully deleted first tdb in chain.\n");
+		return 0;
+	} else {
+		for (tdbtp = ipsec_sadb_hash[hashval];
+		     tdbtp;
+		     tdbtp = tdbtp->ips_hnext) {
+			if (tdbtp->ips_hnext == ips) {
+				tdbtp->ips_hnext = ips->ips_hnext;
+				ips->ips_hnext = NULL;
+				KLIPS_PRINT(debug_xform,
+					    "klips_debug:deltdb: "
+					    "successfully deleted link in tdb chain.\n");
+				return 0;
+			}
+		}
+	}
+	
+	KLIPS_PRINT(debug_xform,
+		    "klips_debug:deltdb: "
+		    "no entries in linked list for hash=%d of SA:%s.\n",
+		    hashval,
+		    sa_len ? sa : " (error)");
+	return -ENOENT;
+}
+
+/*
+  The tdb table better be locked before it is handed in, or races might happen
+*/
+int
+ipsec_sa_delchain(struct ipsec_sa *ips)
+{
+	struct ipsec_sa *tdbdel;
+	int error = 0;
+        char sa[SATOA_BUF];
+	size_t sa_len;
+
+	if(!ips) {
+		KLIPS_PRINT(debug_xform,
+			    "klips_error:deltdbchain: "
+			    "null pointer passed in!\n");
+		return -ENODATA;
+	}
+
+	sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF);
+	KLIPS_PRINT(debug_xform,
+		    "klips_debug:deltdbchain: "
+		    "passed SA:%s\n",
+		    sa_len ? sa : " (error)");
+	while(ips->ips_onext) {
+		ips = ips->ips_onext;
+	}
+
+	while(ips) {
+		/* XXX send a pfkey message up to advise of deleted TDB */
+		sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF);
+		KLIPS_PRINT(debug_xform,
+			    "klips_debug:deltdbchain: "
+			    "unlinking and delting SA:%s",
+			    sa_len ? sa : " (error)");
+		tdbdel = ips;
+		ips = ips->ips_inext;
+		if(ips) {
+			sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF);
+			KLIPS_PRINT(debug_xform,
+				    ", inext=%s",
+				    sa_len ? sa : " (error)");
+			tdbdel->ips_inext = NULL;
+			ips->ips_onext = NULL;
+		}
+		KLIPS_PRINT(debug_xform,
+			    ".\n");
+		if((error = ipsec_sa_del(tdbdel))) {
+			KLIPS_PRINT(debug_xform,
+				    "klips_debug:deltdbchain: "
+				    "deltdb returned error %d.\n", -error);
+			return error;
+		}
+		if((error = ipsec_sa_wipe(tdbdel))) {
+			KLIPS_PRINT(debug_xform,
+				    "klips_debug:deltdbchain: "
+				    "ipsec_tdbwipe returned error %d.\n", -error);
+			return error;
+		}
+	}
+	return error;
+}
+
+int 
+ipsec_sadb_cleanup(__u8 proto)
+{
+	int i;
+	int error = 0;
+	struct ipsec_sa *ips, **ipsprev, *tdbdel;
+        char sa[SATOA_BUF];
+	size_t sa_len;
+
+	KLIPS_PRINT(debug_xform,
+		    "klips_debug:ipsec_tdbcleanup: "
+		    "cleaning up proto=%d.\n",
+		    proto);
+
+	spin_lock_bh(&tdb_lock);
+
+	for (i = 0; i < SADB_HASHMOD; i++) {
+		ipsprev = &(ipsec_sadb_hash[i]);
+		ips = ipsec_sadb_hash[i];
+		for(; ips;) {
+			sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF);
+			KLIPS_PRINT(debug_xform,
+				    "klips_debug:ipsec_tdbcleanup: "
+				    "checking SA:%s, hash=%d",
+				    sa_len ? sa : " (error)",
+				    i);
+			tdbdel = ips;
+			ips = tdbdel->ips_hnext;
+			if(ips) {
+				sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF);
+				KLIPS_PRINT(debug_xform,
+					    ", hnext=%s",
+					    sa_len ? sa : " (error)");
+			}
+			if(*ipsprev) {
+				sa_len = satoa((*ipsprev)->ips_said, 0, sa, SATOA_BUF);
+				KLIPS_PRINT(debug_xform,
+					    ", *ipsprev=%s",
+					    sa_len ? sa : " (error)");
+				if((*ipsprev)->ips_hnext) {
+					sa_len = satoa((*ipsprev)->ips_hnext->ips_said, 0, sa, SATOA_BUF);
+					KLIPS_PRINT(debug_xform,
+						    ", *ipsprev->ips_hnext=%s",
+						    sa_len ? sa : " (error)");
+				}
+			}
+			KLIPS_PRINT(debug_xform,
+				    ".\n");
+			if(!proto || (proto == tdbdel->ips_said.proto)) {
+				sa_len = satoa(tdbdel->ips_said, 0, sa, SATOA_BUF);
+				KLIPS_PRINT(debug_xform,
+					    "klips_debug:ipsec_tdbcleanup: "
+					    "deleting SA chain:%s.\n",
+					    sa_len ? sa : " (error)");
+				if((error = ipsec_sa_delchain(tdbdel))) {
+					SENDERR(-error);
+				}
+				ipsprev = &(ipsec_sadb_hash[i]);
+				ips = ipsec_sadb_hash[i];
+
+				KLIPS_PRINT(debug_xform,
+					    "klips_debug:ipsec_tdbcleanup: "
+					    "deleted SA chain:%s",
+					    sa_len ? sa : " (error)");
+				if(ips) {
+					sa_len = satoa(ips->ips_said, 0, sa, SATOA_BUF);
+					KLIPS_PRINT(debug_xform,
+						    ", tdbh[%d]=%s",
+						    i,
+						    sa_len ? sa : " (error)");
+				}
+				if(*ipsprev) {
+					sa_len = satoa((*ipsprev)->ips_said, 0, sa, SATOA_BUF);
+					KLIPS_PRINT(debug_xform,
+						    ", *ipsprev=%s",
+						    sa_len ? sa : " (error)");
+					if((*ipsprev)->ips_hnext) {
+						sa_len = satoa((*ipsprev)->ips_hnext->ips_said, 0, sa, SATOA_BUF);
+						KLIPS_PRINT(debug_xform,
+							    ", *ipsprev->ips_hnext=%s",
+							    sa_len ? sa : " (error)");
+					}
+				}
+				KLIPS_PRINT(debug_xform,
+					    ".\n");
+			} else {
+				ipsprev = &tdbdel;
+			}
+		}
+	}
+ errlab:
+
+	spin_unlock_bh(&tdb_lock);
+
+	return(error);
+}
+
+int
+ipsec_sa_wipe(struct ipsec_sa *ips)
+{
+	if(!ips) {
+		return -ENODATA;
+	}
+
+	if(ips->ips_addr_s) {
+		memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size);
+		kfree(ips->ips_addr_s);
+	}
+	ips->ips_addr_s = NULL;
+
+	if(ips->ips_addr_d) {
+		memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size);
+		kfree(ips->ips_addr_d);
+	}
+	ips->ips_addr_d = NULL;
+
+	if(ips->ips_addr_p) {
+		memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size);
+		kfree(ips->ips_addr_p);
+	}
+	ips->ips_addr_p = NULL;
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	if(ips->ips_natt_oa) {
+		memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size);
+		kfree(ips->ips_natt_oa);
+	}
+	ips->ips_natt_oa = NULL;
+#endif
+
+	if(ips->ips_key_a) {
+		memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size);
+		kfree(ips->ips_key_a);
+	}
+	ips->ips_key_a = NULL;
+
+	if(ips->ips_key_e) {
+#ifdef CONFIG_IPSEC_ALG
+		if (ips->ips_alg_enc&&ips->ips_alg_enc->ixt_e_destroy_key) {
+			ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, 
+					ips->ips_key_e);
+		} else {
+#endif /* CONFIG_IPSEC_ALG */
+		memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size);
+		kfree(ips->ips_key_e);
+#ifdef CONFIG_IPSEC_ALG
+		}
+#endif /* CONFIG_IPSEC_ALG */
+	}
+	ips->ips_key_e = NULL;
+
+	if(ips->ips_iv) {
+		memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size);
+		kfree(ips->ips_iv);
+	}
+	ips->ips_iv = NULL;
+
+	if(ips->ips_ident_s.data) {
+		memset((caddr_t)(ips->ips_ident_s.data),
+                       0,
+		       ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident));
+		kfree(ips->ips_ident_s.data);
+        }
+	ips->ips_ident_s.data = NULL;
+	
+	if(ips->ips_ident_d.data) {
+		memset((caddr_t)(ips->ips_ident_d.data),
+                       0,
+		       ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident));
+		kfree(ips->ips_ident_d.data);
+        }
+	ips->ips_ident_d.data = NULL;
+
+#ifdef CONFIG_IPSEC_ALG
+	if (ips->ips_alg_enc||ips->ips_alg_auth) {
+		ipsec_alg_sa_wipe(ips);
+	}
+#endif /* CONFIG_IPSEC_ALG */
+	
+	memset((caddr_t)ips, 0, sizeof(*ips));
+	kfree(ips);
+	ips = NULL;
+
+	return 0;
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.5  2003/02/07 13:14:25  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.4.2.1  2003/02/06 22:09:50  jjo
+ * sync to alg-0.8.1-rc4
+ *
+ * Revision 1.4  2002/10/30 12:41:26  ken
+ * #ifdef around ipsec_alg_sa_wipe when not using ALGs
+ *
+ * Revision 1.3  2002/09/05 03:53:52  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.2  2002/09/05 03:27:08  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.5  2002/01/29 17:17:56  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.4  2002/01/29 04:00:52  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.3  2002/01/29 02:13:18  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.2  2001/11/26 09:16:15  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.2  2001/10/22 21:05:41  mcr
+ * 	removed phony prototype for des_set_key.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:24:57  mcr
+ * 	struct tdb -> struct ipsec_sa.
+ * 	sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
+ * 	ipsec_xform.c removed. header file still contains useful things.
+ *
+ *
+ *
+ * CLONED from ipsec_xform.c:
+ * Revision 1.53  2001/09/08 21:13:34  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.52  2001/06/14 19:35:11  rgb
+ * Update copyright date.
+ *
+ * Revision 1.51  2001/05/30 08:14:03  rgb
+ * Removed vestiges of esp-null transforms.
+ *
+ * Revision 1.50  2001/05/03 19:43:18  rgb
+ * Initialise error return variable.
+ * Update SENDERR macro.
+ * Fix sign of error return code for ipsec_tdbcleanup().
+ * Use more appropriate return code for ipsec_tdbwipe().
+ *
+ * Revision 1.49  2001/04/19 18:56:17  rgb
+ * Fixed tdb table locking comments.
+ *
+ * Revision 1.48  2001/02/27 22:24:55  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.47  2000/11/06 04:32:08  rgb
+ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
+ *
+ * Revision 1.46  2000/09/20 16:21:57  rgb
+ * Cleaned up ident string alloc/free.
+ *
+ * Revision 1.45  2000/09/08 19:16:51  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Removed all references to CONFIG_IPSEC_PFKEYv2.
+ *
+ * Revision 1.44  2000/08/30 05:29:04  rgb
+ * Compiler-define out no longer used tdb_init() in ipsec_xform.c.
+ *
+ * Revision 1.43  2000/08/18 21:30:41  rgb
+ * Purged all tdb_spi, tdb_proto and tdb_dst macros.  They are unclear.
+ *
+ * Revision 1.42  2000/08/01 14:51:51  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.41  2000/07/28 14:58:31  rgb
+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
+ *
+ * Revision 1.40  2000/06/28 05:50:11  rgb
+ * Actually set iv_bits.
+ *
+ * Revision 1.39  2000/05/10 23:11:09  rgb
+ * Added netlink debugging output.
+ * Added a cast to quiet down the ntohl bug.
+ *
+ * Revision 1.38  2000/05/10 19:18:42  rgb
+ * Cast output of ntohl so that the broken prototype doesn't make our
+ * compile noisy.
+ *
+ * Revision 1.37  2000/03/16 14:04:59  rgb
+ * Hardwired CONFIG_IPSEC_PFKEYv2 on.
+ *
+ * Revision 1.36  2000/01/26 10:11:28  rgb
+ * Fixed spacing in error text causing run-in words.
+ *
+ * Revision 1.35  2000/01/21 06:17:16  rgb
+ * Tidied up compiler directive indentation for readability.
+ * Added ictx,octx vars for simplification.(kravietz)
+ * Added macros for HMAC padding magic numbers.(kravietz)
+ * Fixed missing key length reporting bug.
+ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in.
+ *
+ * Revision 1.34  1999/12/08 00:04:19  rgb
+ * Fixed SA direction overwriting bug for netlink users.
+ *
+ * Revision 1.33  1999/12/01 22:16:44  rgb
+ * Minor formatting changes in ESP MD5 initialisation.
+ *
+ * Revision 1.32  1999/11/25 09:06:36  rgb
+ * Fixed error return messages, should be returning negative numbers.
+ * Implemented SENDERR macro for propagating error codes.
+ * Added debug message and separate error code for algorithms not compiled
+ * in.
+ *
+ * Revision 1.31  1999/11/23 23:06:26  rgb
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ *
+ * Revision 1.30  1999/11/18 04:09:20  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.29  1999/11/17 15:53:40  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.28  1999/10/18 20:04:01  rgb
+ * Clean-out unused cruft.
+ *
+ * Revision 1.27  1999/10/03 19:01:03  rgb
+ * Spinlock support for 2.3.xx and 2.0.xx kernels.
+ *
+ * Revision 1.26  1999/10/01 16:22:24  rgb
+ * Switch from assignment init. to functional init. of spinlocks.
+ *
+ * Revision 1.25  1999/10/01 15:44:54  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.24  1999/10/01 00:03:46  rgb
+ * Added tdb structure locking.
+ * Minor formatting changes.
+ * Add function to initialize tdb hash table.
+ *
+ * Revision 1.23  1999/05/25 22:42:12  rgb
+ * Add deltdbchain() debugging.
+ *
+ * Revision 1.22  1999/05/25 21:24:31  rgb
+ * Add debugging statements to deltdbchain().
+ *
+ * Revision 1.21  1999/05/25 03:51:48  rgb
+ * Refix error return code.
+ *
+ * Revision 1.20  1999/05/25 03:34:07  rgb
+ * Fix error return for flush.
+ *
+ * Revision 1.19  1999/05/09 03:25:37  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.18  1999/05/05 22:02:32  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.17  1999/04/29 15:20:16  rgb
+ * Change gettdb parameter to a pointer to reduce stack loading and
+ * facilitate parameter sanity checking.
+ * Add sanity checking for null pointer arguments.
+ * Add debugging instrumentation.
+ * Add function deltdbchain() which will take care of unlinking,
+ * zeroing and deleting a chain of tdbs.
+ * Add a parameter to tdbcleanup to be able to delete a class of SAs.
+ * tdbwipe now actually zeroes the tdb as well as any of its pointed
+ * structures.
+ *
+ * Revision 1.16  1999/04/16 15:36:29  rgb
+ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing.
+ *
+ * Revision 1.15  1999/04/11 00:29:01  henry
+ * GPL boilerplate
+ *
+ * Revision 1.14  1999/04/06 04:54:28  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.13  1999/02/19 18:23:01  rgb
+ * Nix debug off compile warning.
+ *
+ * Revision 1.12  1999/02/17 16:52:16  rgb
+ * Consolidate satoa()s for space and speed efficiency.
+ * Convert DEBUG_IPSEC to KLIPS_PRINT
+ * Clean out unused cruft.
+ * Ditch NET_IPIP dependancy.
+ * Loop for 3des key setting.
+ *
+ * Revision 1.11  1999/01/26 02:09:05  rgb
+ * Remove ah/esp/IPIP switching on include files.
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ * Removed dead code.
+ * Clean up debug code when switched off.
+ * Remove references to INET_GET_PROTOCOL.
+ * Added code exclusion macros to reduce code from unused algorithms.
+ *
+ * Revision 1.10  1999/01/22 06:28:55  rgb
+ * Cruft clean-out.
+ * Put random IV generation in kernel.
+ * Added algorithm switch code.
+ * Enhanced debugging.
+ * 64-bit clean-up.
+ *
+ * Revision 1.9  1998/11/30 13:22:55  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.8  1998/11/25 04:59:06  rgb
+ * Add conditionals for no IPIP tunnel code.
+ * Delete commented out code.
+ *
+ * Revision 1.7  1998/10/31 06:50:41  rgb
+ * Convert xform ASCII names to no spaces.
+ * Fixed up comments in #endif directives.
+ *
+ * Revision 1.6  1998/10/19 14:44:28  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.5  1998/10/09 04:32:19  rgb
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ *
+ * Revision 1.4  1998/08/12 00:11:31  rgb
+ * Added new xform functions to the xform table.
+ * Fixed minor debug output spelling error.
+ *
+ * Revision 1.3  1998/07/09 17:45:31  rgb
+ * Clarify algorithm not available message.
+ *
+ * Revision 1.2  1998/06/23 03:00:51  rgb
+ * Check for presence of IPIP protocol if it is setup one way (we don't
+ * know what has been set up the other way and can only assume it will be
+ * symmetrical with the exception of keys).
+ *
+ * Revision 1.1  1998/06/18 21:27:51  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.3  1998/06/11 05:54:59  rgb
+ * Added transform version string pointer to xformsw initialisations.
+ *
+ * Revision 1.2  1998/04/21 21:28:57  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1  1998/04/09 03:06:13  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5  1997/06/03 04:24:48  ji
+ * Added ESP-3DES-MD5-96
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Added new transforms.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_sa.h linux-patched/net/ipsec/ipsec_sa.h
--- linux/net/ipsec/ipsec_sa.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_sa.h	Thu Sep  5 04:53:52 2002
@@ -0,0 +1,215 @@
+/*
+ * @(#) Definitions of IPsec Security Association (ipsec_sa)
+ *
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ * This file derived from ipsec_xform.h on 2001/9/18 by mcr.
+ *
+ */
+
+/* 
+ * This file describes the IPsec Security Association Structure.
+ *
+ * This structure keeps track of a single transform that may be done
+ * to a set of packets. It can describe applying the transform or
+ * apply the reverse. (e.g. compression vs expansion). However, it
+ * only describes one at a time. To describe both, two structures would
+ * be used, but since the sides of the transform are performed 
+ * on different machines typically it is usual to have only one side
+ * of each association.
+ * 
+ */
+
+#ifndef _IPSEC_SA_H_
+
+#include "ipsec_stats.h"
+#include "ipsec_life.h"
+#include "ipsec_eroute.h"
+
+/* 'struct ipsec_sa' should be 64bit aligned when allocated. */
+struct ipsec_sa 	                        
+{
+	atomic_t         ips_usecount;       /* use count for this struct */
+	struct ipsec_sa	*ips_hnext;	     /* next in hash chain */
+	struct ipsec_sa	*ips_inext;	     /* pointer to next xform */
+	struct ipsec_sa	*ips_onext;	     /* pointer to prev xform */
+
+	struct ifnet	*ips_rcvif;	     /* related rcv encap interface */
+
+	struct sa_id	ips_said;	     /* SA ID */
+
+	__u32		ips_seq;    /* seq num of msg that initiated this SA */
+	__u32		ips_pid;    /* PID of process that initiated this SA */
+	__u8		ips_authalg;	     /* auth algorithm for this SA */
+	__u8		ips_encalg;	     /* enc algorithm for this SA */
+
+	struct ipsec_stats ips_errs;
+
+	__u8		ips_replaywin;		/* replay window size */
+	__u8		ips_state;		/* state of SA */
+	__u32		ips_replaywin_lastseq;	/* last pkt sequence num */
+	__u64		ips_replaywin_bitmap;	/* bitmap of received pkts */
+	__u32		ips_replaywin_maxdiff;	/* max pkt sequence difference */
+
+	__u32		ips_flags;		/* generic xform flags */
+
+
+	struct ipsec_lifetimes ips_life;             /* lifetime records */
+
+	/* selector information */
+	struct sockaddr*ips_addr_s;		/* src sockaddr */
+	struct sockaddr*ips_addr_d;		/* dst sockaddr */
+	struct sockaddr*ips_addr_p;		/* proxy sockaddr */
+	__u16		ips_addr_s_size;
+	__u16		ips_addr_d_size;
+	__u16		ips_addr_p_size;
+	ip_address	ips_flow_s;
+	ip_address	ips_flow_d;
+	ip_address	ips_mask_s;
+	ip_address	ips_mask_d;
+
+	__u16		ips_key_bits_a;	    /* size of authkey in bits */
+	__u16		ips_auth_bits;	    /* size of authenticator in bits */
+	__u16		ips_key_bits_e;	    /* size of enckey in bits */
+	__u16		ips_iv_bits;	    /* size of IV in bits */
+	__u8		ips_iv_size;
+	__u16		ips_key_a_size;
+	__u16		ips_key_e_size;
+
+	caddr_t		ips_key_a;		/* authentication key */
+	caddr_t		ips_key_e;		/* encryption key */
+	caddr_t	        ips_iv;			/* Initialisation Vector */
+
+	struct ident	ips_ident_s;		/* identity src */
+	struct ident	ips_ident_d;		/* identity dst */
+
+#ifdef CONFIG_IPSEC_IPCOMP
+	__u16		ips_comp_adapt_tries;	/* ipcomp self-adaption tries */
+	__u16		ips_comp_adapt_skip;	/* ipcomp self-adaption to-skip */
+	__u64		ips_comp_ratio_cbytes;	/* compressed bytes */
+	__u64		ips_comp_ratio_dbytes;	/* decompressed (or uncompressed) bytes */
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	__u8        ips_natt_type;
+	__u8        ips_natt_reserved[3];
+	__u16       ips_natt_sport;
+	__u16       ips_natt_dport;
+ 
+	struct sockaddr *ips_natt_oa;
+	__u16		ips_natt_oa_size;
+	__u16		ips_natt_reserved2;
+#endif
+
+#if 0
+	__u32		ips_sens_dpd;
+	__u8		ips_sens_sens_level;
+	__u8		ips_sens_sens_len;
+	__u64*		ips_sens_sens_bitmap;
+	__u8		ips_sens_integ_level;
+	__u8		ips_sens_integ_len;
+	__u64*		ips_sens_integ_bitmap;
+#endif
+	struct ipsec_alg_enc *ips_alg_enc;
+	struct ipsec_alg_auth *ips_alg_auth;
+};
+
+enum ipsec_direction {
+	ipsec_incoming = 1,
+	ipsec_outgoing = 2
+};
+
+#ifdef IPSEC_KLIPS1_COMPAT
+#define tdb_hnext ips_hnext
+#define tdb_inext ips_inext
+#define tdb_onext ips_onext
+#define tdb_said  ips_said
+#define tdb_addr_s ips_addr_s
+#define tdb_addr_s_size ips_addr_s_size
+#define tdb_addr_d ips_addr_d
+#define tdb_addr_d_size ips_addr_d_size
+#define tdb_addr_p ips_addr_p
+#define tdb_addr_p_size ips_addr_p_size
+#define tdb_ident_s ips_ident_s
+#define tdb_ident_d ips_ident_d
+#define tdb_state   ips_state
+
+#define tdb_replaywin ips_replaywin
+#define tdb_replaywin_lastseq ips_replaywin_lastseq
+#define tdb_replaywin_bitmap  ips_replaywin_bitmap
+#define tdb_replaywin_maxdiff ips_replaywin_maxdiff
+#define tdb_replaywin_errs    ips_errs.ips_replaywin_errs
+
+#define tdb_encalg    ips_encalg
+#define tdb_encsize_errs ips_errs.ips_encsize_errs
+#define tdb_encpad_errs  ips_errs.ips_encpad_errs
+#define tdb_alg_errs  ips_errs.ips_alg_errs
+#define tdb_authalg   ips_authalg
+#define tdb_auth_errs ips_errs.ips_auth_errs
+#define tdb_iv        ips_iv
+#define tdb_iv_size   ips_iv_size
+#define tdb_iv_bits   ips_iv_bits
+#define tdb_key_e     ips_key_e
+#define tdb_key_e_size ips_key_e_size
+#define tdb_key_bits_e ips_key_bits_e
+#define tdb_key_bits_a ips_key_bits_a
+#define tdb_key_a     ips_key_a
+#define tdb_auth_bits ips_auth_bits
+#define tdb_key_a_size ips_key_a_size
+
+#define tdb_comp_ratio_cbytes ips_comp_ratio_cbytes 
+#define tdb_comp_ratio_dbytes ips_comp_ratio_dbytes 
+#define tdb_comp_adapt_tries  ips_comp_adapt_tries
+#define tdb_comp_adapt_skip   ips_comp_adapt_skip
+
+#define tdb_mask_s    ips_mask_s
+#define tdb_flow_s    ips_flow_s
+#define tdb_mask_d    ips_mask_d
+#define tdb_flow_d    ips_flow_d
+
+#define tdb_flags     ips_flags
+#define tdb_rcvif     ips_rcvif
+
+#endif /* IPSEC_KLIPS1_COMPAT */
+
+#define _IPSEC_SA_H
+#endif /* _IPSEC_SA_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.3  2002/09/05 03:53:52  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.2  2002/09/05 03:27:08  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.2  2001/11/26 09:16:15  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:24:58  mcr
+ * 	struct tdb -> struct ipsec_sa.
+ * 	sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
+ * 	ipsec_xform.c removed. header file still contains useful things.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_sha1.c linux-patched/net/ipsec/ipsec_sha1.c
--- linux/net/ipsec/ipsec_sha1.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_sha1.c	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,204 @@
+/*
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ * The rest of the code is derived from sha1.c by Steve Reid, which is
+ * public domain.
+ * Minor cosmetic changes to accomodate it in the Linux kernel by ji.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/string.h>
+
+#include "ipsec_sha1.h"
+
+#if defined(rol)
+#undef rol
+#endif
+
+#define SHA1HANDSOFF
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef __LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+    |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+    ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(__u32 state[5], __u8 buffer[64])
+{
+__u32 a, b, c, d, e;
+typedef union {
+    unsigned char c[64];
+    __u32 l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+    block = (CHAR64LONG16*)workspace;
+    memcpy(block, buffer, 64);
+#else
+    block = (CHAR64LONG16*)buffer;
+#endif
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, unsigned char* data, __u32 len)
+{
+__u32 i, j;
+
+    j = context->count[0];
+    if ((context->count[0] += len << 3) < j)
+	context->count[1]++;
+    context->count[1] += (len>>29);
+    j = (j >> 3) & 63;
+    if ((j + len) > 63) {
+        memcpy(&context->buffer[j], data, (i = 64-j));
+        SHA1Transform(context->state, context->buffer);
+        for ( ; i + 63 < len; i += 64) {
+            SHA1Transform(context->state, &data[i]);
+        }
+        j = 0;
+    }
+    else i = 0;
+    memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+__u32 i, j;
+unsigned char finalcount[8];
+
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+    }
+    SHA1Update(context, (unsigned char *)"\200", 1);
+    while ((context->count[0] & 504) != 448) {
+        SHA1Update(context, (unsigned char *)"\0", 1);
+    }
+    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
+    for (i = 0; i < 20; i++) {
+        digest[i] = (unsigned char)
+         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+    }
+    /* Wipe variables */
+    i = j = 0;
+    memset(context->buffer, 0, 64);
+    memset(context->state, 0, 20);
+    memset(context->count, 0, 8);
+    memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite its own static vars */
+    SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.5  1999/12/13 13:59:13  rgb
+ * Quick fix to argument size to Update bugs.
+ *
+ * Revision 1.4  1999/04/11 00:29:00  henry
+ * GPL boilerplate
+ *
+ * Revision 1.3  1999/04/06 04:54:27  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.2  1999/01/22 06:55:50  rgb
+ * 64-bit clean-up.
+ *
+ * Revision 1.1  1998/06/18 21:27:50  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2  1998/04/23 20:54:04  rgb
+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
+ * verified.
+ *
+ * Revision 1.1  1998/04/09 03:06:11  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:05  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * New transform
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_sha1.h linux-patched/net/ipsec/ipsec_sha1.h
--- linux/net/ipsec/ipsec_sha1.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_sha1.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,71 @@
+/*
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ * Here is the original comment from the distribution:
+
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+ * Adapted for use by the IPSEC code by John Ioannidis
+ */
+
+
+#ifndef _IPSEC_SHA1_H_
+#define _IPSEC_SHA1_H_
+
+typedef struct
+{
+	__u32	state[5];
+	__u32	count[2];
+	__u8	buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(__u32 state[5], __u8 buffer[64]);
+void SHA1Init(SHA1_CTX *context);
+void SHA1Update(SHA1_CTX *context, unsigned char *data, __u32 len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX *context);
+
+ 
+#endif /* _IPSEC_SHA1_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.5  1999/12/13 13:59:13  rgb
+ * Quick fix to argument size to Update bugs.
+ *
+ * Revision 1.4  1999/12/07 18:16:23  rgb
+ * Fixed comments at end of #endif lines.
+ *
+ * Revision 1.3  1999/04/06 04:54:27  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.2  1998/11/30 13:22:54  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.1  1998/06/18 21:27:50  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.2  1998/04/23 20:54:05  rgb
+ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
+ * verified.
+ *
+ * Revision 1.1  1998/04/09 03:04:21  henry
+ * sources moved up from linux/net/ipsec
+ * these two include files modified not to include others except in kernel
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * New transform
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_stats.h linux-patched/net/ipsec/ipsec_stats.h
--- linux/net/ipsec/ipsec_stats.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_stats.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,55 @@
+/*
+ * @(#) definition of ipsec_stats structure
+ *
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ */
+
+/* 
+ * This file describes the errors/statistics that FreeSWAN collects.
+ */
+
+#ifndef _IPSEC_STATS_H_
+
+struct ipsec_stats {
+	__u32		ips_alg_errs;	       /* number of algorithm errors */
+	__u32		ips_auth_errs;	       /* # of authentication errors */
+	__u32		ips_encsize_errs;      /* # of encryption size errors*/
+	__u32		ips_encpad_errs;       /* # of encryption pad  errors*/
+	__u32		ips_replaywin_errs;    /* # of pkt sequence errors */
+};
+
+#define _IPSEC_STATS_H_
+#endif /* _IPSEC_STATS_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.2  2001/11/26 09:16:16  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.1.2.1  2001/09/25 02:27:00  mcr
+ * 	statistics moved to seperate structure.
+ *
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_tunnel.c linux-patched/net/ipsec/ipsec_tunnel.c
--- linux/net/ipsec/ipsec_tunnel.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_tunnel.c	Fri Jul  4 20:07:34 2003
@@ -0,0 +1,4164 @@
+/*
+ * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+char ipsec_tunnel_c_version[] = "RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/config.h>	/* for CONFIG_IP_FORWARD */
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+/* XXX-mcr remove this definition when the code has been properly rototiled */
+#define IPSEC_KLIPS1_COMPAT 1
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/tcp.h>         /* struct tcphdr */
+#include <linux/udp.h>         /* struct udphdr */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+#ifdef NET_21
+# define MSS_HACK_		/* experimental */
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+# define ip_chk_addr inet_addr_type
+# define IS_MYADDR RTN_LOCAL
+# include <net/dst.h>
+# undef dev_kfree_skb
+# define dev_kfree_skb(a,b) kfree_skb(a)
+# define proto_priv cb
+# define PHYSDEV_TYPE
+#endif /* NET_21 */
+#include <asm/checksum.h>
+#include <net/icmp.h>		/* icmp_send() */
+#include <net/ip.h>
+#ifdef NETDEV_23
+# include <linux/netfilter_ipv4.h>
+#endif /* NETDEV_23 */
+
+#include "ipsec_alg.h"
+
+#include <linux/if_arp.h>
+#ifdef MSS_HACK
+# include <net/tcp.h>		/* TCP options */
+#endif	/* MSS_HACK */
+
+#include "radij.h"
+#include "ipsec_life.h"
+#include "ipsec_xform.h"
+#include "ipsec_eroute.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_sa.h"
+#include "ipsec_tunnel.h"
+#include "ipsec_ipe4.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+
+#ifdef CONFIG_IPSEC_IPCOMP
+# include "ipcomp.h"
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_proto.h"
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+#include <linux/udp.h>
+#endif
+
+static __u32 zeroes[64];
+
+#ifdef CONFIG_IPSEC_DEBUG
+int debug_tunnel = 0;
+int sysctl_ipsec_debug_verbose = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+int sysctl_ipsec_icmp = 0;
+int sysctl_ipsec_tos = 0;
+
+/*
+ * If the IP packet (iph) is a carrying TCP/UDP, then set the encaps
+ * source and destination ports to those from the TCP/UDP header.
+ */
+static void extract_ports(struct iphdr * iph, struct sockaddr_encap * er)
+{
+	struct udphdr *udp;
+
+	switch (iph->protocol) {
+	case IPPROTO_UDP:
+	case IPPROTO_TCP:
+		/*
+		 * The ports are at the same offsets in a TCP and UDP
+		 * header so hack it ...
+		 */
+		udp = (struct udphdr*)(((char*)iph)+(iph->ihl<<2));
+		er->sen_sport = udp->source;
+		er->sen_dport = udp->dest;
+		break;
+	default:
+		er->sen_sport = 0;
+		er->sen_dport = 0;
+		break;
+	}
+}
+
+/*
+ * A TRAP eroute is installed and we want to replace it with a HOLD
+ * eroute.
+ */
+static int create_hold_eroute(struct sk_buff * skb, struct iphdr * iph,
+			      uint32_t eroute_pid)
+{
+	struct eroute hold_eroute;
+	struct sa_id hold_said;
+	struct sk_buff *first, *last;
+	int error;
+
+	first = last = NULL;
+	memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute));
+	memset((caddr_t)&hold_said, 0, sizeof(hold_said));
+	
+	hold_said.proto = IPPROTO_INT;
+	hold_said.spi = htonl(SPI_HOLD);
+	hold_said.dst.s_addr = INADDR_ANY;
+	
+	hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap);
+	hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap);
+	hold_eroute.er_eaddr.sen_family = AF_ENCAP;
+	hold_eroute.er_emask.sen_family = AF_ENCAP;
+	hold_eroute.er_eaddr.sen_type = SENT_IP4;
+	hold_eroute.er_emask.sen_type = 255;
+	
+	hold_eroute.er_eaddr.sen_ip_src.s_addr = iph->saddr;
+	hold_eroute.er_eaddr.sen_ip_dst.s_addr = iph->daddr;
+	hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST;
+	hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST;
+	hold_eroute.er_emask.sen_sport = ~0;
+	hold_eroute.er_emask.sen_dport = ~0;
+	hold_eroute.er_pid = eroute_pid;
+	hold_eroute.er_count = 0;
+	hold_eroute.er_lasttime = jiffies/HZ;
+						
+	hold_eroute.er_eaddr.sen_proto = iph->protocol;
+	extract_ports(iph, &hold_eroute.er_eaddr);
+
+#ifdef CONFIG_IPSEC_DEBUG
+	if (debug_pfkey) {
+		char buf1[64], buf2[64];
+		subnettoa(hold_eroute.er_eaddr.sen_ip_src,
+			  hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(hold_eroute.er_eaddr.sen_ip_dst,
+			  hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "calling breakeroute and makeroute for %s:%d->%s:%d %d HOLD eroute.\n",
+			    buf1, ntohs(hold_eroute.er_eaddr.sen_sport),
+			    buf2, ntohs(hold_eroute.er_eaddr.sen_dport),
+			    hold_eroute.er_eaddr.sen_proto);
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	if (ipsec_breakroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask),
+			     &first, &last)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "HOLD breakeroute found nothing.\n");
+	} else {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "HOLD breakroute deleted %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u %u\n",
+			    NIPQUAD(hold_eroute.er_eaddr.sen_ip_src),
+			    ntohs(hold_eroute.er_eaddr.sen_sport),
+			    NIPQUAD(hold_eroute.er_eaddr.sen_ip_dst),
+			    ntohs(hold_eroute.er_eaddr.sen_dport),
+			    hold_eroute.er_eaddr.sen_proto);
+	}
+	if (first != NULL)
+		kfree_skb(first);
+	if (last != NULL)
+		kfree_skb(last);
+
+	error = ipsec_makeroute(&(hold_eroute.er_eaddr),
+				&(hold_eroute.er_emask),
+				hold_said, eroute_pid, skb, NULL, NULL);
+	if (error) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "HOLD makeroute returned %d, failed.\n", error);
+	} else {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "HOLD makeroute call successful.\n");
+	}
+	return (error == 0);
+}
+
+
+
+#ifdef CONFIG_IPSEC_DEBUG_
+DEBUG_NO_STATIC void
+dmp(char *s, caddr_t bb, int len)
+{
+	int i;
+	unsigned char *b = bb;
+  
+	if (debug_tunnel) {
+		printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: "
+		       "at %s, len=%d:",
+		       s,
+		       len);
+		for (i=0; i < len; i++) {
+			if(!(i%16)){
+				printk("\nklips_debug:  ");
+			}
+			printk(" %02x", *b++);
+		}
+		printk("\n");
+	}
+}
+#else /* CONFIG_IPSEC_DEBUG */
+#define dmp(_x, _y, _z) 
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#ifndef SKB_COPY_EXPAND
+/*
+ *	This is mostly skbuff.c:skb_copy().
+ */
+struct sk_buff *
+skb_copy_expand(struct sk_buff *skb, int headroom, int tailroom, int priority)
+{
+	struct sk_buff *n;
+	unsigned long offset;
+
+	/*
+	 *	Do sanity checking
+	 */
+	if((headroom < 0) || (tailroom < 0) || ((headroom+tailroom) < 0)) {
+		printk(KERN_WARNING
+		       "klips_error:skb_copy_expand: "
+		       "Illegal negative head,tailroom %d,%d\n",
+		       headroom,
+		       tailroom);
+		return NULL;
+	}
+	/*
+	 *	Allocate the copy buffer
+	 */
+	 
+#ifndef NET_21
+	IS_SKB(skb);
+#endif /* !NET_21 */
+
+
+	n=alloc_skb(skb->end - skb->head + headroom + tailroom, priority);
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+		    "klips_debug:skb_copy_expand: "
+		    "head=%p data=%p tail=%p end=%p end-head=%d tail-data=%d\n",
+		    skb->head,
+		    skb->data,
+		    skb->tail,
+		    skb->end,
+		    skb->end - skb->head,
+		    skb->tail - skb->data);
+
+	if(n==NULL)
+		return NULL;
+
+	/*
+	 *	Shift between the two data areas in bytes
+	 */
+	 
+	/* offset=n->head-skb->head; */ /* moved down a few lines */
+
+	/* Set the data pointer */
+	skb_reserve(n,skb->data-skb->head+headroom);
+	/* Set the tail pointer and length */
+	if(skb_tailroom(n) < skb->len) {
+		printk(KERN_WARNING "klips_error:skb_copy_expand: "
+		       "tried to skb_put %ld, %d available.  This should never happen, please report.\n",
+		       (unsigned long int)skb->len,
+		       skb_tailroom(n));
+		dev_kfree_skb(n, FREE_WRITE);
+		return NULL;
+	}
+	skb_put(n,skb->len);
+
+	offset=n->head + headroom - skb->head;
+
+	/* Copy the bytes */
+	memcpy(n->head + headroom, skb->head,skb->end-skb->head);
+#ifdef NET_21
+	n->csum=skb->csum;
+	n->priority=skb->priority;
+	n->dst=dst_clone(skb->dst);
+	if(skb->nh.raw)
+		n->nh.raw=skb->nh.raw+offset;
+#ifndef NETDEV_23
+	n->is_clone=0;
+#endif /* NETDEV_23 */
+	atomic_set(&n->users, 1);
+	n->destructor = NULL;
+	n->security=skb->security;
+#else /* NET_21 */
+	n->link3=NULL;
+	n->when=skb->when;
+	if(skb->ip_hdr)
+	        n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
+	n->saddr=skb->saddr;
+	n->daddr=skb->daddr;
+	n->raddr=skb->raddr;
+	n->seq=skb->seq;
+	n->end_seq=skb->end_seq;
+	n->ack_seq=skb->ack_seq;
+	n->acked=skb->acked;
+	n->free=1;
+	n->arp=skb->arp;
+	n->tries=0;
+	n->lock=0;
+	n->users=0;
+#endif /* NET_21 */
+	n->protocol=skb->protocol;
+	n->list=NULL;
+	n->sk=NULL;
+	n->dev=skb->dev;
+	if(skb->h.raw)
+		n->h.raw=skb->h.raw+offset;
+	if(skb->mac.raw) 
+		n->mac.raw=skb->mac.raw+offset;
+	memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
+#ifndef NETDEV_23
+	n->used=skb->used;
+#endif /* !NETDEV_23 */
+	n->pkt_type=skb->pkt_type;
+	n->stamp=skb->stamp;
+	
+#ifndef NET_21
+	IS_SKB(n);
+#endif /* !NET_21 */
+	return n;
+}
+#endif /* !SKB_COPY_EXPAND */
+
+#ifdef CONFIG_IPSEC_DEBUG
+void
+ipsec_print_ip(struct iphdr *ip)
+{
+	char buf[ADDRTOA_BUF];
+
+	printk(KERN_INFO "klips_debug:   IP:");
+	printk(" ihl:%d", ip->ihl*4);
+	printk(" ver:%d", ip->version);
+	printk(" tos:%d", ip->tos);
+	printk(" tlen:%d", ntohs(ip->tot_len));
+	printk(" id:%d", ntohs(ip->id));
+	printk(" %s%s%sfrag_off:%d",
+               ip->frag_off & __constant_htons(IP_CE) ? "CE " : "",
+               ip->frag_off & __constant_htons(IP_DF) ? "DF " : "",
+               ip->frag_off & __constant_htons(IP_MF) ? "MF " : "",
+               (ntohs(ip->frag_off) & IP_OFFSET) << 3);
+	printk(" ttl:%d", ip->ttl);
+	printk(" proto:%d", ip->protocol);
+	if(ip->protocol == IPPROTO_UDP)
+		printk(" (UDP)");
+	if(ip->protocol == IPPROTO_TCP)
+		printk(" (TCP)");
+	if(ip->protocol == IPPROTO_ICMP)
+		printk(" (ICMP)");
+	printk(" chk:%d", ntohs(ip->check));
+	addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf));
+	printk(" saddr:%s", buf);
+	if(ip->protocol == IPPROTO_UDP)
+		printk(":%d",
+		       ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));
+	if(ip->protocol == IPPROTO_TCP)
+		printk(":%d",
+		       ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));
+	addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf));
+	printk(" daddr:%s", buf);
+	if(ip->protocol == IPPROTO_UDP)
+		printk(":%d",
+		       ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));
+	if(ip->protocol == IPPROTO_TCP)
+		printk(":%d",
+		       ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));
+	if(ip->protocol == IPPROTO_ICMP)
+		printk(" type:code=%d:%d",
+		       ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type,
+		       ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code);
+	printk("\n");
+
+	if(sysctl_ipsec_debug_verbose) {
+		__u8 *c;
+		int i;
+		
+		c = ((__u8*)ip) + ip->ihl*4;
+		for(i = 0; i < ntohs(ip->tot_len) - ip->ihl*4; i++ /*, c++*/) {
+			if(!(i % 16)) {
+				printk(KERN_INFO
+				       "klips_debug:   @%03x:",
+				       i);
+			}
+			printk(" %02x", /***/c[i]);
+			if(!((i + 1) % 16)) {
+				printk("\n");
+			}
+		}
+		if(i % 16) {
+			printk("\n");
+		}
+	}
+}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#ifdef REAL_LOCKING_P
+/*
+ *	Locking
+ */
+ 
+#if 0
+DEBUG_NO_STATIC int
+ipsec_tunnel_lock(struct ipsecpriv *prv)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	/*
+	 *	Lock in an interrupt may fail
+	 */
+	if(prv->locked && in_interrupt()) {
+		restore_flags(flags);
+		return 0;
+	}
+	while(prv->locked)
+		sleep_on(&prv->wait_queue);
+	prv->locked=1;
+	restore_flags(flags);
+	return 1;
+}
+#endif
+
+#if 0
+DEBUG_NO_STATIC void
+ipsec_tunnel_unlock(struct ipsecpriv *prv)
+{
+	prv->locked=0;
+	wake_up(&prv->wait_queue);
+}
+#endif
+#endif /* REAL_LOCKING_P */
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_open(struct device *dev)
+{
+	struct ipsecpriv *prv = dev->priv;
+	
+	/*
+	 * Can't open until attached.
+	 */
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_open: "
+		    "dev = %s, prv->dev = %s\n",
+		    dev->name, prv->dev?prv->dev->name:"NONE");
+
+	if (prv->dev == NULL)
+		return -ENODEV;
+	
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_close(struct device *dev)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+#ifdef MSS_HACK
+/*
+ * Issues:
+ *  1) Fragments arriving in the tunnel should probably be rejected.
+ *  2) How does this affect syncookies, mss_cache, dst cache ?
+ *  3) Path MTU discovery handling needs to be reviewed.  For example,
+ *     if we receive an ICMP 'packet too big' message from an intermediate 
+ *     router specifying it's next hop MTU, our stack may process this and
+ *     adjust the MSS without taking our AH/ESP overheads into account.
+ */
+
+ 
+/*
+ * Recaclulate checksum using differences between changed datum, 
+ * borrowed from netfilter.
+ */
+DEBUG_NO_STATIC u_int16_t 
+ipsec_fast_csum(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
+{
+	u_int32_t diffs[] = { oldvalinv, newval };
+	return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
+	oldcheck^0xFFFF));
+}
+
+/*
+ * Determine effective MSS.
+ *
+ * Note that we assume that there is always an MSS option for our own
+ * SYN segments, which is mentioned in tcp_syn_build_options(), kernel 2.2.x.
+ * This could change, and we should probably parse TCP options instead.
+ *
+ */
+DEBUG_NO_STATIC u_int8_t
+ipsec_adjust_mss(struct sk_buff *skb, struct tcphdr *tcph, u_int16_t mtu)
+{
+	u_int16_t oldmss, newmss;
+	u_int32_t *mssp;
+	struct sock *sk = skb->sk;
+	
+	newmss = tcp_sync_mss(sk, mtu);
+	printk(KERN_INFO "klips: setting mss to %u\n", newmss);
+	mssp = (u_int32_t *)tcph + sizeof(struct tcphdr) / sizeof(u_int32_t);
+	oldmss = ntohl(*mssp) & 0x0000FFFF;
+	*mssp = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | newmss);
+	tcph->check = ipsec_fast_csum(htons(~oldmss), 
+	                              htons(newmss), tcph->check);
+	return 1;
+}
+#endif	/* MSS_HACK */
+                                                        
+#ifdef NETDEV_23
+static inline int ipsec_tunnel_xmit2(struct sk_buff *skb)
+{
+	return ip_send(skb);
+}
+#endif /* NETDEV_23 */
+
+/*
+ *	This function assumes it is being called from dev_queue_xmit()
+ *	and that skb is filled properly by that function.
+ */
+
+int
+ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct ipsecpriv *prv;		/* Our device' private space */
+	struct sk_buff *oskb = NULL;	/* Original skb pointer */
+	struct net_device_stats *stats;	/* This device's statistics */
+	struct iphdr  *iph;		/* Our new IP header */
+	__u32   newdst;			/* The other SG's IP address */
+	__u32	orgdst;			/* Original IP destination address */
+	__u32	orgedst;		/* 1st SG's IP address */
+	__u32   newsrc;			/* The new source SG's IP address */
+	__u32	orgsrc;			/* Original IP source address */
+	__u32	innersrc;		/* Innermost IP source address */
+	int	iphlen;			/* IP header length */
+	int	pyldsz;			/* upper protocol payload size */
+	int	headroom;
+	int	tailroom;
+	int     max_headroom = 0;	/* The extra header space needed */
+	int	max_tailroom = 0;	/* The extra stuffing needed */
+	int     ll_headroom;		/* The extra link layer hard_header space needed */
+	int     tot_headroom = 0;	/* The total header space needed */
+	int	tot_tailroom = 0;	/* The totalstuffing needed */
+	__u8	*saved_header = NULL;	/* saved copy of the hard header */
+	int i;
+	unsigned short   sport,dport;
+
+	struct sockaddr_encap matcher;	/* eroute search key */
+	struct eroute *er;
+	struct ipsec_sa *tdbp, *tdbq;	/* Tunnel Descriptor Block pointers */
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	int hard_header_stripped = 0;	/* has the hard header been removed yet? */
+	int hard_header_len = 0;
+	struct device *physdev;
+/*	struct device *virtdev; */
+	short physmtu;
+	short mtudiff;
+	int blocksize = 8;
+#ifdef NET_21
+	struct rtable *rt = NULL;
+#endif /* NET_21 */
+	struct sa_id outgoing_said;
+#ifdef NET_21
+	int pass = 0;
+#endif /* NET_21 */
+	int error = 0;
+	uint32_t eroute_pid = 0;
+	struct ipsec_sa tdb;
+#ifdef CONFIG_IPSEC_ALG
+	struct ipsec_alg_enc *ixt_e = NULL;
+	struct ipsec_alg_auth *ixt_a = NULL;
+#endif /* CONFIG_IPSEC_ALG */
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	uint8_t natt_type = 0, natt_head = 0;
+	uint16_t natt_sport = 0, natt_dport = 0;
+#endif
+
+	dport=sport=0;
+
+	memset((char*)&tdb, 0, sizeof(struct ipsec_sa));
+
+	/*
+	 *	Return if there is nothing to do.  (Does this ever happen?) XXX
+	 */
+	if (skb == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_error:ipsec_tunnel_start_xmit: "
+			    "Nothing to do!\n" );
+		goto cleanup;
+	}
+	if (dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_error:ipsec_tunnel_start_xmit: "
+			    "No device associated with skb!\n" );
+		goto cleanup;
+	}
+
+	prv = dev->priv;
+	if (prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_error:ipsec_tunnel_start_xmit: "
+			    "Device has no private structure!\n" );
+		goto cleanup;
+	}
+
+	physdev = prv->dev;
+	if (physdev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_error:ipsec_tunnel_start_xmit: "
+			    "Device is not attached to physical device!\n" );
+		goto cleanup;
+	}
+
+	physmtu = physdev->mtu;
+
+	stats = (struct net_device_stats *) &(prv->mystats);
+
+#ifdef NET_21
+	/* if skb was cloned (most likely due to a packet sniffer such as
+	   tcpdump being momentarily attached to the interface), make
+	   a copy of our own to modify */
+	if(skb_cloned(skb)) {
+		if
+#ifdef SKB_COW_NEW
+	       (skb_cow(skb, skb_headroom(skb)) != 0)
+#else /* SKB_COW_NEW */
+	       ((skb = skb_cow(skb, skb_headroom(skb))) == NULL)
+#endif /* SKB_COW_NEW */
+		{
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_error:ipsec_tunnel_start_xmit: "
+				    "skb_cow failed to allocate buffer, dropping.\n" );
+			stats->tx_dropped++;
+			goto cleanup;
+		}
+	}
+#endif /* NET_21 */
+
+#ifdef NET_21
+	iph = skb->nh.iph;
+#else /* NET_21 */
+	iph = skb->ip_hdr;
+#endif /* NET_21 */
+
+	/* sanity check for IP version as we can't handle IPv6 right now */
+	if (iph->version != 4) {
+		KLIPS_PRINT(debug_tunnel,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "found IP Version %d but cannot process other IP versions than v4.\n",
+			    iph->version); /* XXX */
+		stats->tx_dropped++;
+		goto cleanup;
+	}
+	
+	/* physdev->hard_header_len is unreliable and should not be used */
+	hard_header_len = (unsigned char *)iph - skb->data;
+
+	if(hard_header_len < 0) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_error:ipsec_tunnel_start_xmit: "
+			    "Negative hard_header_len (%d)?!\n", hard_header_len);
+		stats->tx_dropped++;
+		goto cleanup;
+	}
+
+	if(hard_header_len == 0) { /* no hard header present */
+		hard_header_stripped = 1;
+	}
+
+#ifdef CONFIG_IPSEC_DEBUG
+	if (debug_tunnel & DB_TN_XMIT) {
+		int i;
+		char c;
+		
+		printk(KERN_INFO "klips_debug:ipsec_tunnel_start_xmit: "
+		       ">>> skb->len=%ld hard_header_len:%d",
+		       (unsigned long int)skb->len, hard_header_len);
+		c = ' ';
+		for (i=0; i < hard_header_len; i++) {
+			printk("%c%02x", c, skb->data[i]);
+			c = ':';
+		}
+		printk(" \n");
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, iph);
+
+	/*
+	 * Sanity checks
+	 */
+
+	if ((iph->ihl << 2) != sizeof (struct iphdr)) {
+		KLIPS_PRINT(debug_tunnel,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "cannot process IP header options yet.  May be mal-formed packet.\n"); /* XXX */
+		stats->tx_dropped++;
+		goto cleanup;
+	}
+	
+#ifndef NET_21
+	/* TTL decrement code (on the way out!) borrowed from ip_forward.c */
+	if(0) {
+		unsigned long checksum = iph->check;
+		iph->ttl--;
+	/*
+	 *	Re-compute the IP header checksum.
+	 *	This is efficient. We know what has happened to the header
+	 *	and can thus adjust the checksum as Phil Karn does in KA9Q
+	 *	except we do this in "network byte order".
+	 */
+		checksum += htons(0x0100);
+		/* carry overflow? */
+		checksum += checksum >> 16;
+		iph->check = checksum;
+	}
+	if (iph->ttl <= 0) {
+		/* Tell the sender its packet died... */
+		ICMP_SEND(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, physdev);
+
+		KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: "
+			    "TTL=0, too many hops!\n");
+		stats->tx_dropped++;
+		goto cleanup;
+	}
+#endif /* !NET_21 */
+
+	/*
+	 * First things first -- look us up in the erouting tables.
+	 */
+	matcher.sen_len = sizeof (struct sockaddr_encap);
+	matcher.sen_family = AF_ENCAP;
+	matcher.sen_type = SENT_IP4;
+	matcher.sen_ip_src.s_addr = iph->saddr;
+	matcher.sen_ip_dst.s_addr = iph->daddr;
+	matcher.sen_proto = iph->protocol;
+	extract_ports(iph, &matcher);
+
+	/*
+	 * The spinlock is to prevent any other process from accessing or deleting
+	 * the eroute while we are using and updating it.
+	 */
+	spin_lock(&eroute_lock);
+	
+	er = ipsec_findroute(&matcher);
+
+	if(iph->protocol == IPPROTO_UDP) {
+		if(skb->sk) {
+			sport=ntohs(skb->sk->sport);
+			dport=ntohs(skb->sk->dport);
+		} else if((ntohs(iph->frag_off) & IP_OFFSET) == 0 &&
+			  iph->ihl << 2 > sizeof(struct iphdr) + sizeof(struct udphdr)) {
+			sport=ntohs(((struct udphdr*)((caddr_t)iph+(iph->ihl<<2)))->source);
+			dport=ntohs(((struct udphdr*)((caddr_t)iph + (iph->ihl<<2)))->dest);
+		} else {
+			sport=0; dport=0;
+		}
+	}
+
+	/* default to a %drop eroute */
+	outgoing_said.proto = IPPROTO_INT;
+	outgoing_said.spi = htonl(SPI_DROP);
+	outgoing_said.dst.s_addr = INADDR_ANY;
+	KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+		    "klips_debug:ipsec_tunnel_start_xmit: "
+		    "checking for local udp/500 IKE packet "
+		    "saddr=%x, er=%p, daddr=%x, er_dst=%x, proto=%d sport=%d dport=%d\n",
+		    ntohl((unsigned int)iph->saddr),
+		    er,
+		    ntohl((unsigned int)iph->daddr),
+		    er ? ntohl((unsigned int)er->er_said.dst.s_addr) : 0,
+		    iph->protocol,
+		    sport,
+		    dport); 
+
+	/*
+	 * Quick cheat for now...are we udp/500? If so, let it through
+	 * without interference since it is most likely an IKE packet.
+	 */
+
+	if (ip_chk_addr((unsigned long)iph->saddr) == IS_MYADDR
+	    && (!er
+		|| iph->daddr == er->er_said.dst.s_addr
+		|| INADDR_ANY == er->er_said.dst.s_addr)
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+ 	    && ((sport == 500) || (sport == 4500))
+#else
+ 	    && (sport == 500)
+#endif
+	    ) {                                                                  
+		/* Whatever the eroute, this is an IKE message
+		 * from us (i.e. not being forwarded).
+		 * Furthermore, if there is a tunnel eroute,
+		 * the destination is the peer for this eroute.
+		 * So %pass the packet: modify the default %drop.
+		 */
+		outgoing_said.spi = htonl(SPI_PASS);
+		if(!(skb->sk) && ((ntohs(iph->frag_off) & IP_MF) != 0)) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n");
+		}
+	} else if (er) {
+		er->er_count++;
+		er->er_lasttime = jiffies/HZ;
+		if(er->er_said.proto==IPPROTO_INT
+		   && er->er_said.spi==htonl(SPI_HOLD)) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "shunt SA of HOLD: skb stored in HOLD.\n");
+			if(er->er_last != NULL) {
+				kfree_skb(er->er_last);
+			}
+			er->er_last = skb;
+			skb = NULL;
+			stats->tx_dropped++;
+			spin_unlock(&eroute_lock);
+			goto cleanup;
+		}
+		outgoing_said = er->er_said;
+		eroute_pid = er->er_pid;
+		/* Copy of the ident for the TRAP/TRAPSUBNET eroutes */
+		if(outgoing_said.proto==IPPROTO_INT
+		   && (outgoing_said.spi==htonl(SPI_TRAP)
+		       || (outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) {
+			int len;
+			
+			tdb.tdb_ident_s.type = er->er_ident_s.type;
+			tdb.tdb_ident_s.id = er->er_ident_s.id;
+			tdb.tdb_ident_s.len = er->er_ident_s.len;
+			if (tdb.tdb_ident_s.len) {
+				len = tdb.tdb_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+				if ((tdb.tdb_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) {
+					printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: "
+					       "Failed, tried to allocate %d bytes for source ident.\n", 
+					       len);
+					stats->tx_dropped++;
+					spin_unlock(&eroute_lock);
+					goto cleanup;
+				}
+				memcpy(tdb.tdb_ident_s.data, er->er_ident_s.data, len);
+			}
+			tdb.tdb_ident_d.type = er->er_ident_d.type;
+			tdb.tdb_ident_d.id = er->er_ident_d.id;
+			tdb.tdb_ident_d.len = er->er_ident_d.len;
+			if (tdb.tdb_ident_d.len) {
+				len = tdb.tdb_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+				if ((tdb.tdb_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) {
+					printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: "
+					       "Failed, tried to allocate %d bytes for dest ident.\n", 
+					       len);
+					stats->tx_dropped++;
+					spin_unlock(&eroute_lock);
+					goto cleanup;
+				}
+				memcpy(tdb.tdb_ident_d.data, er->er_ident_d.data, len);
+			}
+		}
+	}
+
+	spin_unlock(&eroute_lock);
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+		    "klips_debug:ipsec_tunnel_start_xmit: "
+		    "Original head,tailroom: %d,%d\n",
+		    skb_headroom(skb), skb_tailroom(skb));
+
+	innersrc = iph->saddr;
+	/* start encapsulation loop here XXX */
+	do {
+		struct ipsec_sa *tdbprev = NULL;
+
+		newdst = orgdst = iph->daddr;
+		newsrc = orgsrc = iph->saddr;
+		orgedst = outgoing_said.dst.s_addr;
+		iphlen = iph->ihl << 2;
+		pyldsz = ntohs(iph->tot_len) - iphlen;
+		max_headroom = max_tailroom = 0;
+		
+		if (outgoing_said.proto == IPPROTO_INT) {
+			switch (ntohl(outgoing_said.spi)) {
+			case SPI_DROP:
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "shunt SA of DROP or no eroute: dropping.\n");
+				stats->tx_dropped++;
+				break;
+				
+			case SPI_REJECT:
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "shunt SA of REJECT: notifying and dropping.\n");
+				ICMP_SEND(skb,
+					  ICMP_DEST_UNREACH,
+					  ICMP_PKT_FILTERED,
+					  0,
+					  physdev);
+				stats->tx_dropped++;
+				break;
+				
+			case SPI_PASS:
+#ifdef NET_21
+				pass = 1;
+#endif /* NET_21 */
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "PASS: calling dev_queue_xmit\n");
+				goto bypass;
+				
+#if 1 /* now moved up to finderoute so we don't need to lock it longer */
+			case SPI_HOLD:
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "shunt SA of HOLD: this does not make sense here, dropping.\n");
+			stats->tx_dropped++;
+			break;
+#endif		
+			case SPI_TRAP:
+			case SPI_TRAPSUBNET:
+			{
+				struct sockaddr_in src, dst;
+#ifdef CONFIG_IPSEC_DEBUG
+				char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF];
+#endif /* CONFIG_IPSEC_DEBUG */
+				
+				/* Signal all listening KMds with a PF_KEY ACQUIRE */
+				tdb.tdb_said.proto = iph->protocol;
+				src.sin_family = AF_INET;
+				dst.sin_family = AF_INET;
+				src.sin_addr.s_addr = iph->saddr;
+				dst.sin_addr.s_addr = iph->daddr;
+				src.sin_port = 
+					(iph->protocol == IPPROTO_UDP
+					 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->source
+					 : (iph->protocol == IPPROTO_TCP
+					    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->source
+					    : 0));
+				dst.sin_port = 
+					(iph->protocol == IPPROTO_UDP
+					 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->dest
+					 : (iph->protocol == IPPROTO_TCP
+					    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest
+					    : 0));
+				for(i = 0;
+				    i < sizeof(struct sockaddr_in)
+					    - offsetof(struct sockaddr_in, sin_zero);
+				    i++) {
+					src.sin_zero[i] = 0;
+					dst.sin_zero[i] = 0;
+				}
+				
+				tdb.tdb_addr_s = (struct sockaddr*)(&src);
+				tdb.tdb_addr_d = (struct sockaddr*)(&dst);
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n",
+					    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR",
+					    ntohs(((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_port),
+					    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR",
+					    ntohs(((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_port),
+					    tdb.tdb_said.proto);
+				
+				if (pfkey_acquire(&tdb) == 0) {
+					
+					if (outgoing_said.spi==htonl(SPI_TRAPSUBNET)) {
+						/*
+						 * The spinlock is to prevent any other
+						 * process from accessing or deleting
+						 * the eroute while we are using and
+						 * updating it.
+						 */
+						spin_lock(&eroute_lock);
+						er = ipsec_findroute(&matcher);
+						if(er) {
+							er->er_said.spi = htonl(SPI_HOLD);
+							er->er_first = skb;
+							skb = NULL;
+						}
+						spin_unlock(&eroute_lock);
+					} else if (create_hold_eroute(skb, iph, eroute_pid)) {
+						skb = NULL;
+					}
+				}
+				stats->tx_dropped++;
+			}
+			default:
+				/* XXX what do we do with an unknown shunt spi? */
+			} /* switch (ntohl(outgoing_said.spi)) */
+			goto cleanup;
+		} /* if (outgoing_said.proto == IPPROTO_INT) */
+		
+		/*
+		  The spinlock is to prevent any other process from
+		  accessing or deleting the TDB hash table or any of the
+		  TDBs while we are using and updating them.
+		  
+		  This is not optimal, but was relatively straightforward
+		  at the time.  A better way to do it has been planned for
+		  more than a year, to lock the hash table and put reference
+		  counts on each TDB instead.  This is not likely to happen
+		  in KLIPS1 unless a volunteer contributes it, but will be
+		  designed into KLIPS2.
+		*/
+		spin_lock(&tdb_lock);
+
+		tdbp = ipsec_sa_getbyid(&outgoing_said);
+		sa_len = satoa(outgoing_said, 0, sa, SATOA_BUF);
+
+		if (tdbp == NULL) {
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "no Tunnel Descriptor Block for SA%s: outgoing packet with no SA, dropped.\n",
+				    sa_len ? sa : " (error)");
+			stats->tx_dropped++;
+			goto cleanup;
+		}
+		
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "found Tunnel Descriptor Block -- SA:<%s%s%s> %s\n",
+			    IPS_XFORM_NAME(tdbp),
+			    sa_len ? sa : " (error)");
+		
+		/*
+		 * How much headroom do we need to be able to apply
+		 * all the grouped transforms?
+		 */
+		tdbq = tdbp;	/* save the head of the tdb chain */
+		while (tdbp)	{
+			sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+			if(sa_len == 0) {
+				strcpy(sa, "(error)");
+			}
+
+			/* If it is in larval state, drop the packet, we cannot process yet. */
+			if(tdbp->tdb_state == SADB_SASTATE_LARVAL) {
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "TDB in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n",
+					    IPS_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
+				spin_unlock(&tdb_lock);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+
+			if(tdbp->tdb_state == SADB_SASTATE_DEAD) {
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "TDB in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n",
+					    IPS_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
+				spin_unlock(&tdb_lock);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+
+			/* If the replay window counter == -1, expire SA, it will roll */
+			if(tdbp->tdb_replaywin && tdbp->tdb_replaywin_lastseq == -1) {
+				pfkey_expire(tdbp, 1);
+				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n",
+					    IPS_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
+				ipsec_sa_delchain(tdbp);
+				spin_unlock(&tdb_lock);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+
+			/*
+			 * if this is the first time we are using this SA, mark start time,
+			 * and offset hard/soft counters by "now" for later checking.
+			 */
+#if 0
+			if(tdbp->ips_life.ipl_usetime.count == 0) {
+				tdbp->ips_life.ipl_usetime.count = jiffies;
+				tdbp->ips_life.ipl_usetime.hard += jiffies;
+				tdbp->ips_life.ipl_usetime.soft += jiffies;
+			}
+#endif
+			  
+
+			if(ipsec_lifetime_check(&tdbp->ips_life.ipl_bytes, "bytes", sa, 
+						ipsec_life_countbased, ipsec_outgoing, tdbp) == ipsec_life_harddied ||
+			   ipsec_lifetime_check(&tdbp->ips_life.ipl_addtime, "addtime",sa,
+						ipsec_life_timebased,  ipsec_outgoing, tdbp) == ipsec_life_harddied ||
+			   ipsec_lifetime_check(&tdbp->ips_life.ipl_usetime, "usetime",sa,
+						ipsec_life_timebased,  ipsec_outgoing, tdbp) == ipsec_life_harddied ||
+			   ipsec_lifetime_check(&tdbp->ips_life.ipl_packets, "packets",sa,
+						ipsec_life_countbased, ipsec_outgoing, tdbp) == ipsec_life_harddied) {
+				
+				ipsec_sa_delchain(tdbp);
+				spin_unlock(&tdb_lock);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			
+
+			headroom = tailroom = 0;
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "calling room for <%s%s%s>, SA:%s\n", 
+				    IPS_XFORM_NAME(tdbp),
+				    sa_len ? sa : " (error)");
+			switch(tdbp->tdb_said.proto) {
+#ifdef CONFIG_IPSEC_AH
+			case IPPROTO_AH:
+				headroom += sizeof(struct ah);
+				break;
+#endif /* CONFIG_IPSEC_AH */
+#ifdef CONFIG_IPSEC_ESP
+			case IPPROTO_ESP:
+#ifdef CONFIG_IPSEC_ALG
+				if ((ixt_e=IPSEC_ALG_SA_ESP_ENC(tdbp))) {
+					blocksize = ixt_e->ixt_blocksize;
+					headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8;
+				} else
+#endif /* CONFIG_IPSEC_ALG */
+				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_3DES
+				case ESP_3DES:
+					headroom += sizeof(struct esp);
+					break;
+#endif /* CONFIG_IPSEC_ENC_3DES */
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}
+#ifdef CONFIG_IPSEC_ALG
+				if ((ixt_a=IPSEC_ALG_SA_ESP_AUTH(tdbp))) {
+					tailroom += AHHMAC_HASHLEN;
+				} else
+#endif /* CONFIG_IPSEC_ALG */
+				switch(tdbp->tdb_authalg) {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+				case AH_MD5:
+					tailroom += AHHMAC_HASHLEN;
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+				case AH_SHA:
+					tailroom += AHHMAC_HASHLEN;
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+				case AH_NONE:
+					break;
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}			
+/*                            tailroom += ((blocksize - ((pyldsz + 2 * sizeof(unsigned char)) % blocksize)) % blocksize) + 2; */
+                              tailroom +=
+                                        blocksize != 1 ?
+                                        ((blocksize - ((pyldsz + 2) % blocksize)) % blocksize) + 2 :
+                                        ((4 - ((pyldsz + 2) % 4)) % 4) +  2;
+
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+				if ((tdbp->ips_natt_type) && (!natt_type)) {
+					natt_type = tdbp->ips_natt_type;
+					natt_sport = tdbp->ips_natt_sport;
+					natt_dport = tdbp->ips_natt_dport;
+					switch (natt_type) {
+						case ESPINUDP_WITH_NON_IKE:
+							natt_head = sizeof(struct udphdr)+(2*sizeof(__u32));
+							break;
+						case ESPINUDP_WITH_NON_ESP:
+							natt_head = sizeof(struct udphdr);
+							break;
+						default:
+							natt_head = 0;
+							break;
+					}
+					tailroom += natt_head;
+				}
+#endif
+				break;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_IPIP
+			case IPPROTO_IPIP:
+				headroom += sizeof(struct iphdr);
+				break;
+#endif /* !CONFIG_IPSEC_IPIP */
+			case IPPROTO_COMP:
+#ifdef CONFIG_IPSEC_IPCOMP
+				/*
+				  We can't predict how much the packet will
+				  shrink without doing the actual compression.
+				  We could do it here, if we were the first
+				  encapsulation in the chain.  That might save
+				  us a skb_copy_expand, since we might fit
+				  into the existing skb then.  However, this
+				  would be a bit unclean (and this hack has
+				  bit us once), so we better not do it. After
+				  all, the skb_copy_expand is cheap in
+				  comparison to the actual compression.
+				  At least we know the packet will not grow.
+				*/
+				break;
+#endif /* CONFIG_IPSEC_IPCOMP */
+			default:
+				spin_unlock(&tdb_lock);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			tdbp = tdbp->tdb_onext;
+#ifdef CONFIG_IPSEC_ALG
+			ixt_e = NULL;	/* invalidate ipsec_alg */
+			ixt_a = NULL;
+#endif /* CONFIG_IPSEC_ALG */
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "Required head,tailroom: %d,%d\n", 
+				    headroom, tailroom);
+			max_headroom += headroom;
+			max_tailroom += tailroom;
+			pyldsz += (headroom + tailroom);
+		}
+		tdbp = tdbq;	/* restore the head of the tdb chain */
+		
+		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n",
+			    skb_headroom(skb), skb_tailroom(skb),
+			    max_headroom, max_tailroom);
+		
+		tot_headroom += max_headroom;
+		tot_tailroom += max_tailroom;
+		
+		mtudiff = prv->mtu + tot_headroom + tot_tailroom - physmtu;
+
+		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n",
+			    prv->mtu, physmtu,
+			    tot_headroom, tot_tailroom, mtudiff, ntohs(iph->tot_len));
+		if(mtudiff > 0) {
+			int newmtu = physmtu - (tot_headroom + ((tot_tailroom + 2) & ~7) + 5);
+
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_info:ipsec_tunnel_start_xmit: "
+				    "dev %s mtu of %d decreased by %d to %d\n",
+				    dev->name,
+				    prv->mtu,
+				    prv->mtu - newmtu,
+				    newmtu);
+			prv->mtu = newmtu;
+#ifdef NET_21
+#if 0
+			skb->dst->pmtu = prv->mtu; /* RGB */
+#endif /* 0 */
+#else /* NET_21 */
+#if 0
+			dev->mtu = prv->mtu; /* RGB */
+#endif /* 0 */
+#endif /* NET_21 */
+		}
+
+		/* 
+		   If the sender is doing PMTU discovery, and the
+		   packet doesn't fit within prv->mtu, notify him
+		   (unless it was an ICMP packet, or it was not the
+		   zero-offset packet) and send it anyways.
+
+		   Note: buggy firewall configuration may prevent the
+		   ICMP packet from getting back.
+		*/
+		if(sysctl_ipsec_icmp
+		   && prv->mtu < ntohs(iph->tot_len)
+		   && (iph->frag_off & __constant_htons(IP_DF)) ) {
+			int notify = iph->protocol != IPPROTO_ICMP
+				&& (iph->frag_off & __constant_htons(IP_OFFSET)) == 0;
+			
+#ifdef IPSEC_obey_DF
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "fragmentation needed and DF set; %sdropping packet\n",
+				    notify ? "sending ICMP and " : "");
+			if (notify)
+				ICMP_SEND(skb,
+					  ICMP_DEST_UNREACH,
+					  ICMP_FRAG_NEEDED,
+					  prv->mtu,
+					  physdev);
+			stats->tx_errors++;
+			goto cleanup;
+#else /* IPSEC_obey_DF */
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "fragmentation needed and DF set; %spassing packet\n",
+				    notify ? "sending ICMP and " : "");
+			if (notify)
+				ICMP_SEND(skb,
+					  ICMP_DEST_UNREACH,
+					  ICMP_FRAG_NEEDED,
+					  prv->mtu,
+					  physdev);
+#endif /* IPSEC_obey_DF */
+		}
+		
+#ifdef MSS_HACK
+		/*
+		 * If this is a transport mode TCP packet with
+		 * SYN set, determine an effective MSS based on 
+		 * AH/ESP overheads determined above.
+		 */
+		if (iph->protocol == IPPROTO_TCP 
+		    && outgoing_said.proto != IPPROTO_IPIP) {
+			struct tcphdr *tcph = skb->h.th;
+			if (tcph->syn && !tcph->ack) {
+				if(!ipsec_adjust_mss(skb, tcph, prv->mtu)) {
+					spin_unlock(&tdb_lock);
+					printk(KERN_WARNING
+					       "klips_warning:ipsec_tunnel_start_xmit: "
+					       "ipsec_adjust_mss() failed\n");
+					stats->tx_errors++;
+					goto cleanup;
+				}
+			}
+		}
+#endif /* MSS_HACK */
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	if ((natt_type) && (outgoing_said.proto != IPPROTO_IPIP)) {
+		/**
+		 * NAT-Traversal and Transport Mode:
+		 *   we need to correct TCP/UDP checksum
+		 *
+		 * If we've got NAT-OA, we can fix checksum without recalculation.
+		 * If we don't we can zero udp checksum.
+		 */
+		__u32 natt_oa = tdbp->ips_natt_oa ?
+			((struct sockaddr_in*)(tdbp->ips_natt_oa))->sin_addr.s_addr : 0;
+		__u16 pkt_len = skb->tail - (unsigned char *)iph;
+		__u16 data_len = pkt_len - (iph->ihl << 2);
+		switch (iph->protocol) {
+			case IPPROTO_TCP:
+				if (data_len >= sizeof(struct tcphdr)) {
+					struct tcphdr *tcp = (struct tcphdr *)((__u32 *)iph+iph->ihl);
+					if (natt_oa) {
+						__u32 buff[2] = { ~iph->daddr, natt_oa };
+						KLIPS_PRINT(debug_tunnel,
+							"klips_debug:ipsec_tunnel_start_xmit: "
+							"NAT-T & TRANSPORT: "
+							"fix TCP checksum using NAT-OA\n");
+						tcp->check = csum_fold(
+							csum_partial((unsigned char *)buff, sizeof(buff),
+							tcp->check^0xffff));
+					}
+					else {
+						KLIPS_PRINT(debug_tunnel,
+							"klips_debug:ipsec_tunnel_start_xmit: "
+							"NAT-T & TRANSPORT: do not recalc TCP checksum\n");
+					}
+				}
+				else {
+					KLIPS_PRINT(debug_tunnel,
+						"klips_debug:ipsec_tunnel_start_xmit: "
+						"NAT-T & TRANSPORT: can't fix TCP checksum\n");
+				}
+				break;
+			case IPPROTO_UDP:
+				if (data_len >= sizeof(struct udphdr)) {
+					struct udphdr *udp = (struct udphdr *)((__u32 *)iph+iph->ihl);
+					if (udp->check == 0) {
+						KLIPS_PRINT(debug_tunnel,
+							"klips_debug:ipsec_tunnel_start_xmit: "
+							"NAT-T & TRANSPORT: UDP checksum already 0\n");
+					}
+					else if (natt_oa) {
+						__u32 buff[2] = { ~iph->daddr, natt_oa };
+						KLIPS_PRINT(debug_tunnel,
+							"klips_debug:ipsec_tunnel_start_xmit: "
+							"NAT-T & TRANSPORT: "
+							"fix UDP checksum using NAT-OA\n");
+						udp->check = csum_fold(
+							csum_partial((unsigned char *)buff, sizeof(buff),
+							udp->check^0xffff));
+					}
+					else {
+						KLIPS_PRINT(debug_tunnel,
+							"klips_debug:ipsec_tunnel_start_xmit: "
+							"NAT-T & TRANSPORT: zero UDP checksum\n");
+						udp->check = 0;
+					}
+				}
+				else {
+					KLIPS_PRINT(debug_tunnel,
+						"klips_debug:ipsec_tunnel_start_xmit: "
+						"NAT-T & TRANSPORT: can't fix UDP checksum\n");
+				}
+				break;
+			default:
+				KLIPS_PRINT(debug_tunnel,
+					"klips_debug:ipsec_tunnel_start_xmit: "
+					"NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n");
+				break;
+		}
+	}
+#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */
+
+		if(!hard_header_stripped) {
+			if((saved_header = kmalloc(hard_header_len, GFP_ATOMIC)) == NULL) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: "
+				       "Failed, tried to allocate %d bytes for temp hard_header.\n", 
+				       hard_header_len);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			for (i = 0; i < hard_header_len; i++) {
+				saved_header[i] = skb->data[i];
+			}
+			if(skb->len < hard_header_len) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
+				       "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",
+				       hard_header_len, (int)(skb->len));
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			skb_pull(skb, hard_header_len);
+			hard_header_stripped = 1;
+			
+/*			iph = (struct iphdr *) (skb->data); */
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "head,tailroom: %d,%d after hard_header stripped.\n",
+				    skb_headroom(skb), skb_tailroom(skb));
+			KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, iph);
+		} else {
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "hard header already stripped.\n");
+		}
+		
+		ll_headroom = (hard_header_len + 15) & ~15;
+
+		if ((skb_headroom(skb) >= max_headroom + 2 * ll_headroom) && 
+		    (skb_tailroom(skb) >= max_tailroom)
+#ifndef NET_21
+			&& skb->free
+#endif /* !NET_21 */
+			) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "data fits in existing skb\n");
+		} else {
+			struct sk_buff* tskb = skb;
+
+			if(!oskb) {
+				oskb = skb;
+			}
+
+			tskb = skb_copy_expand(skb,
+			/* The reason for 2 * link layer length here still baffles me...RGB */
+					       max_headroom + 2 * ll_headroom,
+					       max_tailroom,
+					       GFP_ATOMIC);
+#ifdef NET_21
+			if(tskb && skb->sk) {
+				skb_set_owner_w(tskb, skb->sk);
+			}
+#endif /* NET_21 */
+			if(!(skb == oskb) ) {
+				dev_kfree_skb(skb, FREE_WRITE);
+			}
+			skb = tskb;
+			if (!skb) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING
+				       "klips_debug:ipsec_tunnel_start_xmit: "
+				       "Failed, tried to allocate %d head and %d tailroom\n", 
+				       max_headroom, max_tailroom);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "head,tailroom: %d,%d after allocation\n",
+				    skb_headroom(skb), skb_tailroom(skb));
+		}
+		
+		/*
+		 * Apply grouped transforms to packet
+		 */
+		while (tdbp) {
+#ifdef CONFIG_IPSEC_ESP
+			struct esp *espp;
+#ifdef CONFIG_IPSEC_ENC_3DES
+			__u32 iv[ESP_IV_MAXSZ_INT];
+#endif /* !CONFIG_IPSEC_ENC_3DES */
+			unsigned char *idat, *pad;
+			int authlen = 0, padlen = 0, i;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+			struct iphdr ipo;
+			struct ah *ahp;
+#endif /* CONFIG_IPSEC_AH */
+#if defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1)
+			union {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+				MD5_CTX md5;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+				SHA1_CTX sha1;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+			} tctx;
+			__u8 hash[AH_AMAX];
+#endif /* defined(CONFIG_IPSEC_AUTH_HMAC_MD5) || defined(CONFIG_IPSEC_AUTH_HMAC_SHA1) */
+			int headroom = 0, tailroom = 0, ilen = 0, len = 0;
+			unsigned char *dat;
+			
+			iphlen = iph->ihl << 2;
+			pyldsz = ntohs(iph->tot_len) - iphlen;
+			sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+			KLIPS_PRINT(debug_tunnel & DB_TN_OXFS,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "calling output for <%s%s%s>, SA:%s\n", 
+				    IPS_XFORM_NAME(tdbp),
+				    sa_len ? sa : " (error)");
+			
+			switch(tdbp->tdb_said.proto) {
+#ifdef CONFIG_IPSEC_AH
+			case IPPROTO_AH:
+				headroom += sizeof(struct ah);
+				break;
+#endif /* CONFIG_IPSEC_AH */
+#ifdef CONFIG_IPSEC_ESP
+			case IPPROTO_ESP:
+#ifdef CONFIG_IPSEC_ALG
+				if ((ixt_e=IPSEC_ALG_SA_ESP_ENC(tdbp))) {
+					blocksize = ixt_e->ixt_blocksize;
+					headroom += ESP_HEADER_LEN + ixt_e->ixt_ivlen/8;
+				} else
+#endif /* CONFIG_IPSEC_ALG */
+				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_3DES
+				case ESP_3DES:
+					headroom += sizeof(struct esp);
+					break;
+#endif /* CONFIG_IPSEC_ENC_3DES */
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}
+#ifdef CONFIG_IPSEC_ALG
+				if ((ixt_a=IPSEC_ALG_SA_ESP_AUTH(tdbp))) {
+					authlen = AHHMAC_HASHLEN;
+				} else
+#endif /* CONFIG_IPSEC_ALG */
+				switch(tdbp->tdb_authalg) {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+				case AH_MD5:
+					authlen = AHHMAC_HASHLEN;
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+				case AH_SHA:
+					authlen = AHHMAC_HASHLEN;
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+				case AH_NONE:
+					break;
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}		
+				tailroom +=
+					blocksize != 1 ?
+					((blocksize - ((pyldsz + 2) % blocksize)) % blocksize) + 2 :
+					((4 - ((pyldsz + 2) % 4)) % 4) + 2;
+				tailroom += authlen;
+				break;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_IPIP
+			case IPPROTO_IPIP:
+				headroom += sizeof(struct iphdr);
+				break;
+#endif /* !CONFIG_IPSEC_IPIP */
+#ifdef CONFIG_IPSEC_IPCOMP
+			case IPPROTO_COMP:
+				break;
+#endif /* CONFIG_IPSEC_IPCOMP */
+			default:
+				spin_unlock(&tdb_lock);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "pushing %d bytes, putting %d, proto %d.\n", 
+				    headroom, tailroom, tdbp->tdb_said.proto);
+			if(skb_headroom(skb) < headroom) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING
+				       "klips_error:ipsec_tunnel_start_xmit: "
+				       "tried to skb_push headroom=%d, %d available.  This should never happen, please report.\n",
+				       headroom, skb_headroom(skb));
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			dat = skb_push(skb, headroom);
+			ilen = skb->len - tailroom;
+			if(skb_tailroom(skb) < tailroom) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING
+				       "klips_error:ipsec_tunnel_start_xmit: "
+				       "tried to skb_put %d, %d available.  This should never happen, please report.\n",
+				       tailroom, skb_tailroom(skb));
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			skb_put(skb, tailroom);
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "head,tailroom: %d,%d before xform.\n",
+				    skb_headroom(skb), skb_tailroom(skb));
+			len = skb->len;
+			if(len > 0xfff0) {
+				spin_unlock(&tdb_lock);
+				printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
+				       "tot_len (%d) > 65520.  This should never happen, please report.\n",
+				       len);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			memmove((void *)dat, (void *)(dat + headroom), iphlen);
+			iph = (struct iphdr *)dat;
+			iph->tot_len = htons(skb->len);
+			
+			switch(tdbp->tdb_said.proto) {
+#ifdef CONFIG_IPSEC_ESP
+			case IPPROTO_ESP:
+				espp = (struct esp *)(dat + iphlen);
+				espp->esp_spi = tdbp->tdb_said.spi;
+				espp->esp_rpl = htonl(++(tdbp->tdb_replaywin_lastseq));
+				
+#ifdef CONFIG_IPSEC_ALG
+				if (!ixt_e)
+#endif /* CONFIG_IPSEC_ALG */
+				switch(tdbp->tdb_encalg) {
+#if defined(CONFIG_IPSEC_ENC_3DES)
+#ifdef CONFIG_IPSEC_ENC_3DES
+				case ESP_3DES:
+#endif /* CONFIG_IPSEC_ENC_3DES */
+					iv[0] = *((__u32*)&(espp->esp_iv)    ) =
+						((__u32*)(tdbp->tdb_iv))[0];
+					iv[1] = *((__u32*)&(espp->esp_iv) + 1) =
+						((__u32*)(tdbp->tdb_iv))[1];
+					break;
+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}
+				
+				idat = dat + iphlen + headroom;
+				ilen = len - (iphlen + headroom + authlen);
+				
+				/* Self-describing padding */
+				pad = &dat[len - tailroom];
+				padlen = tailroom - 2 - authlen;
+				for (i = 0; i < padlen; i++) {
+					pad[i] = i + 1; 
+				}
+				dat[len - authlen - 2] = padlen;
+				
+				dat[len - authlen - 1] = iph->protocol;
+				iph->protocol = IPPROTO_ESP;
+				
+#ifdef CONFIG_IPSEC_ALG
+				/* Do all operations here:
+				 * copy IV->ESP, encrypt, update ips IV
+				 */
+				if (ixt_e) {
+					int ret;
+					memcpy(espp->esp_iv, 
+						tdbp->ips_iv, 
+						ixt_e->ixt_ivlen/8);
+					ret=ipsec_alg_esp_encrypt(tdbp, 
+						idat, ilen, espp->esp_iv,
+						IPSEC_ALG_ENCRYPT);
+					memcpy(tdbp->ips_iv,
+						idat + ilen - ixt_e->ixt_ivlen/8,
+						ixt_e->ixt_ivlen/8);
+				} else
+#endif /* CONFIG_IPSEC_ALG */
+				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_3DES
+				case ESP_3DES:
+					des_ede3_cbc_encrypt((des_cblock *)idat,
+							     (des_cblock *)idat,
+							     ilen,
+							     ((struct des_eks *)(tdbp->tdb_key_e))[0].ks,
+							     ((struct des_eks *)(tdbp->tdb_key_e))[1].ks,
+							     ((struct des_eks *)(tdbp->tdb_key_e))[2].ks,
+							     (des_cblock *)iv, 1);
+					break;
+#endif /* CONFIG_IPSEC_ENC_3DES */
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}
+#ifdef CONFIG_IPSEC_ALG
+				if (!ixt_e)
+#endif /* CONFIG_IPSEC_ALG */
+				
+				switch(tdbp->tdb_encalg) {
+#if defined(CONFIG_IPSEC_ENC_3DES)
+#ifdef CONFIG_IPSEC_ENC_3DES
+				case ESP_3DES:
+#endif /* CONFIG_IPSEC_ENC_3DES */
+					/* XXX update IV with the last 8 octets of the encryption */
+					((__u32*)(tdbp->tdb_iv))[0] =
+						((__u32 *)(idat))[(ilen >> 2) - 2];
+					((__u32*)(tdbp->tdb_iv))[1] =
+						((__u32 *)(idat))[(ilen >> 2) - 1];
+					break;
+#endif /* defined(CONFIG_IPSEC_ENC_3DES) */
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}
+#ifdef CONFIG_IPSEC_ALG
+				if (ixt_a) {
+					ipsec_alg_sa_esp_hash(tdbp,
+					(caddr_t)espp, len - iphlen - authlen,
+					&(dat[len - authlen]), authlen);
+
+				} else
+#endif /* CONFIG_IPSEC_ALG */
+				
+				switch(tdbp->tdb_authalg) {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+				case AH_MD5:
+					dmp("espp", (char*)espp, len - iphlen - authlen);
+					tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx;
+					dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Update(&tctx.md5, (caddr_t)espp, len - iphlen - authlen);
+					dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Final(hash, &tctx.md5);
+					dmp("ictx hash", (char*)&hash, sizeof(hash));
+					tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx;
+					dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Update(&tctx.md5, hash, AHMD596_ALEN);
+					dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Final(hash, &tctx.md5);
+					dmp("octx hash", (char*)&hash, sizeof(hash));
+					memcpy(&(dat[len - authlen]), hash, authlen);
+
+					/* paranoid */
+					memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));
+					memset((caddr_t)hash, 0, sizeof(*hash));
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+				case AH_SHA:
+					tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx;
+					SHA1Update(&tctx.sha1, (caddr_t)espp, len - iphlen - authlen);
+					SHA1Final(hash, &tctx.sha1);
+					tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx;
+					SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);
+					SHA1Final(hash, &tctx.sha1);
+					memcpy(&(dat[len - authlen]), hash, authlen);
+					
+					/* paranoid */
+					memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));
+					memset((caddr_t)hash, 0, sizeof(*hash));
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+				case AH_NONE:
+					break;
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}
+#ifdef NET_21
+				skb->h.raw = (unsigned char*)espp;
+#endif /* NET_21 */
+				break;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_AH
+			case IPPROTO_AH:
+				ahp = (struct ah *)(dat + iphlen);
+				ahp->ah_spi = tdbp->tdb_said.spi;
+				ahp->ah_rpl = htonl(++(tdbp->tdb_replaywin_lastseq));
+				ahp->ah_rv = 0;
+				ahp->ah_nh = iph->protocol;
+				ahp->ah_hl = (headroom >> 2) - sizeof(__u64)/sizeof(__u32);
+				iph->protocol = IPPROTO_AH;
+				dmp("ahp", (char*)ahp, sizeof(*ahp));
+				
+				ipo = *iph;
+				ipo.tos = 0;
+				ipo.frag_off = 0;
+				ipo.ttl = 0;
+				ipo.check = 0;
+				dmp("ipo", (char*)&ipo, sizeof(ipo));
+				
+				switch(tdbp->tdb_authalg) {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+				case AH_MD5:
+					tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx;
+					dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr));
+					dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data));
+					dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN);
+					dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Update(&tctx.md5,  dat + iphlen + headroom, len - iphlen - headroom);
+					dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Final(hash, &tctx.md5);
+					dmp("ictx hash", (char*)&hash, sizeof(hash));
+					tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx;
+					dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Update(&tctx.md5, hash, AHMD596_ALEN);
+					dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));
+					MD5Final(hash, &tctx.md5);
+					dmp("octx hash", (char*)&hash, sizeof(hash));
+					
+					memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);
+					
+					/* paranoid */
+					memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));
+					memset((caddr_t)hash, 0, sizeof(hash));
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+				case AH_SHA:
+					tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx;
+					SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr));
+					SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data));
+					SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN);
+					SHA1Update(&tctx.sha1,  dat + iphlen + headroom, len - iphlen - headroom);
+					SHA1Final(hash, &tctx.sha1);
+					tctx.sha1 = ((struct sha1_ctx*)(tdbp->tdb_key_a))->octx;
+					SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);
+					SHA1Final(hash, &tctx.sha1);
+					
+					memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);
+					
+					/* paranoid */
+					memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));
+					memset((caddr_t)hash, 0, sizeof(hash));
+					break;
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+				default:
+					spin_unlock(&tdb_lock);
+					stats->tx_errors++;
+					goto cleanup;
+				}
+#ifdef NET_21
+				skb->h.raw = (unsigned char*)ahp;
+#endif /* NET_21 */
+				break;
+#endif /* CONFIG_IPSEC_AH */
+#ifdef CONFIG_IPSEC_IPIP
+			case IPPROTO_IPIP:
+				iph->version  = 4;
+				switch(sysctl_ipsec_tos) {
+				case 0:
+#ifdef NET_21
+					iph->tos = skb->nh.iph->tos;
+#else /* NET_21 */
+					iph->tos = skb->ip_hdr->tos;
+#endif /* NET_21 */
+					break;
+				case 1:
+					iph->tos = 0;
+					break;
+				default:
+				}
+#ifdef NET_21
+#ifdef NETDEV_23
+				iph->ttl      = sysctl_ip_default_ttl;
+#else /* NETDEV_23 */
+				iph->ttl      = ip_statistics.IpDefaultTTL;
+#endif /* NETDEV_23 */
+#else /* NET_21 */
+				iph->ttl      = 64; /* ip_statistics.IpDefaultTTL; */
+#endif /* NET_21 */
+				iph->frag_off = 0;
+				iph->saddr    = ((struct sockaddr_in*)(tdbp->tdb_addr_s))->sin_addr.s_addr;
+				iph->daddr    = ((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr.s_addr;
+				iph->protocol = IPPROTO_IPIP;
+				iph->ihl      = sizeof(struct iphdr) >> 2 /* 5 */;
+#ifdef IP_SELECT_IDENT
+				/* XXX use of skb->dst below is a questionable
+				   substitute for &rt->u.dst which is only
+				   available later-on */
+#ifdef IP_SELECT_IDENT_NEW
+				ip_select_ident(iph, skb->dst, NULL);
+#else /* IP_SELECT_IDENT_NEW */
+                                ip_select_ident(iph, skb->dst);
+#endif /* IP_SELECT_IDENT_NEW */
+#else /* IP_SELECT_IDENT */
+				iph->id       = htons(ip_id_count++);   /* Race condition here? */
+#endif /* IP_SELECT_IDENT */
+
+				newdst = (__u32)iph->daddr;
+				newsrc = (__u32)iph->saddr;
+		
+#ifdef NET_21
+				skb->h.ipiph = skb->nh.iph;
+#endif /* NET_21 */
+				break;
+#endif /* !CONFIG_IPSEC_IPIP */
+#ifdef CONFIG_IPSEC_IPCOMP
+			case IPPROTO_COMP:
+				{
+					unsigned int flags = 0;
+#ifdef CONFIG_IPSEC_DEBUG
+					unsigned int old_tot_len = ntohs(iph->tot_len);
+#endif /* CONFIG_IPSEC_DEBUG */
+					tdbp->tdb_comp_ratio_dbytes += ntohs(iph->tot_len);
+
+					skb = skb_compress(skb, tdbp, &flags);
+
+#ifdef NET_21
+					iph = skb->nh.iph;
+#else /* NET_21 */
+					iph = skb->ip_hdr;
+#endif /* NET_21 */
+
+					tdbp->tdb_comp_ratio_cbytes += ntohs(iph->tot_len);
+
+#ifdef CONFIG_IPSEC_DEBUG
+					if (debug_tunnel & DB_TN_CROUT)
+					{
+						if (old_tot_len > ntohs(iph->tot_len))
+							KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+								    "klips_debug:ipsec_tunnel_start_xmit: "
+								    "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n",
+								    old_tot_len, ntohs(iph->tot_len),
+								    ntohs(((struct ipcomphdr*)(((char*)iph) + ((iph->ihl) << 2)))->ipcomp_cpi),
+								    ntohl(tdbp->tdb_said.spi),
+								    (__u16)(ntohl(tdbp->tdb_said.spi) & 0x0000ffff));
+						else
+							KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+								    "klips_debug:ipsec_tunnel_start_xmit: "
+								    "packet did not compress (flags = %d).\n",
+								    flags);
+					}
+#endif /* CONFIG_IPSEC_DEBUG */
+				}
+				break;
+#endif /* CONFIG_IPSEC_IPCOMP */
+			default:
+				spin_unlock(&tdb_lock);
+				stats->tx_errors++;
+				goto cleanup;
+			}
+			
+#ifdef NET_21
+			skb->nh.raw = skb->data;
+#else /* NET_21 */
+			skb->ip_hdr = skb->h.iph = (struct iphdr *) skb->data;
+#endif /* NET_21 */
+			iph->check = 0;
+			iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+			
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "after <%s%s%s>, SA:%s:\n",
+				    IPS_XFORM_NAME(tdbp),
+				    sa_len ? sa : " (error)");
+			KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, iph);
+ 			
+			tdbp->ips_life.ipl_bytes.ipl_count += len;
+			tdbp->ips_life.ipl_bytes.ipl_last = len;
+
+			if(!tdbp->ips_life.ipl_usetime.ipl_count) {
+				tdbp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;
+			}
+			tdbp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;
+			tdbp->ips_life.ipl_packets.ipl_count++; 
+
+			tdbprev = tdbp;
+			tdbp = tdbp->ips_onext;
+#ifdef CONFIG_IPSEC_ALG
+			ixt_e = NULL;	/* invalidate ipsec_alg */
+			ixt_a = NULL;
+#endif /* CONFIG_IPSEC_ALG */
+			
+		}
+		/* end encapsulation loop here XXX */
+
+		spin_unlock(&tdb_lock);
+
+		matcher.sen_ip_src.s_addr = iph->saddr;
+		matcher.sen_ip_dst.s_addr = iph->daddr;
+		matcher.sen_proto = iph->protocol;
+		extract_ports(iph, &matcher);
+		
+		spin_lock(&eroute_lock);
+		er = ipsec_findroute(&matcher);
+		if(er) {
+			outgoing_said = er->er_said;
+			eroute_pid = er->er_pid;
+			er->er_count++;
+			er->er_lasttime = jiffies/HZ;
+		}
+		spin_unlock(&eroute_lock);
+		KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) &&
+			    /* ((orgdst != newdst) || (orgsrc != newsrc)) */
+			    (orgedst != outgoing_said.dst.s_addr) &&
+			    outgoing_said.dst.s_addr &&
+			    er,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "We are recursing here.\n");
+	} while(/*((orgdst != newdst) || (orgsrc != newsrc))*/
+		(orgedst != outgoing_said.dst.s_addr) &&
+		outgoing_said.dst.s_addr &&
+		er);
+	
+	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+		    "klips_debug:ipsec_tunnel_start_xmit: "
+		    "After recursive xforms -- head,tailroom: %d,%d\n",
+		    skb_headroom(skb), skb_tailroom(skb));
+
+	if(saved_header) {
+		if(skb_headroom(skb) < hard_header_len) {
+			printk(KERN_WARNING
+			       "klips_error:ipsec_tunnel_start_xmit: "
+			       "tried to skb_push hhlen=%d, %d available.  This should never happen, please report.\n",
+			       hard_header_len, skb_headroom(skb));
+			stats->tx_errors++;
+			goto cleanup;
+		}
+		skb_push(skb, hard_header_len);
+		for (i = 0; i < hard_header_len; i++) {
+			skb->data[i] = saved_header[i];
+		}
+	}
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	if (natt_type && natt_head) {
+		struct iphdr *ipp = skb->nh.iph;
+		struct udphdr *udp;
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			"klips_debug:ipsec_tunnel_start_xmit: "
+			"encapsuling packet into UDP (NAT-Traversal)\n");
+		iphlen = ipp->ihl << 2;
+		ipp->tot_len =
+			htons(ntohs(ipp->tot_len) + natt_head);
+		if(skb_tailroom(skb) < natt_head) {
+			printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
+				"tried to skb_put %d, %d available. "
+				"This should never happen, please report.\n",
+				natt_head,
+				skb_tailroom(skb));
+			stats->tx_errors++;
+			goto cleanup;
+		}
+		skb_put(skb, natt_head);
+		udp = (struct udphdr *)((char *)ipp + iphlen);
+		/* move ESP hdr after UDP hdr */
+		memmove((void *)((char *)udp + natt_head),
+			(void *)(udp),
+			ntohs(ipp->tot_len) - iphlen - natt_head);
+		/* clear UDP & Non-IKE Markers (if any) */
+		memset(udp, 0, natt_head);
+		/* fill UDP with usefull informations ;-) */
+		udp->source = htons(natt_sport);
+		udp->dest = htons(natt_dport);
+		udp->len = htons(ntohs(ipp->tot_len) - iphlen);
+		/* set protocol */
+		ipp->protocol = IPPROTO_UDP;
+		/* fix IP checksum */
+		ipp->check = 0;
+		ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl);
+	}
+#endif
+ bypass:
+	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+		    "klips_debug:ipsec_tunnel_start_xmit: "
+		    "With hard_header, final head,tailroom: %d,%d\n",
+		    skb_headroom(skb), skb_tailroom(skb));
+
+#ifdef NET_21	/* 2.2 and 2.4 kernels */
+	/* new route/dst cache code from James Morris */
+	skb->dev = physdev;
+	/*skb_orphan(skb);*/
+	if((error = ip_route_output(&rt,
+				    skb->nh.iph->daddr,
+				    pass ? 0 : skb->nh.iph->saddr,
+				    RT_TOS(skb->nh.iph->tos),
+				    physdev->iflink /* rgb: should this be 0? */))) {
+		stats->tx_errors++;
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n",
+			    error,
+			    rt->u.dst.dev->name);
+		goto cleanup;
+	}
+	if(dev == rt->u.dst.dev) {
+		ip_rt_put(rt);
+		/* This is recursion, drop it. */
+		stats->tx_errors++;
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n", dev->name);
+		goto cleanup;
+	}
+	dst_release(skb->dst);
+	skb->dst = &rt->u.dst;
+	stats->tx_bytes += skb->len;
+	if(skb->len < skb->nh.raw - skb->data) {
+		stats->tx_errors++;
+		printk(KERN_WARNING
+		       "klips_error:ipsec_tunnel_start_xmit: "
+		       "tried to __skb_pull nh-data=%d, %d available.  This should never happen, please report.\n",
+		       skb->nh.raw - skb->data, skb->len);
+		goto cleanup;
+	}
+	__skb_pull(skb, skb->nh.raw - skb->data);
+#ifdef SKB_RESET_NFCT
+        if(!pass) {                                                                                                   
+        	nf_conntrack_put(skb->nfct);                                                                                 
+        	skb->nfct = NULL;                                                                                            
+        }        
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif /* CONFIG_NETFILTER_DEBUG */
+#endif /* SKB_RESET_NFCT */
+	KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+		    "klips_debug:ipsec_tunnel_start_xmit: "
+		    "...done, calling ip_send() on device:%s\n",
+		    skb->dev ? skb->dev->name : "NULL");
+	KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, skb->nh.iph);
+#ifdef NETDEV_23	/* 2.4 kernels */
+	{
+		int err;
+
+		err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+			      ipsec_tunnel_xmit2);
+		if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) {
+			if(net_ratelimit())
+				printk(KERN_ERR
+				       "klips_error:ipsec_tunnel_start_xmit: "
+				       "ip_send() failed, err=%d\n", 
+				       -err);
+			stats->tx_errors++;
+			stats->tx_aborted_errors++;
+			skb = NULL;
+			goto cleanup;
+		}
+	}
+#else /* NETDEV_23 */	/* 2.2 kernels */
+	ip_send(skb);
+#endif /* NETDEV_23 */
+#else /* NET_21 */	/* 2.0 kernels */
+	skb->arp = 1;
+	/* ISDN/ASYNC PPP from Matjaz Godec. */
+	/*	skb->protocol = htons(ETH_P_IP); */
+	KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+		    "klips_debug:ipsec_tunnel_start_xmit: "
+		    "...done, calling dev_queue_xmit() or ip_fragment().\n");
+	IP_SEND(skb, physdev);
+#endif /* NET_21 */
+	stats->tx_packets++;
+
+	skb = NULL;
+ cleanup:
+#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE)
+	netif_wake_queue(dev);
+#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
+	dev->tbusy = 0;
+#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
+	if(saved_header) {
+		kfree(saved_header);
+	}
+	if(skb) {
+		dev_kfree_skb(skb, FREE_WRITE);
+	}
+	if(oskb) {
+		dev_kfree_skb(oskb, FREE_WRITE);
+	}
+	if (tdb.tdb_ident_s.data) {
+		kfree(tdb.tdb_ident_s.data);
+	}
+	if (tdb.tdb_ident_d.data) {
+		kfree(tdb.tdb_ident_d.data);
+	}
+	return 0;
+}
+
+DEBUG_NO_STATIC struct net_device_stats *
+ipsec_tunnel_get_stats(struct device *dev)
+{
+	return &(((struct ipsecpriv *)(dev->priv))->mystats);
+}
+
+/*
+ * Revectored calls.
+ * For each of these calls, a field exists in our private structure.
+ */
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_hard_header(struct sk_buff *skb, struct device *dev,
+	unsigned short type, void *daddr, void *saddr, unsigned len)
+{
+	struct ipsecpriv *prv = dev->priv;
+	struct device *tmp;
+	int ret;
+	struct net_device_stats *stats;	/* This device's statistics */
+	
+	if(skb == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "no skb...\n");
+		return -ENODATA;
+	}
+
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "no device...\n");
+		return -ENODEV;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel_hard_header: "
+		    "skb->dev=%s dev=%s.\n",
+		    skb->dev ? skb->dev->name : "NULL",
+		    dev->name);
+	
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "no private space associated with dev=%s\n",
+			    dev->name ? dev->name : "NULL");
+		return -ENODEV;
+	}
+
+	stats = (struct net_device_stats *) &(prv->mystats);
+
+	if(prv->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "no physical device associated with dev=%s\n",
+			    dev->name ? dev->name : "NULL");
+		stats->tx_dropped++;
+		return -ENODEV;
+	}
+
+	/* check if we have to send a IPv6 packet. It might be a Router
+	   Solicitation, where the building of the packet happens in
+	   reverse order:
+	   1. ll hdr,
+	   2. IPv6 hdr,
+	   3. ICMPv6 hdr
+	   -> skb->nh.raw is still uninitialized when this function is
+	   called!!  If this is no IPv6 packet, we can print debugging
+	   messages, otherwise we skip all debugging messages and just
+	   build the ll header */
+	if(type != ETH_P_IPV6) {
+		/* execute this only, if we don't have to build the
+		   header for a IPv6 packet */
+		if(!prv->hard_header) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+				    "klips_debug:ipsec_tunnel_hard_header: "
+				    "physical device has been detached, packet dropped 0x%p->0x%p len=%d type=%d dev=%s->NULL ",
+				    saddr,
+				    daddr,
+				    len,
+				    type,
+				    dev->name);
+#ifdef NET_21
+			KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
+					"ip=%08x->%08x\n",
+					(__u32)ntohl(skb->nh.iph->saddr),
+					(__u32)ntohl(skb->nh.iph->daddr) );
+#else /* NET_21 */
+			KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
+					"ip=%08x->%08x\n",
+					(__u32)ntohl(skb->ip_hdr->saddr),
+					(__u32)ntohl(skb->ip_hdr->daddr) );
+#endif /* NET_21 */
+			stats->tx_dropped++;
+			return -ENODEV;
+		}
+		
+#define da ((struct device *)(prv->dev))->dev_addr
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "Revectored 0x%p->0x%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ",
+			    saddr,
+			    daddr,
+			    len,
+			    type,
+			    dev->name,
+			    prv->dev->name,
+			    da[0], da[1], da[2], da[3], da[4], da[5]);
+#ifdef NET_21
+		KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
+			    "ip=%08x->%08x\n",
+			    (__u32)ntohl(skb->nh.iph->saddr),
+			    (__u32)ntohl(skb->nh.iph->daddr) );
+#else /* NET_21 */
+		KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
+			    "ip=%08x->%08x\n",
+			    (__u32)ntohl(skb->ip_hdr->saddr),
+			    (__u32)ntohl(skb->ip_hdr->daddr) );
+#endif /* NET_21 */
+	} else {
+		KLIPS_PRINT(debug_tunnel,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n");
+	}                                                                       
+	tmp = skb->dev;
+	skb->dev = prv->dev;
+	ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len);
+	skb->dev = tmp;
+	return ret;
+}
+
+DEBUG_NO_STATIC int
+#ifdef NET_21
+ipsec_tunnel_rebuild_header(struct sk_buff *skb)
+#else /* NET_21 */
+ipsec_tunnel_rebuild_header(void *buff, struct device *dev,
+			unsigned long raddr, struct sk_buff *skb)
+#endif /* NET_21 */
+{
+	struct ipsecpriv *prv = skb->dev->priv;
+	struct device *tmp;
+	int ret;
+	struct net_device_stats *stats;	/* This device's statistics */
+	
+	if(skb->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_rebuild_header: "
+			    "no device...");
+		return -ENODEV;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_rebuild_header: "
+			    "no private space associated with dev=%s",
+			    skb->dev->name ? skb->dev->name : "NULL");
+		return -ENODEV;
+	}
+
+	stats = (struct net_device_stats *) &(prv->mystats);
+
+	if(prv->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_rebuild_header: "
+			    "no physical device associated with dev=%s",
+			    skb->dev->name ? skb->dev->name : "NULL");
+		stats->tx_dropped++;
+		return -ENODEV;
+	}
+
+	if(!prv->rebuild_header) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_rebuild_header: "
+			    "physical device has been detached, packet dropped skb->dev=%s->NULL ",
+			    skb->dev->name);
+#ifdef NET_21
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "ip=%08x->%08x\n",
+			    (__u32)ntohl(skb->nh.iph->saddr),
+			    (__u32)ntohl(skb->nh.iph->daddr) );
+#else /* NET_21 */
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "ip=%08x->%08x\n",
+			    (__u32)ntohl(skb->ip_hdr->saddr),
+			    (__u32)ntohl(skb->ip_hdr->daddr) );
+#endif /* NET_21 */
+		stats->tx_dropped++;
+		return -ENODEV;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel: "
+		    "Revectored rebuild_header dev=%s->%s ",
+		    skb->dev->name, prv->dev->name);
+#ifdef NET_21
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "ip=%08x->%08x\n",
+		    (__u32)ntohl(skb->nh.iph->saddr),
+		    (__u32)ntohl(skb->nh.iph->daddr) );
+#else /* NET_21 */
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "ip=%08x->%08x\n",
+		    (__u32)ntohl(skb->ip_hdr->saddr),
+		    (__u32)ntohl(skb->ip_hdr->daddr) );
+#endif /* NET_21 */
+	tmp = skb->dev;
+	skb->dev = prv->dev;
+	
+#ifdef NET_21
+	ret = prv->rebuild_header(skb);
+#else /* NET_21 */
+	ret = prv->rebuild_header(buff, prv->dev, raddr, skb);
+#endif /* NET_21 */
+	skb->dev = tmp;
+	return ret;
+}
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_set_mac_address(struct device *dev, void *addr)
+{
+	struct ipsecpriv *prv = dev->priv;
+	
+	struct net_device_stats *stats;	/* This device's statistics */
+	
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_set_mac_address: "
+			    "no device...");
+		return -ENODEV;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_set_mac_address: "
+			    "no private space associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		return -ENODEV;
+	}
+
+	stats = (struct net_device_stats *) &(prv->mystats);
+
+	if(prv->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_set_mac_address: "
+			    "no physical device associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		stats->tx_dropped++;
+		return -ENODEV;
+	}
+
+	if(!prv->set_mac_address) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_set_mac_address: "
+			    "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
+			    dev->name);
+		return -ENODEV;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel_set_mac_address: "
+		    "Revectored dev=%s->%s addr=%p\n",
+		    dev->name, prv->dev->name, addr);
+	return prv->set_mac_address(prv->dev, addr);
+
+}
+
+#ifndef NET_21
+DEBUG_NO_STATIC void
+ipsec_tunnel_cache_bind(struct hh_cache **hhp, struct device *dev,
+				 unsigned short htype, __u32 daddr)
+{
+	struct ipsecpriv *prv = dev->priv;
+	
+	struct net_device_stats *stats;	/* This device's statistics */
+	
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_bind: "
+			    "no device...");
+		return;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_bind: "
+			    "no private space associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		return;
+	}
+
+	stats = (struct net_device_stats *) &(prv->mystats);
+
+	if(prv->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_bind: "
+			    "no physical device associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		stats->tx_dropped++;
+		return;
+	}
+
+	if(!prv->header_cache_bind) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_bind: "
+			    "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
+			    dev->name);
+		stats->tx_dropped++;
+		return;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel_cache_bind: "
+		    "Revectored \n");
+	prv->header_cache_bind(hhp, prv->dev, htype, daddr);
+	return;
+}
+#endif /* !NET_21 */
+
+
+DEBUG_NO_STATIC void
+ipsec_tunnel_cache_update(struct hh_cache *hh, struct device *dev, unsigned char *  haddr)
+{
+	struct ipsecpriv *prv = dev->priv;
+	
+	struct net_device_stats *stats;	/* This device's statistics */
+	
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_update: "
+			    "no device...");
+		return;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_update: "
+			    "no private space associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		return;
+	}
+
+	stats = (struct net_device_stats *) &(prv->mystats);
+
+	if(prv->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_update: "
+			    "no physical device associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		stats->tx_dropped++;
+		return;
+	}
+
+	if(!prv->header_cache_update) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_cache_update: "
+			    "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
+			    dev->name);
+		return;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel: "
+		    "Revectored cache_update\n");
+	prv->header_cache_update(hh, prv->dev, haddr);
+	return;
+}
+
+#ifdef NET_21
+DEBUG_NO_STATIC int
+ipsec_tunnel_neigh_setup(struct neighbour *n)
+{
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel_neigh_setup:\n");
+
+        if (n->nud_state == NUD_NONE) {
+                n->ops = &arp_broken_ops;
+                n->output = n->ops->output;
+        }
+        return 0;
+}
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+{
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel_neigh_setup_dev: "
+		    "setting up %s\n",
+		    dev ? dev->name : "NULL");
+
+        if (p->tbl->family == AF_INET) {
+                p->neigh_setup = ipsec_tunnel_neigh_setup;
+                p->ucast_probes = 0;
+                p->mcast_probes = 0;
+        }
+        return 0;
+}
+#endif /* NET_21 */
+
+/*
+ * We call the attach routine to attach another device.
+ */
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_attach(struct device *dev, struct device *physdev)
+{
+        int i;
+	struct ipsecpriv *prv = dev->priv;
+
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_attach: "
+			    "no device...");
+		return -ENODEV;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_attach: "
+			    "no private space associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		return -ENODATA;
+	}
+
+	prv->dev = physdev;
+	prv->hard_start_xmit = physdev->hard_start_xmit;
+	prv->get_stats = physdev->get_stats;
+
+	if (physdev->hard_header) {
+		prv->hard_header = physdev->hard_header;
+		dev->hard_header = ipsec_tunnel_hard_header;
+	} else
+		dev->hard_header = NULL;
+	
+	if (physdev->rebuild_header) {
+		prv->rebuild_header = physdev->rebuild_header;
+		dev->rebuild_header = ipsec_tunnel_rebuild_header;
+	} else
+		dev->rebuild_header = NULL;
+	
+	if (physdev->set_mac_address) {
+		prv->set_mac_address = physdev->set_mac_address;
+		dev->set_mac_address = ipsec_tunnel_set_mac_address;
+	} else
+		dev->set_mac_address = NULL;
+	
+#ifndef NET_21
+	if (physdev->header_cache_bind) {
+		prv->header_cache_bind = physdev->header_cache_bind;
+		dev->header_cache_bind = ipsec_tunnel_cache_bind;
+	} else
+		dev->header_cache_bind = NULL;
+#endif /* !NET_21 */
+
+	if (physdev->header_cache_update) {
+		prv->header_cache_update = physdev->header_cache_update;
+		dev->header_cache_update = ipsec_tunnel_cache_update;
+	} else
+		dev->header_cache_update = NULL;
+
+	dev->hard_header_len = physdev->hard_header_len;
+
+#ifdef NET_21
+/*	prv->neigh_setup        = physdev->neigh_setup; */
+	dev->neigh_setup        = ipsec_tunnel_neigh_setup_dev;
+#endif /* NET_21 */
+	dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */
+	prv->mtu = physdev->mtu;
+
+#ifdef PHYSDEV_TYPE
+	dev->type = physdev->type /* ARPHRD_TUNNEL */;	/* initially */
+#endif /*  PHYSDEV_TYPE */
+
+	dev->addr_len = physdev->addr_len;
+	for (i=0; i<dev->addr_len; i++) {
+		dev->dev_addr[i] = physdev->dev_addr[i];
+	}
+#ifdef CONFIG_IPSEC_DEBUG
+	if(debug_tunnel & DB_TN_INIT) {
+		printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: "
+		       "physical device %s being attached has HW address: %2x",
+		       physdev->name, physdev->dev_addr[0]);
+		for (i=1; i < physdev->addr_len; i++) {
+			printk(":%02x", physdev->dev_addr[i]);
+		}
+		printk("\n");
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	return 0;
+}
+
+/*
+ * We call the detach routine to detach the ipsec tunnel from another device.
+ */
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_detach(struct device *dev)
+{
+        int i;
+	struct ipsecpriv *prv = dev->priv;
+
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_detach: "
+			    "no device...");
+		return -ENODEV;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_detach: "
+			    "no private space associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		return -ENODATA;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_detach: "
+		    "physical device %s being detached from virtual device %s\n",
+		    prv->dev ? prv->dev->name : "NULL",
+		    dev->name);
+
+	prv->dev = NULL;
+	prv->hard_start_xmit = NULL;
+	prv->get_stats = NULL;
+
+	prv->hard_header = NULL;
+#ifdef DETACH_AND_DOWN
+	dev->hard_header = NULL;
+#endif /* DETACH_AND_DOWN */
+	
+	prv->rebuild_header = NULL;
+#ifdef DETACH_AND_DOWN
+	dev->rebuild_header = NULL;
+#endif /* DETACH_AND_DOWN */
+	
+	prv->set_mac_address = NULL;
+#ifdef DETACH_AND_DOWN
+	dev->set_mac_address = NULL;
+#endif /* DETACH_AND_DOWN */
+	
+#ifndef NET_21
+	prv->header_cache_bind = NULL;
+#ifdef DETACH_AND_DOWN
+	dev->header_cache_bind = NULL;
+#endif /* DETACH_AND_DOWN */
+#endif /* !NET_21 */
+
+	prv->header_cache_update = NULL;
+#ifdef DETACH_AND_DOWN
+	dev->header_cache_update = NULL;
+#endif /* DETACH_AND_DOWN */
+
+#ifdef NET_21
+/*	prv->neigh_setup        = NULL; */
+#ifdef DETACH_AND_DOWN
+	dev->neigh_setup        = NULL;
+#endif /* DETACH_AND_DOWN */
+#endif /* NET_21 */
+	dev->hard_header_len = 0;
+#ifdef DETACH_AND_DOWN
+	dev->mtu = 0;
+#endif /* DETACH_AND_DOWN */
+	prv->mtu = 0;
+	for (i=0; i<MAX_ADDR_LEN; i++) {
+		dev->dev_addr[i] = 0;
+	}
+	dev->addr_len = 0;
+#ifdef PHYSDEV_TYPE
+	dev->type = ARPHRD_TUNNEL;
+#endif /*  PHYSDEV_TYPE */
+	
+	return 0;
+}
+
+/*
+ * We call the clear routine to detach all ipsec tunnels from other devices.
+ */
+DEBUG_NO_STATIC int
+ipsec_tunnel_clear(void)
+{
+	int i;
+	struct device *ipsecdev = NULL, *prvdev;
+	struct ipsecpriv *prv;
+	char name[9];
+	int ret;
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_clear: .\n");
+
+	for(i = 0; i < IPSEC_NUM_IF; i++) {
+		sprintf(name, "ipsec%d", i);
+		if((ipsecdev = ipsec_dev_get(name)) != NULL) {
+			if((prv = (struct ipsecpriv *)(ipsecdev->priv))) {
+				prvdev = (struct device *)(prv->dev);
+				if(prvdev) {
+					KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+						    "klips_debug:ipsec_tunnel_clear: "
+						    "physical device for device %s is %s\n",
+						    name, prvdev->name);
+					if((ret = ipsec_tunnel_detach(ipsecdev))) {
+						KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+							    "klips_debug:ipsec_tunnel_clear: "
+							    "error %d detatching device %s from device %s.\n",
+							    ret, name, prvdev->name);
+						return ret;
+					}
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+DEBUG_NO_STATIC int
+ipsec_tunnel_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+{
+	struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data;
+	struct ipsecpriv *prv = dev->priv;
+	struct device *them; /* physical device */
+#ifdef CONFIG_IP_ALIAS
+	char *colon;
+	char realphysname[IFNAMSIZ];
+#endif /* CONFIG_IP_ALIAS */
+	
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_tunnel_ioctl: "
+			    "device not supplied.\n");
+		return -ENODEV;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_ioctl: "
+		    "tncfg service call #%d for dev=%s\n",
+		    cmd,
+		    dev->name ? dev->name : "NULL");
+	switch (cmd) {
+	/* attach a virtual ipsec? device to a physical device */
+	case IPSEC_SET_DEV:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_tunnel_ioctl: "
+			    "calling ipsec_tunnel_attatch...\n");
+#ifdef CONFIG_IP_ALIAS
+		/* If this is an IP alias interface, get its real physical name */
+		strncpy(realphysname, cf->cf_name, IFNAMSIZ);
+		realphysname[IFNAMSIZ-1] = 0;
+		colon = strchr(realphysname, ':');
+		if (colon) *colon = 0;
+		them = ipsec_dev_get(realphysname);
+#else /* CONFIG_IP_ALIAS */
+		them = ipsec_dev_get(cf->cf_name);
+#endif /* CONFIG_IP_ALIAS */
+
+		if (them == NULL) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_tunnel_ioctl: "
+				    "physical device %s requested is null\n",
+				    cf->cf_name);
+			return -ENXIO;
+		}
+		
+#if 0
+		if (them->flags & IFF_UP) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_tunnel_ioctl: "
+				    "physical device %s requested is not up.\n",
+				    cf->cf_name);
+			return -ENXIO;
+		}
+#endif
+		
+		if (prv && prv->dev) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_tunnel_ioctl: "
+				    "virtual device is already connected to %s.\n",
+				    prv->dev->name ? prv->dev->name : "NULL");
+			return -EBUSY;
+		}
+		return ipsec_tunnel_attach(dev, them);
+
+	case IPSEC_DEL_DEV:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_tunnel_ioctl: "
+			    "calling ipsec_tunnel_detatch.\n");
+		if (! prv->dev) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_tunnel_ioctl: "
+				    "physical device not connected.\n");
+			return -ENODEV;
+		}
+		return ipsec_tunnel_detach(dev);
+	       
+	case IPSEC_CLR_DEV:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_tunnel_ioctl: "
+			    "calling ipsec_tunnel_clear.\n");
+		return ipsec_tunnel_clear();
+
+	default:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_tunnel_ioctl: "
+			    "unknown command %d.\n",
+			    cmd);
+		return -EOPNOTSUPP;
+	}
+}
+
+int
+ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
+{
+	struct device *dev = ptr;
+	struct device *ipsec_dev;
+	struct ipsecpriv *priv;
+	char name[9];
+	int i;
+
+	if (dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "dev=NULL for event type %ld.\n",
+			    event);
+		return(NOTIFY_DONE);
+	}
+
+	/* check for loopback devices */
+	if (dev && (dev->flags & IFF_LOOPBACK)) {
+		return(NOTIFY_DONE);
+	}
+
+	switch (event) {
+	case NETDEV_DOWN:
+		/* look very carefully at the scope of these compiler
+		   directives before changing anything... -- RGB */
+#ifdef NET_21
+	case NETDEV_UNREGISTER:
+		switch (event) {
+		case NETDEV_DOWN:
+#endif /* NET_21 */
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_device_event: "
+				    "NETDEV_DOWN dev=%s flags=%x\n",
+				    dev->name,
+				    dev->flags);
+			if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) {
+				printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n",
+				       dev->name);
+			}
+#ifdef NET_21
+			break;
+		case NETDEV_UNREGISTER:
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_device_event: "
+				    "NETDEV_UNREGISTER dev=%s flags=%x\n",
+				    dev->name,
+				    dev->flags);
+			break;
+		}
+#endif /* NET_21 */
+		
+		/* find the attached physical device and detach it. */
+		for(i = 0; i < IPSEC_NUM_IF; i++) {
+			sprintf(name, "ipsec%d", i);
+			ipsec_dev = ipsec_dev_get(name);
+			if(ipsec_dev) {
+				priv = (struct ipsecpriv *)(ipsec_dev->priv);
+				if(priv) {
+					;
+					if(((struct device *)(priv->dev)) == dev) {
+						/* dev_close(ipsec_dev); */
+						/* return */ ipsec_tunnel_detach(ipsec_dev);
+						KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+							    "klips_debug:ipsec_device_event: "
+							    "device '%s' has been detached.\n",
+							    ipsec_dev->name);
+						break;
+					}
+				} else {
+					KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+						    "klips_debug:ipsec_device_event: "
+						    "device '%s' has no private data space!\n",
+						    ipsec_dev->name);
+				}
+			}
+		}
+		break;
+	case NETDEV_UP:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_UP dev=%s\n",
+			    dev->name);
+		break;
+#ifdef NET_21
+	case NETDEV_REBOOT:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_REBOOT dev=%s\n",
+			    dev->name);
+		break;
+	case NETDEV_CHANGE:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_CHANGE dev=%s flags=%x\n",
+			    dev->name,
+			    dev->flags);
+		break;
+	case NETDEV_REGISTER:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_REGISTER dev=%s\n",
+			    dev->name);
+		break;
+	case NETDEV_CHANGEMTU:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_CHANGEMTU dev=%s to mtu=%d\n",
+			    dev->name,
+			    dev->mtu);
+		break;
+	case NETDEV_CHANGEADDR:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_CHANGEADDR dev=%s\n",
+			    dev->name);
+		break;
+	case NETDEV_GOING_DOWN:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_GOING_DOWN dev=%s\n",
+			    dev->name);
+		break;
+	case NETDEV_CHANGENAME:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_CHANGENAME dev=%s\n",
+			    dev->name);
+		break;
+#endif /* NET_21 */
+	default:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "event type %ld unrecognised for dev=%s\n",
+			    event,
+			    dev->name);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+/*
+ *	Called when an ipsec tunnel device is initialized.
+ *	The ipsec tunnel device structure is passed to us.
+ */
+ 
+int
+ipsec_tunnel_init(struct device *dev)
+{
+	int i;
+
+#if 0
+	printk(KERN_INFO
+	       "klips_debug:ipsec_tunnel_init: "
+	       "initialisation of device: %s\n",
+	       dev->name ? dev->name : "NULL");
+#endif
+
+	/* Add our tunnel functions to the device */
+	dev->open		= ipsec_tunnel_open;
+	dev->stop		= ipsec_tunnel_close;
+	dev->hard_start_xmit	= ipsec_tunnel_start_xmit;
+	dev->get_stats		= ipsec_tunnel_get_stats;
+
+	dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL);
+	if (dev->priv == NULL)
+		return -ENOMEM;
+	memset(dev->priv, 0, sizeof(struct ipsecpriv));
+
+	for(i = 0; i < sizeof(zeroes); i++) {
+		((__u8*)(zeroes))[i] = 0;
+	}
+	
+#ifndef NET_21
+	/* Initialize the tunnel device structure */
+	for (i = 0; i < DEV_NUMBUFFS; i++)
+		skb_queue_head_init(&dev->buffs[i]);
+#endif /* !NET_21 */
+
+	dev->set_multicast_list = NULL;
+	dev->do_ioctl		= ipsec_tunnel_ioctl;
+	dev->hard_header	= NULL;
+	dev->rebuild_header 	= NULL;
+	dev->set_mac_address 	= NULL;
+#ifndef NET_21
+	dev->header_cache_bind 	= NULL;
+#endif /* !NET_21 */
+	dev->header_cache_update= NULL;
+
+#ifdef NET_21
+/*	prv->neigh_setup        = NULL; */
+	dev->neigh_setup        = ipsec_tunnel_neigh_setup_dev;
+#endif /* NET_21 */
+	dev->hard_header_len 	= 0;
+	dev->mtu		= 0;
+	dev->addr_len		= 0;
+	dev->type		= ARPHRD_TUNNEL; /* 0 */ /* ARPHRD_ETHER; */ /* initially */
+	dev->tx_queue_len	= 10;		/* Small queue */
+	memset(dev->broadcast,0xFF, ETH_ALEN);	/* what if this is not attached to ethernet? */
+
+	/* New-style flags. */
+	dev->flags		= IFF_NOARP /* 0 */ /* Petr Novak */;
+#ifdef NET_21
+	dev_init_buffers(dev);
+#else /* NET_21 */
+	dev->family		= AF_INET;
+	dev->pa_addr		= 0;
+	dev->pa_brdaddr 	= 0;
+	dev->pa_mask		= 0;
+	dev->pa_alen		= 4;
+#endif /* NET_21 */
+
+	/* We're done.  Have I forgotten anything? */
+	return 0;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/*  Module specific interface (but it links with the rest of IPSEC  */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+int
+ipsec_tunnel_probe(struct device *dev)
+{
+	ipsec_tunnel_init(dev); 
+	return 0;
+}
+
+static struct device dev_ipsec3 = 
+{
+	"ipsec3\0   ",		/* name */
+	0,			/* recv memory end */
+	0,			/* recv memory start */
+	0,			/* memory end */
+	0,			/* memory start */
+ 	0x0,			/* base I/O address */
+	0,			/* IRQ */
+	0, 0, 0,		/* flags */
+	NULL,			/* next device */
+	ipsec_tunnel_probe	/* setup */
+};
+
+static struct device dev_ipsec2 = 
+{
+	"ipsec2\0   ",		/* name */
+	0,			/* recv memory end */
+	0,			/* recv memory start */
+	0,			/* memory end */
+	0,			/* memory start */
+ 	0x0,			/* base I/O address */
+	0,			/* IRQ */
+	0, 0, 0,		/* flags */
+	NULL,			/* next device */
+	ipsec_tunnel_probe	/* setup */
+};
+
+static struct device dev_ipsec1 = 
+{
+	"ipsec1\0   ",		/* name */
+	0,			/* recv memory end */
+	0,			/* recv memory start */
+	0,			/* memory end */
+	0,			/* memory start */
+ 	0x0,			/* base I/O address */
+	0,			/* IRQ */
+	0, 0, 0,		/* flags */
+	NULL,			/* next device */
+	ipsec_tunnel_probe	/* setup */
+};
+
+static struct device dev_ipsec0 = 
+{
+	"ipsec0\0   ",		/* name */
+	0,			/* recv memory end */
+	0,			/* recv memory start */
+	0,			/* memory end */
+	0,			/* memory start */
+ 	0x0,			/* base I/O address */
+	0,			/* IRQ */
+	0, 0, 0,		/* flags */
+	NULL,			/* next device */
+	ipsec_tunnel_probe	/* setup */
+};
+
+int 
+ipsec_tunnel_init_devices(void)
+{
+#if 0
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_init_devices: "
+		    "registering device %s\n",
+		    dev_ipsec0.name);
+#endif
+	if (register_netdev(&dev_ipsec0) != 0)
+		return -EIO;
+#if 0
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_init_devices: "
+		    "registering device %s\n",
+		    dev_ipsec1.name);
+#endif
+	if (register_netdev(&dev_ipsec1) != 0)
+		return -EIO;
+#if 0
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_init_devices: "
+		    "registering device %s\n",
+		    dev_ipsec2.name);
+#endif
+	if (register_netdev(&dev_ipsec2) != 0)
+		return -EIO;
+#if 0
+	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+		    "klips_debug:ipsec_tunnel_init_devices: "
+		    "registering device %s\n",
+		    dev_ipsec3.name);
+#endif
+	if (register_netdev(&dev_ipsec3) != 0)
+		return -EIO;
+	return 0;
+}
+
+/* void */
+int
+ipsec_tunnel_cleanup_devices(void)
+{
+	int error = 0;
+
+	unregister_netdev(&dev_ipsec0);
+	unregister_netdev(&dev_ipsec1);
+	unregister_netdev(&dev_ipsec2);
+	unregister_netdev(&dev_ipsec3);
+	kfree(dev_ipsec0.priv);
+	kfree(dev_ipsec1.priv);
+	kfree(dev_ipsec2.priv);
+	kfree(dev_ipsec3.priv);
+	dev_ipsec0.priv=NULL;
+	dev_ipsec1.priv=NULL;
+	dev_ipsec2.priv=NULL;
+	dev_ipsec3.priv=NULL;
+
+	return error;
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.14  2003/07/04 19:07:34  ken
+ * Added NAT-T 0.6 diff/patch from Tuomo
+ *
+ * Revision 1.13  2003/04/09 15:22:54  ken
+ * OE SNAT Fix (mcr)
+ *
+ * Revision 1.12  2003/02/07 13:14:25  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.11.2.1  2003/02/06 22:09:50  jjo
+ * sync to alg-0.8.1-rc4
+ *
+ * Revision 1.11  2003/01/19 22:32:30  ken
+ * X.509 0.9.19 -> 0.9.20
+ *
+ * Revision 1.10  2003/01/09 04:33:54  ken
+ * Applied diffs from X.509 0.9.18 -> 0.9.19
+ *
+ * Revision 1.9  2003/01/06 15:27:46  ken
+ * Patched NAT-T 0.5 -> 0.5a - mlafon
+ *
+ * Revision 1.8  2003/01/06 00:13:17  ken
+ * Fix from NAT-T 0.5a - keep udp/4500 (NAT-T Float) hole open.  mlafon
+ *
+ * Revision 1.7  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.6  2002/10/16 00:21:47  ken
+ * Applied JuanJo's NULL Patch
+ *
+ * Revision 1.5  2002/10/16 00:16:50  ken
+ * Backed out David patch in prep for JuanJo's
+ *
+ * Revision 1.4  2002/10/15 17:52:47  ken
+ * Added David De Reu's NULL ALG Bugfix
+ *
+ * Revision 1.3  2002/09/05 03:53:52  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.2  2002/09/05 03:27:08  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.187  2002/03/23 19:55:17  rgb
+ * Fix for 2.2 local IKE fragmentation blackhole.  Still won't work if
+ * iptraf or another pcap app is running.
+ *
+ * Revision 1.186  2002/03/19 03:26:22  rgb
+ * Applied DHR's tunnel patch to streamline IKE/specialSA processing.
+ *
+ * Revision 1.185  2002/02/20 04:13:05  rgb
+ * Send back ICMP_PKT_FILTERED upon %reject.
+ *
+ * Revision 1.184  2002/01/29 17:17:56  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.183  2002/01/29 04:00:53  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.182  2002/01/29 02:13:18  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.181  2002/01/07 20:00:33  rgb
+ * Added IKE destination port debugging.
+ *
+ * Revision 1.180  2001/12/21 21:49:54  rgb
+ * Fixed bug as a result of moving IKE bypass above %trap/%hold code.
+ *
+ * Revision 1.179  2001/12/19 21:08:14  rgb
+ * Added transport protocol ports to ipsec_print_ip().
+ * Update eroute info for non-SA targets.
+ * Added obey DF code disabled.
+ * Fixed formatting bugs in ipsec_tunnel_hard_header().
+ *
+ * Revision 1.178  2001/12/05 09:36:10  rgb
+ * Moved the UDP/500 IKE check just above the %hold/%trap checks to avoid
+ * IKE packets being stolen by the %hold (and returned to the sending KMd
+ * in an ACQUIRE, ironically  ;-).
+ *
+ * Revision 1.177  2001/11/26 09:23:50  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.170.2.1  2001/09/25 02:28:27  mcr
+ * 	struct tdb -> struct ipsec_sa.
+ * 	lifetime checks moved to common routines.
+ * 	cleaned up includes.
+ *
+ * Revision 1.170.2.2  2001/10/22 21:08:01  mcr
+ * 	include des.h, removed phony prototypes and fixed calling
+ * 	conventions to match real prototypes.
+ *
+ * Revision 1.176  2001/11/09 18:32:31  rgb
+ * Added Hans Schultz' fragmented UDP/500 IKE socket port selector.
+ *
+ * Revision 1.175  2001/11/06 20:47:00  rgb
+ * Added Eric Espie's TRAPSUBNET fix, minus spin-lock-bh dabbling.
+ *
+ * Revision 1.174  2001/11/06 19:50:43  rgb
+ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for
+ * use also by pfkey_v2_parser.c
+ *
+ * Revision 1.173  2001/10/29 21:53:44  henry
+ * tone down the device-down message slightly, until we can make it smarter
+ *
+ * Revision 1.172  2001/10/26 04:59:37  rgb
+ * Added a critical level syslog message if an ipsec device goes down.
+ *
+ * Revision 1.171  2001/10/18 04:45:21  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.170  2001/09/25 00:09:50  rgb
+ * Added NetCelo's TRAPSUBNET code to convert a new type TRAPSUBNET into a
+ * HOLD.
+ *
+ * Revision 1.169  2001/09/15 16:24:05  rgb
+ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
+ *
+ * Revision 1.168  2001/09/14 16:58:37  rgb
+ * Added support for storing the first and last packets through a HOLD.
+ *
+ * Revision 1.167  2001/09/08 21:13:33  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.166  2001/08/27 19:47:59  rgb
+ * Clear tdb  before usage.
+ * Added comment: clear IF before calling routing?
+ *
+ * Revision 1.165  2001/07/03 01:23:53  rgb
+ * Send back ICMP iff DF set, !ICMP, offset==0, sysctl_icmp, iph->tot_len >
+ * emtu, and don't drop.
+ *
+ * Revision 1.164  2001/06/14 19:35:10  rgb
+ * Update copyright date.
+ *
+ * Revision 1.163  2001/06/06 20:28:51  rgb
+ * Added sanity checks for NULL skbs and devices.
+ * Added more debugging output to various functions.
+ * Removed redundant dev->priv argument to ipsec_tunnel_{at,de}tach().
+ * Renamed ipsec_tunnel_attach() virtual and physical device arguments.
+ * Corrected neigh_setup() device function assignment.
+ * Keep valid pointers to ipsec_tunnel_*() on detach.
+ * Set dev->type to the originally-initiallised value.
+ *
+ * Revision 1.162  2001/06/01 07:28:04  rgb
+ * Added sanity checks for detached devices.  Don't down virtual devices
+ * to prevent packets going out in the clear if the detached device comes
+ * back up.
+ *
+ * Revision 1.161  2001/05/30 08:14:52  rgb
+ * Removed vestiges of esp-null transforms.
+ * NetDev Notifier instrumentation to track down disappearing devices.
+ *
+ * Revision 1.160  2001/05/29 05:15:12  rgb
+ * Added SS' PMTU patch which notifies sender if packet doesn't fit
+ * physical MTU (if it wasn't ICMP) and then drops it.
+ *
+ * Revision 1.159  2001/05/27 06:12:12  rgb
+ * Added structures for pid, packet count and last access time to eroute.
+ * Added packet count to beginning of /proc/net/ipsec_eroute.
+ *
+ * Revision 1.158  2001/05/24 05:39:33  rgb
+ * Applied source zeroing to 2.2 ip_route_output() call as well to enable
+ * PASS eroutes for opportunism.
+ *
+ * Revision 1.157  2001/05/23 22:35:28  rgb
+ * 2.4 source override simplification.
+ *
+ * Revision 1.156  2001/05/23 21:41:31  rgb
+ * Added error return code printing on ip_route_output().
+ *
+ * Revision 1.155  2001/05/23 05:09:13  rgb
+ * Fixed incorrect ip_route_output() failure message.
+ *
+ * Revision 1.154  2001/05/21 14:53:31  rgb
+ * Added debug statement for case when ip_route_output() fails, causing
+ * packet to be dropped, but log looked ok.
+ *
+ * Revision 1.153  2001/05/19 02:37:54  rgb
+ * Fixed missing comment termination.
+ *
+ * Revision 1.152  2001/05/19 02:35:50  rgb
+ * Debug code optimisation for non-debug speed.
+ * Kernel version compiler define comments.
+ * 2.2 and 2.4 kernel ip_send device and ip debug output added.
+ *
+ * Revision 1.151  2001/05/18 16:17:35  rgb
+ * Changed reference from "magic" to "shunt" SAs.
+ *
+ * Revision 1.150  2001/05/18 16:12:19  rgb
+ * Changed UDP/500 bypass test from 3 nested ifs to one anded if.
+ *
+ * Revision 1.149  2001/05/16 04:39:33  rgb
+ * Add default == eroute.dest to IKE bypass conditions for magic eroutes.
+ *
+ * Revision 1.148  2001/05/05 03:31:41  rgb
+ * IP frag debugging updates and enhancements.
+ *
+ * Revision 1.147  2001/05/03 19:41:40  rgb
+ * Added SS' skb_cow fix for 2.4.4.
+ *
+ * Revision 1.146  2001/04/30 19:28:16  rgb
+ * Update for 2.4.4.  ip_select_ident() now has 3 args.
+ *
+ * Revision 1.145  2001/04/23 14:56:10  rgb
+ * Added spin_lock() check to prevent double-locking for multiple
+ * transforms and hence kernel lock-ups with SMP kernels.
+ *
+ * Revision 1.144  2001/04/21 23:04:45  rgb
+ * Define out skb->used for 2.4 kernels.
+ * Check if soft expire has already been sent before sending another to
+ * prevent ACQUIRE flooding.
+ *
+ * Revision 1.143  2001/03/16 07:37:21  rgb
+ * Added comments to all #endifs.
+ *
+ * Revision 1.142  2001/02/28 05:03:27  rgb
+ * Clean up and rationalise startup messages.
+ *
+ * Revision 1.141  2001/02/27 22:24:54  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.140  2001/02/27 06:40:12  rgb
+ * Fixed TRAP->HOLD eroute byte order.
+ *
+ * Revision 1.139  2001/02/26 20:38:59  rgb
+ * Added compiler defines for 2.4.x-specific code.
+ *
+ * Revision 1.138  2001/02/26 19:57:27  rgb
+ * Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
+ * of the new SPD and to support opportunistic.
+ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs.
+ *
+ * Revision 1.137  2001/02/19 22:29:49  rgb
+ * Fixes for presence of active ipv6 segments which share ipsec physical
+ * device (gg).
+ *
+ * Revision 1.136  2001/01/29 22:30:38  rgb
+ * Fixed minor acquire debug printing bug.
+ *
+ * Revision 1.135  2001/01/29 22:19:45  rgb
+ * Zero source address for 2.4 bypass route lookup.
+ *
+ * Revision 1.134  2001/01/23 20:19:49  rgb
+ * 2.4 fix to remove removed is_clone member.
+ *
+ * Revision 1.133  2000/12/09 22:08:35  rgb
+ * Fix NET_23 bug, should be NETDEV_23.
+ *
+ * Revision 1.132  2000/12/01 06:54:50  rgb
+ * Fix for new 2.4 IP TTL default variable name.
+ *
+ * Revision 1.131  2000/11/09 20:52:15  rgb
+ * More spinlock shuffling, locking earlier and unlocking later in rcv to
+ * include ipcomp and prevent races, renaming some tdb variables that got
+ * forgotten, moving some unlocks to include tdbs and adding a missing
+ * unlock.  Thanks to Svenning for some of these.
+ *
+ * Revision 1.130  2000/11/09 20:11:22  rgb
+ * Minor shuffles to fix non-standard kernel config option selection.
+ *
+ * Revision 1.129  2000/11/06 04:32:49  rgb
+ * Clean up debug printing.
+ * Copy skb->protocol for all kernel versions.
+ * Ditched spin_lock_irqsave in favour of spin_lock.
+ * Disabled TTL decrement, done in ip_forward.
+ * Added debug printing before pfkey_acquire().
+ * Fixed printk-deltdbchain-spin_lock races (Svenning).
+ * Use defaultTTL for 2.1+ kernels.
+ * Add Svenning's adaptive content compression.
+ * Fix up debug display arguments.
+ *
+ * Revision 1.128  2000/09/28 00:58:57  rgb
+ * Moved the IKE passthrough check after the eroute lookup so we can pass
+ * IKE through intermediate tunnels.
+ *
+ * Revision 1.127  2000/09/22 17:52:11  rgb
+ * Fixed misleading ipcomp debug output.
+ *
+ * Revision 1.126  2000/09/22 04:22:56  rgb
+ * Fixed dumb spi->cpi conversion error.
+ *
+ * Revision 1.125  2000/09/21 04:34:48  rgb
+ * A few debug-specific things should be hidden under
+ * CONFIG_IPSEC_DEBUG.(MB)
+ * Improved ip_send() error handling.(MB)
+ *
+ * Revision 1.124  2000/09/21 03:40:58  rgb
+ * Added more debugging to try and track down the cpi outward copy problem.
+ *
+ * Revision 1.123  2000/09/19 07:08:49  rgb
+ * Added debugging to outgoing compression report.
+ *
+ * Revision 1.122  2000/09/18 19:21:26  henry
+ * RGB-supplied fix for RH5.2 problem
+ *
+ * Revision 1.121  2000/09/17 21:05:09  rgb
+ * Added tdb to skb_compress call to write in cpi.
+ *
+ * Revision 1.120  2000/09/17 16:57:16  rgb
+ * Added Svenning's patch to remove restriction of ipcomp to innermost
+ * transform.
+ *
+ * Revision 1.119  2000/09/15 11:37:01  rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.118  2000/09/15 04:57:16  rgb
+ * Moved debug output after sanity check.
+ * Added tos copy sysctl.
+ *
+ * Revision 1.117  2000/09/12 03:22:51  rgb
+ * Converted ipsec_icmp, no_eroute_pass, opportunistic and #if0 debugs to
+ * sysctl.
+ *
+ * Revision 1.116  2000/09/08 19:18:19  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Added outgoing opportunistic hook, ifdef'ed out.
+ *
+ * Revision 1.115  2000/08/30 05:27:29  rgb
+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst.
+ * Kill remainder of tdb_xform, tdb_xdata, xformsw.
+ *
+ * Revision 1.114  2000/08/28 18:15:46  rgb
+ * Added MB's nf-debug reset patch.
+ *
+ * Revision 1.113  2000/08/27 02:26:40  rgb
+ * Send all no-eroute-bypass, pluto-bypass and passthrough packets through
+ * fragmentation machinery for 2.0, 2.2 and 2.4 kernels.
+ *
+ * Revision 1.112  2000/08/20 21:37:33  rgb
+ * Activated pfkey_expire() calls.
+ * Added a hard/soft expiry parameter to pfkey_expire(). (Momchil)
+ * Re-arranged the order of soft and hard expiry to conform to RFC2367.
+ * Clean up references to CONFIG_IPSEC_PFKEYv2.
+ *
+ * Revision 1.111  2000/08/01 14:51:51  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.110  2000/07/28 14:58:31  rgb
+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
+ *
+ * Revision 1.109  2000/07/28 13:50:54  rgb
+ * Changed enet_statistics to net_device_stats and added back compatibility
+ * for pre-2.1.19.
+ *
+ * Revision 1.108  2000/05/16 03:03:11  rgb
+ * Updates for 2.3.99pre8 from MB.
+ *
+ * Revision 1.107  2000/05/10 23:08:21  rgb
+ * Print a debug warning about bogus packets received by the outgoing
+ * processing machinery only when klipsdebug is not set to none.
+ * Comment out the device initialisation informational messages.
+ *
+ * Revision 1.106  2000/05/10 19:17:14  rgb
+ * Define an IP_SEND macro, intending to have all packet passthroughs
+ * use fragmentation.  This didn't quite work, but is a step in the
+ * right direction.
+ * Added buffer allocation debugging statements.
+ * Added configure option to shut off no eroute passthrough.
+ * Only check usetime against soft and hard limits if the tdb has been
+ * used.
+ * Cast output of ntohl so that the broken prototype doesn't make our
+ * compile noisy.
+ *
+ * Revision 1.105  2000/03/22 16:15:37  rgb
+ * Fixed renaming of dev_get (MB).
+ *
+ * Revision 1.104  2000/03/16 14:04:15  rgb
+ * Indented headers for readability.
+ * Fixed debug scope to enable compilation with debug off.
+ * Added macros for ip_chk_addr and IS_MYADDR for identifying self.
+ *
+ * Revision 1.103  2000/03/16 07:11:07  rgb
+ * Hardcode PF_KEYv2 support.
+ * Fixed bug which allowed UDP/500 packet from another machine
+ * through in the clear.
+ * Added disabled skb->protocol fix for ISDN/ASYNC PPP from Matjaz Godec.
+ *
+ * Revision 1.102  2000/03/14 12:26:59  rgb
+ * Added skb->nfct support for clearing netfilter conntrack bits (MB).
+ *
+ * Revision 1.101  2000/02/14 21:05:22  rgb
+ * Added MB's netif_queue fix for kernels 2.3.43+.
+ *
+ * Revision 1.100  2000/01/26 10:04:57  rgb
+ * Fixed noisy 2.0 printk arguments.
+ *
+ * Revision 1.99  2000/01/21 06:16:25  rgb
+ * Added sanity checks on skb_push(), skb_pull() to prevent panics.
+ * Switched to AF_ENCAP macro.
+ * Shortened debug output per packet and re-arranging debug_tunnel
+ * bitmap flags, while retaining necessary information to avoid
+ * trampling the kernel print ring buffer.
+ * Reformatted recursion switch code.
+ * Changed all references to tdb_proto to tdb_said.proto for clarity.
+ *
+ * Revision 1.98  2000/01/13 08:09:31  rgb
+ * Shuffled debug_tunnel switches to focus output.
+ * Fixed outgoing recursion bug, limiting to recursing only if the remote
+ * SG changes and if it is valid, ie. not passthrough.
+ * Clarified a number of debug messages.
+ *
+ * Revision 1.97  2000/01/10 16:37:16  rgb
+ * MB support for new ip_select_ident() upon disappearance of
+ * ip_id_count in 2.3.36+.
+ *
+ * Revision 1.96  1999/12/31 14:59:08  rgb
+ * MB fix to use new skb_copy_expand in kernel 2.3.35.
+ *
+ * Revision 1.95  1999/12/29 21:15:44  rgb
+ * Fix tncfg to aliased device bug.
+ *
+ * Revision 1.94  1999/12/22 04:26:06  rgb
+ * Converted all 'static' functions to 'DEBUG_NO_STATIC' to enable
+ * debugging by providing external labels to all functions with debugging
+ * turned on.
+ *
+ * Revision 1.93  1999/12/13 13:30:14  rgb
+ * Changed MTU reports and HW address reporting back to debug only.
+ *
+ * Revision 1.92  1999/12/07 18:57:56  rgb
+ * Fix PFKEY symbol compile error (SADB_*) without pfkey enabled.
+ *
+ * Revision 1.91  1999/12/01 22:15:36  rgb
+ * Add checks for LARVAL and DEAD SAs.
+ * Change state of SA from MATURE to DYING when a soft lifetime is
+ * reached and print debug warning.
+ *
+ * Revision 1.90  1999/11/23 23:04:04  rgb
+ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ *
+ * Revision 1.89  1999/11/18 18:50:59  rgb
+ * Changed all device registrations for static linking to
+ * dynamic to reduce the number and size of patches.
+ *
+ * Revision 1.88  1999/11/18 04:09:19  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.87  1999/11/17 15:53:40  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.86  1999/10/16 18:25:37  rgb
+ * Moved SA lifetime expiry checks before packet processing.
+ * Expire SA on replay counter rollover.
+ *
+ * Revision 1.85  1999/10/16 04:24:31  rgb
+ * Add stats for time since last packet.
+ *
+ * Revision 1.84  1999/10/16 00:30:47  rgb
+ * Added SA lifetime counting.
+ *
+ * Revision 1.83  1999/10/15 22:15:57  rgb
+ * Clean out cruft.
+ * Add debugging.
+ *
+ * Revision 1.82  1999/10/08 18:26:19  rgb
+ * Fix 2.0.3x outgoing fragmented packet memory leak.
+ *
+ * Revision 1.81  1999/10/05 02:38:54  rgb
+ * Lower the default mtu of virtual devices to 16260.
+ *
+ * Revision 1.80  1999/10/03 18:56:41  rgb
+ * Spinlock support for 2.3.xx.
+ * Don't forget to undo spinlocks on error!
+ * Check for valid eroute before copying the structure.
+ *
+ * Revision 1.79  1999/10/01 15:44:53  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.78  1999/10/01 00:02:43  rgb
+ * Added tdb structure locking.
+ * Added eroute structure locking.
+ *
+ * Revision 1.77  1999/09/30 02:52:29  rgb
+ * Add Marc Boucher's Copy-On-Write code (same as ipsec_rcv.c).
+ *
+ * Revision 1.76  1999/09/25 19:31:27  rgb
+ * Refine MSS hack to affect SYN, but not SYN+ACK packets.
+ *
+ * Revision 1.75  1999/09/24 22:52:38  rgb
+ * Fix two things broken in 2.0.38 by trying to fix network notifiers.
+ *
+ * Revision 1.74  1999/09/24 00:30:37  rgb
+ * Add test for changed source as well as destination to check for
+ * recursion.
+ *
+ * Revision 1.73  1999/09/23 20:52:24  rgb
+ * Add James Morris' MSS hack patch, disabled.
+ *
+ * Revision 1.72  1999/09/23 20:22:40  rgb
+ * Enable, tidy and fix network notifier code.
+ *
+ * Revision 1.71  1999/09/23 18:09:05  rgb
+ * Clean up 2.2.x fragmenting traces.
+ * Disable dev->type switching, forcing ARPHRD_TUNNEL.
+ *
+ * Revision 1.70  1999/09/22 14:14:24  rgb
+ * Add sanity checks for revectored calls to prevent calling a downed I/F.
+ *
+ * Revision 1.69  1999/09/21 15:00:57  rgb
+ * Add Marc Boucher's packet size check.
+ * Flesh out network device notifier code.
+ *
+ * Revision 1.68  1999/09/18 11:39:57  rgb
+ * Start to add (disabled) netdevice notifier code.
+ *
+ * Revision 1.67  1999/09/17 23:44:40  rgb
+ * Add a comment warning potential code hackers to stay away from mac.raw.
+ *
+ * Revision 1.66  1999/09/17 18:04:02  rgb
+ * Add fix for unpredictable hard_header_len for ISDN folks (thanks MB).
+ * Ditch TTL decrement in 2.2 (MB).
+ *
+ * Revision 1.65  1999/09/15 23:15:35  henry
+ * Marc Boucher's PPP fixes
+ *
+ * Revision 1.64  1999/09/07 13:40:53  rgb
+ * Ditch unreliable references to skb->mac.raw.
+ *
+ * Revision 1.63  1999/08/28 11:33:09  rgb
+ * Check for null skb->mac pointer.
+ *
+ * Revision 1.62  1999/08/28 02:02:30  rgb
+ * Add Marc Boucher's fix for properly dealing with skb->sk.
+ *
+ * Revision 1.61  1999/08/27 05:23:05  rgb
+ * Clean up skb->data/raw/nh/h manipulation.
+ * Add Marc Boucher's mods to aid tcpdump.
+ * Add sanity checks to skb->raw/nh/h pointer copies in skb_copy_expand.
+ * Re-order hard_header stripping -- might be able to remove it...
+ *
+ * Revision 1.60  1999/08/26 20:01:02  rgb
+ * Tidy up compiler directives and macros.
+ * Re-enable ICMP for tunnels where inner_dst !=  outer_dst.
+ * Remove unnecessary skb->dev = physdev assignment affecting 2.2.x.
+ *
+ * Revision 1.59  1999/08/25 15:44:41  rgb
+ * Clean up from 2.2.x instrumenting for compilation under 2.0.36.
+ *
+ * Revision 1.58  1999/08/25 15:00:54  rgb
+ * Add dst cache code for 2.2.xx.
+ * Add sanity check for skb packet header pointers.
+ * Add/modify debugging instrumentation to *_start_xmit, *_hard_header and
+ * *_rebuild_header.
+ * Add neigh_* cache code.
+ * Change dev->type back to ARPHRD_TUNNEL.
+ *
+ * Revision 1.57  1999/08/17 21:50:23  rgb
+ * Fixed minor debug output bugs.
+ * Regrouped error recovery exit code.
+ * Added compiler directives to remove unwanted code and symbols.
+ * Shut off ICMP messages: to be refined to only send ICMP to remote systems.
+ * Add debugging code for output function addresses.
+ * Fix minor bug in (possibly unused) header_cache_bind function.
+ * Add device neighbour caching code.
+ * Change dev->type from ARPHRD_TUNNEL to physdev->type.
+ *
+ * Revision 1.56  1999/08/03 17:22:56  rgb
+ * Debug output clarification using KERN_* macros.  Other inactive changes
+ * added.
+ *
+ * Revision 1.55  1999/08/03 16:58:46  rgb
+ * Fix skb_copy_expand size bug.  Was getting incorrect size.
+ *
+ * Revision 1.54  1999/07/14 19:32:38  rgb
+ * Fix oversize packet crash and ssh stalling in 2.2.x kernels.
+ *
+ * Revision 1.53  1999/06/10 15:44:02  rgb
+ * Minor reformatting and clean-up.
+ *
+ * Revision 1.52  1999/05/09 03:25:36  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.51  1999/05/08 21:24:59  rgb
+ * Add casting to silence the 2.2.x compile.
+ *
+ * Revision 1.50  1999/05/05 22:02:32  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.49  1999/04/29 15:18:52  rgb
+ * Change gettdb parameter to a pointer to reduce stack loading and
+ * facilitate parameter sanity checking.
+ * Fix undetected bug that might have tried to access a null pointer.
+ * Eliminate unnessessary usage of tdb_xform member to further switch
+ * away from the transform switch to the algorithm switch.
+ * Add return values to init and cleanup functions.
+ *
+ * Revision 1.48  1999/04/16 15:38:00  rgb
+ * Minor rearrangement of freeing code to avoid memory leaks with impossible or
+ * rare situations.
+ *
+ * Revision 1.47  1999/04/15 15:37:25  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.32.2.4  1999/04/13 21:00:18  rgb
+ * Ditch 'things I wish I had known before...'.
+ *
+ * Revision 1.32.2.3  1999/04/13 20:34:38  rgb
+ * Free skb after fragmentation.
+ * Use stats more effectively.
+ * Add I/F to mtu notch-down reporting.
+ *
+ * Revision 1.32.2.2  1999/04/02 04:26:14  rgb
+ * Backcheck from HEAD, pre1.0.
+ *
+ * Revision 1.46  1999/04/11 00:29:00  henry
+ * GPL boilerplate
+ *
+ * Revision 1.45  1999/04/07 15:42:01  rgb
+ * Fix mtu/ping bug AGAIN!
+ *
+ * Revision 1.44  1999/04/06 04:54:27  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.43  1999/04/04 03:57:07  rgb
+ * ip_fragment() doesn't free the supplied skb.  Freed.
+ *
+ * Revision 1.42  1999/04/01 23:27:15  rgb
+ * Preload size of virtual mtu.
+ *
+ * Revision 1.41  1999/04/01 09:31:23  rgb
+ * Invert meaning of ICMP PMTUD config option and clarify.
+ * Code clean-up.
+ *
+ * Revision 1.40  1999/04/01 04:37:17  rgb
+ * SSH stalling bug fix.
+ *
+ * Revision 1.39  1999/03/31 23:44:28  rgb
+ * Don't send ICMP on DF and frag_off.
+ *
+ * Revision 1.38  1999/03/31 15:20:10  rgb
+ * Quiet down debugging.
+ *
+ * Revision 1.37  1999/03/31 08:30:31  rgb
+ * Add switch to shut off ICMP PMTUD packets.
+ *
+ * Revision 1.36  1999/03/31 05:44:47  rgb
+ * Keep PMTU reduction private.
+ *
+ * Revision 1.35  1999/03/27 15:13:02  rgb
+ * PMTU/fragmentation bug fix.
+ *
+ * Revision 1.34  1999/03/17 21:19:26  rgb
+ * Fix kmalloc nonatomic bug.
+ *
+ * Revision 1.33  1999/03/17 15:38:42  rgb
+ * Code clean-up.
+ * ESP_NULL IV bug fix.
+ *
+ * Revision 1.32  1999/03/01 20:44:25  rgb
+ * Code clean-up.
+ * Memory leak bug fix.
+ *
+ * Revision 1.31  1999/02/27 00:02:09  rgb
+ * Tune to report the MTU reduction once, rather than after every recursion
+ * through the encapsulating code, preventing tcp stream stalling.
+ *
+ * Revision 1.30  1999/02/24 20:21:01  rgb
+ * Reformat debug printk's.
+ * Fix recursive encapsulation, dynamic MTU bugs and add debugging code.
+ * Clean-up.
+ *
+ * Revision 1.29  1999/02/22 17:08:14  rgb
+ * Fix recursive encapsulation code.
+ *
+ * Revision 1.28  1999/02/19 18:27:02  rgb
+ * Improve DF, fragmentation and PMTU behaviour and add dynamic MTU discovery.
+ *
+ * Revision 1.27  1999/02/17 16:51:37  rgb
+ * Clean out unused cruft.
+ * Temporarily tone down volume of debug output.
+ * Temporarily shut off fragment rejection.
+ * Disabled temporary failed recursive encapsulation loop.
+ *
+ * Revision 1.26  1999/02/12 21:21:26  rgb
+ * Move KLIPS_PRINT to ipsec_netlink.h for accessibility.
+ *
+ * Revision 1.25  1999/02/11 19:38:27  rgb
+ * More clean-up.
+ * Add sanity checking for skb_copy_expand() to prevent kernel panics on
+ * skb_put() values out of range.
+ * Fix head/tailroom calculation causing skb_put() out-of-range values.
+ * Fix return values to prevent 'nonatomic alloc_skb' warnings.
+ * Allocate new skb iff needed.
+ * Added more debug statements.
+ * Make headroom depend on structure, not hard-coded values.
+ *
+ * Revision 1.24  1999/02/10 23:20:33  rgb
+ * Shut up annoying 'statement has no effect' compiler warnings with
+ * debugging compiled out.
+ *
+ * Revision 1.23  1999/02/10 22:36:30  rgb
+ * Clean-up obsolete, unused and messy code.
+ * Converted most IPSEC_DEBUG statements to KLIPS_PRINT macros.
+ * Rename ipsec_tunnel_do_xmit to ipsec_tunnel_start_xmit and eliminated
+ * original ipsec_tunnel_start_xmit.
+ * Send all packet with different inner and outer destinations directly to
+ * the attached physical device, rather than back through ip_forward,
+ * preventing disappearing routes problems.
+ * Do sanity checking before investing too much CPU in allocating new
+ * structures.
+ * Fail on IP header options: We cannot process them yet.
+ * Add some helpful comments.
+ * Use virtual device for parameters instead of physical device.
+ *
+ * Revision 1.22  1999/02/10 03:03:02  rgb
+ * Duh.  Fixed the TTL bug: forgot to update the checksum.
+ *
+ * Revision 1.21  1999/02/09 23:17:53  rgb
+ * Add structure members to ipsec_print_ip debug function.
+ * Temporarily fix TTL bug preventing tunnel mode from functioning.
+ *
+ * Revision 1.20  1999/02/09 00:14:25  rgb
+ * Add KLIPSPRINT macro.  (Not used yet, though.)
+ * Delete old ip_tunnel code (BADCODE).
+ * Decrement TTL in outgoing packet.
+ * Set TTL on new IPIP_TUNNEL to default, not existing packet TTL.
+ * Delete ethernet only feature and fix hard-coded hard_header_len.
+ *
+ * Revision 1.19  1999/01/29 17:56:22  rgb
+ * 64-bit re-fix submitted by Peter Onion.
+ *
+ * Revision 1.18  1999/01/28 22:43:24  rgb
+ * Fixed bug in ipsec_print_ip that caused an OOPS, found by P.Onion.
+ *
+ * Revision 1.17  1999/01/26 02:08:16  rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ * Removed dead code.
+ *
+ * Revision 1.16  1999/01/22 06:25:26  rgb
+ * Cruft clean-out.
+ * Added algorithm switch code.
+ * 64-bit clean-up.
+ * Passthrough on IPIP protocol, spi 0x0 fix.
+ * Enhanced debugging.
+ *
+ * Revision 1.15  1998/12/01 13:22:04  rgb
+ * Added support for debug printing of version info.
+ *
+ * Revision 1.14  1998/11/30 13:22:55  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.13  1998/11/17 21:13:52  rgb
+ * Put IKE port bypass debug output in user-switched debug statements.
+ *
+ * Revision 1.12  1998/11/13 13:20:25  rgb
+ * Fixed ntohs bug in udp/500 hole for IKE.
+ *
+ * Revision 1.11  1998/11/10 08:01:19  rgb
+ * Kill tcp/500 hole,  keep udp/500 hole.
+ *
+ * Revision 1.10  1998/11/09 21:29:26  rgb
+ * If no eroute is found, discard packet and incr. tx_error.
+ *
+ * Revision 1.9  1998/10/31 06:50:00  rgb
+ * Add tcp/udp/500 bypass.
+ * Fixed up comments in #endif directives.
+ *
+ * Revision 1.8  1998/10/27 00:34:31  rgb
+ * Reformat debug output of IP headers.
+ * Newlines added before calls to ipsec_print_ip.
+ *
+ * Revision 1.7  1998/10/19 14:44:28  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.6  1998/10/09 04:31:35  rgb
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ *
+ * Revision 1.5  1998/08/28 03:09:51  rgb
+ * Prevent kernel log spam with default route through ipsec.
+ *
+ * Revision 1.4  1998/08/05 22:23:09  rgb
+ * Change setdev return code to ENXIO for a non-existant physical device.
+ *
+ * Revision 1.3  1998/07/29 20:41:11  rgb
+ * Add ipsec_tunnel_clear to clear all tunnel attachments.
+ *
+ * Revision 1.2  1998/06/25 20:00:33  rgb
+ * Clean up #endif comments.
+ * Rename dev_ipsec to dev_ipsec0 for consistency.
+ * Document ipsec device fields.
+ * Make ipsec_tunnel_probe visible from rest of kernel for static linking.
+ * Get debugging report for *every* ipsec device initialisation.
+ * Comment out redundant code.
+ *
+ * Revision 1.1  1998/06/18 21:27:50  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.8  1998/06/14 23:49:40  rgb
+ * Clarify version reporting on module loading.
+ *
+ * Revision 1.7  1998/05/27 23:19:20  rgb
+ * Added version reporting.
+ *
+ * Revision 1.6  1998/05/18 21:56:23  rgb
+ * Clean up for numerical consistency of output and cleaning up debug code.
+ *
+ * Revision 1.5  1998/05/12 02:44:23  rgb
+ * Clarifying 'no e-route to host' message.
+ *
+ * Revision 1.4  1998/04/30 15:34:35  rgb
+ * Enclosed most remaining debugging statements in #ifdef's to make it quieter.
+ *
+ * Revision 1.3  1998/04/21 21:28:54  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.2  1998/04/12 22:03:24  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:06:12  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5  1997/06/03 04:24:48  ji
+ * Added transport mode.
+ * Changed the way routing is done.
+ * Lots of bug fixes.
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_tunnel.h linux-patched/net/ipsec/ipsec_tunnel.h
--- linux/net/ipsec/ipsec_tunnel.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_tunnel.h	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,248 @@
+/*
+ * IPSEC tunneling code
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+
+#ifdef NET_21
+# define DEV_QUEUE_XMIT(skb, device, pri) {\
+	skb->dev = device; \
+	neigh_compat_output(skb); \
+	/* skb->dst->output(skb); */ \
+ }
+# define ICMP_SEND(skb_in, type, code, info, dev) \
+	icmp_send(skb_in, type, code, htonl(info))
+# define IP_SEND(skb, dev) \
+	ip_send(skb);
+#else /* NET_21 */
+# define DEV_QUEUE_XMIT(skb, device, pri) {\
+	dev_queue_xmit(skb, device, pri); \
+ }
+# define ICMP_SEND(skb_in, type, code, info, dev) \
+	icmp_send(skb_in, type, code, info, dev)
+# define IP_SEND(skb, dev) \
+	if(ntohs(iph->tot_len) > physmtu) { \
+		ip_fragment(NULL, skb, dev, 0); \
+		dev_kfree_skb(skb, FREE_WRITE); \
+	} else { \
+		dev_queue_xmit(skb, dev, SOPRI_NORMAL); \
+	}
+#endif /* NET_21 */
+
+
+/*
+ * Heavily based on drivers/net/new_tunnel.c.  Lots
+ * of ideas also taken from the 2.1.x version of drivers/net/shaper.c
+ */
+
+struct ipsectunnelconf
+{
+	__u32	cf_cmd;
+	union
+	{
+		char 	cfu_name[12];
+	} cf_u;
+#define cf_name cf_u.cfu_name
+};
+
+#define IPSEC_SET_DEV	(SIOCDEVPRIVATE)
+#define IPSEC_DEL_DEV	(SIOCDEVPRIVATE + 1)
+#define IPSEC_CLR_DEV	(SIOCDEVPRIVATE + 2)
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#  define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+struct ipsecpriv
+{
+	struct sk_buff_head sendq;
+	struct device *dev;
+	struct wait_queue *wait_queue;
+	char locked;
+	int  (*hard_start_xmit) (struct sk_buff *skb,
+		struct device *dev);
+	int  (*hard_header) (struct sk_buff *skb,
+		struct device *dev,
+		unsigned short type,
+		void *daddr,
+		void *saddr,
+		unsigned len);
+#ifdef NET_21
+	int  (*rebuild_header)(struct sk_buff *skb);
+#else /* NET_21 */
+	int  (*rebuild_header)(void *buff, struct device *dev,
+			unsigned long raddr, struct sk_buff *skb);
+#endif /* NET_21 */
+	int  (*set_mac_address)(struct device *dev, void *addr);
+#ifndef NET_21
+	void (*header_cache_bind)(struct hh_cache **hhp, struct device *dev,
+				 unsigned short htype, __u32 daddr);
+#endif /* !NET_21 */
+	void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char *  haddr);
+	struct net_device_stats *(*get_stats)(struct device *dev);
+	struct net_device_stats mystats;
+	int mtu;	/* What is the desired MTU? */
+};
+
+#define IPSEC_NUM_IF	4
+
+extern char ipsec_tunnel_c_version[];
+
+int ipsec_tunnel_init_devices(void);
+
+/* void */ int ipsec_tunnel_cleanup_devices(void);
+
+extern /* void */ int ipsec_init(void);
+
+extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev);
+
+#ifdef CONFIG_IPSEC_DEBUG
+extern int debug_tunnel;
+extern int sysctl_ipsec_debug_verbose;
+#endif /* CONFIG_IPSEC_DEBUG */
+#endif /* __KERNEL__ */
+
+#ifdef CONFIG_IPSEC_DEBUG
+#define DB_TN_INIT	0x0001
+#define DB_TN_PROCFS	0x0002
+#define DB_TN_XMIT	0x0010
+#define DB_TN_OHDR	0x0020
+#define DB_TN_CROUT	0x0040
+#define DB_TN_OXFS	0x0080
+#define DB_TN_REVEC	0x0100
+#endif /* CONFIG_IPSEC_DEBUG */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.23  2001/11/06 19:50:44  rgb
+ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for
+ * use also by pfkey_v2_parser.c
+ *
+ * Revision 1.22  2001/09/15 16:24:05  rgb
+ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
+ *
+ * Revision 1.21  2001/06/14 19:35:10  rgb
+ * Update copyright date.
+ *
+ * Revision 1.20  2000/09/15 11:37:02  rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.19  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.18  2000/07/28 13:50:54  rgb
+ * Changed enet_statistics to net_device_stats and added back compatibility
+ * for pre-2.1.19.
+ *
+ * Revision 1.17  1999/11/19 01:12:15  rgb
+ * Purge unneeded proc_info prototypes, now that static linking uses
+ * dynamic proc_info registration.
+ *
+ * Revision 1.16  1999/11/18 18:51:00  rgb
+ * Changed all device registrations for static linking to
+ * dynamic to reduce the number and size of patches.
+ *
+ * Revision 1.15  1999/11/18 04:14:21  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
+ * Added Marc Boucher's 2.3.25 proc patches.
+ *
+ * Revision 1.14  1999/05/25 02:50:10  rgb
+ * Fix kernel version macros for 2.0.x static linking.
+ *
+ * Revision 1.13  1999/05/25 02:41:06  rgb
+ * Add ipsec_klipsdebug support for static linking.
+ *
+ * Revision 1.12  1999/05/05 22:02:32  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.11  1999/04/29 15:19:50  rgb
+ * Add return values to init and cleanup functions.
+ *
+ * Revision 1.10  1999/04/16 16:02:39  rgb
+ * Bump up macro to 4 ipsec I/Fs.
+ *
+ * Revision 1.9  1999/04/15 15:37:25  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.5.2.1  1999/04/02 04:26:14  rgb
+ * Backcheck from HEAD, pre1.0.
+ *
+ * Revision 1.8  1999/04/11 00:29:01  henry
+ * GPL boilerplate
+ *
+ * Revision 1.7  1999/04/06 04:54:28  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.6  1999/03/31 05:44:48  rgb
+ * Keep PMTU reduction private.
+ *
+ * Revision 1.5  1999/02/10 22:31:20  rgb
+ * Change rebuild_header member to reflect generality of link layer.
+ *
+ * Revision 1.4  1998/12/01 13:22:04  rgb
+ * Added support for debug printing of version info.
+ *
+ * Revision 1.3  1998/07/29 20:42:46  rgb
+ * Add a macro for clearing all tunnel devices.
+ * Rearrange structures and declarations for sharing with userspace.
+ *
+ * Revision 1.2  1998/06/25 20:01:45  rgb
+ * Make prototypes available for ipsec_init and ipsec proc_dir_entries
+ * for static linking.
+ *
+ * Revision 1.1  1998/06/18 21:27:50  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.3  1998/05/18 21:51:50  rgb
+ * Added macros for num of I/F's and a procfs debug switch.
+ *
+ * Revision 1.2  1998/04/21 21:29:09  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1  1998/04/09 03:06:13  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:05  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5  1997/06/03 04:24:48  ji
+ * Added transport mode.
+ * Changed the way routing is done.
+ * Lots of bug fixes.
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_xform.c linux-patched/net/ipsec/ipsec_xform.c
--- linux/net/ipsec/ipsec_xform.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_xform.c	Thu Sep  5 04:13:17 2002
@@ -0,0 +1,368 @@
+/*
+ * Common routines for IPSEC transformations.
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#include <linux/random.h>	/* get_random_bytes() */
+#include <freeswan.h>
+#ifdef SPINLOCK
+# ifdef SPINLOCK_23
+#  include <linux/spinlock.h> /* *lock* */
+# else /* SPINLOCK_23 */
+#  include <asm/spinlock.h> /* *lock* */
+# endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+#endif
+#include <asm/checksum.h>
+#include <net/ip.h>
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_ipe4.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#ifdef CONFIG_IPSEC_DEBUG
+int debug_xform = 0;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+extern int des_set_key(caddr_t, caddr_t);
+
+struct xformsw xformsw[] = {
+{ XF_IP4,		0,		"IPv4_Encapsulation"},
+{ XF_AHHMACMD5,		XFT_AUTH,	"HMAC_MD5_Authentication"},
+{ XF_AHHMACSHA1,	XFT_AUTH,	"HMAC_SHA-1_Authentication"},
+{ XF_ESP3DES,		XFT_CONF,	"3DES_Encryption"},
+{ XF_ESP3DESMD596,	XFT_CONF,	"3DES-MD5-96_Encryption"},
+{ XF_ESP3DESSHA196,	XFT_CONF,	"3DES-SHA1-96_Encryption"},
+{ XF_ESPNULLMD596,	XFT_CONF,	"NULL-MD5-96_ESP_*Plaintext*"},
+{ XF_ESPNULLSHA196,	XFT_CONF,	"NULL-SHA1-96_ESP_*Plaintext*"},
+};
+
+struct tdb *tdbh[TDB_HASHMOD];
+#ifdef SPINLOCK
+spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED;
+#else /* SPINLOCK */
+spinlock_t tdb_lock;
+#endif /* SPINLOCK */
+struct xformsw *xformswNXFORMSW = &xformsw[sizeof(xformsw)/sizeof(xformsw[0])];
+
+int
+ipsec_tdbinit(void)
+{
+	int i;
+
+	for(i = 1; i < TDB_HASHMOD; i++) {
+		tdbh[i] = NULL;
+	}
+	return 0;
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.59  2002/03/29 15:01:36  rgb
+ * Delete decommissioned code.
+ *
+ * Revision 1.58  2002/01/29 17:17:57  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.57  2002/01/29 04:00:53  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.56  2001/11/27 05:17:22  mcr
+ * 	turn off the worst of the per-packet debugging.
+ *
+ * Revision 1.55  2001/11/26 09:23:50  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.54  2001/10/18 04:45:21  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.53  2001/09/08 21:13:34  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.52  2001/06/14 19:35:11  rgb
+ * Update copyright date.
+ *
+ * Revision 1.51  2001/05/30 08:14:03  rgb
+ * Removed vestiges of esp-null transforms.
+ *
+ * Revision 1.50  2001/05/03 19:43:18  rgb
+ * Initialise error return variable.
+ * Update SENDERR macro.
+ * Fix sign of error return code for ipsec_tdbcleanup().
+ * Use more appropriate return code for ipsec_tdbwipe().
+ *
+ * Revision 1.49  2001/04/19 18:56:17  rgb
+ * Fixed tdb table locking comments.
+ *
+ * Revision 1.48  2001/02/27 22:24:55  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.47  2000/11/06 04:32:08  rgb
+ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
+ *
+ * Revision 1.46  2000/09/20 16:21:57  rgb
+ * Cleaned up ident string alloc/free.
+ *
+ * Revision 1.45  2000/09/08 19:16:51  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Removed all references to CONFIG_IPSEC_PFKEYv2.
+ *
+ * Revision 1.44  2000/08/30 05:29:04  rgb
+ * Compiler-define out no longer used tdb_init() in ipsec_xform.c.
+ *
+ * Revision 1.43  2000/08/18 21:30:41  rgb
+ * Purged all tdb_spi, tdb_proto and tdb_dst macros.  They are unclear.
+ *
+ * Revision 1.42  2000/08/01 14:51:51  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.41  2000/07/28 14:58:31  rgb
+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
+ *
+ * Revision 1.40  2000/06/28 05:50:11  rgb
+ * Actually set iv_bits.
+ *
+ * Revision 1.39  2000/05/10 23:11:09  rgb
+ * Added netlink debugging output.
+ * Added a cast to quiet down the ntohl bug.
+ *
+ * Revision 1.38  2000/05/10 19:18:42  rgb
+ * Cast output of ntohl so that the broken prototype doesn't make our
+ * compile noisy.
+ *
+ * Revision 1.37  2000/03/16 14:04:59  rgb
+ * Hardwired CONFIG_IPSEC_PFKEYv2 on.
+ *
+ * Revision 1.36  2000/01/26 10:11:28  rgb
+ * Fixed spacing in error text causing run-in words.
+ *
+ * Revision 1.35  2000/01/21 06:17:16  rgb
+ * Tidied up compiler directive indentation for readability.
+ * Added ictx,octx vars for simplification.(kravietz)
+ * Added macros for HMAC padding magic numbers.(kravietz)
+ * Fixed missing key length reporting bug.
+ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in.
+ *
+ * Revision 1.34  1999/12/08 00:04:19  rgb
+ * Fixed SA direction overwriting bug for netlink users.
+ *
+ * Revision 1.33  1999/12/01 22:16:44  rgb
+ * Minor formatting changes in ESP MD5 initialisation.
+ *
+ * Revision 1.32  1999/11/25 09:06:36  rgb
+ * Fixed error return messages, should be returning negative numbers.
+ * Implemented SENDERR macro for propagating error codes.
+ * Added debug message and separate error code for algorithms not compiled
+ * in.
+ *
+ * Revision 1.31  1999/11/23 23:06:26  rgb
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ *
+ * Revision 1.30  1999/11/18 04:09:20  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.29  1999/11/17 15:53:40  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.28  1999/10/18 20:04:01  rgb
+ * Clean-out unused cruft.
+ *
+ * Revision 1.27  1999/10/03 19:01:03  rgb
+ * Spinlock support for 2.3.xx and 2.0.xx kernels.
+ *
+ * Revision 1.26  1999/10/01 16:22:24  rgb
+ * Switch from assignment init. to functional init. of spinlocks.
+ *
+ * Revision 1.25  1999/10/01 15:44:54  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.24  1999/10/01 00:03:46  rgb
+ * Added tdb structure locking.
+ * Minor formatting changes.
+ * Add function to initialize tdb hash table.
+ *
+ * Revision 1.23  1999/05/25 22:42:12  rgb
+ * Add deltdbchain() debugging.
+ *
+ * Revision 1.22  1999/05/25 21:24:31  rgb
+ * Add debugging statements to deltdbchain().
+ *
+ * Revision 1.21  1999/05/25 03:51:48  rgb
+ * Refix error return code.
+ *
+ * Revision 1.20  1999/05/25 03:34:07  rgb
+ * Fix error return for flush.
+ *
+ * Revision 1.19  1999/05/09 03:25:37  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.18  1999/05/05 22:02:32  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.17  1999/04/29 15:20:16  rgb
+ * Change gettdb parameter to a pointer to reduce stack loading and
+ * facilitate parameter sanity checking.
+ * Add sanity checking for null pointer arguments.
+ * Add debugging instrumentation.
+ * Add function deltdbchain() which will take care of unlinking,
+ * zeroing and deleting a chain of tdbs.
+ * Add a parameter to tdbcleanup to be able to delete a class of SAs.
+ * tdbwipe now actually zeroes the tdb as well as any of its pointed
+ * structures.
+ *
+ * Revision 1.16  1999/04/16 15:36:29  rgb
+ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing.
+ *
+ * Revision 1.15  1999/04/11 00:29:01  henry
+ * GPL boilerplate
+ *
+ * Revision 1.14  1999/04/06 04:54:28  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.13  1999/02/19 18:23:01  rgb
+ * Nix debug off compile warning.
+ *
+ * Revision 1.12  1999/02/17 16:52:16  rgb
+ * Consolidate satoa()s for space and speed efficiency.
+ * Convert DEBUG_IPSEC to KLIPS_PRINT
+ * Clean out unused cruft.
+ * Ditch NET_IPIP dependancy.
+ * Loop for 3des key setting.
+ *
+ * Revision 1.11  1999/01/26 02:09:05  rgb
+ * Remove ah/esp/IPIP switching on include files.
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ * Removed dead code.
+ * Clean up debug code when switched off.
+ * Remove references to INET_GET_PROTOCOL.
+ * Added code exclusion macros to reduce code from unused algorithms.
+ *
+ * Revision 1.10  1999/01/22 06:28:55  rgb
+ * Cruft clean-out.
+ * Put random IV generation in kernel.
+ * Added algorithm switch code.
+ * Enhanced debugging.
+ * 64-bit clean-up.
+ *
+ * Revision 1.9  1998/11/30 13:22:55  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.8  1998/11/25 04:59:06  rgb
+ * Add conditionals for no IPIP tunnel code.
+ * Delete commented out code.
+ *
+ * Revision 1.7  1998/10/31 06:50:41  rgb
+ * Convert xform ASCII names to no spaces.
+ * Fixed up comments in #endif directives.
+ *
+ * Revision 1.6  1998/10/19 14:44:28  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.5  1998/10/09 04:32:19  rgb
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ *
+ * Revision 1.4  1998/08/12 00:11:31  rgb
+ * Added new xform functions to the xform table.
+ * Fixed minor debug output spelling error.
+ *
+ * Revision 1.3  1998/07/09 17:45:31  rgb
+ * Clarify algorithm not available message.
+ *
+ * Revision 1.2  1998/06/23 03:00:51  rgb
+ * Check for presence of IPIP protocol if it is setup one way (we don't
+ * know what has been set up the other way and can only assume it will be
+ * symmetrical with the exception of keys).
+ *
+ * Revision 1.1  1998/06/18 21:27:51  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.3  1998/06/11 05:54:59  rgb
+ * Added transform version string pointer to xformsw initialisations.
+ *
+ * Revision 1.2  1998/04/21 21:28:57  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1  1998/04/09 03:06:13  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5  1997/06/03 04:24:48  ji
+ * Added ESP-3DES-MD5-96
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Added new transforms.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/ipsec_xform.h linux-patched/net/ipsec/ipsec_xform.h
--- linux/net/ipsec/ipsec_xform.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/ipsec_xform.h	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,325 @@
+/*
+ * Definitions relevant to IPSEC transformations
+ * Copyright (C) 1996, 1997  John Ioannidis.
+ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#ifndef _IPSEC_XFORM_H_
+
+#include <freeswan.h>
+
+#define XF_NONE			0	/* No transform set */
+#define XF_IP4			1	/* IPv4 inside IPv4 */
+#define XF_AHMD5		2	/* AH MD5 */
+#define XF_AHSHA		3	/* AH SHA */
+#define XF_ESP3DES		5	/* ESP DES3-CBC */
+#define XF_AHHMACMD5		6	/* AH-HMAC-MD5 with opt replay prot */
+#define XF_AHHMACSHA1		7	/* AH-HMAC-SHA1 with opt replay prot */
+#define XF_ESP3DESMD5		9	/* triple DES, HMAC-MD-5, 128-bits of authentication */
+#define	XF_ESP3DESMD596		10	/* triple DES, HMAC-MD-5, 96-bits of authentication */
+#define	XF_ESPNULLMD596		12	/* NULL, HMAC-MD-5 with 96-bits of authentication */
+#define	XF_ESPNULLSHA196	13	/* NULL, HMAC-SHA-1 with 96-bits of authentication */
+#define	XF_ESP3DESSHA196	14	/* triple DES, HMAC-SHA-1, 96-bits of authentication */
+#define XF_IP6			15	/* IPv6 inside IPv6 */
+#define XF_COMPDEFLATE		16	/* IPCOMP deflate */
+
+#define XF_CLR			126	/* Clear SA table */
+#define XF_DEL			127	/* Delete SA */
+
+/* IPsec AH transform values
+ * RFC 2407
+ * draft-ietf-ipsec-doi-tc-mib-02.txt
+ */
+
+#define AH_NONE			0
+#define AH_MD5			2
+#define AH_SHA			3
+/* draft-ietf-ipsec-ciph-aes-cbc-03.txt */
+#define AH_SHA2_256		5
+#define AH_SHA2_384		6
+#define AH_SHA2_512		7
+#define AH_RIPEMD		8
+#define AH_MAX			15
+
+/* IPsec ESP transform values */
+
+#define ESP_NONE		0
+#define ESP_DES			2
+#define ESP_3DES		3
+#define ESP_RC5			4
+#define ESP_IDEA		5
+#define ESP_CAST		6
+#define ESP_BLOWFISH		7
+#define ESP_3IDEA		8
+#define ESP_RC4			10
+#define ESP_NULL		11
+#define ESP_AES			12
+
+/* as draft-ietf-ipsec-ciph-aes-cbc-02.txt */
+#define ESP_MARS		249
+#define	ESP_RC6			250
+#define ESP_SERPENT		252
+#define ESP_TWOFISH		253
+			 
+/* IPCOMP transform values */
+
+#define IPCOMP_NONE		0
+#define IPCOMP_OUI		1
+#define IPCOMP_DEFLAT		2
+#define IPCOMP_LZS		3
+#define IPCOMP_V42BIS		4
+
+#define XFT_AUTH		0x0001
+#define XFT_CONF		0x0100
+
+/* available if CONFIG_IPSEC_DEBUG is defined */
+#define DB_XF_INIT		0x0001
+
+#define PROTO2TXT(x) \
+	(x) == IPPROTO_AH ? "AH" : \
+	(x) == IPPROTO_ESP ? "ESP" : \
+	(x) == IPPROTO_IPIP ? "IPIP" : \
+	(x) == IPPROTO_COMP ? "COMP" : \
+	"UNKNOWN_proto"
+static inline const char *enc_name_id (unsigned id) {
+	static char buf[16];
+	snprintf(buf, sizeof(buf), "_ID%d", id);
+	return buf;
+}
+static inline const char *auth_name_id (unsigned id) {
+	static char buf[16];
+	snprintf(buf, sizeof(buf), "_ID%d", id);
+	return buf;
+}
+#define IPS_XFORM_NAME(x) \
+	PROTO2TXT((x)->ips_said.proto), \
+	(x)->ips_said.proto == IPPROTO_COMP ? \
+		((x)->ips_encalg == SADB_X_CALG_DEFLATE ? \
+		 "_DEFLATE" : "_UNKNOWN_comp") : \
+	(x)->ips_encalg == ESP_NONE ? "" : \
+	(x)->ips_encalg == ESP_3DES ? "_3DES" : \
+ 	(x)->ips_encalg == ESP_RC5 ? "_RC5" : \
+ 	(x)->ips_encalg == ESP_IDEA ? "_IDEA" : \
+ 	(x)->ips_encalg == ESP_CAST ? "_CAST" : \
+ 	(x)->ips_encalg == ESP_BLOWFISH ? "_BLOWFISH" : \
+ 	(x)->ips_encalg == ESP_3IDEA ? "_3IDEA" : \
+ 	(x)->ips_encalg == ESP_RC4 ? "_RC4" : \
+ 	(x)->ips_encalg == ESP_NULL ? "_NULL" : \
+ 	(x)->ips_encalg == ESP_AES ? "_AES" : \
+ 	(x)->ips_encalg == ESP_MARS ? "_MARS" : \
+ 	(x)->ips_encalg == ESP_RC6 ? "_RC6" : \
+ 	(x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \
+ 	(x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \
+ 	(x)->ips_encalg == ESP_DES ? "_DES" : \
+	enc_name_id(x->ips_encalg)/* "_UNKNOWN_encr" */, \
+	(x)->ips_authalg == AH_NONE ? "" : \
+	(x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \
+	(x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \
+	(x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \
+	(x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \
+	(x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \
+	(x)->ips_authalg == AH_RIPEMD ? "_HMAC_RIPEMD" : \
+	auth_name_id(x->ips_authalg) /* "_UNKNOWN_auth" */ \
+
+
+#define _IPSEC_XFORM_H_
+#endif /* _IPSEC_XFORM_H_ */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.3  2003/02/07 13:14:25  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.2.2.1  2003/02/06 22:09:50  jjo
+ * sync to alg-0.8.1-rc4
+ *
+ * Revision 1.2  2002/09/05 03:27:09  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:17  ken
+ * 1.98b
+ *
+ * Revision 1.35  2001/11/26 09:23:51  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.33.2.1  2001/09/25 02:24:58  mcr
+ * 	struct tdb -> struct ipsec_sa.
+ * 	sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
+ * 	ipsec_xform.c removed. header file still contains useful things.
+ *
+ * Revision 1.34  2001/11/06 19:47:17  rgb
+ * Changed lifetime_packets to uint32 from uint64.
+ *
+ * Revision 1.33  2001/09/08 21:13:34  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.32  2001/07/06 07:40:01  rgb
+ * Reformatted for readability.
+ * Added inbound policy checking fields for use with IPIP SAs.
+ *
+ * Revision 1.31  2001/06/14 19:35:11  rgb
+ * Update copyright date.
+ *
+ * Revision 1.30  2001/05/30 08:14:03  rgb
+ * Removed vestiges of esp-null transforms.
+ *
+ * Revision 1.29  2001/01/30 23:42:47  rgb
+ * Allow pfkey msgs from pid other than user context required for ACQUIRE
+ * and subsequent ADD or UDATE.
+ *
+ * Revision 1.28  2000/11/06 04:30:40  rgb
+ * Add Svenning's adaptive content compression.
+ *
+ * Revision 1.27  2000/09/19 00:38:25  rgb
+ * Fixed algorithm name bugs introduced for ipcomp.
+ *
+ * Revision 1.26  2000/09/17 21:36:48  rgb
+ * Added proto2txt macro.
+ *
+ * Revision 1.25  2000/09/17 18:56:47  rgb
+ * Added IPCOMP support.
+ *
+ * Revision 1.24  2000/09/12 19:34:12  rgb
+ * Defined XF_IP6 from Gerhard for ipv6 tunnel support.
+ *
+ * Revision 1.23  2000/09/12 03:23:14  rgb
+ * Cleaned out now unused tdb_xform and tdb_xdata members of struct tdb.
+ *
+ * Revision 1.22  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.21  2000/09/01 18:32:43  rgb
+ * Added (disabled) sensitivity members to tdb struct.
+ *
+ * Revision 1.20  2000/08/30 05:31:01  rgb
+ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst.
+ * Kill remainder of tdb_xform, tdb_xdata, xformsw.
+ *
+ * Revision 1.19  2000/08/01 14:51:52  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.18  2000/01/21 06:17:45  rgb
+ * Tidied up spacing.
+ *
+ * Revision 1.17  1999/11/17 15:53:40  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.16  1999/10/16 04:23:07  rgb
+ * Add stats for replaywin_errs, replaywin_max_sequence_difference,
+ * authentication errors, encryption size errors, encryption padding
+ * errors, and time since last packet.
+ *
+ * Revision 1.15  1999/10/16 00:29:11  rgb
+ * Added SA lifetime packet counting variables.
+ *
+ * Revision 1.14  1999/10/01 00:04:14  rgb
+ * Added tdb structure locking.
+ * Add function to initialize tdb hash table.
+ *
+ * Revision 1.13  1999/04/29 15:20:57  rgb
+ * dd return values to init and cleanup functions.
+ * Eliminate unnessessary usage of tdb_xform member to further switch
+ * away from the transform switch to the algorithm switch.
+ * Change gettdb parameter to a pointer to reduce stack loading and
+ * facilitate parameter sanity checking.
+ * Add a parameter to tdbcleanup to be able to delete a class of SAs.
+ *
+ * Revision 1.12  1999/04/15 15:37:25  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.9.2.2  1999/04/13 20:35:57  rgb
+ * Fix spelling mistake in comment.
+ *
+ * Revision 1.9.2.1  1999/03/30 17:13:52  rgb
+ * Extend struct tdb to support pfkey.
+ *
+ * Revision 1.11  1999/04/11 00:29:01  henry
+ * GPL boilerplate
+ *
+ * Revision 1.10  1999/04/06 04:54:28  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.9  1999/01/26 02:09:31  rgb
+ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
+ * Removed dead code.
+ *
+ * Revision 1.8  1999/01/22 06:29:35  rgb
+ * Added algorithm switch code.
+ * Cruft clean-out.
+ *
+ * Revision 1.7  1998/11/10 05:37:35  rgb
+ * Add support for SA direction flag.
+ *
+ * Revision 1.6  1998/10/19 14:44:29  rgb
+ * Added inclusion of freeswan.h.
+ * sa_id structure implemented and used: now includes protocol.
+ *
+ * Revision 1.5  1998/08/12 00:12:30  rgb
+ * Added macros for new xforms.  Added prototypes for new xforms.
+ *
+ * Revision 1.4  1998/07/28 00:04:20  rgb
+ * Add macro for clearing the SA table.
+ *
+ * Revision 1.3  1998/07/14 18:06:46  rgb
+ * Added #ifdef __KERNEL__ directives to restrict scope of header.
+ *
+ * Revision 1.2  1998/06/23 03:02:19  rgb
+ * Created a prototype for ipsec_tdbcleanup when it was moved from
+ * ipsec_init.c.
+ *
+ * Revision 1.1  1998/06/18 21:27:51  henry
+ * move sources from klips/src to klips/net/ipsec, to keep stupid
+ * kernel-build scripts happier in the presence of symlinks
+ *
+ * Revision 1.4  1998/06/11 05:55:31  rgb
+ * Added transform version string pointer to xformsw structure definition.
+ * Added extern declarations for transform version strings.
+ *
+ * Revision 1.3  1998/05/18 22:02:54  rgb
+ * Modify the *_zeroize function prototypes to include one parameter.
+ *
+ * Revision 1.2  1998/04/21 21:29:08  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.1  1998/04/09 03:06:14  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:06  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.5  1997/06/03 04:24:48  ji
+ * Added ESP-3DES-MD5-96
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * Added new transforms.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/include/cbc_generic.h linux-patched/net/ipsec/libcrypto/include/cbc_generic.h
--- linux/net/ipsec/libcrypto/include/cbc_generic.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/include/cbc_generic.h	Thu Sep  5 04:26:31 2002
@@ -0,0 +1,110 @@
+#ifndef _CBC_GENERIC_H
+#define _CBC_GENERIC_H
+/*
+ * CBC macro helpers
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+
+/*
+ * 	Heavily inspired in loop_AES
+ */
+#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \
+int name(ctx_type *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \
+	int ret=ilen, pos; \
+	const u_int32_t *iv_i; \
+	if ((ilen) % 16) return 0; \
+	if (encrypt) { \
+		pos=0; \
+		while(pos<ilen) { \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) iv; \
+			else \
+				iv_i=(const u_int32_t*) (out-16); \
+			*((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \
+			*((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \
+			*((u_int32_t *)(&out[ 8])) = iv_i[2]^*((const u_int32_t *)(&in[ 8])); \
+			*((u_int32_t *)(&out[12])) = iv_i[3]^*((const u_int32_t *)(&in[12])); \
+			enc_func(ctx, (addr_type) out, (addr_type) out); \
+			in+=16; \
+			out+=16; \
+			pos+=16; \
+		} \
+	} else { \
+		pos=ilen-16; \
+		in+=pos; \
+		out+=pos; \
+		while(pos>=0) { \
+			dec_func(ctx, (const addr_type) in, (addr_type) out); \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) (iv); \
+			else \
+				iv_i=(const u_int32_t*) (in-16); \
+			*((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \
+			*((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \
+			*((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \
+			*((u_int32_t *)(&out[12])) ^= iv_i[3]; \
+			in-=16; \
+			out-=16; \
+			pos-=16; \
+		} \
+	} \
+	return ret; \
+} 
+#define CBC_IMPL_BLK8(name, ctx_type, addr_type,  enc_func, dec_func) \
+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \
+	int ret=ilen, pos; \
+	const u_int32_t *iv_i; \
+	if ((ilen) % 8) return 0; \
+	if (encrypt) { \
+		pos=0; \
+		while(pos<ilen) { \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) iv; \
+			else \
+				iv_i=(const u_int32_t*) (out-8); \
+			*((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \
+			*((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \
+			enc_func(ctx, (addr_type)out, (addr_type)out); \
+			in+=8; \
+			out+=8; \
+			pos+=8; \
+		} \
+	} else { \
+		pos=ilen-8; \
+		in+=pos; \
+		out+=pos; \
+		while(pos>=0) { \
+			dec_func(ctx, (const addr_type)in, (addr_type)out); \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) (iv); \
+			else \
+				iv_i=(const u_int32_t*) (in-8); \
+			*((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \
+			*((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \
+			in-=8; \
+			out-=8; \
+			pos-=8; \
+		} \
+	} \
+	return ret; \
+} 
+#define CBC_DECL(name, ctx_type) \
+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt)
+/*
+Eg.:
+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt);
+CBC_DECL(AES_cbc_encrypt, aes_context);
+*/
+#endif /* _CBC_GENERIC_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/include/hmac_generic.h linux-patched/net/ipsec/libcrypto/include/hmac_generic.h
--- linux/net/ipsec/libcrypto/include/hmac_generic.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/include/hmac_generic.h	Thu Sep  5 04:26:31 2002
@@ -0,0 +1,60 @@
+#ifndef _HMAC_GENERIC_H
+#define _HMAC_GENERIC_H
+/*
+ * HMAC macro helpers
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+
+#ifndef DIVUP
+#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */
+#endif
+#ifndef HMAC_IPAD
+#define		HMAC_IPAD	0x36
+#define		HMAC_OPAD	0x5C
+#endif
+#define HMAC_SET_KEY_IMPL(func_name, hctx_t, blocksize, func_init, func_update) \
+void func_name(hctx_t *hctx, const u_int8_t * key, int keylen) { \
+	int i;\
+	u_int8_t kb[blocksize];		\
+	for (i = 0; i < DIVUP(keylen*8, 8); i++) {	\
+		kb[i] = key[i] ^ HMAC_IPAD;	\
+	}					\
+	for (; i < blocksize; i++) {		\
+		kb[i] = HMAC_IPAD;		\
+	}					\
+	func_init(&hctx->ictx);			\
+	func_update(&hctx->ictx, kb, blocksize);	\
+	for (i = 0; i < blocksize; i++) {	\
+		kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);	\
+	}					\
+	func_init(&hctx->octx);			\
+	func_update(&hctx->octx, kb, blocksize);	\
+}
+#define HMAC_HASH_IMPL(func_name, hctx_t, ctx_t, ahlen, func_update, func_result ) \
+void func_name(hctx_t *hctx, const u_int8_t * dat, int len, u_int8_t * hash, int hashlen) {	\
+	ctx_t ctx;	\
+	ctx=hctx->ictx;	\
+	if (dat) func_update(&ctx, dat, len);	\
+	if (hash) {				\
+		u_int8_t hash_buf[ahlen];			\
+		func_result(&ctx, hash_buf, ahlen);	\
+		ctx=hctx->octx;				\
+		func_update(&ctx, hash_buf, ahlen);	\
+		func_result(&ctx, hash, hashlen);	\
+		memset(&ctx, 0, sizeof (ctx));		\
+		memset(&hash_buf, 0, sizeof (hash_buf));\
+	}					\
+}
+#endif /* _HMAC_GENERIC_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/include/md32_common.h linux-patched/net/ipsec/libcrypto/include/md32_common.h
--- linux/net/ipsec/libcrypto/include/md32_common.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/include/md32_common.h	Thu Sep  5 04:26:31 2002
@@ -0,0 +1,607 @@
+/* crypto/md32_common.h */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  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 acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * This is a generic 32 bit "collector" for message digest algorithms.
+ * Whenever needed it collects input character stream into chunks of
+ * 32 bit values and invokes a block function that performs actual hash
+ * calculations.
+ *
+ * Porting guide.
+ *
+ * Obligatory macros:
+ *
+ * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
+ *	this macro defines byte order of input stream.
+ * HASH_CBLOCK
+ *	size of a unit chunk HASH_BLOCK operates on.
+ * HASH_LONG
+ *	has to be at lest 32 bit wide, if it's wider, then
+ *	HASH_LONG_LOG2 *has to* be defined along
+ * HASH_CTX
+ *	context structure that at least contains following
+ *	members:
+ *		typedef struct {
+ *			...
+ *			HASH_LONG	Nl,Nh;
+ *			HASH_LONG	data[HASH_LBLOCK];
+ *			int		num;
+ *			...
+ *			} HASH_CTX;
+ * HASH_UPDATE
+ *	name of "Update" function, implemented here.
+ * HASH_TRANSFORM
+ *	name of "Transform" function, implemented here.
+ * HASH_FINAL
+ *	name of "Final" function, implemented here.
+ * HASH_BLOCK_HOST_ORDER
+ *	name of "block" function treating *aligned* input message
+ *	in host byte order, implemented externally.
+ * HASH_BLOCK_DATA_ORDER
+ *	name of "block" function treating *unaligned* input message
+ *	in original (data) byte order, implemented externally (it
+ *	actually is optional if data and host are of the same
+ *	"endianess").
+ * HASH_MAKE_STRING
+ *	macro convering context variables to an ASCII hash string.
+ *
+ * Optional macros:
+ *
+ * B_ENDIAN or L_ENDIAN
+ *	defines host byte-order.
+ * HASH_LONG_LOG2
+ *	defaults to 2 if not states otherwise.
+ * HASH_LBLOCK
+ *	assumed to be HASH_CBLOCK/4 if not stated otherwise.
+ * HASH_BLOCK_DATA_ORDER_ALIGNED
+ *	alternative "block" function capable of treating
+ *	aligned input message in original (data) order,
+ *	implemented externally.
+ *
+ * MD5 example:
+ *
+ *	#define DATA_ORDER_IS_LITTLE_ENDIAN
+ *
+ *	#define HASH_LONG		MD5_LONG
+ *	#define HASH_LONG_LOG2		MD5_LONG_LOG2
+ *	#define HASH_CTX		MD5_CTX
+ *	#define HASH_CBLOCK		MD5_CBLOCK
+ *	#define HASH_LBLOCK		MD5_LBLOCK
+ *	#define HASH_UPDATE		MD5_Update
+ *	#define HASH_TRANSFORM		MD5_Transform
+ *	#define HASH_FINAL		MD5_Final
+ *	#define HASH_BLOCK_HOST_ORDER	md5_block_host_order
+ *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
+ *
+ *					<appro@fy.chalmers.se>
+ */
+
+#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#error "DATA_ORDER must be defined!"
+#endif
+
+#ifndef HASH_CBLOCK
+#error "HASH_CBLOCK must be defined!"
+#endif
+#ifndef HASH_LONG
+#error "HASH_LONG must be defined!"
+#endif
+#ifndef HASH_CTX
+#error "HASH_CTX must be defined!"
+#endif
+
+#ifndef HASH_UPDATE
+#error "HASH_UPDATE must be defined!"
+#endif
+#ifndef HASH_TRANSFORM
+#error "HASH_TRANSFORM must be defined!"
+#endif
+#ifndef HASH_FINAL
+#error "HASH_FINAL must be defined!"
+#endif
+
+#ifndef HASH_BLOCK_HOST_ORDER
+#error "HASH_BLOCK_HOST_ORDER must be defined!"
+#endif
+
+#if 0
+/*
+ * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
+ * isn't defined.
+ */
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+#endif
+
+#ifndef HASH_LBLOCK
+#define HASH_LBLOCK	(HASH_CBLOCK/4)
+#endif
+
+#ifndef HASH_LONG_LOG2
+#define HASH_LONG_LOG2	2
+#endif
+
+/*
+ * Engage compiler specific rotate intrinsic function if available.
+ */
+#undef ROTATE
+#ifndef PEDANTIC
+# if defined(_MSC_VER)
+#  define ROTATE(a,n)	_lrotl(a,n)
+# elif defined(__MWERKS__)
+#  if defined(__POWERPC__)
+#   define ROTATE(a,n)	__rlwinm(a,n,0,31)
+#  elif defined(__MC68K__)
+    /* Motorola specific tweak. <appro@fy.chalmers.se> */
+#   define ROTATE(a,n)	( n<24 ? __rol(a,n) : __ror(a,32-n) )
+#  else
+#   define ROTATE(a,n)	__rol(a,n)
+#  endif
+# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)
+  /*
+   * Some GNU C inline assembler templates. Note that these are
+   * rotates by *constant* number of bits! But that's exactly
+   * what we need here...
+   *
+   * 					<appro@fy.chalmers.se>
+   */
+#  if defined(__i386)
+#   define ROTATE(a,n)	({ register unsigned int ret;	\
+				asm (			\
+				"roll %1,%0"		\
+				: "=r"(ret)		\
+				: "I"(n), "0"(a)	\
+				: "cc");		\
+			   ret;				\
+			})
+#  elif defined(__powerpc) || defined(__ppc)
+#   define ROTATE(a,n)	({ register unsigned int ret;	\
+				asm (			\
+				"rlwinm %0,%1,%2,0,31"	\
+				: "=r"(ret)		\
+				: "r"(a), "I"(n));	\
+			   ret;				\
+			})
+#  endif
+# endif
+
+/*
+ * Engage compiler specific "fetch in reverse byte order"
+ * intrinsic function if available.
+ */
+# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)
+  /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
+#  if defined(__i386) && !defined(I386_ONLY)
+#   define BE_FETCH32(a)	({ register unsigned int l=(a);\
+				asm (			\
+				"bswapl %0"		\
+				: "=r"(l) : "0"(l));	\
+			  l;				\
+			})
+#  elif defined(__powerpc)
+#   define LE_FETCH32(a)	({ register unsigned int l;	\
+				asm (			\
+				"lwbrx %0,0,%1"		\
+				: "=r"(l)		\
+				: "r"(a));		\
+			   l;				\
+			})
+
+#  elif defined(__sparc) && defined(ULTRASPARC)
+#  define LE_FETCH32(a)	({ register unsigned int l;		\
+				asm (				\
+				"lda [%1]#ASI_PRIMARY_LITTLE,%0"\
+				: "=r"(l)			\
+				: "r"(a));			\
+			   l;					\
+			})
+#  endif
+# endif
+#endif /* PEDANTIC */
+
+#if HASH_LONG_LOG2==2	/* Engage only if sizeof(HASH_LONG)== 4 */
+/* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
+#ifdef ROTATE
+/* 5 instructions with rotate instruction, else 9 */
+#define REVERSE_FETCH32(a,l)	(					\
+		l=*(const HASH_LONG *)(a),				\
+		((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))	\
+				)
+#else
+/* 6 instructions with rotate instruction, else 8 */
+#define REVERSE_FETCH32(a,l)	(				\
+		l=*(const HASH_LONG *)(a),			\
+		l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)),	\
+		ROTATE(l,16)					\
+				)
+/*
+ * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
+ * It's rewritten as above for two reasons:
+ *	- RISCs aren't good at long constants and have to explicitely
+ *	  compose 'em with several (well, usually 2) instructions in a
+ *	  register before performing the actual operation and (as you
+ *	  already realized:-) having same constant should inspire the
+ *	  compiler to permanently allocate the only register for it;
+ *	- most modern CPUs have two ALUs, but usually only one has
+ *	  circuitry for shifts:-( this minor tweak inspires compiler
+ *	  to schedule shift instructions in a better way...
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#endif
+#endif
+
+#ifndef ROTATE
+#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
+#endif
+
+/*
+ * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
+ * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
+ * and host are of the same "endianess". It's possible to mask
+ * this with blank #define HASH_BLOCK_DATA_ORDER though...
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#if defined(B_ENDIAN)
+#  if defined(DATA_ORDER_IS_BIG_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#    ifndef HOST_FETCH32
+#      ifdef LE_FETCH32
+#        define HOST_FETCH32(p,l)	LE_FETCH32(p)
+#      elif defined(REVERSE_FETCH32)
+#        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
+#      endif
+#    endif
+#  endif
+#elif defined(L_ENDIAN)
+#  if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  elif defined(DATA_ORDER_IS_BIG_ENDIAN)
+#    ifndef HOST_FETCH32
+#      ifdef BE_FETCH32
+#        define HOST_FETCH32(p,l)	BE_FETCH32(p)
+#      elif defined(REVERSE_FETCH32)
+#        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
+#      endif
+#    endif
+#  endif
+#endif
+
+#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+#endif
+
+#if defined(DATA_ORDER_IS_BIG_ENDIAN)
+
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))<<24),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))    ),		\
+			 l)
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 3: l|=((unsigned long)(*((c)++)));		\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<< 8;	\
+			case 2: l|=((unsigned long)(*(--(c))))<<16;	\
+			case 1: l|=((unsigned long)(*(--(c))))<<24;	\
+				} }
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 l)
+
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<<24),		\
+			 l)
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 3: l|=((unsigned long)(*((c)++)))<<24;	\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<<16;	\
+			case 2: l|=((unsigned long)(*(--(c))))<< 8;	\
+			case 1: l|=((unsigned long)(*(--(c))));		\
+				} }
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 l)
+
+#endif
+
+/*
+ * Time for some action:-)
+ */
+
+void HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
+	{
+	const unsigned char *data=data_;
+	register HASH_LONG * p;
+	register unsigned long l;
+	int sw,sc,ew,ec;
+
+	if (len==0) return;
+
+	l=(c->Nl+(len<<3))&0xffffffffL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh+=(len>>29);
+	c->Nl=l;
+
+	if (c->num != 0)
+		{
+		p=c->data;
+		sw=c->num>>2;
+		sc=c->num&0x03;
+
+		if ((c->num+len) >= HASH_CBLOCK)
+			{
+			l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
+			for (; sw<HASH_LBLOCK; sw++)
+				{
+				HOST_c2l(data,l); p[sw]=l;
+				}
+			HASH_BLOCK_HOST_ORDER (c,p,1);
+			len-=(HASH_CBLOCK-c->num);
+			c->num=0;
+			/* drop through and do the rest */
+			}
+		else
+			{
+			c->num+=len;
+			if ((sc+len) < 4) /* ugly, add char's to a word */
+				{
+				l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
+				}
+			else
+				{
+				ew=(c->num>>2);
+				ec=(c->num&0x03);
+				l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
+				for (; sw < ew; sw++)
+					{
+					HOST_c2l(data,l); p[sw]=l;
+					}
+				if (ec)
+					{
+					HOST_c2l_p(data,l,ec); p[sw]=l;
+					}
+				}
+			return;
+			}
+		}
+
+	sw=len/HASH_CBLOCK;
+	if (sw > 0)
+		{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+		/*
+		 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
+		 * only if sizeof(HASH_LONG)==4.
+		 */
+		if ((((unsigned long)data)%4) == 0)
+			{
+			/* data is properly aligned so that we can cast it: */
+			HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+		else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+			while (sw--)
+				{
+				memcpy (p=c->data,data,HASH_CBLOCK);
+				HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
+				data+=HASH_CBLOCK;
+				len-=HASH_CBLOCK;
+				}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+			{
+			HASH_BLOCK_DATA_ORDER(c,data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+#endif
+		}
+
+	if (len!=0)
+		{
+		p = c->data;
+		c->num = len;
+		ew=len>>2;	/* words to copy */
+		ec=len&0x03;
+		for (; ew; ew--,p++)
+			{
+			HOST_c2l(data,l); *p=l;
+			}
+		HOST_c2l_p(data,l,ec);
+		*p=l;
+		}
+	}
+
+
+void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
+	{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+	if ((((unsigned long)data)%4) == 0)
+		/* data is properly aligned so that we can cast it: */
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1);
+	else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+		{
+		memcpy (c->data,data,HASH_CBLOCK);
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
+		}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+	HASH_BLOCK_DATA_ORDER (c,data,1);
+#endif
+	}
+
+
+void HASH_FINAL (unsigned char *md, HASH_CTX *c)
+	{
+	register HASH_LONG *p;
+	register unsigned long l;
+	register int i,j;
+	static const unsigned char end[4]={0x80,0x00,0x00,0x00};
+	const unsigned char *cp=end;
+
+	/* c->num should definitly have room for at least one more byte. */
+	p=c->data;
+	i=c->num>>2;
+	j=c->num&0x03;
+
+#if 0
+	/* purify often complains about the following line as an
+	 * Uninitialized Memory Read.  While this can be true, the
+	 * following p_c2l macro will reset l when that case is true.
+	 * This is because j&0x03 contains the number of 'valid' bytes
+	 * already in p[i].  If and only if j&0x03 == 0, the UMR will
+	 * occur but this is also the only time p_c2l will do
+	 * l= *(cp++) instead of l|= *(cp++)
+	 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
+	 * 'potential bug' */
+#ifdef PURIFY
+	if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */
+#endif
+	l=p[i];
+#else
+	l = (j==0) ? 0 : p[i];
+#endif
+	HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
+
+	if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
+		{
+		if (i<HASH_LBLOCK) p[i]=0;
+		HASH_BLOCK_HOST_ORDER (c,p,1);
+		i=0;
+		}
+	for (; i<(HASH_LBLOCK-2); i++)
+		p[i]=0;
+
+#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nh;
+	p[HASH_LBLOCK-1]=c->Nl;
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nl;
+	p[HASH_LBLOCK-1]=c->Nh;
+#endif
+	HASH_BLOCK_HOST_ORDER (c,p,1);
+
+#ifndef HASH_MAKE_STRING
+#error "HASH_MAKE_STRING must be defined!"
+#else
+	HASH_MAKE_STRING(c,md);
+#endif
+
+	c->num=0;
+	/* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
+	 * but I'm not worried :-)
+	memset((void *)c,0,sizeof(HASH_CTX));
+	 */
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/Makefile linux-patched/net/ipsec/libcrypto/libaes/Makefile
--- linux/net/ipsec/libcrypto/libaes/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/Makefile	Tue Jul  8 15:21:05 2003
@@ -0,0 +1,40 @@
+CFLAGS=-O3 -fomit-frame-pointer -D__KERNEL__  -Wall  -Wcast-qual $(EXTRA_CFLAGS)
+INC=-I../include 
+
+AES_CORE_OBJ:=aes.o
+
+ASM-$(ARCH_ASM):=1
+ASM_X86:=$(ASM-i586)$(ASM-i686)
+ifneq ($(strip $(ASM_X86)),)
+AES_CORE_OBJ:= asm/aes-i586.o
+endif
+
+LIBOBJ := aes_xcbc_mac.o aes_cbc.o $(AES_CORE_OBJ)
+LDLIBS := -laes
+LDFLAGS := -L.
+
+BLIB := libaes.a
+
+L_TARGET := $(BLIB)
+
+.c.o:
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c $< -o $@
+
+.S.o:
+	$(CC) $(AFLAGS) -c $< -o $@
+
+$(BLIB): $(LIBOBJ)
+	/bin/rm -f $(BLIB)
+	ar cr $(BLIB) $(LIBOBJ)
+	-if test -s /bin/ranlib; then /bin/ranlib $(BLIB); \
+	else if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(BLIB); \
+	else exit 0; fi; fi
+
+testx: test_main_mac.o $(BLIB)
+	$(CC) -o $@ $^ 
+
+test: test_main.o $(BLIB)
+	$(CC) -o $@ $^ 
+
+clean:
+	rm -f *.[oa] asm/*.o core $(TARGET) test testx
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/aes.c linux-patched/net/ipsec/libcrypto/libaes/aes.c
--- linux/net/ipsec/libcrypto/libaes/aes.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/aes.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,1415 @@
+// I retain copyright in this code but I encourage its free use provided
+// that I don't carry any responsibility for the results. I am especially 
+// happy to see it used in free and open source software. If you do use 
+// it I would appreciate an acknowledgement of its origin in the code or
+// the product that results and I would also appreciate knowing a little
+// about the use to which it is being put. I am grateful to Frank Yellin
+// for some ideas that are used in this implementation.
+//
+// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001.
+//
+// This is an implementation of the AES encryption algorithm (Rijndael)
+// designed by Joan Daemen and Vincent Rijmen. This version is designed
+// to provide both fixed and dynamic block and key lengths and can also 
+// run with either big or little endian internal byte order (see aes.h). 
+// It inputs block and key lengths in bytes with the legal values being 
+// 16, 24 and 32.
+
+/*
+ * Modified by Jari Ruusu,  May 1 2001
+ *  - Fixed some compile warnings, code was ok but gcc warned anyway.
+ *  - Changed basic types: byte -> unsigned char, word -> u_int32_t
+ *  - Major name space cleanup: Names visible to outside now begin
+ *    with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c
+ *  - Removed C++ and DLL support as part of name space cleanup.
+ *  - Eliminated unnecessary recomputation of tables. (actual bug fix)
+ *  - Merged precomputed constant tables to aes.c file.
+ *  - Removed data alignment restrictions for portability reasons.
+ *  - Made block and key lengths accept bit count (128/192/256)
+ *    as well byte count (16/24/32).
+ *  - Removed all error checks. This change also eliminated the need
+ *    to preinitialize the context struct to zero.
+ *  - Removed some totally unused constants.
+ */
+
+#include "aes.h"
+
+// CONFIGURATION OPTIONS (see also aes.h)
+//
+// 1.  Define UNROLL for full loop unrolling in encryption and decryption.
+// 2.  Define PARTIAL_UNROLL to unroll two loops in encryption and decryption.
+// 3.  Define FIXED_TABLES for compiled rather than dynamic tables.
+// 4.  Define FF_TABLES to use tables for field multiplies and inverses.
+//     Do not enable this without understanding stack space requirements.
+// 5.  Define ARRAYS to use arrays to hold the local state block. If this
+//     is not defined, individually declared 32-bit words are used.
+// 6.  Define FAST_VARIABLE if a high speed variable block implementation
+//     is needed (essentially three separate fixed block size code sequences)
+// 7.  Define either ONE_TABLE or FOUR_TABLES for a fast table driven 
+//     version using 1 table (2 kbytes of table space) or 4 tables (8
+//     kbytes of table space) for higher speed.
+// 8.  Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed 
+//     increase by using tables for the last rounds but with more table
+//     space (2 or 8 kbytes extra).
+// 9.  If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but 
+//     slower version is provided.
+// 10. If fast decryption key scheduling is needed define ONE_IM_TABLE
+//     or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra).
+
+#define UNROLL
+//#define PARTIAL_UNROLL
+
+#define FIXED_TABLES
+//#define FF_TABLES
+//#define ARRAYS
+#define FAST_VARIABLE
+
+//#define ONE_TABLE
+#define FOUR_TABLES
+
+//#define ONE_LR_TABLE
+#define FOUR_LR_TABLES
+
+//#define ONE_IM_TABLE
+#define FOUR_IM_TABLES
+
+#if defined(UNROLL) && defined (PARTIAL_UNROLL)
+#error both UNROLL and PARTIAL_UNROLL are defined
+#endif
+
+#if defined(ONE_TABLE) && defined (FOUR_TABLES)
+#error both ONE_TABLE and FOUR_TABLES are defined
+#endif
+
+#if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES)
+#error both ONE_LR_TABLE and FOUR_LR_TABLES are defined
+#endif
+
+#if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES)
+#error both ONE_IM_TABLE and FOUR_IM_TABLES are defined
+#endif
+
+#if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && AES_BLOCK_SIZE != 32
+#error an illegal block size has been specified
+#endif  
+
+// upr(x,n): rotates bytes within words by n positions, moving bytes 
+// to higher index positions with wrap around into low positions
+// ups(x,n): moves bytes by n positions to higher index positions in 
+// words but without wrap around
+// bval(x,n): extracts a byte from a word
+
+#define upr(x,n)        (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n))))
+#define ups(x,n)        ((x) << 8 * (n))
+#define bval(x,n)       ((unsigned char)((x) >> 8 * (n)))
+#define bytes2word(b0, b1, b2, b3)  \
+        ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | (b0))
+
+
+/* little endian processor without data alignment restrictions: AES_LE_OK */
+/* original code: i386 */
+#if defined(i386) || defined(_I386) || defined(__i386__) || defined(__i386) 
+#define	AES_LE_OK 1
+/* added (tested): alpha  --jjo */
+#elif defined(__alpha__)|| defined (__alpha)
+#define AES_LE_OK 1
+/* added (tested): ia64  --jjo */
+#elif defined(__ia64__)|| defined (__ia64)
+#define AES_LE_OK 1
+#endif
+
+#ifdef AES_LE_OK
+/* little endian processor without data alignment restrictions */
+#define word_in(x)      *(u_int32_t*)(x)
+#define const_word_in(x)      *(const u_int32_t*)(x)
+#define word_out(x,v)   *(u_int32_t*)(x) = (v)
+#define const_word_out(x,v)   *(const u_int32_t*)(x) = (v)
+#else
+/* slower but generic big endian or with data alignment restrictions */
+/* some additional "const" touches to stop "gcc -Wcast-qual" complains --jjo */
+#define word_in(x)      ((u_int32_t)(((unsigned char *)(x))[0])|((u_int32_t)(((unsigned char *)(x))[1])<<8)|((u_int32_t)(((unsigned char *)(x))[2])<<16)|((u_int32_t)(((unsigned char *)(x))[3])<<24))
+#define const_word_in(x)      ((const u_int32_t)(((const unsigned char *)(x))[0])|((const u_int32_t)(((const unsigned char *)(x))[1])<<8)|((const u_int32_t)(((const unsigned char *)(x))[2])<<16)|((const u_int32_t)(((const unsigned char *)(x))[3])<<24))
+#define word_out(x,v)   ((unsigned char *)(x))[0]=(v),((unsigned char *)(x))[1]=((v)>>8),((unsigned char *)(x))[2]=((v)>>16),((unsigned char *)(x))[3]=((v)>>24)
+#define const_word_out(x,v)   ((const unsigned char *)(x))[0]=(v),((const unsigned char *)(x))[1]=((v)>>8),((const unsigned char *)(x))[2]=((v)>>16),((const unsigned char *)(x))[3]=((v)>>24)
+#endif
+
+// Disable at least some poor combinations of options
+
+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
+#define FIXED_TABLES
+#undef  UNROLL
+#undef  ONE_LR_TABLE
+#undef  FOUR_LR_TABLES
+#undef  ONE_IM_TABLE
+#undef  FOUR_IM_TABLES
+#elif !defined(FOUR_TABLES)
+#ifdef  FOUR_LR_TABLES
+#undef  FOUR_LR_TABLES
+#define ONE_LR_TABLE
+#endif
+#ifdef  FOUR_IM_TABLES
+#undef  FOUR_IM_TABLES
+#define ONE_IM_TABLE
+#endif
+#elif !defined(AES_BLOCK_SIZE)
+#if defined(UNROLL)
+#define PARTIAL_UNROLL
+#undef UNROLL
+#endif
+#endif
+
+// the finite field modular polynomial and elements
+
+#define ff_poly 0x011b
+#define ff_hi   0x80
+
+// multiply four bytes in GF(2^8) by 'x' {02} in parallel
+
+#define m1  0x80808080
+#define m2  0x7f7f7f7f
+#define m3  0x0000001b
+#define FFmulX(x)  ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * m3))
+
+// The following defines provide alternative definitions of FFmulX that might
+// give improved performance if a fast 32-bit multiply is not available. Note
+// that a temporary variable u needs to be defined where FFmulX is used.
+
+// #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) 
+// #define m4  0x1b1b1b1b
+// #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) 
+
+// perform column mix operation on four bytes in parallel
+
+#define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ upr(x ^ f2,3) ^ upr(x,2) ^ upr(x,1))
+
+#if defined(FIXED_TABLES)
+
+// the S-Box table
+
+static const unsigned char s_box[256] =
+{
+    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+    0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+    0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+    0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+    0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+    0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+    0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+    0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+    0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+    0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+    0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+    0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+    0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+    0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+    0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+    0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+    0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+// the inverse S-Box table
+
+static const unsigned char inv_s_box[256] =
+{
+    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
+    0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+    0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+    0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+    0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
+    0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
+    0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+    0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+    0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+    0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+    0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+    0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+    0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+    0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+    0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
+    0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
+    0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+    0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+    0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
+    0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
+    0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+    0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
+    0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
+    0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+};
+
+#define w0(p)          0x000000##p
+
+// Number of elements required in this table for different
+// block and key lengths is:
+//
+// Nk =      4  6  8
+//        ----------
+// Nb = 4 | 10  8  7
+//      6 | 19 12 11
+//      8 | 29 19 14
+//
+// this table can be a table of bytes if the key schedule
+// code is adjusted accordingly
+
+static const u_int32_t rcon_tab[29] =
+{
+    w0(01), w0(02), w0(04), w0(08),
+    w0(10), w0(20), w0(40), w0(80),
+    w0(1b), w0(36), w0(6c), w0(d8),
+    w0(ab), w0(4d), w0(9a), w0(2f),
+    w0(5e), w0(bc), w0(63), w0(c6),
+    w0(97), w0(35), w0(6a), w0(d4),
+    w0(b3), w0(7d), w0(fa), w0(ef),
+    w0(c5)
+};
+
+#undef  w0
+
+#define r0(p,q,r,s) 0x##p##q##r##s
+#define r1(p,q,r,s) 0x##q##r##s##p
+#define r2(p,q,r,s) 0x##r##s##p##q
+#define r3(p,q,r,s) 0x##s##p##q##r
+#define w0(p)          0x000000##p
+#define w1(p)        0x0000##p##00
+#define w2(p)        0x00##p##0000
+#define w3(p)        0x##p##000000
+
+#if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES)) 
+
+//  data for forward tables (other than last round)
+
+#define f_table \
+    r(a5,63,63,c6), r(84,7c,7c,f8), r(99,77,77,ee), r(8d,7b,7b,f6),\
+    r(0d,f2,f2,ff), r(bd,6b,6b,d6), r(b1,6f,6f,de), r(54,c5,c5,91),\
+    r(50,30,30,60), r(03,01,01,02), r(a9,67,67,ce), r(7d,2b,2b,56),\
+    r(19,fe,fe,e7), r(62,d7,d7,b5), r(e6,ab,ab,4d), r(9a,76,76,ec),\
+    r(45,ca,ca,8f), r(9d,82,82,1f), r(40,c9,c9,89), r(87,7d,7d,fa),\
+    r(15,fa,fa,ef), r(eb,59,59,b2), r(c9,47,47,8e), r(0b,f0,f0,fb),\
+    r(ec,ad,ad,41), r(67,d4,d4,b3), r(fd,a2,a2,5f), r(ea,af,af,45),\
+    r(bf,9c,9c,23), r(f7,a4,a4,53), r(96,72,72,e4), r(5b,c0,c0,9b),\
+    r(c2,b7,b7,75), r(1c,fd,fd,e1), r(ae,93,93,3d), r(6a,26,26,4c),\
+    r(5a,36,36,6c), r(41,3f,3f,7e), r(02,f7,f7,f5), r(4f,cc,cc,83),\
+    r(5c,34,34,68), r(f4,a5,a5,51), r(34,e5,e5,d1), r(08,f1,f1,f9),\
+    r(93,71,71,e2), r(73,d8,d8,ab), r(53,31,31,62), r(3f,15,15,2a),\
+    r(0c,04,04,08), r(52,c7,c7,95), r(65,23,23,46), r(5e,c3,c3,9d),\
+    r(28,18,18,30), r(a1,96,96,37), r(0f,05,05,0a), r(b5,9a,9a,2f),\
+    r(09,07,07,0e), r(36,12,12,24), r(9b,80,80,1b), r(3d,e2,e2,df),\
+    r(26,eb,eb,cd), r(69,27,27,4e), r(cd,b2,b2,7f), r(9f,75,75,ea),\
+    r(1b,09,09,12), r(9e,83,83,1d), r(74,2c,2c,58), r(2e,1a,1a,34),\
+    r(2d,1b,1b,36), r(b2,6e,6e,dc), r(ee,5a,5a,b4), r(fb,a0,a0,5b),\
+    r(f6,52,52,a4), r(4d,3b,3b,76), r(61,d6,d6,b7), r(ce,b3,b3,7d),\
+    r(7b,29,29,52), r(3e,e3,e3,dd), r(71,2f,2f,5e), r(97,84,84,13),\
+    r(f5,53,53,a6), r(68,d1,d1,b9), r(00,00,00,00), r(2c,ed,ed,c1),\
+    r(60,20,20,40), r(1f,fc,fc,e3), r(c8,b1,b1,79), r(ed,5b,5b,b6),\
+    r(be,6a,6a,d4), r(46,cb,cb,8d), r(d9,be,be,67), r(4b,39,39,72),\
+    r(de,4a,4a,94), r(d4,4c,4c,98), r(e8,58,58,b0), r(4a,cf,cf,85),\
+    r(6b,d0,d0,bb), r(2a,ef,ef,c5), r(e5,aa,aa,4f), r(16,fb,fb,ed),\
+    r(c5,43,43,86), r(d7,4d,4d,9a), r(55,33,33,66), r(94,85,85,11),\
+    r(cf,45,45,8a), r(10,f9,f9,e9), r(06,02,02,04), r(81,7f,7f,fe),\
+    r(f0,50,50,a0), r(44,3c,3c,78), r(ba,9f,9f,25), r(e3,a8,a8,4b),\
+    r(f3,51,51,a2), r(fe,a3,a3,5d), r(c0,40,40,80), r(8a,8f,8f,05),\
+    r(ad,92,92,3f), r(bc,9d,9d,21), r(48,38,38,70), r(04,f5,f5,f1),\
+    r(df,bc,bc,63), r(c1,b6,b6,77), r(75,da,da,af), r(63,21,21,42),\
+    r(30,10,10,20), r(1a,ff,ff,e5), r(0e,f3,f3,fd), r(6d,d2,d2,bf),\
+    r(4c,cd,cd,81), r(14,0c,0c,18), r(35,13,13,26), r(2f,ec,ec,c3),\
+    r(e1,5f,5f,be), r(a2,97,97,35), r(cc,44,44,88), r(39,17,17,2e),\
+    r(57,c4,c4,93), r(f2,a7,a7,55), r(82,7e,7e,fc), r(47,3d,3d,7a),\
+    r(ac,64,64,c8), r(e7,5d,5d,ba), r(2b,19,19,32), r(95,73,73,e6),\
+    r(a0,60,60,c0), r(98,81,81,19), r(d1,4f,4f,9e), r(7f,dc,dc,a3),\
+    r(66,22,22,44), r(7e,2a,2a,54), r(ab,90,90,3b), r(83,88,88,0b),\
+    r(ca,46,46,8c), r(29,ee,ee,c7), r(d3,b8,b8,6b), r(3c,14,14,28),\
+    r(79,de,de,a7), r(e2,5e,5e,bc), r(1d,0b,0b,16), r(76,db,db,ad),\
+    r(3b,e0,e0,db), r(56,32,32,64), r(4e,3a,3a,74), r(1e,0a,0a,14),\
+    r(db,49,49,92), r(0a,06,06,0c), r(6c,24,24,48), r(e4,5c,5c,b8),\
+    r(5d,c2,c2,9f), r(6e,d3,d3,bd), r(ef,ac,ac,43), r(a6,62,62,c4),\
+    r(a8,91,91,39), r(a4,95,95,31), r(37,e4,e4,d3), r(8b,79,79,f2),\
+    r(32,e7,e7,d5), r(43,c8,c8,8b), r(59,37,37,6e), r(b7,6d,6d,da),\
+    r(8c,8d,8d,01), r(64,d5,d5,b1), r(d2,4e,4e,9c), r(e0,a9,a9,49),\
+    r(b4,6c,6c,d8), r(fa,56,56,ac), r(07,f4,f4,f3), r(25,ea,ea,cf),\
+    r(af,65,65,ca), r(8e,7a,7a,f4), r(e9,ae,ae,47), r(18,08,08,10),\
+    r(d5,ba,ba,6f), r(88,78,78,f0), r(6f,25,25,4a), r(72,2e,2e,5c),\
+    r(24,1c,1c,38), r(f1,a6,a6,57), r(c7,b4,b4,73), r(51,c6,c6,97),\
+    r(23,e8,e8,cb), r(7c,dd,dd,a1), r(9c,74,74,e8), r(21,1f,1f,3e),\
+    r(dd,4b,4b,96), r(dc,bd,bd,61), r(86,8b,8b,0d), r(85,8a,8a,0f),\
+    r(90,70,70,e0), r(42,3e,3e,7c), r(c4,b5,b5,71), r(aa,66,66,cc),\
+    r(d8,48,48,90), r(05,03,03,06), r(01,f6,f6,f7), r(12,0e,0e,1c),\
+    r(a3,61,61,c2), r(5f,35,35,6a), r(f9,57,57,ae), r(d0,b9,b9,69),\
+    r(91,86,86,17), r(58,c1,c1,99), r(27,1d,1d,3a), r(b9,9e,9e,27),\
+    r(38,e1,e1,d9), r(13,f8,f8,eb), r(b3,98,98,2b), r(33,11,11,22),\
+    r(bb,69,69,d2), r(70,d9,d9,a9), r(89,8e,8e,07), r(a7,94,94,33),\
+    r(b6,9b,9b,2d), r(22,1e,1e,3c), r(92,87,87,15), r(20,e9,e9,c9),\
+    r(49,ce,ce,87), r(ff,55,55,aa), r(78,28,28,50), r(7a,df,df,a5),\
+    r(8f,8c,8c,03), r(f8,a1,a1,59), r(80,89,89,09), r(17,0d,0d,1a),\
+    r(da,bf,bf,65), r(31,e6,e6,d7), r(c6,42,42,84), r(b8,68,68,d0),\
+    r(c3,41,41,82), r(b0,99,99,29), r(77,2d,2d,5a), r(11,0f,0f,1e),\
+    r(cb,b0,b0,7b), r(fc,54,54,a8), r(d6,bb,bb,6d), r(3a,16,16,2c)
+
+//  data for inverse tables (other than last round)
+
+#define i_table \
+    r(50,a7,f4,51), r(53,65,41,7e), r(c3,a4,17,1a), r(96,5e,27,3a),\
+    r(cb,6b,ab,3b), r(f1,45,9d,1f), r(ab,58,fa,ac), r(93,03,e3,4b),\
+    r(55,fa,30,20), r(f6,6d,76,ad), r(91,76,cc,88), r(25,4c,02,f5),\
+    r(fc,d7,e5,4f), r(d7,cb,2a,c5), r(80,44,35,26), r(8f,a3,62,b5),\
+    r(49,5a,b1,de), r(67,1b,ba,25), r(98,0e,ea,45), r(e1,c0,fe,5d),\
+    r(02,75,2f,c3), r(12,f0,4c,81), r(a3,97,46,8d), r(c6,f9,d3,6b),\
+    r(e7,5f,8f,03), r(95,9c,92,15), r(eb,7a,6d,bf), r(da,59,52,95),\
+    r(2d,83,be,d4), r(d3,21,74,58), r(29,69,e0,49), r(44,c8,c9,8e),\
+    r(6a,89,c2,75), r(78,79,8e,f4), r(6b,3e,58,99), r(dd,71,b9,27),\
+    r(b6,4f,e1,be), r(17,ad,88,f0), r(66,ac,20,c9), r(b4,3a,ce,7d),\
+    r(18,4a,df,63), r(82,31,1a,e5), r(60,33,51,97), r(45,7f,53,62),\
+    r(e0,77,64,b1), r(84,ae,6b,bb), r(1c,a0,81,fe), r(94,2b,08,f9),\
+    r(58,68,48,70), r(19,fd,45,8f), r(87,6c,de,94), r(b7,f8,7b,52),\
+    r(23,d3,73,ab), r(e2,02,4b,72), r(57,8f,1f,e3), r(2a,ab,55,66),\
+    r(07,28,eb,b2), r(03,c2,b5,2f), r(9a,7b,c5,86), r(a5,08,37,d3),\
+    r(f2,87,28,30), r(b2,a5,bf,23), r(ba,6a,03,02), r(5c,82,16,ed),\
+    r(2b,1c,cf,8a), r(92,b4,79,a7), r(f0,f2,07,f3), r(a1,e2,69,4e),\
+    r(cd,f4,da,65), r(d5,be,05,06), r(1f,62,34,d1), r(8a,fe,a6,c4),\
+    r(9d,53,2e,34), r(a0,55,f3,a2), r(32,e1,8a,05), r(75,eb,f6,a4),\
+    r(39,ec,83,0b), r(aa,ef,60,40), r(06,9f,71,5e), r(51,10,6e,bd),\
+    r(f9,8a,21,3e), r(3d,06,dd,96), r(ae,05,3e,dd), r(46,bd,e6,4d),\
+    r(b5,8d,54,91), r(05,5d,c4,71), r(6f,d4,06,04), r(ff,15,50,60),\
+    r(24,fb,98,19), r(97,e9,bd,d6), r(cc,43,40,89), r(77,9e,d9,67),\
+    r(bd,42,e8,b0), r(88,8b,89,07), r(38,5b,19,e7), r(db,ee,c8,79),\
+    r(47,0a,7c,a1), r(e9,0f,42,7c), r(c9,1e,84,f8), r(00,00,00,00),\
+    r(83,86,80,09), r(48,ed,2b,32), r(ac,70,11,1e), r(4e,72,5a,6c),\
+    r(fb,ff,0e,fd), r(56,38,85,0f), r(1e,d5,ae,3d), r(27,39,2d,36),\
+    r(64,d9,0f,0a), r(21,a6,5c,68), r(d1,54,5b,9b), r(3a,2e,36,24),\
+    r(b1,67,0a,0c), r(0f,e7,57,93), r(d2,96,ee,b4), r(9e,91,9b,1b),\
+    r(4f,c5,c0,80), r(a2,20,dc,61), r(69,4b,77,5a), r(16,1a,12,1c),\
+    r(0a,ba,93,e2), r(e5,2a,a0,c0), r(43,e0,22,3c), r(1d,17,1b,12),\
+    r(0b,0d,09,0e), r(ad,c7,8b,f2), r(b9,a8,b6,2d), r(c8,a9,1e,14),\
+    r(85,19,f1,57), r(4c,07,75,af), r(bb,dd,99,ee), r(fd,60,7f,a3),\
+    r(9f,26,01,f7), r(bc,f5,72,5c), r(c5,3b,66,44), r(34,7e,fb,5b),\
+    r(76,29,43,8b), r(dc,c6,23,cb), r(68,fc,ed,b6), r(63,f1,e4,b8),\
+    r(ca,dc,31,d7), r(10,85,63,42), r(40,22,97,13), r(20,11,c6,84),\
+    r(7d,24,4a,85), r(f8,3d,bb,d2), r(11,32,f9,ae), r(6d,a1,29,c7),\
+    r(4b,2f,9e,1d), r(f3,30,b2,dc), r(ec,52,86,0d), r(d0,e3,c1,77),\
+    r(6c,16,b3,2b), r(99,b9,70,a9), r(fa,48,94,11), r(22,64,e9,47),\
+    r(c4,8c,fc,a8), r(1a,3f,f0,a0), r(d8,2c,7d,56), r(ef,90,33,22),\
+    r(c7,4e,49,87), r(c1,d1,38,d9), r(fe,a2,ca,8c), r(36,0b,d4,98),\
+    r(cf,81,f5,a6), r(28,de,7a,a5), r(26,8e,b7,da), r(a4,bf,ad,3f),\
+    r(e4,9d,3a,2c), r(0d,92,78,50), r(9b,cc,5f,6a), r(62,46,7e,54),\
+    r(c2,13,8d,f6), r(e8,b8,d8,90), r(5e,f7,39,2e), r(f5,af,c3,82),\
+    r(be,80,5d,9f), r(7c,93,d0,69), r(a9,2d,d5,6f), r(b3,12,25,cf),\
+    r(3b,99,ac,c8), r(a7,7d,18,10), r(6e,63,9c,e8), r(7b,bb,3b,db),\
+    r(09,78,26,cd), r(f4,18,59,6e), r(01,b7,9a,ec), r(a8,9a,4f,83),\
+    r(65,6e,95,e6), r(7e,e6,ff,aa), r(08,cf,bc,21), r(e6,e8,15,ef),\
+    r(d9,9b,e7,ba), r(ce,36,6f,4a), r(d4,09,9f,ea), r(d6,7c,b0,29),\
+    r(af,b2,a4,31), r(31,23,3f,2a), r(30,94,a5,c6), r(c0,66,a2,35),\
+    r(37,bc,4e,74), r(a6,ca,82,fc), r(b0,d0,90,e0), r(15,d8,a7,33),\
+    r(4a,98,04,f1), r(f7,da,ec,41), r(0e,50,cd,7f), r(2f,f6,91,17),\
+    r(8d,d6,4d,76), r(4d,b0,ef,43), r(54,4d,aa,cc), r(df,04,96,e4),\
+    r(e3,b5,d1,9e), r(1b,88,6a,4c), r(b8,1f,2c,c1), r(7f,51,65,46),\
+    r(04,ea,5e,9d), r(5d,35,8c,01), r(73,74,87,fa), r(2e,41,0b,fb),\
+    r(5a,1d,67,b3), r(52,d2,db,92), r(33,56,10,e9), r(13,47,d6,6d),\
+    r(8c,61,d7,9a), r(7a,0c,a1,37), r(8e,14,f8,59), r(89,3c,13,eb),\
+    r(ee,27,a9,ce), r(35,c9,61,b7), r(ed,e5,1c,e1), r(3c,b1,47,7a),\
+    r(59,df,d2,9c), r(3f,73,f2,55), r(79,ce,14,18), r(bf,37,c7,73),\
+    r(ea,cd,f7,53), r(5b,aa,fd,5f), r(14,6f,3d,df), r(86,db,44,78),\
+    r(81,f3,af,ca), r(3e,c4,68,b9), r(2c,34,24,38), r(5f,40,a3,c2),\
+    r(72,c3,1d,16), r(0c,25,e2,bc), r(8b,49,3c,28), r(41,95,0d,ff),\
+    r(71,01,a8,39), r(de,b3,0c,08), r(9c,e4,b4,d8), r(90,c1,56,64),\
+    r(61,84,cb,7b), r(70,b6,32,d5), r(74,5c,6c,48), r(42,57,b8,d0)
+
+// generate the required tables in the desired endian format
+
+#undef  r
+#define r   r0
+
+#if defined(ONE_TABLE)
+static const u_int32_t ft_tab[256] =
+    {   f_table };
+#elif defined(FOUR_TABLES)
+static const u_int32_t ft_tab[4][256] =
+{   {   f_table },
+#undef  r
+#define r   r1
+    {   f_table },
+#undef  r
+#define r   r2
+    {   f_table },
+#undef  r
+#define r   r3
+    {   f_table }
+};
+#endif
+
+#undef  r
+#define r   r0
+#if defined(ONE_TABLE)
+static const u_int32_t it_tab[256] =
+    {   i_table };
+#elif defined(FOUR_TABLES)
+static const u_int32_t it_tab[4][256] =
+{   {   i_table },
+#undef  r
+#define r   r1
+    {   i_table },
+#undef  r
+#define r   r2
+    {   i_table },
+#undef  r
+#define r   r3
+    {   i_table }
+};
+#endif
+
+#endif
+
+#if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES)) 
+
+//  data for inverse tables (last round)
+
+#define li_table    \
+    w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38),\
+    w(bf), w(40), w(a3), w(9e), w(81), w(f3), w(d7), w(fb),\
+    w(7c), w(e3), w(39), w(82), w(9b), w(2f), w(ff), w(87),\
+    w(34), w(8e), w(43), w(44), w(c4), w(de), w(e9), w(cb),\
+    w(54), w(7b), w(94), w(32), w(a6), w(c2), w(23), w(3d),\
+    w(ee), w(4c), w(95), w(0b), w(42), w(fa), w(c3), w(4e),\
+    w(08), w(2e), w(a1), w(66), w(28), w(d9), w(24), w(b2),\
+    w(76), w(5b), w(a2), w(49), w(6d), w(8b), w(d1), w(25),\
+    w(72), w(f8), w(f6), w(64), w(86), w(68), w(98), w(16),\
+    w(d4), w(a4), w(5c), w(cc), w(5d), w(65), w(b6), w(92),\
+    w(6c), w(70), w(48), w(50), w(fd), w(ed), w(b9), w(da),\
+    w(5e), w(15), w(46), w(57), w(a7), w(8d), w(9d), w(84),\
+    w(90), w(d8), w(ab), w(00), w(8c), w(bc), w(d3), w(0a),\
+    w(f7), w(e4), w(58), w(05), w(b8), w(b3), w(45), w(06),\
+    w(d0), w(2c), w(1e), w(8f), w(ca), w(3f), w(0f), w(02),\
+    w(c1), w(af), w(bd), w(03), w(01), w(13), w(8a), w(6b),\
+    w(3a), w(91), w(11), w(41), w(4f), w(67), w(dc), w(ea),\
+    w(97), w(f2), w(cf), w(ce), w(f0), w(b4), w(e6), w(73),\
+    w(96), w(ac), w(74), w(22), w(e7), w(ad), w(35), w(85),\
+    w(e2), w(f9), w(37), w(e8), w(1c), w(75), w(df), w(6e),\
+    w(47), w(f1), w(1a), w(71), w(1d), w(29), w(c5), w(89),\
+    w(6f), w(b7), w(62), w(0e), w(aa), w(18), w(be), w(1b),\
+    w(fc), w(56), w(3e), w(4b), w(c6), w(d2), w(79), w(20),\
+    w(9a), w(db), w(c0), w(fe), w(78), w(cd), w(5a), w(f4),\
+    w(1f), w(dd), w(a8), w(33), w(88), w(07), w(c7), w(31),\
+    w(b1), w(12), w(10), w(59), w(27), w(80), w(ec), w(5f),\
+    w(60), w(51), w(7f), w(a9), w(19), w(b5), w(4a), w(0d),\
+    w(2d), w(e5), w(7a), w(9f), w(93), w(c9), w(9c), w(ef),\
+    w(a0), w(e0), w(3b), w(4d), w(ae), w(2a), w(f5), w(b0),\
+    w(c8), w(eb), w(bb), w(3c), w(83), w(53), w(99), w(61),\
+    w(17), w(2b), w(04), w(7e), w(ba), w(77), w(d6), w(26),\
+    w(e1), w(69), w(14), w(63), w(55), w(21), w(0c), w(7d),
+
+// generate the required tables in the desired endian format
+
+#undef  r
+#define r(p,q,r,s)  w0(q)
+#if defined(ONE_LR_TABLE)
+static const u_int32_t fl_tab[256] =
+    {   f_table     };
+#elif defined(FOUR_LR_TABLES)
+static const u_int32_t fl_tab[4][256] =
+{   {   f_table    },
+#undef  r
+#define r(p,q,r,s)   w1(q)
+    {   f_table    },
+#undef  r
+#define r(p,q,r,s)   w2(q)
+    {   f_table    },
+#undef  r
+#define r(p,q,r,s)   w3(q)
+    {   f_table    }
+};
+#endif
+
+#undef  w
+#define w   w0
+#if defined(ONE_LR_TABLE)
+static const u_int32_t il_tab[256] =
+    {   li_table    };
+#elif defined(FOUR_LR_TABLES)
+static const u_int32_t il_tab[4][256] =
+{   {   li_table    },
+#undef  w
+#define w   w1
+    {   li_table    },
+#undef  w
+#define w   w2
+    {   li_table    },
+#undef  w
+#define w   w3
+    {   li_table    }
+};
+#endif
+
+#endif
+
+#if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES)) 
+
+#define m_table \
+    r(00,00,00,00), r(0b,0d,09,0e), r(16,1a,12,1c), r(1d,17,1b,12),\
+    r(2c,34,24,38), r(27,39,2d,36), r(3a,2e,36,24), r(31,23,3f,2a),\
+    r(58,68,48,70), r(53,65,41,7e), r(4e,72,5a,6c), r(45,7f,53,62),\
+    r(74,5c,6c,48), r(7f,51,65,46), r(62,46,7e,54), r(69,4b,77,5a),\
+    r(b0,d0,90,e0), r(bb,dd,99,ee), r(a6,ca,82,fc), r(ad,c7,8b,f2),\
+    r(9c,e4,b4,d8), r(97,e9,bd,d6), r(8a,fe,a6,c4), r(81,f3,af,ca),\
+    r(e8,b8,d8,90), r(e3,b5,d1,9e), r(fe,a2,ca,8c), r(f5,af,c3,82),\
+    r(c4,8c,fc,a8), r(cf,81,f5,a6), r(d2,96,ee,b4), r(d9,9b,e7,ba),\
+    r(7b,bb,3b,db), r(70,b6,32,d5), r(6d,a1,29,c7), r(66,ac,20,c9),\
+    r(57,8f,1f,e3), r(5c,82,16,ed), r(41,95,0d,ff), r(4a,98,04,f1),\
+    r(23,d3,73,ab), r(28,de,7a,a5), r(35,c9,61,b7), r(3e,c4,68,b9),\
+    r(0f,e7,57,93), r(04,ea,5e,9d), r(19,fd,45,8f), r(12,f0,4c,81),\
+    r(cb,6b,ab,3b), r(c0,66,a2,35), r(dd,71,b9,27), r(d6,7c,b0,29),\
+    r(e7,5f,8f,03), r(ec,52,86,0d), r(f1,45,9d,1f), r(fa,48,94,11),\
+    r(93,03,e3,4b), r(98,0e,ea,45), r(85,19,f1,57), r(8e,14,f8,59),\
+    r(bf,37,c7,73), r(b4,3a,ce,7d), r(a9,2d,d5,6f), r(a2,20,dc,61),\
+    r(f6,6d,76,ad), r(fd,60,7f,a3), r(e0,77,64,b1), r(eb,7a,6d,bf),\
+    r(da,59,52,95), r(d1,54,5b,9b), r(cc,43,40,89), r(c7,4e,49,87),\
+    r(ae,05,3e,dd), r(a5,08,37,d3), r(b8,1f,2c,c1), r(b3,12,25,cf),\
+    r(82,31,1a,e5), r(89,3c,13,eb), r(94,2b,08,f9), r(9f,26,01,f7),\
+    r(46,bd,e6,4d), r(4d,b0,ef,43), r(50,a7,f4,51), r(5b,aa,fd,5f),\
+    r(6a,89,c2,75), r(61,84,cb,7b), r(7c,93,d0,69), r(77,9e,d9,67),\
+    r(1e,d5,ae,3d), r(15,d8,a7,33), r(08,cf,bc,21), r(03,c2,b5,2f),\
+    r(32,e1,8a,05), r(39,ec,83,0b), r(24,fb,98,19), r(2f,f6,91,17),\
+    r(8d,d6,4d,76), r(86,db,44,78), r(9b,cc,5f,6a), r(90,c1,56,64),\
+    r(a1,e2,69,4e), r(aa,ef,60,40), r(b7,f8,7b,52), r(bc,f5,72,5c),\
+    r(d5,be,05,06), r(de,b3,0c,08), r(c3,a4,17,1a), r(c8,a9,1e,14),\
+    r(f9,8a,21,3e), r(f2,87,28,30), r(ef,90,33,22), r(e4,9d,3a,2c),\
+    r(3d,06,dd,96), r(36,0b,d4,98), r(2b,1c,cf,8a), r(20,11,c6,84),\
+    r(11,32,f9,ae), r(1a,3f,f0,a0), r(07,28,eb,b2), r(0c,25,e2,bc),\
+    r(65,6e,95,e6), r(6e,63,9c,e8), r(73,74,87,fa), r(78,79,8e,f4),\
+    r(49,5a,b1,de), r(42,57,b8,d0), r(5f,40,a3,c2), r(54,4d,aa,cc),\
+    r(f7,da,ec,41), r(fc,d7,e5,4f), r(e1,c0,fe,5d), r(ea,cd,f7,53),\
+    r(db,ee,c8,79), r(d0,e3,c1,77), r(cd,f4,da,65), r(c6,f9,d3,6b),\
+    r(af,b2,a4,31), r(a4,bf,ad,3f), r(b9,a8,b6,2d), r(b2,a5,bf,23),\
+    r(83,86,80,09), r(88,8b,89,07), r(95,9c,92,15), r(9e,91,9b,1b),\
+    r(47,0a,7c,a1), r(4c,07,75,af), r(51,10,6e,bd), r(5a,1d,67,b3),\
+    r(6b,3e,58,99), r(60,33,51,97), r(7d,24,4a,85), r(76,29,43,8b),\
+    r(1f,62,34,d1), r(14,6f,3d,df), r(09,78,26,cd), r(02,75,2f,c3),\
+    r(33,56,10,e9), r(38,5b,19,e7), r(25,4c,02,f5), r(2e,41,0b,fb),\
+    r(8c,61,d7,9a), r(87,6c,de,94), r(9a,7b,c5,86), r(91,76,cc,88),\
+    r(a0,55,f3,a2), r(ab,58,fa,ac), r(b6,4f,e1,be), r(bd,42,e8,b0),\
+    r(d4,09,9f,ea), r(df,04,96,e4), r(c2,13,8d,f6), r(c9,1e,84,f8),\
+    r(f8,3d,bb,d2), r(f3,30,b2,dc), r(ee,27,a9,ce), r(e5,2a,a0,c0),\
+    r(3c,b1,47,7a), r(37,bc,4e,74), r(2a,ab,55,66), r(21,a6,5c,68),\
+    r(10,85,63,42), r(1b,88,6a,4c), r(06,9f,71,5e), r(0d,92,78,50),\
+    r(64,d9,0f,0a), r(6f,d4,06,04), r(72,c3,1d,16), r(79,ce,14,18),\
+    r(48,ed,2b,32), r(43,e0,22,3c), r(5e,f7,39,2e), r(55,fa,30,20),\
+    r(01,b7,9a,ec), r(0a,ba,93,e2), r(17,ad,88,f0), r(1c,a0,81,fe),\
+    r(2d,83,be,d4), r(26,8e,b7,da), r(3b,99,ac,c8), r(30,94,a5,c6),\
+    r(59,df,d2,9c), r(52,d2,db,92), r(4f,c5,c0,80), r(44,c8,c9,8e),\
+    r(75,eb,f6,a4), r(7e,e6,ff,aa), r(63,f1,e4,b8), r(68,fc,ed,b6),\
+    r(b1,67,0a,0c), r(ba,6a,03,02), r(a7,7d,18,10), r(ac,70,11,1e),\
+    r(9d,53,2e,34), r(96,5e,27,3a), r(8b,49,3c,28), r(80,44,35,26),\
+    r(e9,0f,42,7c), r(e2,02,4b,72), r(ff,15,50,60), r(f4,18,59,6e),\
+    r(c5,3b,66,44), r(ce,36,6f,4a), r(d3,21,74,58), r(d8,2c,7d,56),\
+    r(7a,0c,a1,37), r(71,01,a8,39), r(6c,16,b3,2b), r(67,1b,ba,25),\
+    r(56,38,85,0f), r(5d,35,8c,01), r(40,22,97,13), r(4b,2f,9e,1d),\
+    r(22,64,e9,47), r(29,69,e0,49), r(34,7e,fb,5b), r(3f,73,f2,55),\
+    r(0e,50,cd,7f), r(05,5d,c4,71), r(18,4a,df,63), r(13,47,d6,6d),\
+    r(ca,dc,31,d7), r(c1,d1,38,d9), r(dc,c6,23,cb), r(d7,cb,2a,c5),\
+    r(e6,e8,15,ef), r(ed,e5,1c,e1), r(f0,f2,07,f3), r(fb,ff,0e,fd),\
+    r(92,b4,79,a7), r(99,b9,70,a9), r(84,ae,6b,bb), r(8f,a3,62,b5),\
+    r(be,80,5d,9f), r(b5,8d,54,91), r(a8,9a,4f,83), r(a3,97,46,8d)
+
+#undef r
+#define r   r0
+
+#if defined(ONE_IM_TABLE)
+static const u_int32_t im_tab[256] =
+    {   m_table };
+#elif defined(FOUR_IM_TABLES)
+static const u_int32_t im_tab[4][256] =
+{   {   m_table },
+#undef  r
+#define r   r1
+    {   m_table },
+#undef  r
+#define r   r2
+    {   m_table },
+#undef  r
+#define r   r3
+    {   m_table }
+};
+#endif
+
+#endif
+
+#else
+
+static int tab_gen = 0;
+
+static unsigned char  s_box[256];            // the S box
+static unsigned char  inv_s_box[256];        // the inverse S box
+static u_int32_t  rcon_tab[AES_RC_LENGTH];   // table of round constants
+
+#if defined(ONE_TABLE)
+static u_int32_t  ft_tab[256];
+static u_int32_t  it_tab[256];
+#elif defined(FOUR_TABLES)
+static u_int32_t  ft_tab[4][256];
+static u_int32_t  it_tab[4][256];
+#endif
+
+#if defined(ONE_LR_TABLE)
+static u_int32_t  fl_tab[256];
+static u_int32_t  il_tab[256];
+#elif defined(FOUR_LR_TABLES)
+static u_int32_t  fl_tab[4][256];
+static u_int32_t  il_tab[4][256];
+#endif
+
+#if defined(ONE_IM_TABLE)
+static u_int32_t  im_tab[256];
+#elif defined(FOUR_IM_TABLES)
+static u_int32_t  im_tab[4][256];
+#endif
+
+// Generate the tables for the dynamic table option
+
+#if !defined(FF_TABLES)
+
+// It will generally be sensible to use tables to compute finite 
+// field multiplies and inverses but where memory is scarse this 
+// code might sometimes be better.
+
+// return 2 ^ (n - 1) where n is the bit number of the highest bit
+// set in x with x in the range 1 < x < 0x00000200.   This form is
+// used so that locals within FFinv can be bytes rather than words
+
+static unsigned char hibit(const u_int32_t x)
+{   unsigned char r = (unsigned char)((x >> 1) | (x >> 2));
+    
+    r |= (r >> 2);
+    r |= (r >> 4);
+    return (r + 1) >> 1;
+}
+
+// return the inverse of the finite field element x
+
+static unsigned char FFinv(const unsigned char x)
+{   unsigned char    p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+    if(x < 2) return x;
+
+    for(;;)
+    {
+        if(!n1) return v1;
+
+        while(n2 >= n1)
+        {   
+            n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
+        }
+        
+        if(!n2) return v2;
+
+        while(n1 >= n2)
+        {   
+            n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
+        }
+    }
+}
+
+// define the finite field multiplies required for Rijndael
+
+#define FFmul02(x)  ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0))
+#define FFmul03(x)  ((x) ^ FFmul02(x))
+#define FFmul09(x)  ((x) ^ FFmul02(FFmul02(FFmul02(x))))
+#define FFmul0b(x)  ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x))))
+#define FFmul0d(x)  ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x))))
+#define FFmul0e(x)  FFmul02((x) ^ FFmul02((x) ^ FFmul02(x)))
+
+#else
+
+#define FFinv(x)    ((x) ? pow[255 - log[x]]: 0)
+
+#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0)
+#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0)
+#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0)
+#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0)
+#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0)
+#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0)
+
+#endif
+
+// The forward and inverse affine transformations used in the S-box
+
+#define fwd_affine(x) \
+    (w = (u_int32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(unsigned char)(w^(w>>8)))
+
+#define inv_affine(x) \
+    (w = (u_int32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(unsigned char)(w^(w>>8)))
+
+static void gen_tabs(void)
+{   u_int32_t  i, w;
+
+#if defined(FF_TABLES)
+
+    unsigned char  pow[512], log[256];
+
+    // log and power tables for GF(2^8) finite field with
+    // 0x011b as modular polynomial - the simplest primitive
+    // root is 0x03, used here to generate the tables
+
+    i = 0; w = 1; 
+    do
+    {   
+        pow[i] = (unsigned char)w;
+        pow[i + 255] = (unsigned char)w;
+        log[w] = (unsigned char)i++;
+        w ^=  (w << 1) ^ (w & ff_hi ? ff_poly : 0);
+    }
+    while (w != 1);
+
+#endif
+
+    for(i = 0, w = 1; i < AES_RC_LENGTH; ++i)
+    {
+        rcon_tab[i] = bytes2word(w, 0, 0, 0);
+        w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
+    }
+
+    for(i = 0; i < 256; ++i)
+    {   unsigned char    b;
+
+        s_box[i] = b = fwd_affine(FFinv((unsigned char)i));
+
+        w = bytes2word(b, 0, 0, 0);
+#if defined(ONE_LR_TABLE)
+        fl_tab[i] = w;
+#elif defined(FOUR_LR_TABLES)
+        fl_tab[0][i] = w;
+        fl_tab[1][i] = upr(w,1);
+        fl_tab[2][i] = upr(w,2);
+        fl_tab[3][i] = upr(w,3);
+#endif
+        w = bytes2word(FFmul02(b), b, b, FFmul03(b));
+#if defined(ONE_TABLE)
+        ft_tab[i] = w;
+#elif defined(FOUR_TABLES)
+        ft_tab[0][i] = w;
+        ft_tab[1][i] = upr(w,1);
+        ft_tab[2][i] = upr(w,2);
+        ft_tab[3][i] = upr(w,3);
+#endif
+        inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i));
+
+        w = bytes2word(b, 0, 0, 0);
+#if defined(ONE_LR_TABLE)
+        il_tab[i] = w;
+#elif defined(FOUR_LR_TABLES)
+        il_tab[0][i] = w;
+        il_tab[1][i] = upr(w,1);
+        il_tab[2][i] = upr(w,2);
+        il_tab[3][i] = upr(w,3);
+#endif
+        w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b));
+#if defined(ONE_TABLE)
+        it_tab[i] = w;
+#elif defined(FOUR_TABLES)
+        it_tab[0][i] = w;
+        it_tab[1][i] = upr(w,1);
+        it_tab[2][i] = upr(w,2);
+        it_tab[3][i] = upr(w,3);
+#endif
+#if defined(ONE_IM_TABLE)
+        im_tab[b] = w;
+#elif defined(FOUR_IM_TABLES)
+        im_tab[0][b] = w;
+        im_tab[1][b] = upr(w,1);
+        im_tab[2][b] = upr(w,2);
+        im_tab[3][b] = upr(w,3);
+#endif
+
+    }
+}
+
+#endif
+
+#define no_table(x,box,vf,rf,c) bytes2word( \
+    box[bval(vf(x,0,c),rf(0,c))], \
+    box[bval(vf(x,1,c),rf(1,c))], \
+    box[bval(vf(x,2,c),rf(2,c))], \
+    box[bval(vf(x,3,c),rf(3,c))])
+
+#define one_table(x,op,tab,vf,rf,c) \
+ (     tab[bval(vf(x,0,c),rf(0,c))] \
+  ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
+  ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
+  ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
+
+#define four_tables(x,tab,vf,rf,c) \
+ (  tab[0][bval(vf(x,0,c),rf(0,c))] \
+  ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
+  ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
+  ^ tab[3][bval(vf(x,3,c),rf(3,c))])
+
+#define vf1(x,r,c)  (x)
+#define rf1(r,c)    (r)
+#define rf2(r,c)    ((r-c)&3)
+
+#if defined(FOUR_LR_TABLES)
+#define ls_box(x,c)     four_tables(x,fl_tab,vf1,rf2,c)
+#elif defined(ONE_LR_TABLE)
+#define ls_box(x,c)     one_table(x,upr,fl_tab,vf1,rf2,c)
+#else
+#define ls_box(x,c)     no_table(x,s_box,vf1,rf2,c)
+#endif
+
+#if defined(FOUR_IM_TABLES)
+#define inv_mcol(x)     four_tables(x,im_tab,vf1,rf1,0)
+#elif defined(ONE_IM_TABLE)
+#define inv_mcol(x)     one_table(x,upr,im_tab,vf1,rf1,0)
+#else
+#define inv_mcol(x) \
+    (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \
+    f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1))
+#endif
+
+// Subroutine to set the block size (if variable) in bytes, legal
+// values being 16, 24 and 32.
+
+#if defined(AES_BLOCK_SIZE)
+#define nc   (AES_BLOCK_SIZE / 4)
+#else
+#define nc   (cx->aes_Ncol)
+
+void aes_set_blk(aes_context *cx, int n_bytes)
+{
+#if !defined(FIXED_TABLES)
+    if(!tab_gen) { gen_tabs(); tab_gen = 1; }
+#endif
+
+    switch(n_bytes) {
+    case 32:        /* bytes */
+    case 256:       /* bits */
+        nc = 8;
+        break;
+    case 24:        /* bytes */
+    case 192:       /* bits */
+        nc = 6;
+        break;
+    case 16:        /* bytes */
+    case 128:       /* bits */
+    default:
+        nc = 4;
+        break;
+    }
+}
+
+#endif
+
+// Initialise the key schedule from the user supplied key. The key
+// length is now specified in bytes - 16, 24 or 32 as appropriate.
+// This corresponds to bit lengths of 128, 192 and 256 bits, and
+// to Nk values of 4, 6 and 8 respectively.
+
+#define mx(t,f) (*t++ = inv_mcol(*f),f++)
+#define cp(t,f) *t++ = *f++
+
+#if   AES_BLOCK_SIZE == 16
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s)
+#elif AES_BLOCK_SIZE == 24
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+                    cp(d,s); cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+                    mx(d,s); mx(d,s)
+#elif AES_BLOCK_SIZE == 32
+#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+                    cp(d,s); cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+                    mx(d,s); mx(d,s); mx(d,s); mx(d,s)
+#else
+
+#define cpy(d,s) \
+switch(nc) \
+{   case 8: cp(d,s); cp(d,s); \
+    case 6: cp(d,s); cp(d,s); \
+    case 4: cp(d,s); cp(d,s); \
+            cp(d,s); cp(d,s); \
+}
+
+#define mix(d,s) \
+switch(nc) \
+{   case 8: mx(d,s); mx(d,s); \
+    case 6: mx(d,s); mx(d,s); \
+    case 4: mx(d,s); mx(d,s); \
+            mx(d,s); mx(d,s); \
+}
+
+#endif
+
+void aes_set_key(aes_context *cx, const unsigned char in_key[], int n_bytes, const int f)
+{   u_int32_t    *kf, *kt, rci;
+
+#if !defined(FIXED_TABLES)
+    if(!tab_gen) { gen_tabs(); tab_gen = 1; }
+#endif
+
+    switch(n_bytes) {
+    case 32:                    /* bytes */
+    case 256:                   /* bits */
+        cx->aes_Nkey = 8;
+        break;
+    case 24:                    /* bytes */
+    case 192:                   /* bits */
+        cx->aes_Nkey = 6;
+        break;
+    case 16:                    /* bytes */
+    case 128:                   /* bits */
+    default:
+        cx->aes_Nkey = 4;
+        break;
+    }
+
+    cx->aes_Nrnd = (cx->aes_Nkey > nc ? cx->aes_Nkey : nc) + 6; 
+
+    cx->aes_e_key[0] = const_word_in(in_key     );
+    cx->aes_e_key[1] = const_word_in(in_key +  4);
+    cx->aes_e_key[2] = const_word_in(in_key +  8);
+    cx->aes_e_key[3] = const_word_in(in_key + 12);
+
+    kf = cx->aes_e_key; 
+    kt = kf + nc * (cx->aes_Nrnd + 1) - cx->aes_Nkey; 
+    rci = 0;
+
+    switch(cx->aes_Nkey)
+    {
+    case 4: do
+            {   kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++];
+                kf[5] = kf[1] ^ kf[4];
+                kf[6] = kf[2] ^ kf[5];
+                kf[7] = kf[3] ^ kf[6];
+                kf += 4;
+            }
+            while(kf < kt);
+            break;
+
+    case 6: cx->aes_e_key[4] = const_word_in(in_key + 16);
+            cx->aes_e_key[5] = const_word_in(in_key + 20);
+            do
+            {   kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++];
+                kf[ 7] = kf[1] ^ kf[ 6];
+                kf[ 8] = kf[2] ^ kf[ 7];
+                kf[ 9] = kf[3] ^ kf[ 8];
+                kf[10] = kf[4] ^ kf[ 9];
+                kf[11] = kf[5] ^ kf[10];
+                kf += 6;
+            }
+            while(kf < kt);
+            break;
+
+    case 8: cx->aes_e_key[4] = const_word_in(in_key + 16);
+            cx->aes_e_key[5] = const_word_in(in_key + 20);
+            cx->aes_e_key[6] = const_word_in(in_key + 24);
+            cx->aes_e_key[7] = const_word_in(in_key + 28);
+            do
+            {   kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++];
+                kf[ 9] = kf[1] ^ kf[ 8];
+                kf[10] = kf[2] ^ kf[ 9];
+                kf[11] = kf[3] ^ kf[10];
+                kf[12] = kf[4] ^ ls_box(kf[11],0);
+                kf[13] = kf[5] ^ kf[12];
+                kf[14] = kf[6] ^ kf[13];
+                kf[15] = kf[7] ^ kf[14];
+                kf += 8;
+            }
+            while (kf < kt);
+            break;
+    }
+
+    if(!f)
+    {   u_int32_t    i;
+        
+        kt = cx->aes_d_key + nc * cx->aes_Nrnd;
+        kf = cx->aes_e_key;
+        
+        cpy(kt, kf); kt -= 2 * nc;
+
+        for(i = 1; i < cx->aes_Nrnd; ++i)
+        { 
+#if defined(ONE_TABLE) || defined(FOUR_TABLES)
+#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES)
+            u_int32_t    f2, f4, f8, f9;
+#endif
+            mix(kt, kf);
+#else
+            cpy(kt, kf);
+#endif
+            kt -= 2 * nc;
+        }
+        
+        cpy(kt, kf);
+    }
+}
+
+// y = output word, x = input word, r = row, c = column
+// for r = 0, 1, 2 and 3 = column accessed for row r
+
+#if defined(ARRAYS)
+#define s(x,c) x[c]
+#else
+#define s(x,c) x##c
+#endif
+
+// I am grateful to Frank Yellin for the following constructions
+// which, given the column (c) of the output state variable that
+// is being computed, return the input state variables which are
+// needed for each row (r) of the state
+
+// For the fixed block size options, compilers reduce these two 
+// expressions to fixed variable references. For variable block 
+// size code conditional clauses will sometimes be returned
+
+#define unused  77  // Sunset Strip
+
+#define fwd_var(x,r,c) \
+ ( r==0 ?			\
+    ( c==0 ? s(x,0) \
+    : c==1 ? s(x,1) \
+    : c==2 ? s(x,2) \
+    : c==3 ? s(x,3) \
+    : c==4 ? s(x,4) \
+    : c==5 ? s(x,5) \
+    : c==6 ? s(x,6) \
+    : s(x,7))		\
+ : r==1 ?			\
+    ( c==0 ? s(x,1) \
+    : c==1 ? s(x,2) \
+    : c==2 ? s(x,3) \
+    : c==3 ? nc==4 ? s(x,0) : s(x,4) \
+    : c==4 ? s(x,5) \
+    : c==5 ? nc==8 ? s(x,6) : s(x,0) \
+    : c==6 ? s(x,7) \
+    : s(x,0))		\
+ : r==2 ?			\
+    ( c==0 ? nc==8 ? s(x,3) : s(x,2) \
+    : c==1 ? nc==8 ? s(x,4) : s(x,3) \
+    : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
+    : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
+    : c==4 ? nc==8 ? s(x,7) : s(x,0) \
+    : c==5 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==6 ? s(x,1) \
+    : s(x,2))		\
+ :					\
+    ( c==0 ? nc==8 ? s(x,4) : s(x,3) \
+    : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
+    : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
+    : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \
+    : c==4 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==6 ? s(x,2) \
+    : s(x,3)))
+
+#define inv_var(x,r,c) \
+ ( r==0 ?			\
+    ( c==0 ? s(x,0) \
+    : c==1 ? s(x,1) \
+    : c==2 ? s(x,2) \
+    : c==3 ? s(x,3) \
+    : c==4 ? s(x,4) \
+    : c==5 ? s(x,5) \
+    : c==6 ? s(x,6) \
+    : s(x,7))		\
+ : r==1 ?			\
+    ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \
+    : c==1 ? s(x,0) \
+    : c==2 ? s(x,1) \
+    : c==3 ? s(x,2) \
+    : c==4 ? s(x,3) \
+    : c==5 ? s(x,4) \
+    : c==6 ? s(x,5) \
+    : s(x,6))		\
+ : r==2 ?			\
+    ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
+    : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
+    : c==2 ? nc==8 ? s(x,7) : s(x,0) \
+    : c==3 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==4 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==5 ? nc==8 ? s(x,2) : s(x,3) \
+    : c==6 ? s(x,3) \
+    : s(x,4))		\
+ :					\
+    ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \
+    : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
+    : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
+    : c==3 ? nc==8 ? s(x,7) : s(x,0) \
+    : c==4 ? nc==8 ? s(x,0) : s(x,1) \
+    : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+    : c==6 ? s(x,2) \
+    : s(x,3)))
+
+#define si(y,x,k,c) s(y,c) = const_word_in(x + 4 * c) ^ k[c]
+#define so(y,x,c)   word_out(y + 4 * c, s(x,c))
+
+#if defined(FOUR_TABLES)
+#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c)
+#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c)
+#elif defined(ONE_TABLE)
+#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c)
+#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c)
+#else
+#define fwd_rnd(y,x,k,c)    s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c]
+#define inv_rnd(y,x,k,c)    s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c])
+#endif
+
+#if defined(FOUR_LR_TABLES)
+#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c)
+#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c)
+#elif defined(ONE_LR_TABLE)
+#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c)
+#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c)
+#else
+#define fwd_lrnd(y,x,k,c)   s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c]
+#define inv_lrnd(y,x,k,c)   s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]
+#endif
+
+#if AES_BLOCK_SIZE == 16
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[4],y[4]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
+// the following defines prevent the compiler requiring the declaration
+// of generated but unused variables in the fwd_var and inv_var macros
+#define b04 unused
+#define b05 unused
+#define b06 unused
+#define b07 unused
+#define b14 unused
+#define b15 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
+
+#elif AES_BLOCK_SIZE == 24
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[6],y[6]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5, \
+                        y##0,y##1,y##2,y##3,y##4,y##5
+#define b06 unused
+#define b07 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
+                        s(y,4) = s(x,4); s(y,5) = s(x,5);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
+                        si(y,x,k,3); si(y,x,k,4); si(y,x,k,5)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); \
+                        so(y,x,3); so(y,x,4); so(y,x,5)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
+                        rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5)
+#else
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[8],y[8]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \
+                        y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7
+#endif
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
+                        s(y,4) = s(x,4); s(y,5) = s(x,5); \
+                        s(y,6) = s(x,6); s(y,7) = s(x,7);
+
+#if AES_BLOCK_SIZE == 32
+
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \
+                        si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \
+                        so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \
+                        rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7)
+#else
+
+#define state_in(y,x,k) \
+switch(nc) \
+{   case 8: si(y,x,k,7); si(y,x,k,6); \
+    case 6: si(y,x,k,5); si(y,x,k,4); \
+    case 4: si(y,x,k,3); si(y,x,k,2); \
+            si(y,x,k,1); si(y,x,k,0); \
+}
+
+#define state_out(y,x) \
+switch(nc) \
+{   case 8: so(y,x,7); so(y,x,6); \
+    case 6: so(y,x,5); so(y,x,4); \
+    case 4: so(y,x,3); so(y,x,2); \
+            so(y,x,1); so(y,x,0); \
+}
+
+#if defined(FAST_VARIABLE)
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
+            rm(y,x,k,5); rm(y,x,k,4); \
+            rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+    case 6: rm(y,x,k,5); rm(y,x,k,4); \
+            rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+    case 4: rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+            break; \
+}
+#else
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
+    case 6: rm(y,x,k,5); rm(y,x,k,4); \
+    case 4: rm(y,x,k,3); rm(y,x,k,2); \
+            rm(y,x,k,1); rm(y,x,k,0); \
+}
+
+#endif
+
+#endif
+#endif
+
+void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
+{   u_int32_t        locals(b0, b1);
+    const u_int32_t  *kp = cx->aes_e_key;
+
+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
+    u_int32_t        f2;
+#endif
+
+    state_in(b0, in_blk, kp); kp += nc;
+
+#if defined(UNROLL)
+
+    switch(cx->aes_Nrnd)
+    {
+    case 14:    round(fwd_rnd,  b1, b0, kp         ); 
+                round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+    case 12:    round(fwd_rnd,  b1, b0, kp         ); 
+                round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+    case 10:    round(fwd_rnd,  b1, b0, kp         );             
+                round(fwd_rnd,  b0, b1, kp +     nc);
+                round(fwd_rnd,  b1, b0, kp + 2 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 3 * nc);
+                round(fwd_rnd,  b1, b0, kp + 4 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 5 * nc);
+                round(fwd_rnd,  b1, b0, kp + 6 * nc); 
+                round(fwd_rnd,  b0, b1, kp + 7 * nc);
+                round(fwd_rnd,  b1, b0, kp + 8 * nc);
+                round(fwd_lrnd, b0, b1, kp + 9 * nc);
+    }
+
+#elif defined(PARTIAL_UNROLL)
+    {   u_int32_t    rnd;
+
+        for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd)
+        {
+            round(fwd_rnd, b1, b0, kp); 
+            round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc;
+        }
+
+        round(fwd_rnd,  b1, b0, kp);
+        round(fwd_lrnd, b0, b1, kp + nc);
+    }
+#else
+    {   u_int32_t    rnd;
+
+        for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd)
+        {
+            round(fwd_rnd, b1, b0, kp); 
+            l_copy(b0, b1); kp += nc;
+        }
+
+        round(fwd_lrnd, b0, b1, kp);
+    }
+#endif
+
+    state_out(out_blk, b0);
+}
+
+void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
+{   u_int32_t        locals(b0, b1);
+    const u_int32_t  *kp = cx->aes_d_key;
+
+#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
+    u_int32_t        f2, f4, f8, f9; 
+#endif
+
+    state_in(b0, in_blk, kp); kp += nc;
+
+#if defined(UNROLL)
+
+    switch(cx->aes_Nrnd)
+    {
+    case 14:    round(inv_rnd,  b1, b0, kp         );
+                round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+    case 12:    round(inv_rnd,  b1, b0, kp         );
+                round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+    case 10:    round(inv_rnd,  b1, b0, kp         );             
+                round(inv_rnd,  b0, b1, kp +     nc);
+                round(inv_rnd,  b1, b0, kp + 2 * nc); 
+                round(inv_rnd,  b0, b1, kp + 3 * nc);
+                round(inv_rnd,  b1, b0, kp + 4 * nc); 
+                round(inv_rnd,  b0, b1, kp + 5 * nc);
+                round(inv_rnd,  b1, b0, kp + 6 * nc); 
+                round(inv_rnd,  b0, b1, kp + 7 * nc);
+                round(inv_rnd,  b1, b0, kp + 8 * nc);
+                round(inv_lrnd, b0, b1, kp + 9 * nc);
+    }
+
+#elif defined(PARTIAL_UNROLL)
+    {   u_int32_t    rnd;
+
+        for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd)
+        {
+            round(inv_rnd, b1, b0, kp); 
+            round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc;
+        }
+
+        round(inv_rnd,  b1, b0, kp);
+        round(inv_lrnd, b0, b1, kp + nc);
+    }
+#else
+    {   u_int32_t    rnd;
+
+        for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd)
+        {
+            round(inv_rnd, b1, b0, kp); 
+            l_copy(b0, b1); kp += nc;
+        }
+
+        round(inv_lrnd, b0, b1, kp);
+    }
+#endif
+
+    state_out(out_blk, b0);
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/aes.h linux-patched/net/ipsec/libcrypto/libaes/aes.h
--- linux/net/ipsec/libcrypto/libaes/aes.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/aes.h	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,97 @@
+// I retain copyright in this code but I encourage its free use provided
+// that I don't carry any responsibility for the results. I am especially 
+// happy to see it used in free and open source software. If you do use 
+// it I would appreciate an acknowledgement of its origin in the code or
+// the product that results and I would also appreciate knowing a little
+// about the use to which it is being put. I am grateful to Frank Yellin
+// for some ideas that are used in this implementation.
+//
+// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001.
+//
+// This is an implementation of the AES encryption algorithm (Rijndael)
+// designed by Joan Daemen and Vincent Rijmen. This version is designed
+// to provide both fixed and dynamic block and key lengths and can also 
+// run with either big or little endian internal byte order (see aes.h). 
+// It inputs block and key lengths in bytes with the legal values being 
+// 16, 24 and 32.
+
+/*
+ * Modified by Jari Ruusu,  May 1 2001
+ *  - Fixed some compile warnings, code was ok but gcc warned anyway.
+ *  - Changed basic types: byte -> unsigned char, word -> u_int32_t
+ *  - Major name space cleanup: Names visible to outside now begin
+ *    with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c
+ *  - Removed C++ and DLL support as part of name space cleanup.
+ *  - Eliminated unnecessary recomputation of tables. (actual bug fix)
+ *  - Merged precomputed constant tables to aes.c file.
+ *  - Removed data alignment restrictions for portability reasons.
+ *  - Made block and key lengths accept bit count (128/192/256)
+ *    as well byte count (16/24/32).
+ *  - Removed all error checks. This change also eliminated the need
+ *    to preinitialize the context struct to zero.
+ *  - Removed some totally unused constants.
+ */
+
+#ifndef _AES_H
+#define _AES_H
+
+#if defined(__linux__) && defined(__KERNEL__)
+#  include <linux/types.h>
+#else 
+#  include <sys/types.h>
+#endif
+
+// CONFIGURATION OPTIONS (see also aes.c)
+//
+// Define AES_BLOCK_SIZE to set the cipher block size (16, 24 or 32) or
+// leave this undefined for dynamically variable block size (this will
+// result in much slower code).
+// IMPORTANT NOTE: AES_BLOCK_SIZE is in BYTES (16, 24, 32 or undefined). If
+// left undefined a slower version providing variable block length is compiled
+
+#define AES_BLOCK_SIZE  16
+
+// The number of key schedule words for different block and key lengths
+// allowing for method of computation which requires the length to be a
+// multiple of the key length
+//
+// Nk =       4   6   8
+//        -------------
+// Nb = 4 |  60  60  64
+//      6 |  96  90  96
+//      8 | 120 120 120
+
+#if !defined(AES_BLOCK_SIZE) || (AES_BLOCK_SIZE == 32)
+#define AES_KS_LENGTH   120
+#define AES_RC_LENGTH    29
+#else
+#define AES_KS_LENGTH   4 * AES_BLOCK_SIZE
+#define AES_RC_LENGTH   (9 * AES_BLOCK_SIZE) / 8 - 8
+#endif
+
+typedef struct
+{
+    u_int32_t    aes_Nkey;      // the number of words in the key input block
+    u_int32_t    aes_Nrnd;      // the number of cipher rounds
+    u_int32_t    aes_e_key[AES_KS_LENGTH];   // the encryption key schedule
+    u_int32_t    aes_d_key[AES_KS_LENGTH];   // the decryption key schedule
+#if !defined(AES_BLOCK_SIZE)
+    u_int32_t    aes_Ncol;      // the number of columns in the cipher state
+#endif
+} aes_context;
+
+// THE CIPHER INTERFACE
+
+#if !defined(AES_BLOCK_SIZE)
+extern void aes_set_blk(aes_context *, const int);
+#endif
+extern void aes_set_key(aes_context *, const unsigned char [], const int, const int);
+extern void aes_encrypt(const aes_context *, const unsigned char [], unsigned char []);
+extern void aes_decrypt(const aes_context *, const unsigned char [], unsigned char []);
+
+// The block length inputs to aes_set_block and aes_set_key are in numbers
+// of bytes or bits.  The calls to subroutines must be made in the above
+// order but multiple calls can be made without repeating earlier calls
+// if their parameters have not changed.
+
+#endif  // _AES_H
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/aes_cbc.c linux-patched/net/ipsec/libcrypto/libaes/aes_cbc.c
--- linux/net/ipsec/libcrypto/libaes/aes_cbc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/aes_cbc.c	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,13 @@
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#include "aes_cbc.h"
+#include "cbc_generic.h"
+/* returns bool success */
+int AES_set_key(aes_context *aes_ctx, const u_int8_t *key, int keysize) {
+	aes_set_key(aes_ctx, key, keysize, 0);
+	return 1;	
+}
+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/aes_cbc.h linux-patched/net/ipsec/libcrypto/libaes/aes_cbc.h
--- linux/net/ipsec/libcrypto/libaes/aes_cbc.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/aes_cbc.h	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,4 @@
+/* Glue header */
+#include "aes.h"
+int AES_set_key(aes_context *aes_ctx, const u_int8_t * key, int keysize);
+int AES_cbc_encrypt(aes_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/aes_xcbc_mac.c linux-patched/net/ipsec/libcrypto/libaes/aes_xcbc_mac.c
--- linux/net/ipsec/libcrypto/libaes/aes_xcbc_mac.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/aes_xcbc_mac.c	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,67 @@
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/kernel.h>
+#define DEBUG(x) 
+#else
+#include <stdio.h>
+#include <sys/types.h>
+#define DEBUG(x) x
+#endif
+
+#include "aes.h"
+#include "aes_xcbc_mac.h"
+
+int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen)
+{
+	int ret=1;
+	aes_block kn[3] = { 
+		{ 0x01010101, 0x01010101, 0x01010101, 0x01010101 },
+		{ 0x02020202, 0x02020202, 0x02020202, 0x02020202 },
+		{ 0x03030303, 0x03030303, 0x03030303, 0x03030303 },
+	};
+	aes_set_key(&ctxm->ctx_k1, key, keylen, 0);
+	aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[0], (u_int8_t *) kn[0]);
+	aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[1], (u_int8_t *) ctxm->k2);
+	aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[2], (u_int8_t *) ctxm->k3);
+	aes_set_key(&ctxm->ctx_k1, (u_int8_t *) kn[0], 16, 0);
+	return ret;
+}
+static void do_pad_xor(u_int8_t *out, const u_int8_t *in, int len) {
+	int pos=0;
+	for (pos=1; pos <= 16; pos++, in++, out++) {
+		if (pos <= len)
+			*out ^= *in;
+		if (pos > len) {
+			DEBUG(printf("put 0x80 at pos=%d\n", pos));
+			*out ^= 0x80;
+			break;
+		}
+	}
+}
+static void xor_block(aes_block res, const aes_block op) {
+	res[0] ^= op[0];
+	res[1] ^= op[1];
+	res[2] ^= op[2];
+	res[3] ^= op[3];
+}
+int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]) {
+	int ret=ilen;
+	u_int32_t out[4] = { 0, 0, 0, 0 }; 
+	for (; ilen > 16 ; ilen-=16) {
+		xor_block(out, (const u_int32_t*) &in[0]);
+		aes_encrypt(&ctxm->ctx_k1, in, (u_int8_t *)&out[0]);
+		in+=16; 
+	}
+	do_pad_xor((u_int8_t *)&out, in, ilen);
+	if (ilen==16) {
+		DEBUG(printf("using k3\n"));
+		xor_block(out, ctxm->k3);
+	}
+	else 
+	{
+		DEBUG(printf("using k2\n"));
+		xor_block(out, ctxm->k2);
+	}
+	aes_encrypt(&ctxm->ctx_k1, (u_int8_t *)out, hash);
+	return ret;
+} 
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/aes_xcbc_mac.h linux-patched/net/ipsec/libcrypto/libaes/aes_xcbc_mac.h
--- linux/net/ipsec/libcrypto/libaes/aes_xcbc_mac.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/aes_xcbc_mac.h	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,12 @@
+#ifndef _AES_XCBC_MAC_H
+#define _AES_XCBC_MAC_H
+
+typedef u_int32_t aes_block[4];
+typedef struct {
+	aes_context ctx_k1;
+	aes_block k2;
+	aes_block k3;
+} aes_context_mac;
+int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen);
+int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]);
+#endif /* _AES_XCBC_MAC_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/asm/aes-i586.S linux-patched/net/ipsec/libcrypto/libaes/asm/aes-i586.S
--- linux/net/ipsec/libcrypto/libaes/asm/aes-i586.S	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/asm/aes-i586.S	Thu Sep  5 04:42:26 2002
@@ -0,0 +1,892 @@
+//
+// Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+// All rights reserved.
+//
+// TERMS
+//
+//  Redistribution and use in source and binary forms, with or without
+//  modification, are permitted subject to the following conditions:
+//
+//  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. The copyright holder's name must not be used to endorse or promote
+//     any products derived from this software without his specific prior
+//     written permission.
+//
+//  This software is provided 'as is' with no express or implied warranties
+//  of correctness or fitness for purpose.
+
+// Modified by Jari Ruusu,  December 24 2001
+//  - Converted syntax to GNU CPP/assembler syntax
+//  - C programming interface converted back to "old" API
+//  - Minor portability cleanups and speed optimizations
+
+// An AES (Rijndael) implementation for the Pentium. This version only
+// implements the standard AES block length (128 bits, 16 bytes). This code
+// does not preserve the eax, ecx or edx registers or the artihmetic status
+// flags. However, the ebx, esi, edi, and ebp registers are preserved across
+// calls.
+
+// void aes_set_key(aes_context *cx, const unsigned char key[], const int key_len, const int f)
+// void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
+// void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
+
+#if defined(USE_UNDERLINE)
+# define aes_set_key _aes_set_key
+# define aes_encrypt _aes_encrypt
+# define aes_decrypt _aes_decrypt
+#endif
+#if !defined(ALIGN32BYTES)
+# define ALIGN32BYTES 32
+#endif
+
+	.file	"aes-i586.S"
+	.globl	aes_set_key
+	.globl	aes_encrypt
+	.globl	aes_decrypt
+
+#define tlen	1024	// length of each of 4 'xor' arrays (256 32-bit words)
+
+// offsets to parameters with one register pushed onto stack
+
+#define ctx	8	// AES context structure
+#define in_blk	12	// input byte array address parameter
+#define out_blk	16	// output byte array address parameter
+
+// offsets in context structure
+
+#define nkey	0	// key length, size 4
+#define nrnd	4	// number of rounds, size 4
+#define ekey	8	// encryption key schedule base address, size 256
+#define dkey	264	// decryption key schedule base address, size 256
+
+// This macro performs a forward encryption cycle. It is entered with
+// the first previous round column values in %eax, %ebx, %esi and %edi and
+// exits with the final values in the same registers.
+
+#define fwd_rnd(p1,p2)			 \
+	mov	%ebx,(%esp)		;\
+	movzbl	%al,%edx		;\
+	mov	%eax,%ecx		;\
+	mov	p2(%ebp),%eax		;\
+	mov	%edi,4(%esp)		;\
+	mov	p2+12(%ebp),%edi	;\
+	xor	p1(,%edx,4),%eax	;\
+	movzbl	%ch,%edx		;\
+	shr	$16,%ecx		;\
+	mov	p2+4(%ebp),%ebx		;\
+	xor	p1+tlen(,%edx,4),%edi	;\
+	movzbl	%cl,%edx		;\
+	movzbl	%ch,%ecx		;\
+	xor	p1+3*tlen(,%ecx,4),%ebx	;\
+	mov	%esi,%ecx		;\
+	mov	p1+2*tlen(,%edx,4),%esi	;\
+	movzbl	%cl,%edx		;\
+	xor	p1(,%edx,4),%esi	;\
+	movzbl	%ch,%edx		;\
+	shr	$16,%ecx		;\
+	xor	p1+tlen(,%edx,4),%ebx	;\
+	movzbl	%cl,%edx		;\
+	movzbl	%ch,%ecx		;\
+	xor	p1+2*tlen(,%edx,4),%eax	;\
+	mov	(%esp),%edx		;\
+	xor	p1+3*tlen(,%ecx,4),%edi ;\
+	movzbl	%dl,%ecx		;\
+	xor	p2+8(%ebp),%esi		;\
+	xor	p1(,%ecx,4),%ebx	;\
+	movzbl	%dh,%ecx		;\
+	shr	$16,%edx		;\
+	xor	p1+tlen(,%ecx,4),%eax	;\
+	movzbl	%dl,%ecx		;\
+	movzbl	%dh,%edx		;\
+	xor	p1+2*tlen(,%ecx,4),%edi	;\
+	mov	4(%esp),%ecx		;\
+	xor	p1+3*tlen(,%edx,4),%esi ;\
+	movzbl	%cl,%edx		;\
+	xor	p1(,%edx,4),%edi	;\
+	movzbl	%ch,%edx		;\
+	shr	$16,%ecx		;\
+	xor	p1+tlen(,%edx,4),%esi	;\
+	movzbl	%cl,%edx		;\
+	movzbl	%ch,%ecx		;\
+	xor	p1+2*tlen(,%edx,4),%ebx	;\
+	xor	p1+3*tlen(,%ecx,4),%eax
+
+// This macro performs an inverse encryption cycle. It is entered with
+// the first previous round column values in %eax, %ebx, %esi and %edi and
+// exits with the final values in the same registers.
+
+#define inv_rnd(p1,p2)			 \
+	movzbl	%al,%edx		;\
+	mov	%ebx,(%esp)		;\
+	mov	%eax,%ecx		;\
+	mov	p2(%ebp),%eax		;\
+	mov	%edi,4(%esp)		;\
+	mov	p2+4(%ebp),%ebx		;\
+	xor	p1(,%edx,4),%eax	;\
+	movzbl	%ch,%edx		;\
+	shr	$16,%ecx		;\
+	mov	p2+12(%ebp),%edi	;\
+	xor	p1+tlen(,%edx,4),%ebx	;\
+	movzbl	%cl,%edx		;\
+	movzbl	%ch,%ecx		;\
+	xor	p1+3*tlen(,%ecx,4),%edi	;\
+	mov	%esi,%ecx		;\
+	mov	p1+2*tlen(,%edx,4),%esi	;\
+	movzbl	%cl,%edx		;\
+	xor	p1(,%edx,4),%esi	;\
+	movzbl	%ch,%edx		;\
+	shr	$16,%ecx		;\
+	xor	p1+tlen(,%edx,4),%edi	;\
+	movzbl	%cl,%edx		;\
+	movzbl	%ch,%ecx		;\
+	xor	p1+2*tlen(,%edx,4),%eax	;\
+	mov	(%esp),%edx		;\
+	xor	p1+3*tlen(,%ecx,4),%ebx ;\
+	movzbl	%dl,%ecx		;\
+	xor	p2+8(%ebp),%esi		;\
+	xor	p1(,%ecx,4),%ebx	;\
+	movzbl	%dh,%ecx		;\
+	shr	$16,%edx		;\
+	xor	p1+tlen(,%ecx,4),%esi	;\
+	movzbl	%dl,%ecx		;\
+	movzbl	%dh,%edx		;\
+	xor	p1+2*tlen(,%ecx,4),%edi	;\
+	mov	4(%esp),%ecx		;\
+	xor	p1+3*tlen(,%edx,4),%eax ;\
+	movzbl	%cl,%edx		;\
+	xor	p1(,%edx,4),%edi	;\
+	movzbl	%ch,%edx		;\
+	shr	$16,%ecx		;\
+	xor	p1+tlen(,%edx,4),%eax	;\
+	movzbl	%cl,%edx		;\
+	movzbl	%ch,%ecx		;\
+	xor	p1+2*tlen(,%edx,4),%ebx	;\
+	xor	p1+3*tlen(,%ecx,4),%esi
+
+// AES (Rijndael) Encryption Subroutine
+
+	.text
+	.align	ALIGN32BYTES
+aes_encrypt:
+	push	%ebp
+	mov	ctx(%esp),%ebp		// pointer to context
+	mov	in_blk(%esp),%ecx
+	push	%ebx
+	push	%esi
+	push	%edi
+	mov	nrnd(%ebp),%edx		// number of rounds
+	lea	ekey+16(%ebp),%ebp	// key pointer
+
+// input four columns and xor in first round key
+
+	mov	(%ecx),%eax
+	mov	4(%ecx),%ebx
+	mov	8(%ecx),%esi
+	mov	12(%ecx),%edi
+	xor	-16(%ebp),%eax
+	xor	-12(%ebp),%ebx
+	xor	-8(%ebp),%esi
+	xor	-4(%ebp),%edi
+
+	sub	$8,%esp			// space for register saves on stack
+
+	sub	$10,%edx
+	je	aes_15
+	add	$32,%ebp
+	sub	$2,%edx
+	je	aes_13
+	add	$32,%ebp
+
+	fwd_rnd(aes_ft_tab,-64)		// 14 rounds for 256-bit key
+	fwd_rnd(aes_ft_tab,-48)
+aes_13:	fwd_rnd(aes_ft_tab,-32)		// 12 rounds for 192-bit key
+	fwd_rnd(aes_ft_tab,-16)
+aes_15:	fwd_rnd(aes_ft_tab,0)		// 10 rounds for 128-bit key
+	fwd_rnd(aes_ft_tab,16)
+	fwd_rnd(aes_ft_tab,32)
+	fwd_rnd(aes_ft_tab,48)
+	fwd_rnd(aes_ft_tab,64)
+	fwd_rnd(aes_ft_tab,80)
+	fwd_rnd(aes_ft_tab,96)
+	fwd_rnd(aes_ft_tab,112)
+	fwd_rnd(aes_ft_tab,128)
+	fwd_rnd(aes_fl_tab,144)		// last round uses a different table
+
+// move final values to the output array.
+
+	mov	out_blk+20(%esp),%ebp
+	add	$8,%esp
+	mov	%eax,(%ebp)
+	mov	%ebx,4(%ebp)
+	mov	%esi,8(%ebp)
+	mov	%edi,12(%ebp)
+	pop	%edi
+	pop	%esi
+	pop	%ebx
+	pop	%ebp
+	ret
+
+
+// AES (Rijndael) Decryption Subroutine
+
+	.align	ALIGN32BYTES
+aes_decrypt:
+	push	%ebp
+	mov	ctx(%esp),%ebp		// pointer to context
+	mov	in_blk(%esp),%ecx
+	push	%ebx
+	push	%esi
+	push	%edi
+	mov	nrnd(%ebp),%edx		// number of rounds
+	lea	dkey+16(%ebp),%ebp	// key pointer
+
+// input four columns and xor in first round key
+
+	mov	(%ecx),%eax
+	mov	4(%ecx),%ebx
+	mov	8(%ecx),%esi
+	mov	12(%ecx),%edi
+	xor	-16(%ebp),%eax
+	xor	-12(%ebp),%ebx
+	xor	-8(%ebp),%esi
+	xor	-4(%ebp),%edi
+
+	sub	$8,%esp			// space for register saves on stack
+
+	sub	$10,%edx
+	je	aes_25
+	add	$32,%ebp
+	sub	$2,%edx
+	je	aes_23
+	add	$32,%ebp
+
+	inv_rnd(aes_it_tab,-64)		// 14 rounds for 256-bit key
+	inv_rnd(aes_it_tab,-48)
+aes_23:	inv_rnd(aes_it_tab,-32)		// 12 rounds for 192-bit key
+	inv_rnd(aes_it_tab,-16)
+aes_25:	inv_rnd(aes_it_tab,0)		// 10 rounds for 128-bit key
+	inv_rnd(aes_it_tab,16)
+	inv_rnd(aes_it_tab,32)
+	inv_rnd(aes_it_tab,48)
+	inv_rnd(aes_it_tab,64)
+	inv_rnd(aes_it_tab,80)
+	inv_rnd(aes_it_tab,96)
+	inv_rnd(aes_it_tab,112)
+	inv_rnd(aes_it_tab,128)
+	inv_rnd(aes_il_tab,144)		// last round uses a different table
+
+// move final values to the output array.
+
+	mov	out_blk+20(%esp),%ebp
+	add	$8,%esp
+	mov	%eax,(%ebp)
+	mov	%ebx,4(%ebp)
+	mov	%esi,8(%ebp)
+	mov	%edi,12(%ebp)
+	pop	%edi
+	pop	%esi
+	pop	%ebx
+	pop	%ebp
+	ret
+
+// AES (Rijndael) Key Schedule Subroutine
+
+// input/output parameters
+
+#define aes_cx	12	// AES context
+#define in_key	16	// key input array address
+#define key_ln	20	// key length, bytes (16,24,32) or bits (128,192,256)
+#define ed_flg	24	// 0=create both encr/decr keys, 1=create encr key only
+
+// offsets for locals
+
+#define cnt	-4
+#define kpf	-8
+#define slen	8
+
+// This macro performs a column mixing operation on an input 32-bit
+// word to give a 32-bit result. It uses each of the 4 bytes in the
+// the input column to index 4 different tables of 256 32-bit words
+// that are xored together to form the output value.
+
+#define mix_col(p1)			 \
+	movzbl	%bl,%ecx		;\
+	mov	p1(,%ecx,4),%eax	;\
+	movzbl	%bh,%ecx		;\
+	ror	$16,%ebx		;\
+	xor	p1+tlen(,%ecx,4),%eax	;\
+	movzbl	%bl,%ecx		;\
+	xor	p1+2*tlen(,%ecx,4),%eax	;\
+	movzbl	%bh,%ecx		;\
+	xor	p1+3*tlen(,%ecx,4),%eax
+
+// Key Schedule Macros
+
+#define ksc4(p1)			 \
+	rol	$24,%ebx		;\
+	mix_col(aes_fl_tab)		;\
+	ror	$8,%ebx			;\
+	xor	4*p1+aes_rcon_tab,%eax	;\
+	xor	%eax,%esi		;\
+	xor	%esi,%ebp		;\
+	mov	%esi,16*p1(%edi)	;\
+	mov	%ebp,16*p1+4(%edi)	;\
+	xor	%ebp,%edx		;\
+	xor	%edx,%ebx		;\
+	mov	%edx,16*p1+8(%edi)	;\
+	mov	%ebx,16*p1+12(%edi)
+
+#define ksc6(p1)			 \
+	rol	$24,%ebx		;\
+	mix_col(aes_fl_tab)		;\
+	ror	$8,%ebx			;\
+	xor	4*p1+aes_rcon_tab,%eax	;\
+	xor	24*p1-24(%edi),%eax	;\
+	mov	%eax,24*p1(%edi)	;\
+	xor	24*p1-20(%edi),%eax	;\
+	mov	%eax,24*p1+4(%edi)	;\
+	xor	%eax,%esi		;\
+	xor	%esi,%ebp		;\
+	mov	%esi,24*p1+8(%edi)	;\
+	mov	%ebp,24*p1+12(%edi)	;\
+	xor	%ebp,%edx		;\
+	xor	%edx,%ebx		;\
+	mov	%edx,24*p1+16(%edi)	;\
+	mov	%ebx,24*p1+20(%edi)
+
+#define ksc8(p1)			 \
+	rol	$24,%ebx		;\
+	mix_col(aes_fl_tab)		;\
+	ror	$8,%ebx			;\
+	xor	4*p1+aes_rcon_tab,%eax	;\
+	xor	32*p1-32(%edi),%eax	;\
+	mov	%eax,32*p1(%edi)	;\
+	xor	32*p1-28(%edi),%eax	;\
+	mov	%eax,32*p1+4(%edi)	;\
+	xor	32*p1-24(%edi),%eax	;\
+	mov	%eax,32*p1+8(%edi)	;\
+	xor	32*p1-20(%edi),%eax	;\
+	mov	%eax,32*p1+12(%edi)	;\
+	push	%ebx			;\
+	mov	%eax,%ebx		;\
+	mix_col(aes_fl_tab)		;\
+	pop	%ebx			;\
+	xor	%eax,%esi		;\
+	xor	%esi,%ebp		;\
+	mov	%esi,32*p1+16(%edi)	;\
+	mov	%ebp,32*p1+20(%edi)	;\
+	xor	%ebp,%edx		;\
+	xor	%edx,%ebx		;\
+	mov	%edx,32*p1+24(%edi)	;\
+	mov	%ebx,32*p1+28(%edi)
+
+	.align	ALIGN32BYTES
+aes_set_key:
+	pushfl
+	push	%ebp
+	mov	%esp,%ebp
+	sub	$slen,%esp
+	push	%ebx
+	push	%esi
+	push	%edi
+
+	mov	aes_cx(%ebp),%edx	// edx -> AES context
+
+	mov	key_ln(%ebp),%ecx	// key length
+	cmpl	$128,%ecx
+	jb	aes_30
+	shr	$3,%ecx
+aes_30:	cmpl	$32,%ecx
+	je	aes_32
+	cmpl	$24,%ecx
+	je	aes_32
+	mov	$16,%ecx
+aes_32:	shr	$2,%ecx
+	mov	%ecx,nkey(%edx)
+
+	lea	6(%ecx),%eax		// 10/12/14 for 4/6/8 32-bit key length
+	mov	%eax,nrnd(%edx)
+
+	mov	in_key(%ebp),%esi	// key input array
+	lea	ekey(%edx),%edi		// key position in AES context
+	cld
+	push	%ebp
+	mov	%ecx,%eax		// save key length in eax
+	rep ;	movsl			// words in the key schedule
+	mov	-4(%esi),%ebx		// put some values in registers
+	mov	-8(%esi),%edx		// to allow faster code
+	mov	-12(%esi),%ebp
+	mov	-16(%esi),%esi
+
+	cmpl	$4,%eax			// jump on key size
+	je	aes_36
+	cmpl	$6,%eax
+	je	aes_35
+
+	ksc8(0)
+	ksc8(1)
+	ksc8(2)
+	ksc8(3)
+	ksc8(4)
+	ksc8(5)
+	ksc8(6)
+	jmp	aes_37
+aes_35:	ksc6(0)
+	ksc6(1)
+	ksc6(2)
+	ksc6(3)
+	ksc6(4)
+	ksc6(5)
+	ksc6(6)
+	ksc6(7)
+	jmp	aes_37
+aes_36:	ksc4(0)
+	ksc4(1)
+	ksc4(2)
+	ksc4(3)
+	ksc4(4)
+	ksc4(5)
+	ksc4(6)
+	ksc4(7)
+	ksc4(8)
+	ksc4(9)
+aes_37:	pop	%ebp
+	mov	aes_cx(%ebp),%edx	// edx -> AES context
+	cmpl	$0,ed_flg(%ebp)
+	jne	aes_39
+
+// compile decryption key schedule from encryption schedule - reverse
+// order and do mix_column operation on round keys except first and last
+
+	mov	nrnd(%edx),%eax		// kt = cx->d_key + nc * cx->Nrnd
+	shl	$2,%eax
+	lea	dkey(%edx,%eax,4),%edi
+	lea	ekey(%edx),%esi		// kf = cx->e_key
+
+	movsl				// copy first round key (unmodified)
+	movsl
+	movsl
+	movsl
+	sub	$32,%edi
+	movl	$1,cnt(%ebp)
+aes_38:					// do mix column on each column of
+	lodsl				// each round key
+	mov	%eax,%ebx
+	mix_col(aes_im_tab)
+	stosl
+	lodsl
+	mov	%eax,%ebx
+	mix_col(aes_im_tab)
+	stosl
+	lodsl
+	mov	%eax,%ebx
+	mix_col(aes_im_tab)
+	stosl
+	lodsl
+	mov	%eax,%ebx
+	mix_col(aes_im_tab)
+	stosl
+	sub	$32,%edi
+
+	incl	cnt(%ebp)
+	mov	cnt(%ebp),%eax
+	cmp	nrnd(%edx),%eax
+	jb	aes_38
+
+	movsl				// copy last round key (unmodified)
+	movsl
+	movsl
+	movsl
+aes_39:	pop	%edi
+	pop	%esi
+	pop	%ebx
+	mov	%ebp,%esp
+	pop	%ebp
+	popfl
+	ret
+
+
+// finite field multiplies by {02}, {04} and {08}
+
+#define f2(x)	((x<<1)^(((x>>7)&1)*0x11b))
+#define f4(x)	((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))
+#define f8(x)	((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))
+
+// finite field multiplies required in table generation
+
+#define f3(x)	(f2(x) ^ x)
+#define f9(x)	(f8(x) ^ x)
+#define fb(x)	(f8(x) ^ f2(x) ^ x)
+#define fd(x)	(f8(x) ^ f4(x) ^ x)
+#define fe(x)	(f8(x) ^ f4(x) ^ f2(x))
+
+// These defines generate the forward table entries
+
+#define u0(x)	((f3(x) << 24) | (x << 16) | (x << 8) | f2(x))
+#define u1(x)	((x << 24) | (x << 16) | (f2(x) << 8) | f3(x))
+#define u2(x)	((x << 24) | (f2(x) << 16) | (f3(x) << 8) | x)
+#define u3(x)	((f2(x) << 24) | (f3(x) << 16) | (x << 8) | x)
+
+// These defines generate the inverse table entries
+
+#define v0(x)	((fb(x) << 24) | (fd(x) << 16) | (f9(x) << 8) | fe(x))
+#define v1(x)	((fd(x) << 24) | (f9(x) << 16) | (fe(x) << 8) | fb(x))
+#define v2(x)	((f9(x) << 24) | (fe(x) << 16) | (fb(x) << 8) | fd(x))
+#define v3(x)	((fe(x) << 24) | (fb(x) << 16) | (fd(x) << 8) | f9(x))
+
+// These defines generate entries for the last round tables
+
+#define w0(x)	(x)
+#define w1(x)	(x <<  8)
+#define w2(x)	(x << 16)
+#define w3(x)	(x << 24)
+
+// macro to generate inverse mix column tables (needed for the key schedule)
+
+#define im_data0(p1) \
+	.long	p1(0x00),p1(0x01),p1(0x02),p1(0x03),p1(0x04),p1(0x05),p1(0x06),p1(0x07) ;\
+	.long	p1(0x08),p1(0x09),p1(0x0a),p1(0x0b),p1(0x0c),p1(0x0d),p1(0x0e),p1(0x0f) ;\
+	.long	p1(0x10),p1(0x11),p1(0x12),p1(0x13),p1(0x14),p1(0x15),p1(0x16),p1(0x17) ;\
+	.long	p1(0x18),p1(0x19),p1(0x1a),p1(0x1b),p1(0x1c),p1(0x1d),p1(0x1e),p1(0x1f)
+#define im_data1(p1) \
+	.long	p1(0x20),p1(0x21),p1(0x22),p1(0x23),p1(0x24),p1(0x25),p1(0x26),p1(0x27) ;\
+	.long	p1(0x28),p1(0x29),p1(0x2a),p1(0x2b),p1(0x2c),p1(0x2d),p1(0x2e),p1(0x2f) ;\
+	.long	p1(0x30),p1(0x31),p1(0x32),p1(0x33),p1(0x34),p1(0x35),p1(0x36),p1(0x37) ;\
+	.long	p1(0x38),p1(0x39),p1(0x3a),p1(0x3b),p1(0x3c),p1(0x3d),p1(0x3e),p1(0x3f)
+#define im_data2(p1) \
+	.long	p1(0x40),p1(0x41),p1(0x42),p1(0x43),p1(0x44),p1(0x45),p1(0x46),p1(0x47) ;\
+	.long	p1(0x48),p1(0x49),p1(0x4a),p1(0x4b),p1(0x4c),p1(0x4d),p1(0x4e),p1(0x4f) ;\
+	.long	p1(0x50),p1(0x51),p1(0x52),p1(0x53),p1(0x54),p1(0x55),p1(0x56),p1(0x57) ;\
+	.long	p1(0x58),p1(0x59),p1(0x5a),p1(0x5b),p1(0x5c),p1(0x5d),p1(0x5e),p1(0x5f)
+#define im_data3(p1) \
+	.long	p1(0x60),p1(0x61),p1(0x62),p1(0x63),p1(0x64),p1(0x65),p1(0x66),p1(0x67) ;\
+	.long	p1(0x68),p1(0x69),p1(0x6a),p1(0x6b),p1(0x6c),p1(0x6d),p1(0x6e),p1(0x6f) ;\
+	.long	p1(0x70),p1(0x71),p1(0x72),p1(0x73),p1(0x74),p1(0x75),p1(0x76),p1(0x77) ;\
+	.long	p1(0x78),p1(0x79),p1(0x7a),p1(0x7b),p1(0x7c),p1(0x7d),p1(0x7e),p1(0x7f)
+#define im_data4(p1) \
+	.long	p1(0x80),p1(0x81),p1(0x82),p1(0x83),p1(0x84),p1(0x85),p1(0x86),p1(0x87) ;\
+	.long	p1(0x88),p1(0x89),p1(0x8a),p1(0x8b),p1(0x8c),p1(0x8d),p1(0x8e),p1(0x8f) ;\
+	.long	p1(0x90),p1(0x91),p1(0x92),p1(0x93),p1(0x94),p1(0x95),p1(0x96),p1(0x97) ;\
+	.long	p1(0x98),p1(0x99),p1(0x9a),p1(0x9b),p1(0x9c),p1(0x9d),p1(0x9e),p1(0x9f)
+#define im_data5(p1) \
+	.long	p1(0xa0),p1(0xa1),p1(0xa2),p1(0xa3),p1(0xa4),p1(0xa5),p1(0xa6),p1(0xa7) ;\
+	.long	p1(0xa8),p1(0xa9),p1(0xaa),p1(0xab),p1(0xac),p1(0xad),p1(0xae),p1(0xaf) ;\
+	.long	p1(0xb0),p1(0xb1),p1(0xb2),p1(0xb3),p1(0xb4),p1(0xb5),p1(0xb6),p1(0xb7) ;\
+	.long	p1(0xb8),p1(0xb9),p1(0xba),p1(0xbb),p1(0xbc),p1(0xbd),p1(0xbe),p1(0xbf)
+#define im_data6(p1) \
+	.long	p1(0xc0),p1(0xc1),p1(0xc2),p1(0xc3),p1(0xc4),p1(0xc5),p1(0xc6),p1(0xc7) ;\
+	.long	p1(0xc8),p1(0xc9),p1(0xca),p1(0xcb),p1(0xcc),p1(0xcd),p1(0xce),p1(0xcf) ;\
+	.long	p1(0xd0),p1(0xd1),p1(0xd2),p1(0xd3),p1(0xd4),p1(0xd5),p1(0xd6),p1(0xd7) ;\
+	.long	p1(0xd8),p1(0xd9),p1(0xda),p1(0xdb),p1(0xdc),p1(0xdd),p1(0xde),p1(0xdf)
+#define im_data7(p1) \
+	.long	p1(0xe0),p1(0xe1),p1(0xe2),p1(0xe3),p1(0xe4),p1(0xe5),p1(0xe6),p1(0xe7) ;\
+	.long	p1(0xe8),p1(0xe9),p1(0xea),p1(0xeb),p1(0xec),p1(0xed),p1(0xee),p1(0xef) ;\
+	.long	p1(0xf0),p1(0xf1),p1(0xf2),p1(0xf3),p1(0xf4),p1(0xf5),p1(0xf6),p1(0xf7) ;\
+	.long	p1(0xf8),p1(0xf9),p1(0xfa),p1(0xfb),p1(0xfc),p1(0xfd),p1(0xfe),p1(0xff)
+
+// S-box data - 256 entries
+
+#define sb_data0(p1) \
+	.long	p1(0x63),p1(0x7c),p1(0x77),p1(0x7b),p1(0xf2),p1(0x6b),p1(0x6f),p1(0xc5) ;\
+	.long	p1(0x30),p1(0x01),p1(0x67),p1(0x2b),p1(0xfe),p1(0xd7),p1(0xab),p1(0x76) ;\
+	.long	p1(0xca),p1(0x82),p1(0xc9),p1(0x7d),p1(0xfa),p1(0x59),p1(0x47),p1(0xf0) ;\
+	.long	p1(0xad),p1(0xd4),p1(0xa2),p1(0xaf),p1(0x9c),p1(0xa4),p1(0x72),p1(0xc0)
+#define sb_data1(p1) \
+	.long	p1(0xb7),p1(0xfd),p1(0x93),p1(0x26),p1(0x36),p1(0x3f),p1(0xf7),p1(0xcc) ;\
+	.long	p1(0x34),p1(0xa5),p1(0xe5),p1(0xf1),p1(0x71),p1(0xd8),p1(0x31),p1(0x15) ;\
+	.long	p1(0x04),p1(0xc7),p1(0x23),p1(0xc3),p1(0x18),p1(0x96),p1(0x05),p1(0x9a) ;\
+	.long	p1(0x07),p1(0x12),p1(0x80),p1(0xe2),p1(0xeb),p1(0x27),p1(0xb2),p1(0x75)
+#define sb_data2(p1) \
+	.long	p1(0x09),p1(0x83),p1(0x2c),p1(0x1a),p1(0x1b),p1(0x6e),p1(0x5a),p1(0xa0) ;\
+	.long	p1(0x52),p1(0x3b),p1(0xd6),p1(0xb3),p1(0x29),p1(0xe3),p1(0x2f),p1(0x84) ;\
+	.long	p1(0x53),p1(0xd1),p1(0x00),p1(0xed),p1(0x20),p1(0xfc),p1(0xb1),p1(0x5b) ;\
+	.long	p1(0x6a),p1(0xcb),p1(0xbe),p1(0x39),p1(0x4a),p1(0x4c),p1(0x58),p1(0xcf)
+#define sb_data3(p1) \
+	.long	p1(0xd0),p1(0xef),p1(0xaa),p1(0xfb),p1(0x43),p1(0x4d),p1(0x33),p1(0x85) ;\
+	.long	p1(0x45),p1(0xf9),p1(0x02),p1(0x7f),p1(0x50),p1(0x3c),p1(0x9f),p1(0xa8) ;\
+	.long	p1(0x51),p1(0xa3),p1(0x40),p1(0x8f),p1(0x92),p1(0x9d),p1(0x38),p1(0xf5) ;\
+	.long	p1(0xbc),p1(0xb6),p1(0xda),p1(0x21),p1(0x10),p1(0xff),p1(0xf3),p1(0xd2)
+#define sb_data4(p1) \
+	.long	p1(0xcd),p1(0x0c),p1(0x13),p1(0xec),p1(0x5f),p1(0x97),p1(0x44),p1(0x17) ;\
+	.long	p1(0xc4),p1(0xa7),p1(0x7e),p1(0x3d),p1(0x64),p1(0x5d),p1(0x19),p1(0x73) ;\
+	.long	p1(0x60),p1(0x81),p1(0x4f),p1(0xdc),p1(0x22),p1(0x2a),p1(0x90),p1(0x88) ;\
+	.long	p1(0x46),p1(0xee),p1(0xb8),p1(0x14),p1(0xde),p1(0x5e),p1(0x0b),p1(0xdb)
+#define sb_data5(p1) \
+	.long	p1(0xe0),p1(0x32),p1(0x3a),p1(0x0a),p1(0x49),p1(0x06),p1(0x24),p1(0x5c) ;\
+	.long	p1(0xc2),p1(0xd3),p1(0xac),p1(0x62),p1(0x91),p1(0x95),p1(0xe4),p1(0x79) ;\
+	.long	p1(0xe7),p1(0xc8),p1(0x37),p1(0x6d),p1(0x8d),p1(0xd5),p1(0x4e),p1(0xa9) ;\
+	.long	p1(0x6c),p1(0x56),p1(0xf4),p1(0xea),p1(0x65),p1(0x7a),p1(0xae),p1(0x08)
+#define sb_data6(p1) \
+	.long	p1(0xba),p1(0x78),p1(0x25),p1(0x2e),p1(0x1c),p1(0xa6),p1(0xb4),p1(0xc6) ;\
+	.long	p1(0xe8),p1(0xdd),p1(0x74),p1(0x1f),p1(0x4b),p1(0xbd),p1(0x8b),p1(0x8a) ;\
+	.long	p1(0x70),p1(0x3e),p1(0xb5),p1(0x66),p1(0x48),p1(0x03),p1(0xf6),p1(0x0e) ;\
+	.long	p1(0x61),p1(0x35),p1(0x57),p1(0xb9),p1(0x86),p1(0xc1),p1(0x1d),p1(0x9e)
+#define sb_data7(p1) \
+	.long	p1(0xe1),p1(0xf8),p1(0x98),p1(0x11),p1(0x69),p1(0xd9),p1(0x8e),p1(0x94) ;\
+	.long	p1(0x9b),p1(0x1e),p1(0x87),p1(0xe9),p1(0xce),p1(0x55),p1(0x28),p1(0xdf) ;\
+	.long	p1(0x8c),p1(0xa1),p1(0x89),p1(0x0d),p1(0xbf),p1(0xe6),p1(0x42),p1(0x68) ;\
+	.long	p1(0x41),p1(0x99),p1(0x2d),p1(0x0f),p1(0xb0),p1(0x54),p1(0xbb),p1(0x16)
+
+// Inverse S-box data - 256 entries
+
+#define ib_data0(p1) \
+	.long	p1(0x52),p1(0x09),p1(0x6a),p1(0xd5),p1(0x30),p1(0x36),p1(0xa5),p1(0x38) ;\
+	.long	p1(0xbf),p1(0x40),p1(0xa3),p1(0x9e),p1(0x81),p1(0xf3),p1(0xd7),p1(0xfb) ;\
+	.long	p1(0x7c),p1(0xe3),p1(0x39),p1(0x82),p1(0x9b),p1(0x2f),p1(0xff),p1(0x87) ;\
+	.long	p1(0x34),p1(0x8e),p1(0x43),p1(0x44),p1(0xc4),p1(0xde),p1(0xe9),p1(0xcb)
+#define ib_data1(p1) \
+	.long	p1(0x54),p1(0x7b),p1(0x94),p1(0x32),p1(0xa6),p1(0xc2),p1(0x23),p1(0x3d) ;\
+	.long	p1(0xee),p1(0x4c),p1(0x95),p1(0x0b),p1(0x42),p1(0xfa),p1(0xc3),p1(0x4e) ;\
+	.long	p1(0x08),p1(0x2e),p1(0xa1),p1(0x66),p1(0x28),p1(0xd9),p1(0x24),p1(0xb2) ;\
+	.long	p1(0x76),p1(0x5b),p1(0xa2),p1(0x49),p1(0x6d),p1(0x8b),p1(0xd1),p1(0x25)
+#define ib_data2(p1) \
+	.long	p1(0x72),p1(0xf8),p1(0xf6),p1(0x64),p1(0x86),p1(0x68),p1(0x98),p1(0x16) ;\
+	.long	p1(0xd4),p1(0xa4),p1(0x5c),p1(0xcc),p1(0x5d),p1(0x65),p1(0xb6),p1(0x92) ;\
+	.long	p1(0x6c),p1(0x70),p1(0x48),p1(0x50),p1(0xfd),p1(0xed),p1(0xb9),p1(0xda) ;\
+	.long	p1(0x5e),p1(0x15),p1(0x46),p1(0x57),p1(0xa7),p1(0x8d),p1(0x9d),p1(0x84)
+#define ib_data3(p1) \
+	.long	p1(0x90),p1(0xd8),p1(0xab),p1(0x00),p1(0x8c),p1(0xbc),p1(0xd3),p1(0x0a) ;\
+	.long	p1(0xf7),p1(0xe4),p1(0x58),p1(0x05),p1(0xb8),p1(0xb3),p1(0x45),p1(0x06) ;\
+	.long	p1(0xd0),p1(0x2c),p1(0x1e),p1(0x8f),p1(0xca),p1(0x3f),p1(0x0f),p1(0x02) ;\
+	.long	p1(0xc1),p1(0xaf),p1(0xbd),p1(0x03),p1(0x01),p1(0x13),p1(0x8a),p1(0x6b)
+#define ib_data4(p1) \
+	.long	p1(0x3a),p1(0x91),p1(0x11),p1(0x41),p1(0x4f),p1(0x67),p1(0xdc),p1(0xea) ;\
+	.long	p1(0x97),p1(0xf2),p1(0xcf),p1(0xce),p1(0xf0),p1(0xb4),p1(0xe6),p1(0x73) ;\
+	.long	p1(0x96),p1(0xac),p1(0x74),p1(0x22),p1(0xe7),p1(0xad),p1(0x35),p1(0x85) ;\
+	.long	p1(0xe2),p1(0xf9),p1(0x37),p1(0xe8),p1(0x1c),p1(0x75),p1(0xdf),p1(0x6e)
+#define ib_data5(p1) \
+	.long	p1(0x47),p1(0xf1),p1(0x1a),p1(0x71),p1(0x1d),p1(0x29),p1(0xc5),p1(0x89) ;\
+	.long	p1(0x6f),p1(0xb7),p1(0x62),p1(0x0e),p1(0xaa),p1(0x18),p1(0xbe),p1(0x1b) ;\
+	.long	p1(0xfc),p1(0x56),p1(0x3e),p1(0x4b),p1(0xc6),p1(0xd2),p1(0x79),p1(0x20) ;\
+	.long	p1(0x9a),p1(0xdb),p1(0xc0),p1(0xfe),p1(0x78),p1(0xcd),p1(0x5a),p1(0xf4)
+#define ib_data6(p1) \
+	.long	p1(0x1f),p1(0xdd),p1(0xa8),p1(0x33),p1(0x88),p1(0x07),p1(0xc7),p1(0x31) ;\
+	.long	p1(0xb1),p1(0x12),p1(0x10),p1(0x59),p1(0x27),p1(0x80),p1(0xec),p1(0x5f) ;\
+	.long	p1(0x60),p1(0x51),p1(0x7f),p1(0xa9),p1(0x19),p1(0xb5),p1(0x4a),p1(0x0d) ;\
+	.long	p1(0x2d),p1(0xe5),p1(0x7a),p1(0x9f),p1(0x93),p1(0xc9),p1(0x9c),p1(0xef)
+#define ib_data7(p1) \
+	.long	p1(0xa0),p1(0xe0),p1(0x3b),p1(0x4d),p1(0xae),p1(0x2a),p1(0xf5),p1(0xb0) ;\
+	.long	p1(0xc8),p1(0xeb),p1(0xbb),p1(0x3c),p1(0x83),p1(0x53),p1(0x99),p1(0x61) ;\
+	.long	p1(0x17),p1(0x2b),p1(0x04),p1(0x7e),p1(0xba),p1(0x77),p1(0xd6),p1(0x26) ;\
+	.long	p1(0xe1),p1(0x69),p1(0x14),p1(0x63),p1(0x55),p1(0x21),p1(0x0c),p1(0x7d)
+
+// The rcon_table (needed for the key schedule)
+//
+// Here is original Dr Brian Gladman's source code:
+//	_rcon_tab:
+//	%assign x   1
+//	%rep 29
+//	    dd  x
+//	%assign x f2(x)
+//	%endrep
+//
+// Here is precomputed output (it's more portable this way):
+
+	.align	ALIGN32BYTES
+aes_rcon_tab:
+	.long	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
+	.long	0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f
+	.long	0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4
+	.long	0xb3,0x7d,0xfa,0xef,0xc5
+
+// The forward xor tables
+
+	.align	ALIGN32BYTES
+aes_ft_tab:
+	sb_data0(u0)
+	sb_data1(u0)
+	sb_data2(u0)
+	sb_data3(u0)
+	sb_data4(u0)
+	sb_data5(u0)
+	sb_data6(u0)
+	sb_data7(u0)
+
+	sb_data0(u1)
+	sb_data1(u1)
+	sb_data2(u1)
+	sb_data3(u1)
+	sb_data4(u1)
+	sb_data5(u1)
+	sb_data6(u1)
+	sb_data7(u1)
+
+	sb_data0(u2)
+	sb_data1(u2)
+	sb_data2(u2)
+	sb_data3(u2)
+	sb_data4(u2)
+	sb_data5(u2)
+	sb_data6(u2)
+	sb_data7(u2)
+
+	sb_data0(u3)
+	sb_data1(u3)
+	sb_data2(u3)
+	sb_data3(u3)
+	sb_data4(u3)
+	sb_data5(u3)
+	sb_data6(u3)
+	sb_data7(u3)
+
+	.align	ALIGN32BYTES
+aes_fl_tab:
+	sb_data0(w0)
+	sb_data1(w0)
+	sb_data2(w0)
+	sb_data3(w0)
+	sb_data4(w0)
+	sb_data5(w0)
+	sb_data6(w0)
+	sb_data7(w0)
+
+	sb_data0(w1)
+	sb_data1(w1)
+	sb_data2(w1)
+	sb_data3(w1)
+	sb_data4(w1)
+	sb_data5(w1)
+	sb_data6(w1)
+	sb_data7(w1)
+
+	sb_data0(w2)
+	sb_data1(w2)
+	sb_data2(w2)
+	sb_data3(w2)
+	sb_data4(w2)
+	sb_data5(w2)
+	sb_data6(w2)
+	sb_data7(w2)
+
+	sb_data0(w3)
+	sb_data1(w3)
+	sb_data2(w3)
+	sb_data3(w3)
+	sb_data4(w3)
+	sb_data5(w3)
+	sb_data6(w3)
+	sb_data7(w3)
+
+// The inverse xor tables
+
+	.align	ALIGN32BYTES
+aes_it_tab:
+	ib_data0(v0)
+	ib_data1(v0)
+	ib_data2(v0)
+	ib_data3(v0)
+	ib_data4(v0)
+	ib_data5(v0)
+	ib_data6(v0)
+	ib_data7(v0)
+
+	ib_data0(v1)
+	ib_data1(v1)
+	ib_data2(v1)
+	ib_data3(v1)
+	ib_data4(v1)
+	ib_data5(v1)
+	ib_data6(v1)
+	ib_data7(v1)
+
+	ib_data0(v2)
+	ib_data1(v2)
+	ib_data2(v2)
+	ib_data3(v2)
+	ib_data4(v2)
+	ib_data5(v2)
+	ib_data6(v2)
+	ib_data7(v2)
+
+	ib_data0(v3)
+	ib_data1(v3)
+	ib_data2(v3)
+	ib_data3(v3)
+	ib_data4(v3)
+	ib_data5(v3)
+	ib_data6(v3)
+	ib_data7(v3)
+
+	.align	ALIGN32BYTES
+aes_il_tab:
+	ib_data0(w0)
+	ib_data1(w0)
+	ib_data2(w0)
+	ib_data3(w0)
+	ib_data4(w0)
+	ib_data5(w0)
+	ib_data6(w0)
+	ib_data7(w0)
+
+	ib_data0(w1)
+	ib_data1(w1)
+	ib_data2(w1)
+	ib_data3(w1)
+	ib_data4(w1)
+	ib_data5(w1)
+	ib_data6(w1)
+	ib_data7(w1)
+
+	ib_data0(w2)
+	ib_data1(w2)
+	ib_data2(w2)
+	ib_data3(w2)
+	ib_data4(w2)
+	ib_data5(w2)
+	ib_data6(w2)
+	ib_data7(w2)
+
+	ib_data0(w3)
+	ib_data1(w3)
+	ib_data2(w3)
+	ib_data3(w3)
+	ib_data4(w3)
+	ib_data5(w3)
+	ib_data6(w3)
+	ib_data7(w3)
+
+// The inverse mix column tables
+
+	.align	ALIGN32BYTES
+aes_im_tab:
+	im_data0(v0)
+	im_data1(v0)
+	im_data2(v0)
+	im_data3(v0)
+	im_data4(v0)
+	im_data5(v0)
+	im_data6(v0)
+	im_data7(v0)
+
+	im_data0(v1)
+	im_data1(v1)
+	im_data2(v1)
+	im_data3(v1)
+	im_data4(v1)
+	im_data5(v1)
+	im_data6(v1)
+	im_data7(v1)
+
+	im_data0(v2)
+	im_data1(v2)
+	im_data2(v2)
+	im_data3(v2)
+	im_data4(v2)
+	im_data5(v2)
+	im_data6(v2)
+	im_data7(v2)
+
+	im_data0(v3)
+	im_data1(v3)
+	im_data2(v3)
+	im_data3(v3)
+	im_data4(v3)
+	im_data5(v3)
+	im_data6(v3)
+	im_data7(v3)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/test_main.c linux-patched/net/ipsec/libcrypto/libaes/test_main.c
--- linux/net/ipsec/libcrypto/libaes/test_main.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/test_main.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "aes_cbc.h"
+#define AES_BLOCK_SIZE	16
+#define KEY_SIZE 	128	/* bits */
+#define KEY 		"1234567890123456"
+#define STR 		"hola guaso como estaisss ... 012"
+#define STRSZ		(sizeof(STR)-1)
+
+#define EMT_AESCBC_BLKLEN AES_BLOCK_SIZE
+#define AES_CONTEXT_T  aes_context
+#define EMT_ESPAES_KEY_SZ 16
+int pretty_print(const unsigned char *buf, int count) {
+	int i=0;
+	for (;i<count;i++) {
+		if (i%8==0) putchar(' ');
+		if (i%16==0) putchar('\n');
+		printf ("%02hhx ", buf[i]);
+	}
+	putchar('\n');
+	return i;
+}
+//#define SIZE STRSZ/2
+#define SIZE STRSZ
+int main() {
+	int ret;
+	char buf0[SIZE+1], buf1[SIZE+1];
+	char IV[AES_BLOCK_SIZE]="\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0";
+	aes_context ac;	
+	AES_set_key(&ac, KEY, KEY_SIZE);
+	//pretty_print((char *)&ac.aes_e_key, sizeof(ac.aes_e_key));
+	memset(buf0, 0, sizeof (buf0));
+	memset(buf1, 0, sizeof (buf1));
+	ret=AES_cbc_encrypt(&ac, STR, buf0, SIZE, IV, 1);
+	pretty_print(buf0, SIZE);
+	printf("size=%d ret=%d\n%s\n", SIZE, ret, buf0);
+	ret=AES_cbc_encrypt(&ac, buf0, buf1, SIZE, IV, 0);
+	printf("size=%d ret=%d\n%s\n", SIZE, ret, buf1);
+	return 0;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libaes/test_main_mac.c linux-patched/net/ipsec/libcrypto/libaes/test_main_mac.c
--- linux/net/ipsec/libcrypto/libaes/test_main_mac.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libaes/test_main_mac.c	Thu Sep  5 04:38:06 2002
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include "aes.h"
+#include "aes_xcbc_mac.h"
+#define STR "Hola guasssso c|mo estais ...012"  
+void print_hash(const __u8 *hash) {
+	printf("%08x %08x %08x %08x\n", 
+			*(__u32*)(&hash[0]), 
+			*(__u32*)(&hash[4]), 
+			*(__u32*)(&hash[8]), 
+			*(__u32*)(&hash[12]));
+}
+int main(int argc, char *argv[]) {
+	aes_block key= { 0xdeadbeef, 0xceedcaca, 0xcafebabe, 0xff010204 };
+	__u8  hash[16];
+	char *str = argv[1];
+	aes_context_mac ctx;
+	if (str==NULL) {
+		fprintf(stderr, "pasame el str\n");
+		return 255;
+	}
+	AES_xcbc_mac_set_key(&ctx, (__u8 *)&key, sizeof(key));
+	AES_xcbc_mac_hash(&ctx, str, strlen(str), hash);
+	print_hash(hash);
+	str[2]='x';
+	AES_xcbc_mac_hash(&ctx, str, strlen(str), hash);
+	print_hash(hash);
+	return 0;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/COPYRIGHT linux-patched/net/ipsec/libcrypto/libblowfish/COPYRIGHT
--- linux/net/ipsec/libcrypto/libblowfish/COPYRIGHT	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/COPYRIGHT	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,46 @@
+Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+All rights reserved.
+
+This package is an Blowfish implementation written
+by Eric Young (eay@cryptsoft.com).
+
+This library is free for commercial and non-commercial use as long as
+the following conditions are aheared to.  The following conditions
+apply to all code found in this distribution.
+
+Copyright remains Eric Young's, and as such any Copyright notices in
+the code are not to be removed.
+
+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 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 Eric Young (eay@cryptsoft.com)
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+
+The license and distribution terms for any publically available version or
+derivative of this code cannot be changed.  i.e. this code cannot simply be
+copied and put under another distrubution license
+[including the GNU Public License.]
+
+The reason behind this being stated in this direct manner is past
+experience in code simply being copied and the attribution removed
+from it and then being distributed as part of other packages. This
+implementation was a non-trivial and unpaid effort.
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/INSTALL linux-patched/net/ipsec/libcrypto/libblowfish/INSTALL
--- linux/net/ipsec/libcrypto/libblowfish/INSTALL	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/INSTALL	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,14 @@
+This Eric Young's blowfish implementation, taken from his SSLeay library
+and made available as a separate library.
+ 
+The version number (0.7.2m) is the SSLeay version that this library was
+taken from.
+ 
+To build, just unpack and type make.
+If you are not using gcc, edit the Makefile.
+If you are compiling for an x86 box, try the assembler (it needs improving).
+There are also some compile time options that can improve performance,
+these are documented in the Makefile.
+ 
+eric 15-Apr-1997
+ 
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/Makefile linux-patched/net/ipsec/libcrypto/libblowfish/Makefile
--- linux/net/ipsec/libcrypto/libblowfish/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/Makefile	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,121 @@
+#
+# SSLeay/crypto/blowfish/Makefile
+#
+
+DIR=	bf
+TOP=	../..
+CC=	cc
+CPP=	$(CC) -E
+INC=-I ../include 
+CFLAG=-g -D__KERNEL__ -I/usr/src/linux/include
+INSTALL_PREFIX=
+OPENSSLDIR=     /usr/local/ssl
+INSTALLTOP=/usr/local/ssl
+MAKE=		make -f Makefile.ssl
+MAKEDEPEND=	$(TOP)/util/domd $(TOP)
+MAKEFILE=	Makefile.ssl
+AR=		ar r
+RANLIB=		ranlib
+PERL=		perl
+
+CFLAGS= $(INC) $(CFLAG)
+
+.c.o:
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c $< -o $@
+
+BF_ASM-i586 := bf-586.pl
+BF_ASM-i686 := bf-686.pl
+BF_ENC := bf_enc.o
+
+ASM-$(ARCH_ASM):=1
+ASM_X86:=$(ASM-i586)$(ASM-i686)
+ifneq ($(strip $(ASM_X86)),)
+	BF_ENC=	asm/bx86-elf.o
+	BF_ASM= $(BF_ASM-$(ARCH_ASM))
+endif
+
+
+GENERAL=Makefile
+TEST=bftest.c
+APPS=
+
+LIB=libblowfish.a
+LIBSRC=bf_skey.c bf_enc.c 
+LIBOBJ=bf_skey.o $(BF_ENC)
+
+SRC= $(LIBSRC)
+
+EXHEADER= blowfish.h
+HEADER=	bf_pi.h bf_locl.h $(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+#top:
+#	(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all:	lib
+
+lib:	$(LIB)
+
+$(LIB):	$(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	$(RANLIB) $(LIB)
+
+# elf
+asm/bx86-elf.o: asm/bx86unix.cpp
+	$(CPP) -DELF -x c asm/bx86unix.cpp | as -o asm/bx86-elf.o
+
+# solaris
+asm/bx86-sol.o: asm/bx86unix.cpp
+	$(CC) -E -DSOL asm/bx86unix.cpp | sed 's/^#.*//' > asm/bx86-sol.s
+	as -o asm/bx86-sol.o asm/bx86-sol.s
+	rm -f asm/bx86-sol.s
+
+# a.out
+asm/bx86-out.o: asm/bx86unix.cpp
+	$(CPP) -DOUT asm/bx86unix.cpp | as -o asm/bx86-out.o
+
+# bsdi
+asm/bx86bsdi.o: asm/bx86unix.cpp
+	$(CPP) -DBSDI asm/bx86unix.cpp | sed 's/ :/:/' | as -o asm/bx86bsdi.o
+
+asm/bx86unix.cpp: asm/$(BF_ASM) ../perlasm/x86asm.pl ../perlasm/cbc.pl
+	(cd asm; $(PERL) $(BF_ASM) cpp $(PROCESSOR) >bx86unix.cpp)
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO
+
+links:
+	@$(TOP)/util/point.sh Makefile.ssl Makefile
+	@$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+	@$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+	@$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install: installs
+
+installs:
+	@for i in $(EXHEADER) ; \
+	do  \
+	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	$(MAKEDEPEND) $(INCLUDES) $(DEPFLAG) $(PROGS) $(LIBSRC)
+
+dclean:
+	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	rm -f asm/bx86unix.cpp *.o asm/*.o *.obj $(LIB) tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/README linux-patched/net/ipsec/libcrypto/libblowfish/README
--- linux/net/ipsec/libcrypto/libblowfish/README	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/README	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,8 @@
+This is a quick packaging up of my blowfish code into a library.
+It has been lifted from SSLeay.
+The copyright notices seem a little harsh because I have not spent the
+time to rewrite the conditions from the normal SSLeay ones.
+
+Basically if you just want to play with the library, not a problem.
+
+eric 15-Apr-1997
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/VERSION linux-patched/net/ipsec/libcrypto/libblowfish/VERSION
--- linux/net/ipsec/libcrypto/libblowfish/VERSION	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/VERSION	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,6 @@
+The version numbers will follow my SSL implementation
+
+0.7.2r - Some reasonable default compiler options from 
+	Peter Gutman <pgut001@cs.auckland.ac.nz>
+
+0.7.2m - the first release
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/asm/bf-586.pl linux-patched/net/ipsec/libcrypto/libblowfish/asm/bf-586.pl
--- linux/net/ipsec/libcrypto/libblowfish/asm/bf-586.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/asm/bf-586.pl	Thu Sep  5 04:42:26 2002
@@ -0,0 +1,136 @@
+#!/usr/local/bin/perl
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+require "cbc.pl";
+
+&asm_init($ARGV[0],"bf-586.pl",$ARGV[$#ARGV] eq "386");
+
+$BF_ROUNDS=16;
+$BF_OFF=($BF_ROUNDS+2)*4;
+$L="edi";
+$R="esi";
+$P="ebp";
+$tmp1="eax";
+$tmp2="ebx";
+$tmp3="ecx";
+$tmp4="edx";
+
+&BF_encrypt("BF_encrypt",1);
+&BF_encrypt("BF_decrypt",0);
+&cbc("BF_cbc_encrypt","BF_encrypt","BF_decrypt",1,4,5,3,-1,-1);
+&asm_finish();
+
+sub BF_encrypt
+	{
+	local($name,$enc)=@_;
+
+	&function_begin_B($name,"");
+
+	&comment("");
+
+	&push("ebp");
+	&push("ebx");
+	&mov($tmp2,&wparam(0));
+	&mov($P,&wparam(1));
+	&push("esi");
+	&push("edi");
+
+	&comment("Load the 2 words");
+	&mov($L,&DWP(0,$tmp2,"",0));
+	&mov($R,&DWP(4,$tmp2,"",0));
+
+	&xor(	$tmp1,	$tmp1);
+
+	# encrypting part
+
+	if ($enc)
+		{
+		 &mov($tmp2,&DWP(0,$P,"",0));
+		&xor(	$tmp3,	$tmp3);
+
+		&xor($L,$tmp2);
+		for ($i=0; $i<$BF_ROUNDS; $i+=2)
+			{
+			&comment("");
+			&comment("Round $i");
+			&BF_ENCRYPT($i+1,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,1);
+
+			&comment("");
+			&comment("Round ".sprintf("%d",$i+1));
+			&BF_ENCRYPT($i+2,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,1);
+			}
+		# &mov($tmp1,&wparam(0)); In last loop
+		&mov($tmp4,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
+		}
+	else
+		{
+		 &mov($tmp2,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
+		&xor(	$tmp3,	$tmp3);
+
+		&xor($L,$tmp2);
+		for ($i=$BF_ROUNDS; $i>0; $i-=2)
+			{
+			&comment("");
+			&comment("Round $i");
+			&BF_ENCRYPT($i,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,0);
+			&comment("");
+			&comment("Round ".sprintf("%d",$i-1));
+			&BF_ENCRYPT($i-1,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,0);
+			}
+		# &mov($tmp1,&wparam(0)); In last loop
+		&mov($tmp4,&DWP(0,$P,"",0));
+		}
+
+	&xor($R,$tmp4);
+	&mov(&DWP(4,$tmp1,"",0),$L);
+
+	&mov(&DWP(0,$tmp1,"",0),$R);
+	&function_end($name);
+	}
+
+sub BF_ENCRYPT
+	{
+	local($i,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,$enc)=@_;
+
+	&mov(	$tmp4,		&DWP(&n2a($i*4),$P,"",0)); # for next round
+
+	&mov(	$tmp2,		$R);
+	&xor(	$L,		$tmp4);
+
+	&shr(	$tmp2,		16);
+	&mov(	$tmp4,		$R);
+
+	&movb(	&LB($tmp1),	&HB($tmp2));	# A
+	&and(	$tmp2,		0xff);		# B
+
+	&movb(	&LB($tmp3),	&HB($tmp4));	# C
+	&and(	$tmp4,		0xff);		# D
+
+	&mov(	$tmp1,		&DWP(&n2a($BF_OFF+0x0000),$P,$tmp1,4));
+	&mov(	$tmp2,		&DWP(&n2a($BF_OFF+0x0400),$P,$tmp2,4));
+
+	&add(	$tmp2,		$tmp1);
+	&mov(	$tmp1,		&DWP(&n2a($BF_OFF+0x0800),$P,$tmp3,4));
+
+	&xor(	$tmp2,		$tmp1);
+	&mov(	$tmp4,		&DWP(&n2a($BF_OFF+0x0C00),$P,$tmp4,4));
+
+	&add(	$tmp2,		$tmp4);
+	if (($enc && ($i != 16)) || ((!$enc) && ($i != 1)))
+		{ &xor(	$tmp1,		$tmp1); }
+	else
+		{
+		&comment("Load parameter 0 ($i) enc=$enc");
+		&mov($tmp1,&wparam(0));
+		} # In last loop
+
+	&xor(	$L,		$tmp2);
+	# delay
+	}
+
+sub n2a
+	{
+	sprintf("%d",$_[0]);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/asm/bf-686.pl linux-patched/net/ipsec/libcrypto/libblowfish/asm/bf-686.pl
--- linux/net/ipsec/libcrypto/libblowfish/asm/bf-686.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/asm/bf-686.pl	Thu Sep  5 04:42:26 2002
@@ -0,0 +1,127 @@
+#!/usr/local/bin/perl
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+require "cbc.pl";
+
+&asm_init($ARGV[0],"bf-686.pl");
+
+$BF_ROUNDS=16;
+$BF_OFF=($BF_ROUNDS+2)*4;
+$L="ecx";
+$R="edx";
+$P="edi";
+$tot="esi";
+$tmp1="eax";
+$tmp2="ebx";
+$tmp3="ebp";
+
+&des_encrypt("BF_encrypt",1);
+&des_encrypt("BF_decrypt",0);
+&cbc("BF_cbc_encrypt","BF_encrypt","BF_decrypt",1,4,5,3,-1,-1);
+
+&asm_finish();
+
+&file_end();
+
+sub des_encrypt
+	{
+	local($name,$enc)=@_;
+
+	&function_begin($name,"");
+
+	&comment("");
+	&comment("Load the 2 words");
+	&mov("eax",&wparam(0));
+	&mov($L,&DWP(0,"eax","",0));
+	&mov($R,&DWP(4,"eax","",0));
+
+	&comment("");
+	&comment("P pointer, s and enc flag");
+	&mov($P,&wparam(1));
+
+	&xor(	$tmp1,	$tmp1);
+	&xor(	$tmp2,	$tmp2);
+
+	# encrypting part
+
+	if ($enc)
+		{
+		&xor($L,&DWP(0,$P,"",0));
+		for ($i=0; $i<$BF_ROUNDS; $i+=2)
+			{
+			&comment("");
+			&comment("Round $i");
+			&BF_ENCRYPT($i+1,$R,$L,$P,$tot,$tmp1,$tmp2,$tmp3);
+
+			&comment("");
+			&comment("Round ".sprintf("%d",$i+1));
+			&BF_ENCRYPT($i+2,$L,$R,$P,$tot,$tmp1,$tmp2,$tmp3);
+			}
+		&xor($R,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
+
+		&mov("eax",&wparam(0));
+		&mov(&DWP(0,"eax","",0),$R);
+		&mov(&DWP(4,"eax","",0),$L);
+		&function_end_A($name);
+		}
+	else
+		{
+		&xor($L,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
+		for ($i=$BF_ROUNDS; $i>0; $i-=2)
+			{
+			&comment("");
+			&comment("Round $i");
+			&BF_ENCRYPT($i,$R,$L,$P,$tot,$tmp1,$tmp2,$tmp3);
+			&comment("");
+			&comment("Round ".sprintf("%d",$i-1));
+			&BF_ENCRYPT($i-1,$L,$R,$P,$tot,$tmp1,$tmp2,$tmp3);
+			}
+		&xor($R,&DWP(0,$P,"",0));
+
+		&mov("eax",&wparam(0));
+		&mov(&DWP(0,"eax","",0),$R);
+		&mov(&DWP(4,"eax","",0),$L);
+		&function_end_A($name);
+		}
+
+	&function_end_B($name);
+	}
+
+sub BF_ENCRYPT
+	{
+	local($i,$L,$R,$P,$tot,$tmp1,$tmp2,$tmp3)=@_;
+
+	&rotr(	$R,		16);
+	&mov(	$tot,		&DWP(&n2a($i*4),$P,"",0));
+
+	&movb(	&LB($tmp1),	&HB($R));
+	&movb(	&LB($tmp2),	&LB($R));
+
+	&rotr(	$R,		16);
+	&xor(	$L,		$tot);
+
+	&mov(	$tot,		&DWP(&n2a($BF_OFF+0x0000),$P,$tmp1,4));
+	&mov(	$tmp3,		&DWP(&n2a($BF_OFF+0x0400),$P,$tmp2,4));
+
+	&movb(	&LB($tmp1),	&HB($R));
+	&movb(	&LB($tmp2),	&LB($R));
+
+	&add(	$tot,		$tmp3);
+	&mov(	$tmp1,		&DWP(&n2a($BF_OFF+0x0800),$P,$tmp1,4)); # delay
+
+	&xor(	$tot,		$tmp1);
+	&mov(	$tmp3,		&DWP(&n2a($BF_OFF+0x0C00),$P,$tmp2,4));
+
+	&add(	$tot,		$tmp3);
+	&xor(	$tmp1,		$tmp1);
+
+	&xor(	$L,		$tot);					
+	# delay
+	}
+
+sub n2a
+	{
+	sprintf("%d",$_[0]);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/asm/readme linux-patched/net/ipsec/libcrypto/libblowfish/asm/readme
--- linux/net/ipsec/libcrypto/libblowfish/asm/readme	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/asm/readme	Thu Sep  5 04:42:26 2002
@@ -0,0 +1,10 @@
+There are blowfish assembler generation scripts.
+bf-586.pl version is for the pentium and
+bf-686.pl is my original version, which is faster on the pentium pro.
+
+When using a bf-586.pl, the pentium pro/II is %8 slower than using
+bf-686.pl.  When using a bf-686.pl, the pentium is %16 slower
+than bf-586.pl
+
+So the default is bf-586.pl
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/bf_enc.c linux-patched/net/ipsec/libcrypto/libblowfish/bf_enc.c
--- linux/net/ipsec/libcrypto/libblowfish/bf_enc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/bf_enc.c	Tue May 13 20:44:33 2003
@@ -0,0 +1,306 @@
+/* crypto/bf/bf_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "blowfish.h"
+#include "bf_locl.h"
+
+/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper'
+ * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION,
+ * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993)
+ */
+
+#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20)
+#error If you set BF_ROUNDS to some value other than 16 or 20, you will have \
+to modify the code.
+#endif
+
+void BF_encrypt(BF_LONG *data, const BF_KEY *key)
+	{
+#ifndef BF_PTR2
+	const BF_LONG *p,*s;
+	BF_LONG l,r;
+
+	p=key->P;
+	s= &(key->S[0]);
+	l=data[0];
+	r=data[1];
+
+	l^=p[0];
+	BF_ENC(r,l,s,p[ 1]);
+	BF_ENC(l,r,s,p[ 2]);
+	BF_ENC(r,l,s,p[ 3]);
+	BF_ENC(l,r,s,p[ 4]);
+	BF_ENC(r,l,s,p[ 5]);
+	BF_ENC(l,r,s,p[ 6]);
+	BF_ENC(r,l,s,p[ 7]);
+	BF_ENC(l,r,s,p[ 8]);
+	BF_ENC(r,l,s,p[ 9]);
+	BF_ENC(l,r,s,p[10]);
+	BF_ENC(r,l,s,p[11]);
+	BF_ENC(l,r,s,p[12]);
+	BF_ENC(r,l,s,p[13]);
+	BF_ENC(l,r,s,p[14]);
+	BF_ENC(r,l,s,p[15]);
+	BF_ENC(l,r,s,p[16]);
+#if BF_ROUNDS == 20
+	BF_ENC(r,l,s,p[17]);
+	BF_ENC(l,r,s,p[18]);
+	BF_ENC(r,l,s,p[19]);
+	BF_ENC(l,r,s,p[20]);
+#endif
+	r^=p[BF_ROUNDS+1];
+
+	data[1]=l&0xffffffffL;
+	data[0]=r&0xffffffffL;
+#else
+	BF_LONG l,r,t,*k;
+
+	l=data[0];
+	r=data[1];
+	k=(BF_LONG*)key;
+
+	l^=k[0];
+	BF_ENC(r,l,k, 1);
+	BF_ENC(l,r,k, 2);
+	BF_ENC(r,l,k, 3);
+	BF_ENC(l,r,k, 4);
+	BF_ENC(r,l,k, 5);
+	BF_ENC(l,r,k, 6);
+	BF_ENC(r,l,k, 7);
+	BF_ENC(l,r,k, 8);
+	BF_ENC(r,l,k, 9);
+	BF_ENC(l,r,k,10);
+	BF_ENC(r,l,k,11);
+	BF_ENC(l,r,k,12);
+	BF_ENC(r,l,k,13);
+	BF_ENC(l,r,k,14);
+	BF_ENC(r,l,k,15);
+	BF_ENC(l,r,k,16);
+#if BF_ROUNDS == 20
+	BF_ENC(r,l,k,17);
+	BF_ENC(l,r,k,18);
+	BF_ENC(r,l,k,19);
+	BF_ENC(l,r,k,20);
+#endif
+	r^=k[BF_ROUNDS+1];
+
+	data[1]=l&0xffffffffL;
+	data[0]=r&0xffffffffL;
+#endif
+	}
+
+#ifndef BF_DEFAULT_OPTIONS
+
+void BF_decrypt(BF_LONG *data, const BF_KEY *key)
+	{
+#ifndef BF_PTR2
+	const BF_LONG *p,*s;
+	BF_LONG l,r;
+
+	p=key->P;
+	s= &(key->S[0]);
+	l=data[0];
+	r=data[1];
+
+	l^=p[BF_ROUNDS+1];
+#if BF_ROUNDS == 20
+	BF_ENC(r,l,s,p[20]);
+	BF_ENC(l,r,s,p[19]);
+	BF_ENC(r,l,s,p[18]);
+	BF_ENC(l,r,s,p[17]);
+#endif
+	BF_ENC(r,l,s,p[16]);
+	BF_ENC(l,r,s,p[15]);
+	BF_ENC(r,l,s,p[14]);
+	BF_ENC(l,r,s,p[13]);
+	BF_ENC(r,l,s,p[12]);
+	BF_ENC(l,r,s,p[11]);
+	BF_ENC(r,l,s,p[10]);
+	BF_ENC(l,r,s,p[ 9]);
+	BF_ENC(r,l,s,p[ 8]);
+	BF_ENC(l,r,s,p[ 7]);
+	BF_ENC(r,l,s,p[ 6]);
+	BF_ENC(l,r,s,p[ 5]);
+	BF_ENC(r,l,s,p[ 4]);
+	BF_ENC(l,r,s,p[ 3]);
+	BF_ENC(r,l,s,p[ 2]);
+	BF_ENC(l,r,s,p[ 1]);
+	r^=p[0];
+
+	data[1]=l&0xffffffffL;
+	data[0]=r&0xffffffffL;
+#else
+	BF_LONG l,r,t,*k;
+
+	l=data[0];
+	r=data[1];
+	k=(BF_LONG *)key;
+
+	l^=k[BF_ROUNDS+1];
+#if BF_ROUNDS == 20
+	BF_ENC(r,l,k,20);
+	BF_ENC(l,r,k,19);
+	BF_ENC(r,l,k,18);
+	BF_ENC(l,r,k,17);
+#endif
+	BF_ENC(r,l,k,16);
+	BF_ENC(l,r,k,15);
+	BF_ENC(r,l,k,14);
+	BF_ENC(l,r,k,13);
+	BF_ENC(r,l,k,12);
+	BF_ENC(l,r,k,11);
+	BF_ENC(r,l,k,10);
+	BF_ENC(l,r,k, 9);
+	BF_ENC(r,l,k, 8);
+	BF_ENC(l,r,k, 7);
+	BF_ENC(r,l,k, 6);
+	BF_ENC(l,r,k, 5);
+	BF_ENC(r,l,k, 4);
+	BF_ENC(l,r,k, 3);
+	BF_ENC(r,l,k, 2);
+	BF_ENC(l,r,k, 1);
+	r^=k[0];
+
+	data[1]=l&0xffffffffL;
+	data[0]=r&0xffffffffL;
+#endif
+	}
+
+void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+	     const BF_KEY *schedule, unsigned char *ivec, int encrypt)
+	{
+	BF_LONG tin0,tin1;
+	BF_LONG tout0,tout1,xor0,xor1;
+	long l=length;
+	BF_LONG tin[2];
+
+	if (encrypt)
+		{
+		n2l(ivec,tout0);
+		n2l(ivec,tout1);
+		ivec-=8;
+		for (l-=8; l>=0; l-=8)
+			{
+			n2l(in,tin0);
+			n2l(in,tin1);
+			tin0^=tout0;
+			tin1^=tout1;
+			tin[0]=tin0;
+			tin[1]=tin1;
+			BF_encrypt(tin,schedule);
+			tout0=tin[0];
+			tout1=tin[1];
+			l2n(tout0,out);
+			l2n(tout1,out);
+			}
+		if (l != -8)
+			{
+			n2ln(in,tin0,tin1,l+8);
+			tin0^=tout0;
+			tin1^=tout1;
+			tin[0]=tin0;
+			tin[1]=tin1;
+			BF_encrypt(tin,schedule);
+			tout0=tin[0];
+			tout1=tin[1];
+			l2n(tout0,out);
+			l2n(tout1,out);
+			}
+		l2n(tout0,ivec);
+		l2n(tout1,ivec);
+		}
+	else
+		{
+		n2l(ivec,xor0);
+		n2l(ivec,xor1);
+		ivec-=8;
+		for (l-=8; l>=0; l-=8)
+			{
+			n2l(in,tin0);
+			n2l(in,tin1);
+			tin[0]=tin0;
+			tin[1]=tin1;
+			BF_decrypt(tin,schedule);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2n(tout0,out);
+			l2n(tout1,out);
+			xor0=tin0;
+			xor1=tin1;
+			}
+		if (l != -8)
+			{
+			n2l(in,tin0);
+			n2l(in,tin1);
+			tin[0]=tin0;
+			tin[1]=tin1;
+			BF_decrypt(tin,schedule);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2nn(tout0,tout1,out,l+8);
+			xor0=tin0;
+			xor1=tin1;
+			}
+		l2n(xor0,ivec);
+		l2n(xor1,ivec);
+		}
+	tin0=tin1=tout0=tout1=xor0=xor1=0;
+	tin[0]=tin[1]=0;
+	}
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/bf_locl.h linux-patched/net/ipsec/libcrypto/libblowfish/bf_locl.h
--- linux/net/ipsec/libcrypto/libblowfish/bf_locl.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/bf_locl.h	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,218 @@
+/* crypto/bf/bf_locl.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BF_LOCL_H
+#define HEADER_BF_LOCL_H
+
+#undef c2l
+#define c2l(c,l)	(l =((unsigned long)(*((c)++)))    , \
+			 l|=((unsigned long)(*((c)++)))<< 8L, \
+			 l|=((unsigned long)(*((c)++)))<<16L, \
+			 l|=((unsigned long)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#undef c2ln
+#define c2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))<<24L; \
+			case 7: l2|=((unsigned long)(*(--(c))))<<16L; \
+			case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \
+			case 5: l2|=((unsigned long)(*(--(c))));     \
+			case 4: l1 =((unsigned long)(*(--(c))))<<24L; \
+			case 3: l1|=((unsigned long)(*(--(c))))<<16L; \
+			case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \
+			case 1: l1|=((unsigned long)(*(--(c))));     \
+				} \
+			}
+
+#undef l2c
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#undef l2cn
+#define l2cn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \
+				} \
+			}
+
+/* NOTE - c is not incremented as per n2l */
+#define n2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))    ; \
+			case 7: l2|=((unsigned long)(*(--(c))))<< 8; \
+			case 6: l2|=((unsigned long)(*(--(c))))<<16; \
+			case 5: l2|=((unsigned long)(*(--(c))))<<24; \
+			case 4: l1 =((unsigned long)(*(--(c))))    ; \
+			case 3: l1|=((unsigned long)(*(--(c))))<< 8; \
+			case 2: l1|=((unsigned long)(*(--(c))))<<16; \
+			case 1: l1|=((unsigned long)(*(--(c))))<<24; \
+				} \
+			}
+
+/* NOTE - c is not incremented as per l2n */
+#define l2nn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)    )&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)    )&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+				} \
+			}
+
+#undef n2l
+#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L, \
+                         l|=((unsigned long)(*((c)++)))<<16L, \
+                         l|=((unsigned long)(*((c)++)))<< 8L, \
+                         l|=((unsigned long)(*((c)++))))
+
+#undef l2n
+#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)     )&0xff))
+
+/* This is actually a big endian algorithm, the most significant byte
+ * is used to lookup array 0 */
+
+#if defined(BF_PTR2)
+
+/*
+ * This is basically a special Intel version. Point is that Intel
+ * doesn't have many registers, but offers a reach choice of addressing
+ * modes. So we spare some registers by directly traversing BF_KEY
+ * structure and hiring the most decorated addressing mode. The code
+ * generated by EGCS is *perfectly* competitive with assembler
+ * implementation!
+ */
+#define BF_ENC(LL,R,KEY,Pi) (\
+	LL^=KEY[Pi], \
+	t=  KEY[BF_ROUNDS+2 +   0 + ((R>>24)&0xFF)], \
+	t+= KEY[BF_ROUNDS+2 + 256 + ((R>>16)&0xFF)], \
+	t^= KEY[BF_ROUNDS+2 + 512 + ((R>>8 )&0xFF)], \
+	t+= KEY[BF_ROUNDS+2 + 768 + ((R    )&0xFF)], \
+	LL^=t \
+	)
+
+#elif defined(BF_PTR)
+
+#ifndef BF_LONG_LOG2
+#define BF_LONG_LOG2  2       /* default to BF_LONG being 32 bits */
+#endif
+#define BF_M  (0xFF<<BF_LONG_LOG2)
+#define BF_0  (24-BF_LONG_LOG2)
+#define BF_1  (16-BF_LONG_LOG2)
+#define BF_2  ( 8-BF_LONG_LOG2)
+#define BF_3  BF_LONG_LOG2 /* left shift */
+
+/*
+ * This is normally very good on RISC platforms where normally you
+ * have to explicitly "multiply" array index by sizeof(BF_LONG)
+ * in order to calculate the effective address. This implementation
+ * excuses CPU from this extra work. Power[PC] uses should have most
+ * fun as (R>>BF_i)&BF_M gets folded into a single instruction, namely
+ * rlwinm. So let'em double-check if their compiler does it.
+ */
+
+#define BF_ENC(LL,R,S,P) ( \
+	LL^=P, \
+	LL^= (((*(BF_LONG *)((unsigned char *)&(S[  0])+((R>>BF_0)&BF_M))+ \
+		*(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \
+		*(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \
+		*(BF_LONG *)((unsigned char *)&(S[768])+((R<<BF_3)&BF_M))) \
+	)
+#else
+
+/*
+ * This is a *generic* version. Seem to perform best on platforms that
+ * offer explicit support for extraction of 8-bit nibbles preferably
+ * complemented with "multiplying" of array index by sizeof(BF_LONG).
+ * For the moment of this writing the list comprises Alpha CPU featuring
+ * extbl and s[48]addq instructions.
+ */
+
+#define BF_ENC(LL,R,S,P) ( \
+	LL^=P, \
+	LL^=(((	S[       ((int)(R>>24)&0xff)] + \
+		S[0x0100+((int)(R>>16)&0xff)])^ \
+		S[0x0200+((int)(R>> 8)&0xff)])+ \
+		S[0x0300+((int)(R    )&0xff)])&0xffffffffL \
+	)
+#endif
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/bf_pi.h linux-patched/net/ipsec/libcrypto/libblowfish/bf_pi.h
--- linux/net/ipsec/libcrypto/libblowfish/bf_pi.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/bf_pi.h	Thu Sep  5 04:39:46 2002
@@ -0,0 +1,325 @@
+/* crypto/bf/bf_pi.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+static const BF_KEY bf_init= {
+	{
+	0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L,
+	0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L,
+	0x452821e6L, 0x38d01377L, 0xbe5466cfL, 0x34e90c6cL,
+	0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, 0xb5470917L,
+	0x9216d5d9L, 0x8979fb1b
+	},{
+	0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L, 
+	0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L, 
+	0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, 0x858efc16L, 
+	0x636920d8L, 0x71574e69L, 0xa458fea3L, 0xf4933d7eL, 
+	0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL, 
+	0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L, 
+	0xc5d1b023L, 0x286085f0L, 0xca417918L, 0xb8db38efL, 
+	0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, 0xb01e8a3eL, 
+	0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, 0x55605c60L, 
+	0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L, 
+	0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL, 
+	0xa15486afL, 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL, 
+	0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, 0x9b87931eL, 
+	0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, 0x28958677L, 
+	0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L, 
+	0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L, 
+	0xef845d5dL, 0xe98575b1L, 0xdc262302L, 0xeb651b88L, 
+	0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, 0x83f44239L, 
+	0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, 0x9e1f9b5eL, 
+	0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L, 
+	0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L, 
+	0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L, 
+	0xa1f1651dL, 0x39af0176L, 0x66ca593eL, 0x82430e88L, 
+	0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, 0x3b8b5ebeL, 
+	0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L, 
+	0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL, 
+	0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL, 
+	0x075372c9L, 0x80991b7bL, 0x25d479d8L, 0xf6e8def7L, 
+	0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, 0x04c006baL, 
+	0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L, 
+	0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL, 
+	0x6dfc511fL, 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L, 
+	0xbee3d004L, 0xde334afdL, 0x660f2807L, 0x192e4bb3L, 
+	0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, 0xb9d3fbdbL, 
+	0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L, 
+	0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L, 
+	0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, 0xad0552abL, 
+	0x323db5faL, 0xfd238760L, 0x53317b48L, 0x3e00df82L, 
+	0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, 0xdf1769dbL, 
+	0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L, 
+	0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L, 
+	0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL, 
+	0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, 0x4bfb9790L, 
+	0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, 0xcee4c6e8L, 
+	0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L, 
+	0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L, 
+	0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L, 
+	0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, 0x900df01cL, 
+	0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, 0xb3a8c1adL, 
+	0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L, 
+	0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L, 
+	0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L, 
+	0x165fa266L, 0x80957705L, 0x93cc7314L, 0x211a1477L, 
+	0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, 0xfb9d35cfL, 
+	0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L, 
+	0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL, 
+	0x2464369bL, 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL, 
+	0x78c14389L, 0xd95a537fL, 0x207d5ba2L, 0x02e5b9c5L, 
+	0x83260376L, 0x6295cfa9L, 0x11c81968L, 0x4e734a41L, 
+	0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L, 
+	0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L, 
+	0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L, 
+	0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, 0xc5855664L, 
+	0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, 0x6e85076aL, 
+	0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L, 
+	0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L, 
+	0xecaa8c71L, 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L, 
+	0x193602a5L, 0x75094c29L, 0xa0591340L, 0xe4183a3eL, 
+	0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, 0x99f73fd6L, 
+	0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L, 
+	0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL, 
+	0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L, 
+	0x687f3584L, 0x52a0e286L, 0xb79c5305L, 0xaa500737L, 
+	0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, 0x5716f2b8L, 
+	0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL, 
+	0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL, 
+	0xd19113f9L, 0x7ca92ff6L, 0x94324773L, 0x22f54701L, 
+	0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, 0x9af3dda7L, 
+	0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, 0xa4751e41L, 
+	0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L, 
+	0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL, 
+	0x2cb81290L, 0x24977c79L, 0x5679b072L, 0xbcaf89afL, 
+	0xde9a771fL, 0xd9930810L, 0xb38bae12L, 0xdccf3f2eL, 
+	0x5512721fL, 0x2e6b7124L, 0x501adde6L, 0x9f84cd87L, 
+	0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL, 
+	0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L, 
+	0xef1c1847L, 0x3215d908L, 0xdd433b37L, 0x24c2ba16L, 
+	0x12a14d43L, 0x2a65c451L, 0x50940002L, 0x133ae4ddL, 
+	0x71dff89eL, 0x10314e55L, 0x81ac77d6L, 0x5f11199bL, 
+	0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L, 
+	0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL, 
+	0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L, 
+	0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, 0x99e71d0fL, 
+	0x803e89d6L, 0x5266c825L, 0x2e4cc978L, 0x9c10b36aL, 
+	0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L, 
+	0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L, 
+	0x5223a708L, 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L, 
+	0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, 0x018cff28L, 
+	0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, 0x68ab9802L, 
+	0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L, 
+	0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L, 
+	0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL, 
+	0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, 0xcbaade14L, 
+	0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, 0xb2f3846eL, 
+	0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L, 
+	0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L, 
+	0x9b540b19L, 0x875fa099L, 0x95f7997eL, 0x623d7da8L, 
+	0xf837889aL, 0x97e32d77L, 0x11ed935fL, 0x16681281L, 
+	0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, 0x7858ba99L, 
+	0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L, 
+	0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L, 
+	0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L, 
+	0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, 0x203e13e0L, 
+	0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, 0xfacb4fd0L, 
+	0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L, 
+	0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L, 
+	0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L, 
+	0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, 0x5692b285L, 
+	0x095bbf00L, 0xad19489dL, 0x1462b174L, 0x23820e00L, 
+	0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L, 
+	0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL, 
+	0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, 0xce77326eL, 
+	0xa6078084L, 0x19f8509eL, 0xe8efd855L, 0x61d99735L, 
+	0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, 0x800bcadcL, 
+	0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L, 
+	0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L, 
+	0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L, 
+	0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, 0xdb83adf7L, 
+	0xe93d5a68L, 0x948140f7L, 0xf64c261cL, 0x94692934L, 
+	0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L, 
+	0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL, 
+	0x1e39f62eL, 0x97244546L, 0x14214f74L, 0xbf8b8840L, 
+	0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, 0x66a02f45L, 
+	0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, 0x31cb8504L, 
+	0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL, 
+	0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL, 
+	0x68dc1462L, 0xd7486900L, 0x680ec0a4L, 0x27a18deeL, 
+	0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, 0x7af4d6b6L, 
+	0xaace1e7cL, 0xd3375fecL, 0xce78a399L, 0x406b2a42L, 
+	0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL, 
+	0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L, 
+	0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL, 
+	0xfb0af54eL, 0xd8feb397L, 0x454056acL, 0xba489527L, 
+	0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, 0xd096954bL, 
+	0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L, 
+	0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL, 
+	0xfdf8e802L, 0x04272f70L, 0x80bb155cL, 0x05282ce3L, 
+	0x95c11548L, 0xe4c66d22L, 0x48c1133fL, 0xc70f86dcL, 
+	0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, 0x5d886e17L, 
+	0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L, 
+	0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL, 
+	0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, 0xcad18115L, 
+	0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, 0xeebeb922L, 
+	0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, 0x2da2f728L, 
+	0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L, 
+	0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL, 
+	0x0a476341L, 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L, 
+	0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, 0xdb6e6b0dL, 
+	0xc67b5510L, 0x6d672c37L, 0x2765d43bL, 0xdcd0e804L, 
+	0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL, 
+	0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L, 
+	0xbb132f88L, 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL, 
+	0x37392eb3L, 0xcc115979L, 0x8026e297L, 0xf42e312dL, 
+	0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, 0x782ef11cL, 
+	0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L, 
+	0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L, 
+	0x44421659L, 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL, 
+	0x64af674eL, 0xda86a85fL, 0xbebfe988L, 0x64e4c3feL, 
+	0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, 0x6003604dL, 
+	0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL, 
+	0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL, 
+	0x77a057beL, 0xbde8ae24L, 0x55464299L, 0xbf582e61L, 
+	0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, 0x8789bdc2L, 
+	0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, 0x46fcd9b9L, 
+	0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L, 
+	0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL, 
+	0xb90bace1L, 0xbb8205d0L, 0x11a86248L, 0x7574a99eL, 
+	0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, 0xc4324633L, 
+	0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, 0x1d6efe10L, 
+	0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L, 
+	0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L, 
+	0x50115e01L, 0xa70683faL, 0xa002b5c4L, 0x0de6d027L, 
+	0x9af88c27L, 0x773f8641L, 0xc3604c06L, 0x61a806b5L, 
+	0xf0177a28L, 0xc0f586e0L, 0x006058aaL, 0x30dc7d62L, 
+	0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L, 
+	0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L, 
+	0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L, 
+	0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, 0xd39eb8fcL, 
+	0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, 0x4dad0fc4L, 
+	0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL, 
+	0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L, 
+	0xd79a3234L, 0x92638212L, 0x670efa8eL, 0x406000e0L, 
+	0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, 0x5ac52d1bL, 
+	0x5cb0679eL, 0x4fa33742L, 0xd3822740L, 0x99bc9bbeL, 
+	0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL, 
+	0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L, 
+	0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L, 
+	0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, 0x4cd04dc6L, 
+	0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, 0xbe5ee304L, 
+	0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L, 
+	0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L, 
+	0x83c061baL, 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L, 
+	0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, 0xef5562e9L, 
+	0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, 0x77fa0a59L, 
+	0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L, 
+	0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L, 
+	0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L, 
+	0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, 0x5a88f54cL, 
+	0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, 0xed93fa9bL, 
+	0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L, 
+	0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL, 
+	0x15056dd4L, 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL, 
+	0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, 0xa93a072aL, 
+	0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, 0x26dcf319L, 
+	0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL, 
+	0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL, 
+	0x4de81751L, 0x3830dc8eL, 0x379d5862L, 0x9320f991L, 
+	0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, 0x774fbe32L, 
+	0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, 0x6413e680L, 
+	0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L, 
+	0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL, 
+	0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL, 
+	0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, 0xbcb4cdd5L, 
+	0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, 0xbf3c6f47L, 
+	0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L, 
+	0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL, 
+	0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L, 
+	0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, 0xce6ea048L, 
+	0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, 0x277227f8L, 
+	0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL, 
+	0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L, 
+	0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L, 
+	0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, 0xd50ada38L, 
+	0x0339c32aL, 0xc6913667L, 0x8df9317cL, 0xe0b12b4fL, 
+	0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL, 
+	0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L, 
+	0xfae59361L, 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L, 
+	0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, 0xcb03a442L, 
+	0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, 0x3278e964L, 
+	0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL, 
+	0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L, 
+	0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL, 
+	0xe54cda54L, 0x1edad891L, 0xce6279cfL, 0xcd3e7e6fL, 
+	0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, 0xf6fb2299L, 
+	0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L, 
+	0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL, 
+	0xde966292L, 0x81b949d0L, 0x4c50901bL, 0x71c65614L, 
+	0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, 0xc3f27b9aL, 
+	0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, 0x35bdd2f6L, 
+	0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL, 
+	0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L, 
+	0xba38209cL, 0xf746ce76L, 0x77afa1c5L, 0x20756060L, 
+	0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, 0x4cf9aa7eL, 
+	0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, 0xd6ebe1f9L, 
+	0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL, 
+	0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L, 
+	}
+	};
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/bf_skey.c linux-patched/net/ipsec/libcrypto/libblowfish/bf_skey.c
--- linux/net/ipsec/libcrypto/libblowfish/bf_skey.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/bf_skey.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,122 @@
+/* crypto/bf/bf_skey.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+
+#include "blowfish.h"
+#include "bf_locl.h"
+#include "bf_pi.h"
+
+void BF_set_key(BF_KEY *key, int len, const unsigned char *data)
+	{
+	int i;
+	BF_LONG *p,ri,in[2];
+	const unsigned char *d,*end;
+
+
+	memcpy((char *)key,(const char *)&bf_init,sizeof(BF_KEY));
+	p=key->P;
+
+	if (len > ((BF_ROUNDS+2)*4)) len=(BF_ROUNDS+2)*4;
+
+	d=data;
+	end= &(data[len]);
+	for (i=0; i<(BF_ROUNDS+2); i++)
+		{
+		ri= *(d++);
+		if (d >= end) d=data;
+
+		ri<<=8;
+		ri|= *(d++);
+		if (d >= end) d=data;
+
+		ri<<=8;
+		ri|= *(d++);
+		if (d >= end) d=data;
+
+		ri<<=8;
+		ri|= *(d++);
+		if (d >= end) d=data;
+
+		p[i]^=ri;
+		}
+
+	in[0]=0L;
+	in[1]=0L;
+	for (i=0; i<(BF_ROUNDS+2); i+=2)
+		{
+		BF_encrypt(in,key);
+		p[i  ]=in[0];
+		p[i+1]=in[1];
+		}
+
+	p=key->S;
+	for (i=0; i<4*256; i+=2)
+		{
+		BF_encrypt(in,key);
+		p[i  ]=in[0];
+		p[i+1]=in[1];
+		}
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libblowfish/blowfish.h linux-patched/net/ipsec/libcrypto/libblowfish/blowfish.h
--- linux/net/ipsec/libcrypto/libblowfish/blowfish.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libblowfish/blowfish.h	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,133 @@
+/* crypto/bf/blowfish.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BLOWFISH_H
+#define HEADER_BLOWFISH_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef NO_BF
+#error BF is disabled.
+#endif
+
+#define BF_ENCRYPT	1
+#define BF_DECRYPT	0
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! BF_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! BF_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(WIN16) || defined(__LP32__)
+#define BF_LONG unsigned long
+#elif defined(_CRAY) || defined(__ILP64__)
+#define BF_LONG unsigned long
+#define BF_LONG_LOG2 3
+#endif
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *					<appro@fy.chalmers.se>
+ */
+	
+/* des.h-like hack <jjo-ipsec@mendoza.gov.ar> */
+#ifndef BF_LONG
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#define BF_LONG u_int32_t
+#endif
+
+#define BF_ROUNDS	16
+#define BF_BLOCK	8
+
+typedef struct bf_key_st
+	{
+	BF_LONG P[BF_ROUNDS+2];
+	BF_LONG S[4*256];
+	} BF_KEY;
+
+ 
+void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+
+void BF_encrypt(BF_LONG *data,const BF_KEY *key);
+void BF_decrypt(BF_LONG *data,const BF_KEY *key);
+
+void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
+	const BF_KEY *key, int enc);
+void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+	const BF_KEY *schedule, unsigned char *ivec, int enc);
+void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+	const BF_KEY *schedule, unsigned char *ivec, int *num, int enc);
+void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+	const BF_KEY *schedule, unsigned char *ivec, int *num);
+const char *BF_options(void);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/Makefile linux-patched/net/ipsec/libcrypto/libcast/Makefile
--- linux/net/ipsec/libcrypto/libcast/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/Makefile	Thu Sep  5 04:48:04 2002
@@ -0,0 +1,112 @@
+#
+# SSLeay/crypto/cast/Makefile
+#
+
+DIR=	cast
+TOP=	../..
+CC=	cc
+CPP=	$(CC) -E
+INCLUDES=
+CFLAG=-g -I ../include -D__KERNEL__ -I/usr/src/linux/include
+INSTALL_PREFIX=
+OPENSSLDIR=     /usr/local/ssl
+INSTALLTOP=/usr/local/ssl
+MAKE=		make -f Makefile.ssl
+MAKEDEPEND=	$(TOP)/util/domd $(TOP)
+MAKEFILE=	Makefile.ssl
+AR=		ar r
+RANLIB=		ranlib
+PERL=		perl
+
+CAST_ENC := c_enc.o
+
+ASM-$(ARCH_ASM):=1
+ASM_X86:=$(ASM-i586)$(ASM-i686)
+ifneq ($(strip $(ASM_X86)),)
+	CAST_ENC:= asm/cx86-elf.o
+endif
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+GENERAL=Makefile
+TEST=casttest.c
+APPS=
+
+LIB=libcast.a
+LIBSRC=c_skey.c c_enc.c
+LIBOBJ=c_skey.o $(CAST_ENC)
+
+SRC= $(LIBSRC)
+
+EXHEADER= cast.h
+HEADER=	cast_s.h cast_lcl.h $(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+#top:
+#	(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all:	lib
+
+lib:	$(LIB)
+
+$(LIB):	$(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	$(RANLIB) $(LIB)
+
+# elf
+asm/cx86-elf.o: asm/cx86unix.cpp
+	$(CPP) -DELF -x c asm/cx86unix.cpp | as -o asm/cx86-elf.o
+
+# solaris
+asm/cx86-sol.o: asm/cx86unix.cpp
+	$(CC) -E -DSOL asm/cx86unix.cpp | sed 's/^#.*//' > asm/cx86-sol.s
+	as -o asm/cx86-sol.o asm/cx86-sol.s
+	rm -f asm/cx86-sol.s
+
+# a.out
+asm/cx86-out.o: asm/cx86unix.cpp
+	$(CPP) -DOUT asm/cx86unix.cpp | as -o asm/cx86-out.o
+
+# bsdi
+asm/cx86bsdi.o: asm/cx86unix.cpp
+	$(CPP) -DBSDI asm/cx86unix.cpp | sed 's/ :/:/' | as -o asm/cx86bsdi.o
+
+asm/cx86unix.cpp: asm/cast-586.pl ../perlasm/x86asm.pl ../perlasm/cbc.pl
+	(cd asm; $(PERL) cast-586.pl cpp $(PROCESSOR) >cx86unix.cpp)
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO
+
+links:
+	@$(TOP)/util/point.sh Makefile.ssl Makefile
+	@$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+	@$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+	@$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install:
+	@for i in $(EXHEADER) ; \
+	do  \
+	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	$(MAKEDEPEND) $(INCLUDES) $(DEPFLAG) $(PROGS) $(LIBSRC)
+
+dclean:
+	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	rm -f asm/cx86unix.cpp *.o asm/*.o *.obj $(LIB) tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/asm/cast-586.pl linux-patched/net/ipsec/libcrypto/libcast/asm/cast-586.pl
--- linux/net/ipsec/libcrypto/libcast/asm/cast-586.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/asm/cast-586.pl	Thu Sep  5 04:48:32 2002
@@ -0,0 +1,176 @@
+#!/usr/local/bin/perl
+
+# define for pentium pro friendly version
+$ppro=1;
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+require "cbc.pl";
+
+&asm_init($ARGV[0],"cast-586.pl",$ARGV[$#ARGV] eq "386");
+
+$CAST_ROUNDS=16;
+$L="edi";
+$R="esi";
+$K="ebp";
+$tmp1="ecx";
+$tmp2="ebx";
+$tmp3="eax";
+$tmp4="edx";
+$S1="CAST_S_table0";
+$S2="CAST_S_table1";
+$S3="CAST_S_table2";
+$S4="CAST_S_table3";
+
+@F1=("add","xor","sub");
+@F2=("xor","sub","add");
+@F3=("sub","add","xor");
+
+&CAST_encrypt("CAST_encrypt",1);
+&CAST_encrypt("CAST_decrypt",0);
+&cbc("CAST_cbc_encrypt","CAST_encrypt","CAST_decrypt",1,4,5,3,-1,-1);
+
+&asm_finish();
+
+sub CAST_encrypt {
+    local($name,$enc)=@_;
+
+    local($win_ex)=<<"EOF";
+EXTERN	_CAST_S_table0:DWORD
+EXTERN	_CAST_S_table1:DWORD
+EXTERN	_CAST_S_table2:DWORD
+EXTERN	_CAST_S_table3:DWORD
+EOF
+    &main::external_label(
+			  "CAST_S_table0",
+			  "CAST_S_table1",
+			  "CAST_S_table2",
+			  "CAST_S_table3",
+			  );
+
+    &function_begin_B($name,$win_ex);
+
+    &comment("");
+
+    &push("ebp");
+    &push("ebx");
+    &mov($tmp2,&wparam(0));
+    &mov($K,&wparam(1));
+    &push("esi");
+    &push("edi");
+
+    &comment("Load the 2 words");
+    &mov($L,&DWP(0,$tmp2,"",0));
+    &mov($R,&DWP(4,$tmp2,"",0));
+
+    &comment('Get short key flag');
+    &mov($tmp3,&DWP(128,$K,"",0));
+    if($enc) {
+	&push($tmp3);
+    } else {
+	&or($tmp3,$tmp3);
+	&jnz(&label('cast_dec_skip'));
+    }
+
+    &xor($tmp3,	$tmp3);
+
+    # encrypting part
+
+    if ($enc) {
+	&E_CAST( 0,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 1,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 2,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 3,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 4,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 5,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 6,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 7,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 8,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 9,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(10,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(11,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&comment('test short key flag');
+	&pop($tmp4);
+	&or($tmp4,$tmp4);
+	&jnz(&label('cast_enc_done'));
+	&E_CAST(12,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(13,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(14,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(15,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+    } else {
+	&E_CAST(15,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(14,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(13,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(12,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&set_label('cast_dec_skip');
+	&E_CAST(11,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST(10,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 9,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 8,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 7,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 6,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 5,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 4,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 3,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 2,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 1,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4);
+	&E_CAST( 0,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4);
+    }
+
+    &set_label('cast_enc_done') if $enc;
+# Why the nop? - Ben 17/1/99
+    &nop();
+    &mov($tmp3,&wparam(0));
+    &mov(&DWP(4,$tmp3,"",0),$L);
+    &mov(&DWP(0,$tmp3,"",0),$R);
+    &function_end($name);
+}
+
+sub E_CAST {
+    local($i,$S,$L,$R,$K,$OP1,$OP2,$OP3,$tmp1,$tmp2,$tmp3,$tmp4)=@_;
+    # Ri needs to have 16 pre added.
+
+    &comment("round $i");
+    &mov(	$tmp4,		&DWP($i*8,$K,"",1));
+
+    &mov(	$tmp1,		&DWP($i*8+4,$K,"",1));
+    &$OP1(	$tmp4,		$R);
+
+    &rotl(	$tmp4,		&LB($tmp1));
+
+    if ($ppro) {
+	&mov(	$tmp2,		$tmp4);		# B
+	&xor(	$tmp1,		$tmp1);
+	
+	&movb(	&LB($tmp1),	&HB($tmp4));	# A
+	&and(	$tmp2,		0xff);
+
+	&shr(	$tmp4,		16); 		#
+	&xor(	$tmp3,		$tmp3);
+    } else {
+	&mov(	$tmp2,		$tmp4);		# B
+	&movb(	&LB($tmp1),	&HB($tmp4));	# A	# BAD BAD BAD
+	
+	&shr(	$tmp4,		16); 		#
+	&and(	$tmp2,		0xff);
+    }
+
+    &movb(	&LB($tmp3),	&HB($tmp4));	# C	# BAD BAD BAD
+    &and(	$tmp4,		0xff);		# D
+
+    &mov(	$tmp1,		&DWP($S1,"",$tmp1,4));
+    &mov(	$tmp2,		&DWP($S2,"",$tmp2,4));
+
+    &$OP2(	$tmp1,		$tmp2);
+    &mov(	$tmp2,		&DWP($S3,"",$tmp3,4));
+
+    &$OP3(	$tmp1,		$tmp2);
+    &mov(	$tmp2,		&DWP($S4,"",$tmp4,4));
+
+    &$OP1(	$tmp1,		$tmp2);
+    # XXX
+
+    &xor(	$L,		$tmp1);
+    # XXX
+}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/asm/readme linux-patched/net/ipsec/libcrypto/libcast/asm/readme
--- linux/net/ipsec/libcrypto/libcast/asm/readme	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/asm/readme	Thu Sep  5 04:48:32 2002
@@ -0,0 +1,7 @@
+There is a ppro flag in cast-586 which turns on/off
+generation of pentium pro/II friendly code
+
+This flag makes the inner loop one cycle longer, but generates 
+code that runs %30 faster on the pentium pro/II, while only %7 slower
+on the pentium.  By default, this flag is on.
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/c_enc.c linux-patched/net/ipsec/libcrypto/libcast/c_enc.c
--- linux/net/ipsec/libcrypto/libcast/c_enc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/c_enc.c	Thu Sep  5 04:48:04 2002
@@ -0,0 +1,207 @@
+/* crypto/cast/c_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "cast.h"
+#include "cast_lcl.h"
+
+void CAST_encrypt(CAST_LONG *data, CAST_KEY *key)
+	{
+	register CAST_LONG l,r,*k,t;
+
+	k= &(key->data[0]);
+	l=data[0];
+	r=data[1];
+
+	E_CAST( 0,k,l,r,+,^,-);
+	E_CAST( 1,k,r,l,^,-,+);
+	E_CAST( 2,k,l,r,-,+,^);
+	E_CAST( 3,k,r,l,+,^,-);
+	E_CAST( 4,k,l,r,^,-,+);
+	E_CAST( 5,k,r,l,-,+,^);
+	E_CAST( 6,k,l,r,+,^,-);
+	E_CAST( 7,k,r,l,^,-,+);
+	E_CAST( 8,k,l,r,-,+,^);
+	E_CAST( 9,k,r,l,+,^,-);
+	E_CAST(10,k,l,r,^,-,+);
+	E_CAST(11,k,r,l,-,+,^);
+	if(!key->short_key)
+	    {
+	    E_CAST(12,k,l,r,+,^,-);
+	    E_CAST(13,k,r,l,^,-,+);
+	    E_CAST(14,k,l,r,-,+,^);
+	    E_CAST(15,k,r,l,+,^,-);
+	    }
+
+	data[1]=l&0xffffffffL;
+	data[0]=r&0xffffffffL;
+	}
+
+void CAST_decrypt(CAST_LONG *data, CAST_KEY *key)
+	{
+	register CAST_LONG l,r,*k,t;
+
+	k= &(key->data[0]);
+	l=data[0];
+	r=data[1];
+
+	if(!key->short_key)
+	    {
+	    E_CAST(15,k,l,r,+,^,-);
+	    E_CAST(14,k,r,l,-,+,^);
+	    E_CAST(13,k,l,r,^,-,+);
+	    E_CAST(12,k,r,l,+,^,-);
+	    }
+	E_CAST(11,k,l,r,-,+,^);
+	E_CAST(10,k,r,l,^,-,+);
+	E_CAST( 9,k,l,r,+,^,-);
+	E_CAST( 8,k,r,l,-,+,^);
+	E_CAST( 7,k,l,r,^,-,+);
+	E_CAST( 6,k,r,l,+,^,-);
+	E_CAST( 5,k,l,r,-,+,^);
+	E_CAST( 4,k,r,l,^,-,+);
+	E_CAST( 3,k,l,r,+,^,-);
+	E_CAST( 2,k,r,l,-,+,^);
+	E_CAST( 1,k,l,r,^,-,+);
+	E_CAST( 0,k,r,l,+,^,-);
+
+	data[1]=l&0xffffffffL;
+	data[0]=r&0xffffffffL;
+	}
+
+void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+	     CAST_KEY *ks, unsigned char *iv, int enc)
+	{
+	register CAST_LONG tin0,tin1;
+	register CAST_LONG tout0,tout1,xor0,xor1;
+	register long l=length;
+	CAST_LONG tin[2];
+
+	if (enc)
+		{
+		n2l(iv,tout0);
+		n2l(iv,tout1);
+		iv-=8;
+		for (l-=8; l>=0; l-=8)
+			{
+			n2l(in,tin0);
+			n2l(in,tin1);
+			tin0^=tout0;
+			tin1^=tout1;
+			tin[0]=tin0;
+			tin[1]=tin1;
+			CAST_encrypt(tin,ks);
+			tout0=tin[0];
+			tout1=tin[1];
+			l2n(tout0,out);
+			l2n(tout1,out);
+			}
+		if (l != -8)
+			{
+			n2ln(in,tin0,tin1,l+8);
+			tin0^=tout0;
+			tin1^=tout1;
+			tin[0]=tin0;
+			tin[1]=tin1;
+			CAST_encrypt(tin,ks);
+			tout0=tin[0];
+			tout1=tin[1];
+			l2n(tout0,out);
+			l2n(tout1,out);
+			}
+		l2n(tout0,iv);
+		l2n(tout1,iv);
+		}
+	else
+		{
+		n2l(iv,xor0);
+		n2l(iv,xor1);
+		iv-=8;
+		for (l-=8; l>=0; l-=8)
+			{
+			n2l(in,tin0);
+			n2l(in,tin1);
+			tin[0]=tin0;
+			tin[1]=tin1;
+			CAST_decrypt(tin,ks);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2n(tout0,out);
+			l2n(tout1,out);
+			xor0=tin0;
+			xor1=tin1;
+			}
+		if (l != -8)
+			{
+			n2l(in,tin0);
+			n2l(in,tin1);
+			tin[0]=tin0;
+			tin[1]=tin1;
+			CAST_decrypt(tin,ks);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2nn(tout0,tout1,out,l+8);
+			xor0=tin0;
+			xor1=tin1;
+			}
+		l2n(xor0,iv);
+		l2n(xor1,iv);
+		}
+	tin0=tin1=tout0=tout1=xor0=xor1=0;
+	tin[0]=tin[1]=0;
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/c_skey.c linux-patched/net/ipsec/libcrypto/libcast/c_skey.c
--- linux/net/ipsec/libcrypto/libcast/c_skey.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/c_skey.c	Thu Sep  5 04:48:04 2002
@@ -0,0 +1,166 @@
+/* crypto/cast/c_skey.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "cast.h"
+#include "cast_lcl.h"
+#include "cast_s.h"
+
+#define CAST_exp(l,A,a,n) \
+	A[n/4]=l; \
+	a[n+3]=(l    )&0xff; \
+	a[n+2]=(l>> 8)&0xff; \
+	a[n+1]=(l>>16)&0xff; \
+	a[n+0]=(l>>24)&0xff;
+
+#define S4 CAST_S_table4
+#define S5 CAST_S_table5
+#define S6 CAST_S_table6
+#define S7 CAST_S_table7
+
+void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data)
+	{
+	CAST_LONG x[16];
+	CAST_LONG z[16];
+	CAST_LONG k[32];
+	CAST_LONG X[4],Z[4];
+	CAST_LONG l,*K;
+	int i;
+
+	for (i=0; i<16; i++) x[i]=0;
+	if (len > 16) len=16;
+	for (i=0; i<len; i++)
+		x[i]=data[i];
+	if(len <= 10)
+	    key->short_key=1;
+	else
+	    key->short_key=0;
+
+	K= &k[0];
+	X[0]=((x[ 0]<<24)|(x[ 1]<<16)|(x[ 2]<<8)|x[ 3])&0xffffffffL;
+	X[1]=((x[ 4]<<24)|(x[ 5]<<16)|(x[ 6]<<8)|x[ 7])&0xffffffffL;
+	X[2]=((x[ 8]<<24)|(x[ 9]<<16)|(x[10]<<8)|x[11])&0xffffffffL;
+	X[3]=((x[12]<<24)|(x[13]<<16)|(x[14]<<8)|x[15])&0xffffffffL;
+
+	for (;;)
+		{
+	l=X[0]^S4[x[13]]^S5[x[15]]^S6[x[12]]^S7[x[14]]^S6[x[ 8]];
+	CAST_exp(l,Z,z, 0);
+	l=X[2]^S4[z[ 0]]^S5[z[ 2]]^S6[z[ 1]]^S7[z[ 3]]^S7[x[10]];
+	CAST_exp(l,Z,z, 4);
+	l=X[3]^S4[z[ 7]]^S5[z[ 6]]^S6[z[ 5]]^S7[z[ 4]]^S4[x[ 9]];
+	CAST_exp(l,Z,z, 8);
+	l=X[1]^S4[z[10]]^S5[z[ 9]]^S6[z[11]]^S7[z[ 8]]^S5[x[11]];
+	CAST_exp(l,Z,z,12);
+
+	K[ 0]= S4[z[ 8]]^S5[z[ 9]]^S6[z[ 7]]^S7[z[ 6]]^S4[z[ 2]];
+	K[ 1]= S4[z[10]]^S5[z[11]]^S6[z[ 5]]^S7[z[ 4]]^S5[z[ 6]];
+	K[ 2]= S4[z[12]]^S5[z[13]]^S6[z[ 3]]^S7[z[ 2]]^S6[z[ 9]];
+	K[ 3]= S4[z[14]]^S5[z[15]]^S6[z[ 1]]^S7[z[ 0]]^S7[z[12]];
+
+	l=Z[2]^S4[z[ 5]]^S5[z[ 7]]^S6[z[ 4]]^S7[z[ 6]]^S6[z[ 0]];
+	CAST_exp(l,X,x, 0);
+	l=Z[0]^S4[x[ 0]]^S5[x[ 2]]^S6[x[ 1]]^S7[x[ 3]]^S7[z[ 2]];
+	CAST_exp(l,X,x, 4);
+	l=Z[1]^S4[x[ 7]]^S5[x[ 6]]^S6[x[ 5]]^S7[x[ 4]]^S4[z[ 1]];
+	CAST_exp(l,X,x, 8);
+	l=Z[3]^S4[x[10]]^S5[x[ 9]]^S6[x[11]]^S7[x[ 8]]^S5[z[ 3]];
+	CAST_exp(l,X,x,12);
+
+	K[ 4]= S4[x[ 3]]^S5[x[ 2]]^S6[x[12]]^S7[x[13]]^S4[x[ 8]];
+	K[ 5]= S4[x[ 1]]^S5[x[ 0]]^S6[x[14]]^S7[x[15]]^S5[x[13]];
+	K[ 6]= S4[x[ 7]]^S5[x[ 6]]^S6[x[ 8]]^S7[x[ 9]]^S6[x[ 3]];
+	K[ 7]= S4[x[ 5]]^S5[x[ 4]]^S6[x[10]]^S7[x[11]]^S7[x[ 7]];
+
+	l=X[0]^S4[x[13]]^S5[x[15]]^S6[x[12]]^S7[x[14]]^S6[x[ 8]];
+	CAST_exp(l,Z,z, 0);
+	l=X[2]^S4[z[ 0]]^S5[z[ 2]]^S6[z[ 1]]^S7[z[ 3]]^S7[x[10]];
+	CAST_exp(l,Z,z, 4);
+	l=X[3]^S4[z[ 7]]^S5[z[ 6]]^S6[z[ 5]]^S7[z[ 4]]^S4[x[ 9]];
+	CAST_exp(l,Z,z, 8);
+	l=X[1]^S4[z[10]]^S5[z[ 9]]^S6[z[11]]^S7[z[ 8]]^S5[x[11]];
+	CAST_exp(l,Z,z,12);
+
+	K[ 8]= S4[z[ 3]]^S5[z[ 2]]^S6[z[12]]^S7[z[13]]^S4[z[ 9]];
+	K[ 9]= S4[z[ 1]]^S5[z[ 0]]^S6[z[14]]^S7[z[15]]^S5[z[12]];
+	K[10]= S4[z[ 7]]^S5[z[ 6]]^S6[z[ 8]]^S7[z[ 9]]^S6[z[ 2]];
+	K[11]= S4[z[ 5]]^S5[z[ 4]]^S6[z[10]]^S7[z[11]]^S7[z[ 6]];
+
+	l=Z[2]^S4[z[ 5]]^S5[z[ 7]]^S6[z[ 4]]^S7[z[ 6]]^S6[z[ 0]];
+	CAST_exp(l,X,x, 0);
+	l=Z[0]^S4[x[ 0]]^S5[x[ 2]]^S6[x[ 1]]^S7[x[ 3]]^S7[z[ 2]];
+	CAST_exp(l,X,x, 4);
+	l=Z[1]^S4[x[ 7]]^S5[x[ 6]]^S6[x[ 5]]^S7[x[ 4]]^S4[z[ 1]];
+	CAST_exp(l,X,x, 8);
+	l=Z[3]^S4[x[10]]^S5[x[ 9]]^S6[x[11]]^S7[x[ 8]]^S5[z[ 3]];
+	CAST_exp(l,X,x,12);
+
+	K[12]= S4[x[ 8]]^S5[x[ 9]]^S6[x[ 7]]^S7[x[ 6]]^S4[x[ 3]];
+	K[13]= S4[x[10]]^S5[x[11]]^S6[x[ 5]]^S7[x[ 4]]^S5[x[ 7]];
+	K[14]= S4[x[12]]^S5[x[13]]^S6[x[ 3]]^S7[x[ 2]]^S6[x[ 8]];
+	K[15]= S4[x[14]]^S5[x[15]]^S6[x[ 1]]^S7[x[ 0]]^S7[x[13]];
+	if (K != k)  break;
+	K+=16;
+		}
+
+	for (i=0; i<16; i++)
+		{
+		key->data[i*2]=k[i];
+		key->data[i*2+1]=((k[i+16])+16)&0x1f;
+		}
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/cast.h linux-patched/net/ipsec/libcrypto/libcast/cast.h
--- linux/net/ipsec/libcrypto/libcast/cast.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/cast.h	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,111 @@
+/* crypto/cast/cast.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CAST_H
+#define HEADER_CAST_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef NO_CAST
+#error CAST is disabled.
+#endif
+
+#define CAST_ENCRYPT	1
+#define CAST_DECRYPT	0
+
+/* des.h-like hack <jjo-ipsec@mendoza.gov.ar> */
+#ifndef CAST_LONG
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#define CAST_LONG u_int32_t
+#endif
+
+#define CAST_BLOCK	8
+#define CAST_KEY_LENGTH	16
+
+typedef struct cast_key_st
+	{
+	CAST_LONG data[32];
+	int short_key;	/* Use reduced rounds for short key */
+	} CAST_KEY;
+
+ 
+void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+void CAST_ecb_encrypt(const unsigned char *in,unsigned char *out,CAST_KEY *key,
+		      int enc);
+void CAST_encrypt(CAST_LONG *data,CAST_KEY *key);
+void CAST_decrypt(CAST_LONG *data,CAST_KEY *key);
+void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+		      CAST_KEY *ks, unsigned char *iv, int enc);
+void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+			long length, CAST_KEY *schedule, unsigned char *ivec,
+			int *num, int enc);
+void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, 
+			long length, CAST_KEY *schedule, unsigned char *ivec,
+			int *num);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/cast_lcl.h linux-patched/net/ipsec/libcrypto/libcast/cast_lcl.h
--- linux/net/ipsec/libcrypto/libcast/cast_lcl.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/cast_lcl.h	Thu Sep  5 04:48:04 2002
@@ -0,0 +1,227 @@
+/* crypto/cast/cast_lcl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifdef WIN32
+#include <stdlib.h>
+#endif
+
+
+# define OPENSSL_EXTERN extern
+# define OPENSSL_GLOBAL
+
+#undef c2l
+#define c2l(c,l)	(l =((unsigned long)(*((c)++)))    , \
+			 l|=((unsigned long)(*((c)++)))<< 8L, \
+			 l|=((unsigned long)(*((c)++)))<<16L, \
+			 l|=((unsigned long)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#undef c2ln
+#define c2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))<<24L; \
+			case 7: l2|=((unsigned long)(*(--(c))))<<16L; \
+			case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \
+			case 5: l2|=((unsigned long)(*(--(c))));     \
+			case 4: l1 =((unsigned long)(*(--(c))))<<24L; \
+			case 3: l1|=((unsigned long)(*(--(c))))<<16L; \
+			case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \
+			case 1: l1|=((unsigned long)(*(--(c))));     \
+				} \
+			}
+
+#undef l2c
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#undef l2cn
+#define l2cn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \
+				} \
+			}
+
+/* NOTE - c is not incremented as per n2l */
+#define n2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))    ; \
+			case 7: l2|=((unsigned long)(*(--(c))))<< 8; \
+			case 6: l2|=((unsigned long)(*(--(c))))<<16; \
+			case 5: l2|=((unsigned long)(*(--(c))))<<24; \
+			case 4: l1 =((unsigned long)(*(--(c))))    ; \
+			case 3: l1|=((unsigned long)(*(--(c))))<< 8; \
+			case 2: l1|=((unsigned long)(*(--(c))))<<16; \
+			case 1: l1|=((unsigned long)(*(--(c))))<<24; \
+				} \
+			}
+
+/* NOTE - c is not incremented as per l2n */
+#define l2nn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)    )&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)    )&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+				} \
+			}
+
+#undef n2l
+#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L, \
+                         l|=((unsigned long)(*((c)++)))<<16L, \
+                         l|=((unsigned long)(*((c)++)))<< 8L, \
+                         l|=((unsigned long)(*((c)++))))
+
+#undef l2n
+#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)     )&0xff))
+
+#if defined(WIN32) && defined(_MSC_VER)
+#define ROTL(a,n)     (_lrotl(a,n))
+#else
+#define ROTL(a,n)     ((((a)<<(n))&0xffffffffL)|((a)>>(32-(n))))
+#endif
+
+#define C_M    0x3fc
+#define C_0    22L
+#define C_1    14L
+#define C_2     6L
+#define C_3     2L /* left shift */
+
+/* The rotate has an extra 16 added to it to help the x86 asm */
+#if defined(CAST_PTR)
+#define E_CAST(n,key,L,R,OP1,OP2,OP3) \
+	{ \
+	int i; \
+	t=(key[n*2] OP1 R)&0xffffffffL; \
+	i=key[n*2+1]; \
+	t=ROTL(t,i); \
+	L^= (((((*(CAST_LONG *)((unsigned char *) \
+			CAST_S_table0+((t>>C_2)&C_M)) OP2 \
+		*(CAST_LONG *)((unsigned char *) \
+			CAST_S_table1+((t<<C_3)&C_M)))&0xffffffffL) OP3 \
+		*(CAST_LONG *)((unsigned char *) \
+			CAST_S_table2+((t>>C_0)&C_M)))&0xffffffffL) OP1 \
+		*(CAST_LONG *)((unsigned char *) \
+			CAST_S_table3+((t>>C_1)&C_M)))&0xffffffffL; \
+	}
+#elif defined(CAST_PTR2)
+#define E_CAST(n,key,L,R,OP1,OP2,OP3) \
+	{ \
+	int i; \
+	CAST_LONG u,v,w; \
+	w=(key[n*2] OP1 R)&0xffffffffL; \
+	i=key[n*2+1]; \
+	w=ROTL(w,i); \
+	u=w>>C_2; \
+	v=w<<C_3; \
+	u&=C_M; \
+	v&=C_M; \
+	t= *(CAST_LONG *)((unsigned char *)CAST_S_table0+u); \
+	u=w>>C_0; \
+	t=(t OP2 *(CAST_LONG *)((unsigned char *)CAST_S_table1+v))&0xffffffffL;\
+	v=w>>C_1; \
+	u&=C_M; \
+	v&=C_M; \
+	t=(t OP3 *(CAST_LONG *)((unsigned char *)CAST_S_table2+u)&0xffffffffL);\
+	t=(t OP1 *(CAST_LONG *)((unsigned char *)CAST_S_table3+v)&0xffffffffL);\
+	L^=(t&0xffffffff); \
+	}
+#else
+#define E_CAST(n,key,L,R,OP1,OP2,OP3) \
+	{ \
+	CAST_LONG a,b,c,d; \
+	t=(key[n*2] OP1 R)&0xffffffff; \
+	t=ROTL(t,(key[n*2+1])); \
+	a=CAST_S_table0[(t>> 8)&0xff]; \
+	b=CAST_S_table1[(t    )&0xff]; \
+	c=CAST_S_table2[(t>>24)&0xff]; \
+	d=CAST_S_table3[(t>>16)&0xff]; \
+	L^=(((((a OP2 b)&0xffffffffL) OP3 c)&0xffffffffL) OP1 d)&0xffffffffL; \
+	}
+#endif
+
+OPENSSL_EXTERN const CAST_LONG CAST_S_table0[256];
+OPENSSL_EXTERN const CAST_LONG CAST_S_table1[256];
+OPENSSL_EXTERN const CAST_LONG CAST_S_table2[256];
+OPENSSL_EXTERN const CAST_LONG CAST_S_table3[256];
+OPENSSL_EXTERN const CAST_LONG CAST_S_table4[256];
+OPENSSL_EXTERN const CAST_LONG CAST_S_table5[256];
+OPENSSL_EXTERN const CAST_LONG CAST_S_table6[256];
+OPENSSL_EXTERN const CAST_LONG CAST_S_table7[256];
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libcast/cast_s.h linux-patched/net/ipsec/libcrypto/libcast/cast_s.h
--- linux/net/ipsec/libcrypto/libcast/cast_s.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libcast/cast_s.h	Thu Sep  5 04:48:04 2002
@@ -0,0 +1,585 @@
+/* crypto/cast/cast_s.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table0[256]={
+	0x30fb40d4,0x9fa0ff0b,0x6beccd2f,0x3f258c7a,
+	0x1e213f2f,0x9c004dd3,0x6003e540,0xcf9fc949,
+	0xbfd4af27,0x88bbbdb5,0xe2034090,0x98d09675,
+	0x6e63a0e0,0x15c361d2,0xc2e7661d,0x22d4ff8e,
+	0x28683b6f,0xc07fd059,0xff2379c8,0x775f50e2,
+	0x43c340d3,0xdf2f8656,0x887ca41a,0xa2d2bd2d,
+	0xa1c9e0d6,0x346c4819,0x61b76d87,0x22540f2f,
+	0x2abe32e1,0xaa54166b,0x22568e3a,0xa2d341d0,
+	0x66db40c8,0xa784392f,0x004dff2f,0x2db9d2de,
+	0x97943fac,0x4a97c1d8,0x527644b7,0xb5f437a7,
+	0xb82cbaef,0xd751d159,0x6ff7f0ed,0x5a097a1f,
+	0x827b68d0,0x90ecf52e,0x22b0c054,0xbc8e5935,
+	0x4b6d2f7f,0x50bb64a2,0xd2664910,0xbee5812d,
+	0xb7332290,0xe93b159f,0xb48ee411,0x4bff345d,
+	0xfd45c240,0xad31973f,0xc4f6d02e,0x55fc8165,
+	0xd5b1caad,0xa1ac2dae,0xa2d4b76d,0xc19b0c50,
+	0x882240f2,0x0c6e4f38,0xa4e4bfd7,0x4f5ba272,
+	0x564c1d2f,0xc59c5319,0xb949e354,0xb04669fe,
+	0xb1b6ab8a,0xc71358dd,0x6385c545,0x110f935d,
+	0x57538ad5,0x6a390493,0xe63d37e0,0x2a54f6b3,
+	0x3a787d5f,0x6276a0b5,0x19a6fcdf,0x7a42206a,
+	0x29f9d4d5,0xf61b1891,0xbb72275e,0xaa508167,
+	0x38901091,0xc6b505eb,0x84c7cb8c,0x2ad75a0f,
+	0x874a1427,0xa2d1936b,0x2ad286af,0xaa56d291,
+	0xd7894360,0x425c750d,0x93b39e26,0x187184c9,
+	0x6c00b32d,0x73e2bb14,0xa0bebc3c,0x54623779,
+	0x64459eab,0x3f328b82,0x7718cf82,0x59a2cea6,
+	0x04ee002e,0x89fe78e6,0x3fab0950,0x325ff6c2,
+	0x81383f05,0x6963c5c8,0x76cb5ad6,0xd49974c9,
+	0xca180dcf,0x380782d5,0xc7fa5cf6,0x8ac31511,
+	0x35e79e13,0x47da91d0,0xf40f9086,0xa7e2419e,
+	0x31366241,0x051ef495,0xaa573b04,0x4a805d8d,
+	0x548300d0,0x00322a3c,0xbf64cddf,0xba57a68e,
+	0x75c6372b,0x50afd341,0xa7c13275,0x915a0bf5,
+	0x6b54bfab,0x2b0b1426,0xab4cc9d7,0x449ccd82,
+	0xf7fbf265,0xab85c5f3,0x1b55db94,0xaad4e324,
+	0xcfa4bd3f,0x2deaa3e2,0x9e204d02,0xc8bd25ac,
+	0xeadf55b3,0xd5bd9e98,0xe31231b2,0x2ad5ad6c,
+	0x954329de,0xadbe4528,0xd8710f69,0xaa51c90f,
+	0xaa786bf6,0x22513f1e,0xaa51a79b,0x2ad344cc,
+	0x7b5a41f0,0xd37cfbad,0x1b069505,0x41ece491,
+	0xb4c332e6,0x032268d4,0xc9600acc,0xce387e6d,
+	0xbf6bb16c,0x6a70fb78,0x0d03d9c9,0xd4df39de,
+	0xe01063da,0x4736f464,0x5ad328d8,0xb347cc96,
+	0x75bb0fc3,0x98511bfb,0x4ffbcc35,0xb58bcf6a,
+	0xe11f0abc,0xbfc5fe4a,0xa70aec10,0xac39570a,
+	0x3f04442f,0x6188b153,0xe0397a2e,0x5727cb79,
+	0x9ceb418f,0x1cacd68d,0x2ad37c96,0x0175cb9d,
+	0xc69dff09,0xc75b65f0,0xd9db40d8,0xec0e7779,
+	0x4744ead4,0xb11c3274,0xdd24cb9e,0x7e1c54bd,
+	0xf01144f9,0xd2240eb1,0x9675b3fd,0xa3ac3755,
+	0xd47c27af,0x51c85f4d,0x56907596,0xa5bb15e6,
+	0x580304f0,0xca042cf1,0x011a37ea,0x8dbfaadb,
+	0x35ba3e4a,0x3526ffa0,0xc37b4d09,0xbc306ed9,
+	0x98a52666,0x5648f725,0xff5e569d,0x0ced63d0,
+	0x7c63b2cf,0x700b45e1,0xd5ea50f1,0x85a92872,
+	0xaf1fbda7,0xd4234870,0xa7870bf3,0x2d3b4d79,
+	0x42e04198,0x0cd0ede7,0x26470db8,0xf881814c,
+	0x474d6ad7,0x7c0c5e5c,0xd1231959,0x381b7298,
+	0xf5d2f4db,0xab838653,0x6e2f1e23,0x83719c9e,
+	0xbd91e046,0x9a56456e,0xdc39200c,0x20c8c571,
+	0x962bda1c,0xe1e696ff,0xb141ab08,0x7cca89b9,
+	0x1a69e783,0x02cc4843,0xa2f7c579,0x429ef47d,
+	0x427b169c,0x5ac9f049,0xdd8f0f00,0x5c8165bf,
+	};
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table1[256]={
+	0x1f201094,0xef0ba75b,0x69e3cf7e,0x393f4380,
+	0xfe61cf7a,0xeec5207a,0x55889c94,0x72fc0651,
+	0xada7ef79,0x4e1d7235,0xd55a63ce,0xde0436ba,
+	0x99c430ef,0x5f0c0794,0x18dcdb7d,0xa1d6eff3,
+	0xa0b52f7b,0x59e83605,0xee15b094,0xe9ffd909,
+	0xdc440086,0xef944459,0xba83ccb3,0xe0c3cdfb,
+	0xd1da4181,0x3b092ab1,0xf997f1c1,0xa5e6cf7b,
+	0x01420ddb,0xe4e7ef5b,0x25a1ff41,0xe180f806,
+	0x1fc41080,0x179bee7a,0xd37ac6a9,0xfe5830a4,
+	0x98de8b7f,0x77e83f4e,0x79929269,0x24fa9f7b,
+	0xe113c85b,0xacc40083,0xd7503525,0xf7ea615f,
+	0x62143154,0x0d554b63,0x5d681121,0xc866c359,
+	0x3d63cf73,0xcee234c0,0xd4d87e87,0x5c672b21,
+	0x071f6181,0x39f7627f,0x361e3084,0xe4eb573b,
+	0x602f64a4,0xd63acd9c,0x1bbc4635,0x9e81032d,
+	0x2701f50c,0x99847ab4,0xa0e3df79,0xba6cf38c,
+	0x10843094,0x2537a95e,0xf46f6ffe,0xa1ff3b1f,
+	0x208cfb6a,0x8f458c74,0xd9e0a227,0x4ec73a34,
+	0xfc884f69,0x3e4de8df,0xef0e0088,0x3559648d,
+	0x8a45388c,0x1d804366,0x721d9bfd,0xa58684bb,
+	0xe8256333,0x844e8212,0x128d8098,0xfed33fb4,
+	0xce280ae1,0x27e19ba5,0xd5a6c252,0xe49754bd,
+	0xc5d655dd,0xeb667064,0x77840b4d,0xa1b6a801,
+	0x84db26a9,0xe0b56714,0x21f043b7,0xe5d05860,
+	0x54f03084,0x066ff472,0xa31aa153,0xdadc4755,
+	0xb5625dbf,0x68561be6,0x83ca6b94,0x2d6ed23b,
+	0xeccf01db,0xa6d3d0ba,0xb6803d5c,0xaf77a709,
+	0x33b4a34c,0x397bc8d6,0x5ee22b95,0x5f0e5304,
+	0x81ed6f61,0x20e74364,0xb45e1378,0xde18639b,
+	0x881ca122,0xb96726d1,0x8049a7e8,0x22b7da7b,
+	0x5e552d25,0x5272d237,0x79d2951c,0xc60d894c,
+	0x488cb402,0x1ba4fe5b,0xa4b09f6b,0x1ca815cf,
+	0xa20c3005,0x8871df63,0xb9de2fcb,0x0cc6c9e9,
+	0x0beeff53,0xe3214517,0xb4542835,0x9f63293c,
+	0xee41e729,0x6e1d2d7c,0x50045286,0x1e6685f3,
+	0xf33401c6,0x30a22c95,0x31a70850,0x60930f13,
+	0x73f98417,0xa1269859,0xec645c44,0x52c877a9,
+	0xcdff33a6,0xa02b1741,0x7cbad9a2,0x2180036f,
+	0x50d99c08,0xcb3f4861,0xc26bd765,0x64a3f6ab,
+	0x80342676,0x25a75e7b,0xe4e6d1fc,0x20c710e6,
+	0xcdf0b680,0x17844d3b,0x31eef84d,0x7e0824e4,
+	0x2ccb49eb,0x846a3bae,0x8ff77888,0xee5d60f6,
+	0x7af75673,0x2fdd5cdb,0xa11631c1,0x30f66f43,
+	0xb3faec54,0x157fd7fa,0xef8579cc,0xd152de58,
+	0xdb2ffd5e,0x8f32ce19,0x306af97a,0x02f03ef8,
+	0x99319ad5,0xc242fa0f,0xa7e3ebb0,0xc68e4906,
+	0xb8da230c,0x80823028,0xdcdef3c8,0xd35fb171,
+	0x088a1bc8,0xbec0c560,0x61a3c9e8,0xbca8f54d,
+	0xc72feffa,0x22822e99,0x82c570b4,0xd8d94e89,
+	0x8b1c34bc,0x301e16e6,0x273be979,0xb0ffeaa6,
+	0x61d9b8c6,0x00b24869,0xb7ffce3f,0x08dc283b,
+	0x43daf65a,0xf7e19798,0x7619b72f,0x8f1c9ba4,
+	0xdc8637a0,0x16a7d3b1,0x9fc393b7,0xa7136eeb,
+	0xc6bcc63e,0x1a513742,0xef6828bc,0x520365d6,
+	0x2d6a77ab,0x3527ed4b,0x821fd216,0x095c6e2e,
+	0xdb92f2fb,0x5eea29cb,0x145892f5,0x91584f7f,
+	0x5483697b,0x2667a8cc,0x85196048,0x8c4bacea,
+	0x833860d4,0x0d23e0f9,0x6c387e8a,0x0ae6d249,
+	0xb284600c,0xd835731d,0xdcb1c647,0xac4c56ea,
+	0x3ebd81b3,0x230eabb0,0x6438bc87,0xf0b5b1fa,
+	0x8f5ea2b3,0xfc184642,0x0a036b7a,0x4fb089bd,
+	0x649da589,0xa345415e,0x5c038323,0x3e5d3bb9,
+	0x43d79572,0x7e6dd07c,0x06dfdf1e,0x6c6cc4ef,
+	0x7160a539,0x73bfbe70,0x83877605,0x4523ecf1,
+	};
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table2[256]={
+	0x8defc240,0x25fa5d9f,0xeb903dbf,0xe810c907,
+	0x47607fff,0x369fe44b,0x8c1fc644,0xaececa90,
+	0xbeb1f9bf,0xeefbcaea,0xe8cf1950,0x51df07ae,
+	0x920e8806,0xf0ad0548,0xe13c8d83,0x927010d5,
+	0x11107d9f,0x07647db9,0xb2e3e4d4,0x3d4f285e,
+	0xb9afa820,0xfade82e0,0xa067268b,0x8272792e,
+	0x553fb2c0,0x489ae22b,0xd4ef9794,0x125e3fbc,
+	0x21fffcee,0x825b1bfd,0x9255c5ed,0x1257a240,
+	0x4e1a8302,0xbae07fff,0x528246e7,0x8e57140e,
+	0x3373f7bf,0x8c9f8188,0xa6fc4ee8,0xc982b5a5,
+	0xa8c01db7,0x579fc264,0x67094f31,0xf2bd3f5f,
+	0x40fff7c1,0x1fb78dfc,0x8e6bd2c1,0x437be59b,
+	0x99b03dbf,0xb5dbc64b,0x638dc0e6,0x55819d99,
+	0xa197c81c,0x4a012d6e,0xc5884a28,0xccc36f71,
+	0xb843c213,0x6c0743f1,0x8309893c,0x0feddd5f,
+	0x2f7fe850,0xd7c07f7e,0x02507fbf,0x5afb9a04,
+	0xa747d2d0,0x1651192e,0xaf70bf3e,0x58c31380,
+	0x5f98302e,0x727cc3c4,0x0a0fb402,0x0f7fef82,
+	0x8c96fdad,0x5d2c2aae,0x8ee99a49,0x50da88b8,
+	0x8427f4a0,0x1eac5790,0x796fb449,0x8252dc15,
+	0xefbd7d9b,0xa672597d,0xada840d8,0x45f54504,
+	0xfa5d7403,0xe83ec305,0x4f91751a,0x925669c2,
+	0x23efe941,0xa903f12e,0x60270df2,0x0276e4b6,
+	0x94fd6574,0x927985b2,0x8276dbcb,0x02778176,
+	0xf8af918d,0x4e48f79e,0x8f616ddf,0xe29d840e,
+	0x842f7d83,0x340ce5c8,0x96bbb682,0x93b4b148,
+	0xef303cab,0x984faf28,0x779faf9b,0x92dc560d,
+	0x224d1e20,0x8437aa88,0x7d29dc96,0x2756d3dc,
+	0x8b907cee,0xb51fd240,0xe7c07ce3,0xe566b4a1,
+	0xc3e9615e,0x3cf8209d,0x6094d1e3,0xcd9ca341,
+	0x5c76460e,0x00ea983b,0xd4d67881,0xfd47572c,
+	0xf76cedd9,0xbda8229c,0x127dadaa,0x438a074e,
+	0x1f97c090,0x081bdb8a,0x93a07ebe,0xb938ca15,
+	0x97b03cff,0x3dc2c0f8,0x8d1ab2ec,0x64380e51,
+	0x68cc7bfb,0xd90f2788,0x12490181,0x5de5ffd4,
+	0xdd7ef86a,0x76a2e214,0xb9a40368,0x925d958f,
+	0x4b39fffa,0xba39aee9,0xa4ffd30b,0xfaf7933b,
+	0x6d498623,0x193cbcfa,0x27627545,0x825cf47a,
+	0x61bd8ba0,0xd11e42d1,0xcead04f4,0x127ea392,
+	0x10428db7,0x8272a972,0x9270c4a8,0x127de50b,
+	0x285ba1c8,0x3c62f44f,0x35c0eaa5,0xe805d231,
+	0x428929fb,0xb4fcdf82,0x4fb66a53,0x0e7dc15b,
+	0x1f081fab,0x108618ae,0xfcfd086d,0xf9ff2889,
+	0x694bcc11,0x236a5cae,0x12deca4d,0x2c3f8cc5,
+	0xd2d02dfe,0xf8ef5896,0xe4cf52da,0x95155b67,
+	0x494a488c,0xb9b6a80c,0x5c8f82bc,0x89d36b45,
+	0x3a609437,0xec00c9a9,0x44715253,0x0a874b49,
+	0xd773bc40,0x7c34671c,0x02717ef6,0x4feb5536,
+	0xa2d02fff,0xd2bf60c4,0xd43f03c0,0x50b4ef6d,
+	0x07478cd1,0x006e1888,0xa2e53f55,0xb9e6d4bc,
+	0xa2048016,0x97573833,0xd7207d67,0xde0f8f3d,
+	0x72f87b33,0xabcc4f33,0x7688c55d,0x7b00a6b0,
+	0x947b0001,0x570075d2,0xf9bb88f8,0x8942019e,
+	0x4264a5ff,0x856302e0,0x72dbd92b,0xee971b69,
+	0x6ea22fde,0x5f08ae2b,0xaf7a616d,0xe5c98767,
+	0xcf1febd2,0x61efc8c2,0xf1ac2571,0xcc8239c2,
+	0x67214cb8,0xb1e583d1,0xb7dc3e62,0x7f10bdce,
+	0xf90a5c38,0x0ff0443d,0x606e6dc6,0x60543a49,
+	0x5727c148,0x2be98a1d,0x8ab41738,0x20e1be24,
+	0xaf96da0f,0x68458425,0x99833be5,0x600d457d,
+	0x282f9350,0x8334b362,0xd91d1120,0x2b6d8da0,
+	0x642b1e31,0x9c305a00,0x52bce688,0x1b03588a,
+	0xf7baefd5,0x4142ed9c,0xa4315c11,0x83323ec5,
+	0xdfef4636,0xa133c501,0xe9d3531c,0xee353783,
+	};
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table3[256]={
+	0x9db30420,0x1fb6e9de,0xa7be7bef,0xd273a298,
+	0x4a4f7bdb,0x64ad8c57,0x85510443,0xfa020ed1,
+	0x7e287aff,0xe60fb663,0x095f35a1,0x79ebf120,
+	0xfd059d43,0x6497b7b1,0xf3641f63,0x241e4adf,
+	0x28147f5f,0x4fa2b8cd,0xc9430040,0x0cc32220,
+	0xfdd30b30,0xc0a5374f,0x1d2d00d9,0x24147b15,
+	0xee4d111a,0x0fca5167,0x71ff904c,0x2d195ffe,
+	0x1a05645f,0x0c13fefe,0x081b08ca,0x05170121,
+	0x80530100,0xe83e5efe,0xac9af4f8,0x7fe72701,
+	0xd2b8ee5f,0x06df4261,0xbb9e9b8a,0x7293ea25,
+	0xce84ffdf,0xf5718801,0x3dd64b04,0xa26f263b,
+	0x7ed48400,0x547eebe6,0x446d4ca0,0x6cf3d6f5,
+	0x2649abdf,0xaea0c7f5,0x36338cc1,0x503f7e93,
+	0xd3772061,0x11b638e1,0x72500e03,0xf80eb2bb,
+	0xabe0502e,0xec8d77de,0x57971e81,0xe14f6746,
+	0xc9335400,0x6920318f,0x081dbb99,0xffc304a5,
+	0x4d351805,0x7f3d5ce3,0xa6c866c6,0x5d5bcca9,
+	0xdaec6fea,0x9f926f91,0x9f46222f,0x3991467d,
+	0xa5bf6d8e,0x1143c44f,0x43958302,0xd0214eeb,
+	0x022083b8,0x3fb6180c,0x18f8931e,0x281658e6,
+	0x26486e3e,0x8bd78a70,0x7477e4c1,0xb506e07c,
+	0xf32d0a25,0x79098b02,0xe4eabb81,0x28123b23,
+	0x69dead38,0x1574ca16,0xdf871b62,0x211c40b7,
+	0xa51a9ef9,0x0014377b,0x041e8ac8,0x09114003,
+	0xbd59e4d2,0xe3d156d5,0x4fe876d5,0x2f91a340,
+	0x557be8de,0x00eae4a7,0x0ce5c2ec,0x4db4bba6,
+	0xe756bdff,0xdd3369ac,0xec17b035,0x06572327,
+	0x99afc8b0,0x56c8c391,0x6b65811c,0x5e146119,
+	0x6e85cb75,0xbe07c002,0xc2325577,0x893ff4ec,
+	0x5bbfc92d,0xd0ec3b25,0xb7801ab7,0x8d6d3b24,
+	0x20c763ef,0xc366a5fc,0x9c382880,0x0ace3205,
+	0xaac9548a,0xeca1d7c7,0x041afa32,0x1d16625a,
+	0x6701902c,0x9b757a54,0x31d477f7,0x9126b031,
+	0x36cc6fdb,0xc70b8b46,0xd9e66a48,0x56e55a79,
+	0x026a4ceb,0x52437eff,0x2f8f76b4,0x0df980a5,
+	0x8674cde3,0xedda04eb,0x17a9be04,0x2c18f4df,
+	0xb7747f9d,0xab2af7b4,0xefc34d20,0x2e096b7c,
+	0x1741a254,0xe5b6a035,0x213d42f6,0x2c1c7c26,
+	0x61c2f50f,0x6552daf9,0xd2c231f8,0x25130f69,
+	0xd8167fa2,0x0418f2c8,0x001a96a6,0x0d1526ab,
+	0x63315c21,0x5e0a72ec,0x49bafefd,0x187908d9,
+	0x8d0dbd86,0x311170a7,0x3e9b640c,0xcc3e10d7,
+	0xd5cad3b6,0x0caec388,0xf73001e1,0x6c728aff,
+	0x71eae2a1,0x1f9af36e,0xcfcbd12f,0xc1de8417,
+	0xac07be6b,0xcb44a1d8,0x8b9b0f56,0x013988c3,
+	0xb1c52fca,0xb4be31cd,0xd8782806,0x12a3a4e2,
+	0x6f7de532,0x58fd7eb6,0xd01ee900,0x24adffc2,
+	0xf4990fc5,0x9711aac5,0x001d7b95,0x82e5e7d2,
+	0x109873f6,0x00613096,0xc32d9521,0xada121ff,
+	0x29908415,0x7fbb977f,0xaf9eb3db,0x29c9ed2a,
+	0x5ce2a465,0xa730f32c,0xd0aa3fe8,0x8a5cc091,
+	0xd49e2ce7,0x0ce454a9,0xd60acd86,0x015f1919,
+	0x77079103,0xdea03af6,0x78a8565e,0xdee356df,
+	0x21f05cbe,0x8b75e387,0xb3c50651,0xb8a5c3ef,
+	0xd8eeb6d2,0xe523be77,0xc2154529,0x2f69efdf,
+	0xafe67afb,0xf470c4b2,0xf3e0eb5b,0xd6cc9876,
+	0x39e4460c,0x1fda8538,0x1987832f,0xca007367,
+	0xa99144f8,0x296b299e,0x492fc295,0x9266beab,
+	0xb5676e69,0x9bd3ddda,0xdf7e052f,0xdb25701c,
+	0x1b5e51ee,0xf65324e6,0x6afce36c,0x0316cc04,
+	0x8644213e,0xb7dc59d0,0x7965291f,0xccd6fd43,
+	0x41823979,0x932bcdf6,0xb657c34d,0x4edfd282,
+	0x7ae5290c,0x3cb9536b,0x851e20fe,0x9833557e,
+	0x13ecf0b0,0xd3ffb372,0x3f85c5c1,0x0aef7ed2,
+	};
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table4[256]={
+	0x7ec90c04,0x2c6e74b9,0x9b0e66df,0xa6337911,
+	0xb86a7fff,0x1dd358f5,0x44dd9d44,0x1731167f,
+	0x08fbf1fa,0xe7f511cc,0xd2051b00,0x735aba00,
+	0x2ab722d8,0x386381cb,0xacf6243a,0x69befd7a,
+	0xe6a2e77f,0xf0c720cd,0xc4494816,0xccf5c180,
+	0x38851640,0x15b0a848,0xe68b18cb,0x4caadeff,
+	0x5f480a01,0x0412b2aa,0x259814fc,0x41d0efe2,
+	0x4e40b48d,0x248eb6fb,0x8dba1cfe,0x41a99b02,
+	0x1a550a04,0xba8f65cb,0x7251f4e7,0x95a51725,
+	0xc106ecd7,0x97a5980a,0xc539b9aa,0x4d79fe6a,
+	0xf2f3f763,0x68af8040,0xed0c9e56,0x11b4958b,
+	0xe1eb5a88,0x8709e6b0,0xd7e07156,0x4e29fea7,
+	0x6366e52d,0x02d1c000,0xc4ac8e05,0x9377f571,
+	0x0c05372a,0x578535f2,0x2261be02,0xd642a0c9,
+	0xdf13a280,0x74b55bd2,0x682199c0,0xd421e5ec,
+	0x53fb3ce8,0xc8adedb3,0x28a87fc9,0x3d959981,
+	0x5c1ff900,0xfe38d399,0x0c4eff0b,0x062407ea,
+	0xaa2f4fb1,0x4fb96976,0x90c79505,0xb0a8a774,
+	0xef55a1ff,0xe59ca2c2,0xa6b62d27,0xe66a4263,
+	0xdf65001f,0x0ec50966,0xdfdd55bc,0x29de0655,
+	0x911e739a,0x17af8975,0x32c7911c,0x89f89468,
+	0x0d01e980,0x524755f4,0x03b63cc9,0x0cc844b2,
+	0xbcf3f0aa,0x87ac36e9,0xe53a7426,0x01b3d82b,
+	0x1a9e7449,0x64ee2d7e,0xcddbb1da,0x01c94910,
+	0xb868bf80,0x0d26f3fd,0x9342ede7,0x04a5c284,
+	0x636737b6,0x50f5b616,0xf24766e3,0x8eca36c1,
+	0x136e05db,0xfef18391,0xfb887a37,0xd6e7f7d4,
+	0xc7fb7dc9,0x3063fcdf,0xb6f589de,0xec2941da,
+	0x26e46695,0xb7566419,0xf654efc5,0xd08d58b7,
+	0x48925401,0xc1bacb7f,0xe5ff550f,0xb6083049,
+	0x5bb5d0e8,0x87d72e5a,0xab6a6ee1,0x223a66ce,
+	0xc62bf3cd,0x9e0885f9,0x68cb3e47,0x086c010f,
+	0xa21de820,0xd18b69de,0xf3f65777,0xfa02c3f6,
+	0x407edac3,0xcbb3d550,0x1793084d,0xb0d70eba,
+	0x0ab378d5,0xd951fb0c,0xded7da56,0x4124bbe4,
+	0x94ca0b56,0x0f5755d1,0xe0e1e56e,0x6184b5be,
+	0x580a249f,0x94f74bc0,0xe327888e,0x9f7b5561,
+	0xc3dc0280,0x05687715,0x646c6bd7,0x44904db3,
+	0x66b4f0a3,0xc0f1648a,0x697ed5af,0x49e92ff6,
+	0x309e374f,0x2cb6356a,0x85808573,0x4991f840,
+	0x76f0ae02,0x083be84d,0x28421c9a,0x44489406,
+	0x736e4cb8,0xc1092910,0x8bc95fc6,0x7d869cf4,
+	0x134f616f,0x2e77118d,0xb31b2be1,0xaa90b472,
+	0x3ca5d717,0x7d161bba,0x9cad9010,0xaf462ba2,
+	0x9fe459d2,0x45d34559,0xd9f2da13,0xdbc65487,
+	0xf3e4f94e,0x176d486f,0x097c13ea,0x631da5c7,
+	0x445f7382,0x175683f4,0xcdc66a97,0x70be0288,
+	0xb3cdcf72,0x6e5dd2f3,0x20936079,0x459b80a5,
+	0xbe60e2db,0xa9c23101,0xeba5315c,0x224e42f2,
+	0x1c5c1572,0xf6721b2c,0x1ad2fff3,0x8c25404e,
+	0x324ed72f,0x4067b7fd,0x0523138e,0x5ca3bc78,
+	0xdc0fd66e,0x75922283,0x784d6b17,0x58ebb16e,
+	0x44094f85,0x3f481d87,0xfcfeae7b,0x77b5ff76,
+	0x8c2302bf,0xaaf47556,0x5f46b02a,0x2b092801,
+	0x3d38f5f7,0x0ca81f36,0x52af4a8a,0x66d5e7c0,
+	0xdf3b0874,0x95055110,0x1b5ad7a8,0xf61ed5ad,
+	0x6cf6e479,0x20758184,0xd0cefa65,0x88f7be58,
+	0x4a046826,0x0ff6f8f3,0xa09c7f70,0x5346aba0,
+	0x5ce96c28,0xe176eda3,0x6bac307f,0x376829d2,
+	0x85360fa9,0x17e3fe2a,0x24b79767,0xf5a96b20,
+	0xd6cd2595,0x68ff1ebf,0x7555442c,0xf19f06be,
+	0xf9e0659a,0xeeb9491d,0x34010718,0xbb30cab8,
+	0xe822fe15,0x88570983,0x750e6249,0xda627e55,
+	0x5e76ffa8,0xb1534546,0x6d47de08,0xefe9e7d4,
+	};
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table5[256]={
+	0xf6fa8f9d,0x2cac6ce1,0x4ca34867,0xe2337f7c,
+	0x95db08e7,0x016843b4,0xeced5cbc,0x325553ac,
+	0xbf9f0960,0xdfa1e2ed,0x83f0579d,0x63ed86b9,
+	0x1ab6a6b8,0xde5ebe39,0xf38ff732,0x8989b138,
+	0x33f14961,0xc01937bd,0xf506c6da,0xe4625e7e,
+	0xa308ea99,0x4e23e33c,0x79cbd7cc,0x48a14367,
+	0xa3149619,0xfec94bd5,0xa114174a,0xeaa01866,
+	0xa084db2d,0x09a8486f,0xa888614a,0x2900af98,
+	0x01665991,0xe1992863,0xc8f30c60,0x2e78ef3c,
+	0xd0d51932,0xcf0fec14,0xf7ca07d2,0xd0a82072,
+	0xfd41197e,0x9305a6b0,0xe86be3da,0x74bed3cd,
+	0x372da53c,0x4c7f4448,0xdab5d440,0x6dba0ec3,
+	0x083919a7,0x9fbaeed9,0x49dbcfb0,0x4e670c53,
+	0x5c3d9c01,0x64bdb941,0x2c0e636a,0xba7dd9cd,
+	0xea6f7388,0xe70bc762,0x35f29adb,0x5c4cdd8d,
+	0xf0d48d8c,0xb88153e2,0x08a19866,0x1ae2eac8,
+	0x284caf89,0xaa928223,0x9334be53,0x3b3a21bf,
+	0x16434be3,0x9aea3906,0xefe8c36e,0xf890cdd9,
+	0x80226dae,0xc340a4a3,0xdf7e9c09,0xa694a807,
+	0x5b7c5ecc,0x221db3a6,0x9a69a02f,0x68818a54,
+	0xceb2296f,0x53c0843a,0xfe893655,0x25bfe68a,
+	0xb4628abc,0xcf222ebf,0x25ac6f48,0xa9a99387,
+	0x53bddb65,0xe76ffbe7,0xe967fd78,0x0ba93563,
+	0x8e342bc1,0xe8a11be9,0x4980740d,0xc8087dfc,
+	0x8de4bf99,0xa11101a0,0x7fd37975,0xda5a26c0,
+	0xe81f994f,0x9528cd89,0xfd339fed,0xb87834bf,
+	0x5f04456d,0x22258698,0xc9c4c83b,0x2dc156be,
+	0x4f628daa,0x57f55ec5,0xe2220abe,0xd2916ebf,
+	0x4ec75b95,0x24f2c3c0,0x42d15d99,0xcd0d7fa0,
+	0x7b6e27ff,0xa8dc8af0,0x7345c106,0xf41e232f,
+	0x35162386,0xe6ea8926,0x3333b094,0x157ec6f2,
+	0x372b74af,0x692573e4,0xe9a9d848,0xf3160289,
+	0x3a62ef1d,0xa787e238,0xf3a5f676,0x74364853,
+	0x20951063,0x4576698d,0xb6fad407,0x592af950,
+	0x36f73523,0x4cfb6e87,0x7da4cec0,0x6c152daa,
+	0xcb0396a8,0xc50dfe5d,0xfcd707ab,0x0921c42f,
+	0x89dff0bb,0x5fe2be78,0x448f4f33,0x754613c9,
+	0x2b05d08d,0x48b9d585,0xdc049441,0xc8098f9b,
+	0x7dede786,0xc39a3373,0x42410005,0x6a091751,
+	0x0ef3c8a6,0x890072d6,0x28207682,0xa9a9f7be,
+	0xbf32679d,0xd45b5b75,0xb353fd00,0xcbb0e358,
+	0x830f220a,0x1f8fb214,0xd372cf08,0xcc3c4a13,
+	0x8cf63166,0x061c87be,0x88c98f88,0x6062e397,
+	0x47cf8e7a,0xb6c85283,0x3cc2acfb,0x3fc06976,
+	0x4e8f0252,0x64d8314d,0xda3870e3,0x1e665459,
+	0xc10908f0,0x513021a5,0x6c5b68b7,0x822f8aa0,
+	0x3007cd3e,0x74719eef,0xdc872681,0x073340d4,
+	0x7e432fd9,0x0c5ec241,0x8809286c,0xf592d891,
+	0x08a930f6,0x957ef305,0xb7fbffbd,0xc266e96f,
+	0x6fe4ac98,0xb173ecc0,0xbc60b42a,0x953498da,
+	0xfba1ae12,0x2d4bd736,0x0f25faab,0xa4f3fceb,
+	0xe2969123,0x257f0c3d,0x9348af49,0x361400bc,
+	0xe8816f4a,0x3814f200,0xa3f94043,0x9c7a54c2,
+	0xbc704f57,0xda41e7f9,0xc25ad33a,0x54f4a084,
+	0xb17f5505,0x59357cbe,0xedbd15c8,0x7f97c5ab,
+	0xba5ac7b5,0xb6f6deaf,0x3a479c3a,0x5302da25,
+	0x653d7e6a,0x54268d49,0x51a477ea,0x5017d55b,
+	0xd7d25d88,0x44136c76,0x0404a8c8,0xb8e5a121,
+	0xb81a928a,0x60ed5869,0x97c55b96,0xeaec991b,
+	0x29935913,0x01fdb7f1,0x088e8dfa,0x9ab6f6f5,
+	0x3b4cbf9f,0x4a5de3ab,0xe6051d35,0xa0e1d855,
+	0xd36b4cf1,0xf544edeb,0xb0e93524,0xbebb8fbd,
+	0xa2d762cf,0x49c92f54,0x38b5f331,0x7128a454,
+	0x48392905,0xa65b1db8,0x851c97bd,0xd675cf2f,
+	};
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table6[256]={
+	0x85e04019,0x332bf567,0x662dbfff,0xcfc65693,
+	0x2a8d7f6f,0xab9bc912,0xde6008a1,0x2028da1f,
+	0x0227bce7,0x4d642916,0x18fac300,0x50f18b82,
+	0x2cb2cb11,0xb232e75c,0x4b3695f2,0xb28707de,
+	0xa05fbcf6,0xcd4181e9,0xe150210c,0xe24ef1bd,
+	0xb168c381,0xfde4e789,0x5c79b0d8,0x1e8bfd43,
+	0x4d495001,0x38be4341,0x913cee1d,0x92a79c3f,
+	0x089766be,0xbaeeadf4,0x1286becf,0xb6eacb19,
+	0x2660c200,0x7565bde4,0x64241f7a,0x8248dca9,
+	0xc3b3ad66,0x28136086,0x0bd8dfa8,0x356d1cf2,
+	0x107789be,0xb3b2e9ce,0x0502aa8f,0x0bc0351e,
+	0x166bf52a,0xeb12ff82,0xe3486911,0xd34d7516,
+	0x4e7b3aff,0x5f43671b,0x9cf6e037,0x4981ac83,
+	0x334266ce,0x8c9341b7,0xd0d854c0,0xcb3a6c88,
+	0x47bc2829,0x4725ba37,0xa66ad22b,0x7ad61f1e,
+	0x0c5cbafa,0x4437f107,0xb6e79962,0x42d2d816,
+	0x0a961288,0xe1a5c06e,0x13749e67,0x72fc081a,
+	0xb1d139f7,0xf9583745,0xcf19df58,0xbec3f756,
+	0xc06eba30,0x07211b24,0x45c28829,0xc95e317f,
+	0xbc8ec511,0x38bc46e9,0xc6e6fa14,0xbae8584a,
+	0xad4ebc46,0x468f508b,0x7829435f,0xf124183b,
+	0x821dba9f,0xaff60ff4,0xea2c4e6d,0x16e39264,
+	0x92544a8b,0x009b4fc3,0xaba68ced,0x9ac96f78,
+	0x06a5b79a,0xb2856e6e,0x1aec3ca9,0xbe838688,
+	0x0e0804e9,0x55f1be56,0xe7e5363b,0xb3a1f25d,
+	0xf7debb85,0x61fe033c,0x16746233,0x3c034c28,
+	0xda6d0c74,0x79aac56c,0x3ce4e1ad,0x51f0c802,
+	0x98f8f35a,0x1626a49f,0xeed82b29,0x1d382fe3,
+	0x0c4fb99a,0xbb325778,0x3ec6d97b,0x6e77a6a9,
+	0xcb658b5c,0xd45230c7,0x2bd1408b,0x60c03eb7,
+	0xb9068d78,0xa33754f4,0xf430c87d,0xc8a71302,
+	0xb96d8c32,0xebd4e7be,0xbe8b9d2d,0x7979fb06,
+	0xe7225308,0x8b75cf77,0x11ef8da4,0xe083c858,
+	0x8d6b786f,0x5a6317a6,0xfa5cf7a0,0x5dda0033,
+	0xf28ebfb0,0xf5b9c310,0xa0eac280,0x08b9767a,
+	0xa3d9d2b0,0x79d34217,0x021a718d,0x9ac6336a,
+	0x2711fd60,0x438050e3,0x069908a8,0x3d7fedc4,
+	0x826d2bef,0x4eeb8476,0x488dcf25,0x36c9d566,
+	0x28e74e41,0xc2610aca,0x3d49a9cf,0xbae3b9df,
+	0xb65f8de6,0x92aeaf64,0x3ac7d5e6,0x9ea80509,
+	0xf22b017d,0xa4173f70,0xdd1e16c3,0x15e0d7f9,
+	0x50b1b887,0x2b9f4fd5,0x625aba82,0x6a017962,
+	0x2ec01b9c,0x15488aa9,0xd716e740,0x40055a2c,
+	0x93d29a22,0xe32dbf9a,0x058745b9,0x3453dc1e,
+	0xd699296e,0x496cff6f,0x1c9f4986,0xdfe2ed07,
+	0xb87242d1,0x19de7eae,0x053e561a,0x15ad6f8c,
+	0x66626c1c,0x7154c24c,0xea082b2a,0x93eb2939,
+	0x17dcb0f0,0x58d4f2ae,0x9ea294fb,0x52cf564c,
+	0x9883fe66,0x2ec40581,0x763953c3,0x01d6692e,
+	0xd3a0c108,0xa1e7160e,0xe4f2dfa6,0x693ed285,
+	0x74904698,0x4c2b0edd,0x4f757656,0x5d393378,
+	0xa132234f,0x3d321c5d,0xc3f5e194,0x4b269301,
+	0xc79f022f,0x3c997e7e,0x5e4f9504,0x3ffafbbd,
+	0x76f7ad0e,0x296693f4,0x3d1fce6f,0xc61e45be,
+	0xd3b5ab34,0xf72bf9b7,0x1b0434c0,0x4e72b567,
+	0x5592a33d,0xb5229301,0xcfd2a87f,0x60aeb767,
+	0x1814386b,0x30bcc33d,0x38a0c07d,0xfd1606f2,
+	0xc363519b,0x589dd390,0x5479f8e6,0x1cb8d647,
+	0x97fd61a9,0xea7759f4,0x2d57539d,0x569a58cf,
+	0xe84e63ad,0x462e1b78,0x6580f87e,0xf3817914,
+	0x91da55f4,0x40a230f3,0xd1988f35,0xb6e318d2,
+	0x3ffa50bc,0x3d40f021,0xc3c0bdae,0x4958c24c,
+	0x518f36b2,0x84b1d370,0x0fedce83,0x878ddada,
+	0xf2a279c7,0x94e01be8,0x90716f4b,0x954b8aa3,
+	};
+OPENSSL_GLOBAL const CAST_LONG CAST_S_table7[256]={
+	0xe216300d,0xbbddfffc,0xa7ebdabd,0x35648095,
+	0x7789f8b7,0xe6c1121b,0x0e241600,0x052ce8b5,
+	0x11a9cfb0,0xe5952f11,0xece7990a,0x9386d174,
+	0x2a42931c,0x76e38111,0xb12def3a,0x37ddddfc,
+	0xde9adeb1,0x0a0cc32c,0xbe197029,0x84a00940,
+	0xbb243a0f,0xb4d137cf,0xb44e79f0,0x049eedfd,
+	0x0b15a15d,0x480d3168,0x8bbbde5a,0x669ded42,
+	0xc7ece831,0x3f8f95e7,0x72df191b,0x7580330d,
+	0x94074251,0x5c7dcdfa,0xabbe6d63,0xaa402164,
+	0xb301d40a,0x02e7d1ca,0x53571dae,0x7a3182a2,
+	0x12a8ddec,0xfdaa335d,0x176f43e8,0x71fb46d4,
+	0x38129022,0xce949ad4,0xb84769ad,0x965bd862,
+	0x82f3d055,0x66fb9767,0x15b80b4e,0x1d5b47a0,
+	0x4cfde06f,0xc28ec4b8,0x57e8726e,0x647a78fc,
+	0x99865d44,0x608bd593,0x6c200e03,0x39dc5ff6,
+	0x5d0b00a3,0xae63aff2,0x7e8bd632,0x70108c0c,
+	0xbbd35049,0x2998df04,0x980cf42a,0x9b6df491,
+	0x9e7edd53,0x06918548,0x58cb7e07,0x3b74ef2e,
+	0x522fffb1,0xd24708cc,0x1c7e27cd,0xa4eb215b,
+	0x3cf1d2e2,0x19b47a38,0x424f7618,0x35856039,
+	0x9d17dee7,0x27eb35e6,0xc9aff67b,0x36baf5b8,
+	0x09c467cd,0xc18910b1,0xe11dbf7b,0x06cd1af8,
+	0x7170c608,0x2d5e3354,0xd4de495a,0x64c6d006,
+	0xbcc0c62c,0x3dd00db3,0x708f8f34,0x77d51b42,
+	0x264f620f,0x24b8d2bf,0x15c1b79e,0x46a52564,
+	0xf8d7e54e,0x3e378160,0x7895cda5,0x859c15a5,
+	0xe6459788,0xc37bc75f,0xdb07ba0c,0x0676a3ab,
+	0x7f229b1e,0x31842e7b,0x24259fd7,0xf8bef472,
+	0x835ffcb8,0x6df4c1f2,0x96f5b195,0xfd0af0fc,
+	0xb0fe134c,0xe2506d3d,0x4f9b12ea,0xf215f225,
+	0xa223736f,0x9fb4c428,0x25d04979,0x34c713f8,
+	0xc4618187,0xea7a6e98,0x7cd16efc,0x1436876c,
+	0xf1544107,0xbedeee14,0x56e9af27,0xa04aa441,
+	0x3cf7c899,0x92ecbae6,0xdd67016d,0x151682eb,
+	0xa842eedf,0xfdba60b4,0xf1907b75,0x20e3030f,
+	0x24d8c29e,0xe139673b,0xefa63fb8,0x71873054,
+	0xb6f2cf3b,0x9f326442,0xcb15a4cc,0xb01a4504,
+	0xf1e47d8d,0x844a1be5,0xbae7dfdc,0x42cbda70,
+	0xcd7dae0a,0x57e85b7a,0xd53f5af6,0x20cf4d8c,
+	0xcea4d428,0x79d130a4,0x3486ebfb,0x33d3cddc,
+	0x77853b53,0x37effcb5,0xc5068778,0xe580b3e6,
+	0x4e68b8f4,0xc5c8b37e,0x0d809ea2,0x398feb7c,
+	0x132a4f94,0x43b7950e,0x2fee7d1c,0x223613bd,
+	0xdd06caa2,0x37df932b,0xc4248289,0xacf3ebc3,
+	0x5715f6b7,0xef3478dd,0xf267616f,0xc148cbe4,
+	0x9052815e,0x5e410fab,0xb48a2465,0x2eda7fa4,
+	0xe87b40e4,0xe98ea084,0x5889e9e1,0xefd390fc,
+	0xdd07d35b,0xdb485694,0x38d7e5b2,0x57720101,
+	0x730edebc,0x5b643113,0x94917e4f,0x503c2fba,
+	0x646f1282,0x7523d24a,0xe0779695,0xf9c17a8f,
+	0x7a5b2121,0xd187b896,0x29263a4d,0xba510cdf,
+	0x81f47c9f,0xad1163ed,0xea7b5965,0x1a00726e,
+	0x11403092,0x00da6d77,0x4a0cdd61,0xad1f4603,
+	0x605bdfb0,0x9eedc364,0x22ebe6a8,0xcee7d28a,
+	0xa0e736a0,0x5564a6b9,0x10853209,0xc7eb8f37,
+	0x2de705ca,0x8951570f,0xdf09822b,0xbd691a6c,
+	0xaa12e4f2,0x87451c0f,0xe0f6a27a,0x3ada4819,
+	0x4cf1764f,0x0d771c2b,0x67cdb156,0x350d8384,
+	0x5938fa0f,0x42399ef3,0x36997b07,0x0e84093d,
+	0x4aa93e61,0x8360d87b,0x1fa98b0c,0x1149382c,
+	0xe97625a5,0x0614d1b7,0x0e25244b,0x0c768347,
+	0x589e8d82,0x0d2059d1,0xa466bb1e,0xf8da0a82,
+	0x04f19130,0xba6e4ec0,0x99265164,0x1ee7230d,
+	0x50b2ad80,0xeaee6801,0x8db2a283,0xea8bf59e,
+	};
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/Makefile linux-patched/net/ipsec/libcrypto/libmd5/Makefile
--- linux/net/ipsec/libcrypto/libmd5/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/Makefile	Thu Sep  5 04:31:27 2002
@@ -0,0 +1,136 @@
+#
+# SSLeay/crypto/md5/Makefile
+#
+
+DIR=    md5
+TOP=    ../..
+CC=     cc
+CPP=    $(CC) -E
+INCLUDES=
+CFLAG=-g -I ../include -D__KERNEL__ -I/usr/src/linux/include
+INSTALL_PREFIX=
+OPENSSLDIR=     /usr/local/ssl
+INSTALLTOP=/usr/local/ssl
+MAKE=           make -f Makefile.ssl
+MAKEDEPEND=	$(TOP)/util/domd $(TOP)
+MAKEFILE=       Makefile.ssl
+AR=             ar r
+RANLIB=		ranlib
+PERL=		perl
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+ASM-$(ARCH_ASM):=1
+ASM_X86=$(ASM-i586)$(ASM-i686)
+ifneq ($(strip $(ASM_X86)),)
+MD5_ASM_OBJ:=asm/mx86-elf.o
+override CFLAGS += -DMD5_ASM
+endif
+# We let the C compiler driver to take care of .s files. This is done in
+# order to be excused from maintaining a separate set of architecture
+# dependent assembler flags. E.g. if you throw -mcpu=ultrasparc at SPARC
+# gcc, then the driver will automatically translate it to -xarch=v8plus
+# and pass it down to assembler.
+AS=$(CC) -c
+ASFLAGS=$(CFLAGS)
+
+GENERAL=Makefile
+TEST=md5test.c
+APPS=
+
+LIB=libmd5.a
+LIBSRC=md5_dgst.c md5_one.c hmac_md5.c
+LIBOBJ=md5_dgst.o md5_one.o $(MD5_ASM_OBJ) hmac_md5.o
+
+SRC= $(LIBSRC)
+
+EXHEADER= md5.h
+HEADER= md5_locl.h $(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+#top:
+#	(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all:    lib
+
+lib:	$(LIB)
+
+$(LIB):    $(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	$(RANLIB) $(LIB)
+
+# elf
+asm/mx86-elf.o: asm/mx86unix.cpp
+	$(CPP) -DELF -x c asm/mx86unix.cpp | as -o asm/mx86-elf.o
+
+# solaris
+asm/mx86-sol.o: asm/mx86unix.cpp
+	$(CC) -E -DSOL asm/mx86unix.cpp | sed 's/^#.*//' > asm/mx86-sol.s
+	as -o asm/mx86-sol.o asm/mx86-sol.s
+	rm -f asm/mx86-sol.s
+
+# a.out
+asm/mx86-out.o: asm/mx86unix.cpp
+	$(CPP) -DOUT asm/mx86unix.cpp | as -o asm/mx86-out.o
+
+# bsdi
+asm/mx86bsdi.o: asm/mx86unix.cpp
+	$(CPP) -DBSDI asm/mx86unix.cpp | sed 's/ :/:/' | as -o asm/mx86bsdi.o
+
+asm/mx86unix.cpp: asm/md5-586.pl ../perlasm/x86asm.pl
+	(cd asm; $(PERL) md5-586.pl cpp >mx86unix.cpp)
+
+asm/md5-sparcv8plus.o: asm/md5-sparcv9.S
+	$(CC) $(ASFLAGS) -DMD5_BLOCK_DATA_ORDER -c \
+		-o asm/md5-sparcv8plus.o asm/md5-sparcv9.S
+
+# Old GNU assembler doesn't understand V9 instructions, so we
+# hire /usr/ccs/bin/as to do the job. Note that option is called
+# *-gcc27, but even gcc 2>=8 users may experience similar problem
+# if they didn't bother to upgrade GNU assembler. Such users should
+# not choose this option, but be adviced to *remove* GNU assembler
+# or upgrade it.
+asm/md5-sparcv8plus-gcc27.o: asm/md5-sparcv9.S
+	$(CC) $(ASFLAGS) -DMD5_BLOCK_DATA_ORDER -E asm/md5-sparcv9.S | \
+		/usr/ccs/bin/as -xarch=v8plus - -o asm/md5-sparcv8plus-gcc27.o
+
+asm/md5-sparcv9.o: asm/md5-sparcv9.S
+	$(CC) $(ASFLAGS) -DMD5_BLOCK_DATA_ORDER -c \
+		-o asm/md5-sparcv9.o asm/md5-sparcv9.S
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO
+
+links:
+	@$(TOP)/util/point.sh Makefile.ssl Makefile
+	@$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+	@$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+	@$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install:
+	@for i in $(EXHEADER) ; \
+	do  \
+	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	$(MAKEDEPEND) $(INCLUDES) $(DEPFLAG) $(PROGS) $(LIBSRC)
+
+dclean:
+	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	rm -f asm/mx86unix.cpp *.o asm/*.o *.obj $(LIB) tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/asm/md5-586.pl linux-patched/net/ipsec/libcrypto/libmd5/asm/md5-586.pl
--- linux/net/ipsec/libcrypto/libmd5/asm/md5-586.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/asm/md5-586.pl	Thu Sep  5 04:35:58 2002
@@ -0,0 +1,306 @@
+#!/usr/local/bin/perl
+
+# Normal is the
+# md5_block_x86(MD5_CTX *c, ULONG *X);
+# version, non-normal is the
+# md5_block_x86(MD5_CTX *c, ULONG *X,int blocks);
+
+$normal=0;
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],$0);
+
+$A="eax";
+$B="ebx";
+$C="ecx";
+$D="edx";
+$tmp1="edi";
+$tmp2="ebp";
+$X="esi";
+
+# What we need to load into $tmp for the next round
+%Ltmp1=("R0",&Np($C), "R1",&Np($C), "R2",&Np($C), "R3",&Np($D));
+@xo=(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,	# R0
+ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,	# R1
+ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,	# R2
+ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9,	# R3
+ );
+
+&md5_block("md5_block_asm_host_order");
+&asm_finish();
+
+sub Np
+	{
+	local($p)=@_;
+	local(%n)=($A,$D,$B,$A,$C,$B,$D,$C);
+	return($n{$p});
+	}
+
+sub R0
+	{
+	local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+
+	&mov($tmp1,$C)  if $pos < 0;
+	&mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one 
+
+	# body proper
+
+	&comment("R0 $ki");
+	&xor($tmp1,$d); # F function - part 2
+
+	&and($tmp1,$b); # F function - part 3
+	&lea($a,&DWP($t,$a,$tmp2,1));
+
+	&xor($tmp1,$d); # F function - part 4
+
+	&add($a,$tmp1);
+	&mov($tmp1,&Np($c)) if $pos < 1;	# next tmp1 for R0
+	&mov($tmp1,&Np($c)) if $pos == 1;	# next tmp1 for R1
+
+	&rotl($a,$s);
+
+	&mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2);
+
+	&add($a,$b);
+	}
+
+sub R1
+	{
+	local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+
+	&comment("R1 $ki");
+
+	&lea($a,&DWP($t,$a,$tmp2,1));
+
+	&xor($tmp1,$b); # G function - part 2
+	&and($tmp1,$d); # G function - part 3
+
+	&mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2);
+	&xor($tmp1,$c);			# G function - part 4
+
+	&add($a,$tmp1);
+	&mov($tmp1,&Np($c)) if $pos < 1;	# G function - part 1
+	&mov($tmp1,&Np($c)) if $pos == 1;	# G function - part 1
+
+	&rotl($a,$s);
+
+	&add($a,$b);
+	}
+
+sub R2
+	{
+	local($n,$pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+	# This one is different, only 3 logical operations
+
+if (($n & 1) == 0)
+	{
+	&comment("R2 $ki");
+	# make sure to do 'D' first, not 'B', else we clash with
+	# the last add from the previous round.
+
+	&xor($tmp1,$d); # H function - part 2
+
+	&xor($tmp1,$b); # H function - part 3
+	&lea($a,&DWP($t,$a,$tmp2,1));
+
+	&add($a,$tmp1);
+
+	&rotl($a,$s);
+
+	&mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0));
+	&mov($tmp1,&Np($c));
+	}
+else
+	{
+	&comment("R2 $ki");
+	# make sure to do 'D' first, not 'B', else we clash with
+	# the last add from the previous round.
+
+	&lea($a,&DWP($t,$a,$tmp2,1));
+
+	&add($b,$c);			# MOVED FORWARD
+	&xor($tmp1,$d); # H function - part 2
+
+	&xor($tmp1,$b); # H function - part 3
+	&mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2);
+
+	&add($a,$tmp1);
+	&mov($tmp1,&Np($c)) if $pos < 1;	# H function - part 1
+	&mov($tmp1,-1) if $pos == 1;		# I function - part 1
+
+	&rotl($a,$s);
+
+	&add($a,$b);
+	}
+	}
+
+sub R3
+	{
+	local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+
+	&comment("R3 $ki");
+
+	# &not($tmp1)
+	&xor($tmp1,$d) if $pos < 0; 	# I function - part 2
+
+	&or($tmp1,$b);				# I function - part 3
+	&lea($a,&DWP($t,$a,$tmp2,1));
+
+	&xor($tmp1,$c); 			# I function - part 4
+	&mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0))	if $pos != 2; # load X/k value
+	&mov($tmp2,&wparam(0)) if $pos == 2;
+
+	&add($a,$tmp1);
+	&mov($tmp1,-1) if $pos < 1;	# H function - part 1
+	&add($K,64) if $pos >=1 && !$normal;
+
+	&rotl($a,$s);
+
+	&xor($tmp1,&Np($d)) if $pos <= 0; 	# I function - part = first time
+	&mov($tmp1,&DWP( 0,$tmp2,"",0)) if $pos > 0;
+	&add($a,$b);
+	}
+
+
+sub md5_block
+	{
+	local($name)=@_;
+
+	&function_begin_B($name,"",3);
+
+	# parameter 1 is the MD5_CTX structure.
+	# A	0
+	# B	4
+	# C	8
+	# D 	12
+
+	&push("esi");
+	 &push("edi");
+	&mov($tmp1,	&wparam(0)); # edi
+	 &mov($X,	&wparam(1)); # esi
+	&mov($C,	&wparam(2));
+	 &push("ebp");
+	&shl($C,	6);
+	&push("ebx");
+	 &add($C,	$X); # offset we end at
+	&sub($C,	64);
+	 &mov($A,	&DWP( 0,$tmp1,"",0));
+	&push($C);	# Put on the TOS
+	 &mov($B,	&DWP( 4,$tmp1,"",0));
+	&mov($C,	&DWP( 8,$tmp1,"",0));
+	 &mov($D,	&DWP(12,$tmp1,"",0));
+
+	&set_label("start") unless $normal;
+	&comment("");
+	&comment("R0 section");
+
+	&R0(-2,$A,$B,$C,$D,$X, 0, 7,0xd76aa478);
+	&R0( 0,$D,$A,$B,$C,$X, 1,12,0xe8c7b756);
+	&R0( 0,$C,$D,$A,$B,$X, 2,17,0x242070db);
+	&R0( 0,$B,$C,$D,$A,$X, 3,22,0xc1bdceee);
+	&R0( 0,$A,$B,$C,$D,$X, 4, 7,0xf57c0faf);
+	&R0( 0,$D,$A,$B,$C,$X, 5,12,0x4787c62a);
+	&R0( 0,$C,$D,$A,$B,$X, 6,17,0xa8304613);
+	&R0( 0,$B,$C,$D,$A,$X, 7,22,0xfd469501);
+	&R0( 0,$A,$B,$C,$D,$X, 8, 7,0x698098d8);
+	&R0( 0,$D,$A,$B,$C,$X, 9,12,0x8b44f7af);
+	&R0( 0,$C,$D,$A,$B,$X,10,17,0xffff5bb1);
+	&R0( 0,$B,$C,$D,$A,$X,11,22,0x895cd7be);
+	&R0( 0,$A,$B,$C,$D,$X,12, 7,0x6b901122);
+	&R0( 0,$D,$A,$B,$C,$X,13,12,0xfd987193);
+	&R0( 0,$C,$D,$A,$B,$X,14,17,0xa679438e);
+	&R0( 1,$B,$C,$D,$A,$X,15,22,0x49b40821);
+
+	&comment("");
+	&comment("R1 section");
+	&R1(-1,$A,$B,$C,$D,$X,16, 5,0xf61e2562);
+	&R1( 0,$D,$A,$B,$C,$X,17, 9,0xc040b340);
+	&R1( 0,$C,$D,$A,$B,$X,18,14,0x265e5a51);
+	&R1( 0,$B,$C,$D,$A,$X,19,20,0xe9b6c7aa);
+	&R1( 0,$A,$B,$C,$D,$X,20, 5,0xd62f105d);
+	&R1( 0,$D,$A,$B,$C,$X,21, 9,0x02441453);
+	&R1( 0,$C,$D,$A,$B,$X,22,14,0xd8a1e681);
+	&R1( 0,$B,$C,$D,$A,$X,23,20,0xe7d3fbc8);
+	&R1( 0,$A,$B,$C,$D,$X,24, 5,0x21e1cde6);
+	&R1( 0,$D,$A,$B,$C,$X,25, 9,0xc33707d6);
+	&R1( 0,$C,$D,$A,$B,$X,26,14,0xf4d50d87);
+	&R1( 0,$B,$C,$D,$A,$X,27,20,0x455a14ed);
+	&R1( 0,$A,$B,$C,$D,$X,28, 5,0xa9e3e905);
+	&R1( 0,$D,$A,$B,$C,$X,29, 9,0xfcefa3f8);
+	&R1( 0,$C,$D,$A,$B,$X,30,14,0x676f02d9);
+	&R1( 1,$B,$C,$D,$A,$X,31,20,0x8d2a4c8a);
+
+	&comment("");
+	&comment("R2 section");
+	&R2( 0,-1,$A,$B,$C,$D,$X,32, 4,0xfffa3942);
+	&R2( 1, 0,$D,$A,$B,$C,$X,33,11,0x8771f681);
+	&R2( 2, 0,$C,$D,$A,$B,$X,34,16,0x6d9d6122);
+	&R2( 3, 0,$B,$C,$D,$A,$X,35,23,0xfde5380c);
+	&R2( 4, 0,$A,$B,$C,$D,$X,36, 4,0xa4beea44);
+	&R2( 5, 0,$D,$A,$B,$C,$X,37,11,0x4bdecfa9);
+	&R2( 6, 0,$C,$D,$A,$B,$X,38,16,0xf6bb4b60);
+	&R2( 7, 0,$B,$C,$D,$A,$X,39,23,0xbebfbc70);
+	&R2( 8, 0,$A,$B,$C,$D,$X,40, 4,0x289b7ec6);
+	&R2( 9, 0,$D,$A,$B,$C,$X,41,11,0xeaa127fa);
+	&R2(10, 0,$C,$D,$A,$B,$X,42,16,0xd4ef3085);
+	&R2(11, 0,$B,$C,$D,$A,$X,43,23,0x04881d05);
+	&R2(12, 0,$A,$B,$C,$D,$X,44, 4,0xd9d4d039);
+	&R2(13, 0,$D,$A,$B,$C,$X,45,11,0xe6db99e5);
+	&R2(14, 0,$C,$D,$A,$B,$X,46,16,0x1fa27cf8);
+	&R2(15, 1,$B,$C,$D,$A,$X,47,23,0xc4ac5665);
+
+	&comment("");
+	&comment("R3 section");
+	&R3(-1,$A,$B,$C,$D,$X,48, 6,0xf4292244);
+	&R3( 0,$D,$A,$B,$C,$X,49,10,0x432aff97);
+	&R3( 0,$C,$D,$A,$B,$X,50,15,0xab9423a7);
+	&R3( 0,$B,$C,$D,$A,$X,51,21,0xfc93a039);
+	&R3( 0,$A,$B,$C,$D,$X,52, 6,0x655b59c3);
+	&R3( 0,$D,$A,$B,$C,$X,53,10,0x8f0ccc92);
+	&R3( 0,$C,$D,$A,$B,$X,54,15,0xffeff47d);
+	&R3( 0,$B,$C,$D,$A,$X,55,21,0x85845dd1);
+	&R3( 0,$A,$B,$C,$D,$X,56, 6,0x6fa87e4f);
+	&R3( 0,$D,$A,$B,$C,$X,57,10,0xfe2ce6e0);
+	&R3( 0,$C,$D,$A,$B,$X,58,15,0xa3014314);
+	&R3( 0,$B,$C,$D,$A,$X,59,21,0x4e0811a1);
+	&R3( 0,$A,$B,$C,$D,$X,60, 6,0xf7537e82);
+	&R3( 0,$D,$A,$B,$C,$X,61,10,0xbd3af235);
+	&R3( 0,$C,$D,$A,$B,$X,62,15,0x2ad7d2bb);
+	&R3( 2,$B,$C,$D,$A,$X,63,21,0xeb86d391);
+
+	# &mov($tmp2,&wparam(0));	# done in the last R3
+	# &mov($tmp1,	&DWP( 0,$tmp2,"",0)); # done is the last R3
+
+	&add($A,$tmp1);
+	 &mov($tmp1,	&DWP( 4,$tmp2,"",0));
+
+	&add($B,$tmp1);
+	&mov($tmp1,	&DWP( 8,$tmp2,"",0));
+
+	&add($C,$tmp1);
+	&mov($tmp1,	&DWP(12,$tmp2,"",0));
+
+	&add($D,$tmp1);
+	&mov(&DWP( 0,$tmp2,"",0),$A);
+
+	&mov(&DWP( 4,$tmp2,"",0),$B);
+	&mov($tmp1,&swtmp(0)) unless $normal;
+
+	&mov(&DWP( 8,$tmp2,"",0),$C);
+	 &mov(&DWP(12,$tmp2,"",0),$D);
+
+	&cmp($tmp1,$X) unless $normal;			# check count
+	 &jge(&label("start")) unless $normal;
+
+	&pop("eax"); # pop the temp variable off the stack
+	 &pop("ebx");
+	&pop("ebp");
+	 &pop("edi");
+	&pop("esi");
+	 &ret();
+	&function_end_B($name);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/hmac_md5.c linux-patched/net/ipsec/libcrypto/libmd5/hmac_md5.c
--- linux/net/ipsec/libcrypto/libmd5/hmac_md5.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/hmac_md5.c	Thu Sep  5 04:31:27 2002
@@ -0,0 +1,21 @@
+#include <linux/types.h>
+#include <linux/string.h>
+#include "hmac_generic.h"
+#include "md5.h"
+#include "hmac_md5.h"
+
+void inline md5_result(MD5_CTX *ctx, __u8 * hash, int hashlen) {
+	if (hashlen==MD5_HASHLEN)
+		MD5_Final(hash, ctx);
+	else {
+		__u8 hash_buf[MD5_HASHLEN];
+		MD5_Final(hash_buf, ctx);
+		memcpy(hash, hash_buf, hashlen);
+	}
+}
+HMAC_SET_KEY_IMPL (md5_hmac_set_key, 
+		md5_hmac_context, MD5_BLOCKSIZE, 
+		MD5_Init, MD5_Update)
+HMAC_HASH_IMPL (md5_hmac_hash, 
+		md5_hmac_context, MD5_CTX, MD5_HASHLEN,
+		MD5_Update, md5_result)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/hmac_md5.h linux-patched/net/ipsec/libcrypto/libmd5/hmac_md5.h
--- linux/net/ipsec/libcrypto/libmd5/hmac_md5.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/hmac_md5.h	Thu Sep  5 04:31:27 2002
@@ -0,0 +1,9 @@
+#include "md5.h"
+typedef struct {
+	MD5_CTX ictx,octx;
+} md5_hmac_context;
+#define MD5_BLOCKSIZE 64
+#define MD5_HASHLEN   16
+
+void md5_hmac_hash(md5_hmac_context *hctx, const __u8 * dat, int len, __u8 * hash, int hashlen);
+void md5_hmac_set_key(md5_hmac_context *hctx, const __u8 * key, int keylen);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/md5.h linux-patched/net/ipsec/libcrypto/libmd5/md5.h
--- linux/net/ipsec/libcrypto/libmd5/md5.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/md5.h	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,122 @@
+/* crypto/md5/md5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD5_H
+#define HEADER_MD5_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#ifdef NO_MD5
+#error MD5 is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD5_LONG_LOG2 has to be defined along.			   !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(WIN16) || defined(__LP32__)
+#define MD5_LONG unsigned long
+#elif defined(_CRAY) || defined(__ILP64__)
+#define MD5_LONG unsigned long
+#define MD5_LONG_LOG2 3
+#endif
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ *					<appro@fy.chalmers.se>
+ */
+
+/* des.h-like hack <jjo-ipsec@mendoza.gov.ar> */
+#ifndef MD5_LONG
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#define MD5_LONG u_int32_t
+#endif
+
+#define MD5_CBLOCK	64
+#define MD5_LBLOCK	(MD5_CBLOCK/4)
+#define MD5_DIGEST_LENGTH 16
+
+typedef struct MD5state_st
+	{
+	MD5_LONG A,B,C,D;
+	MD5_LONG Nl,Nh;
+	MD5_LONG data[MD5_LBLOCK];
+	int num;
+	} MD5_CTX;
+
+void MD5_Init(MD5_CTX *c);
+void MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
+void MD5_Final(unsigned char *md, MD5_CTX *c);
+unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md);
+void MD5_Transform(MD5_CTX *c, const unsigned char *b);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/md5_dgst.c linux-patched/net/ipsec/libcrypto/libmd5/md5_dgst.c
--- linux/net/ipsec/libcrypto/libmd5/md5_dgst.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/md5_dgst.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,321 @@
+/* crypto/md5/md5_dgst.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#endif
+#include "md5_locl.h"
+
+/* Implemented from RFC1321 The MD5 Message-Digest Algorithm
+ */
+
+#define INIT_DATA_A (unsigned long)0x67452301L
+#define INIT_DATA_B (unsigned long)0xefcdab89L
+#define INIT_DATA_C (unsigned long)0x98badcfeL
+#define INIT_DATA_D (unsigned long)0x10325476L
+
+void MD5_Init(MD5_CTX *c)
+	{
+	c->A=INIT_DATA_A;
+	c->B=INIT_DATA_B;
+	c->C=INIT_DATA_C;
+	c->D=INIT_DATA_D;
+	c->Nl=0;
+	c->Nh=0;
+	c->num=0;
+	}
+
+#ifndef md5_block_host_order
+void md5_block_host_order (MD5_CTX *c, const void *data, int num)
+	{
+	const MD5_LONG *X=data;
+	register unsigned long A,B,C,D;
+	/*
+	 * In case you wonder why A-D are declared as long and not
+	 * as MD5_LONG. Doing so results in slight performance
+	 * boost on LP64 architectures. The catch is we don't
+	 * really care if 32 MSBs of a 64-bit register get polluted
+	 * with eventual overflows as we *save* only 32 LSBs in
+	 * *either* case. Now declaring 'em long excuses the compiler
+	 * from keeping 32 MSBs zeroed resulting in 13% performance
+	 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
+	 * Well, to be honest it should say that this *prevents* 
+	 * performance degradation.
+	 *
+	 *				<appro@fy.chalmers.se>
+	 */
+
+	A=c->A;
+	B=c->B;
+	C=c->C;
+	D=c->D;
+
+	for (;num--;X+=HASH_LBLOCK)
+		{
+	/* Round 0 */
+	R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
+	R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
+	R0(C,D,A,B,X[ 2],17,0x242070dbL);
+	R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
+	R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
+	R0(D,A,B,C,X[ 5],12,0x4787c62aL);
+	R0(C,D,A,B,X[ 6],17,0xa8304613L);
+	R0(B,C,D,A,X[ 7],22,0xfd469501L);
+	R0(A,B,C,D,X[ 8], 7,0x698098d8L);
+	R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
+	R0(C,D,A,B,X[10],17,0xffff5bb1L);
+	R0(B,C,D,A,X[11],22,0x895cd7beL);
+	R0(A,B,C,D,X[12], 7,0x6b901122L);
+	R0(D,A,B,C,X[13],12,0xfd987193L);
+	R0(C,D,A,B,X[14],17,0xa679438eL);
+	R0(B,C,D,A,X[15],22,0x49b40821L);
+	/* Round 1 */
+	R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
+	R1(D,A,B,C,X[ 6], 9,0xc040b340L);
+	R1(C,D,A,B,X[11],14,0x265e5a51L);
+	R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
+	R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
+	R1(D,A,B,C,X[10], 9,0x02441453L);
+	R1(C,D,A,B,X[15],14,0xd8a1e681L);
+	R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
+	R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
+	R1(D,A,B,C,X[14], 9,0xc33707d6L);
+	R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
+	R1(B,C,D,A,X[ 8],20,0x455a14edL);
+	R1(A,B,C,D,X[13], 5,0xa9e3e905L);
+	R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
+	R1(C,D,A,B,X[ 7],14,0x676f02d9L);
+	R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
+	/* Round 2 */
+	R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
+	R2(D,A,B,C,X[ 8],11,0x8771f681L);
+	R2(C,D,A,B,X[11],16,0x6d9d6122L);
+	R2(B,C,D,A,X[14],23,0xfde5380cL);
+	R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
+	R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
+	R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
+	R2(B,C,D,A,X[10],23,0xbebfbc70L);
+	R2(A,B,C,D,X[13], 4,0x289b7ec6L);
+	R2(D,A,B,C,X[ 0],11,0xeaa127faL);
+	R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
+	R2(B,C,D,A,X[ 6],23,0x04881d05L);
+	R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
+	R2(D,A,B,C,X[12],11,0xe6db99e5L);
+	R2(C,D,A,B,X[15],16,0x1fa27cf8L);
+	R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
+	/* Round 3 */
+	R3(A,B,C,D,X[ 0], 6,0xf4292244L);
+	R3(D,A,B,C,X[ 7],10,0x432aff97L);
+	R3(C,D,A,B,X[14],15,0xab9423a7L);
+	R3(B,C,D,A,X[ 5],21,0xfc93a039L);
+	R3(A,B,C,D,X[12], 6,0x655b59c3L);
+	R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
+	R3(C,D,A,B,X[10],15,0xffeff47dL);
+	R3(B,C,D,A,X[ 1],21,0x85845dd1L);
+	R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
+	R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
+	R3(C,D,A,B,X[ 6],15,0xa3014314L);
+	R3(B,C,D,A,X[13],21,0x4e0811a1L);
+	R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
+	R3(D,A,B,C,X[11],10,0xbd3af235L);
+	R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
+	R3(B,C,D,A,X[ 9],21,0xeb86d391L);
+
+	A = c->A += A;
+	B = c->B += B;
+	C = c->C += C;
+	D = c->D += D;
+		}
+	}
+#endif
+
+#ifndef md5_block_data_order
+#ifdef X
+#undef X
+#endif
+void md5_block_data_order (MD5_CTX *c, const void *data_, int num)
+	{
+	const unsigned char *data=data_;
+	register unsigned long A,B,C,D,l;
+	/*
+	 * In case you wonder why A-D are declared as long and not
+	 * as MD5_LONG. Doing so results in slight performance
+	 * boost on LP64 architectures. The catch is we don't
+	 * really care if 32 MSBs of a 64-bit register get polluted
+	 * with eventual overflows as we *save* only 32 LSBs in
+	 * *either* case. Now declaring 'em long excuses the compiler
+	 * from keeping 32 MSBs zeroed resulting in 13% performance
+	 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
+	 * Well, to be honest it should say that this *prevents* 
+	 * performance degradation.
+	 *
+	 *				<appro@fy.chalmers.se>
+	 */
+#ifndef MD32_XARRAY
+	/* See comment in crypto/sha/sha_locl.h for details. */
+	unsigned long	XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
+			XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
+# define X(i)	XX##i
+#else
+	MD5_LONG XX[MD5_LBLOCK];
+# define X(i)	XX[i]
+#endif
+
+	A=c->A;
+	B=c->B;
+	C=c->C;
+	D=c->D;
+
+	for (;num--;)
+		{
+	HOST_c2l(data,l); X( 0)=l;		HOST_c2l(data,l); X( 1)=l;
+	/* Round 0 */
+	R0(A,B,C,D,X( 0), 7,0xd76aa478L);	HOST_c2l(data,l); X( 2)=l;
+	R0(D,A,B,C,X( 1),12,0xe8c7b756L);	HOST_c2l(data,l); X( 3)=l;
+	R0(C,D,A,B,X( 2),17,0x242070dbL);	HOST_c2l(data,l); X( 4)=l;
+	R0(B,C,D,A,X( 3),22,0xc1bdceeeL);	HOST_c2l(data,l); X( 5)=l;
+	R0(A,B,C,D,X( 4), 7,0xf57c0fafL);	HOST_c2l(data,l); X( 6)=l;
+	R0(D,A,B,C,X( 5),12,0x4787c62aL);	HOST_c2l(data,l); X( 7)=l;
+	R0(C,D,A,B,X( 6),17,0xa8304613L);	HOST_c2l(data,l); X( 8)=l;
+	R0(B,C,D,A,X( 7),22,0xfd469501L);	HOST_c2l(data,l); X( 9)=l;
+	R0(A,B,C,D,X( 8), 7,0x698098d8L);	HOST_c2l(data,l); X(10)=l;
+	R0(D,A,B,C,X( 9),12,0x8b44f7afL);	HOST_c2l(data,l); X(11)=l;
+	R0(C,D,A,B,X(10),17,0xffff5bb1L);	HOST_c2l(data,l); X(12)=l;
+	R0(B,C,D,A,X(11),22,0x895cd7beL);	HOST_c2l(data,l); X(13)=l;
+	R0(A,B,C,D,X(12), 7,0x6b901122L);	HOST_c2l(data,l); X(14)=l;
+	R0(D,A,B,C,X(13),12,0xfd987193L);	HOST_c2l(data,l); X(15)=l;
+	R0(C,D,A,B,X(14),17,0xa679438eL);
+	R0(B,C,D,A,X(15),22,0x49b40821L);
+	/* Round 1 */
+	R1(A,B,C,D,X( 1), 5,0xf61e2562L);
+	R1(D,A,B,C,X( 6), 9,0xc040b340L);
+	R1(C,D,A,B,X(11),14,0x265e5a51L);
+	R1(B,C,D,A,X( 0),20,0xe9b6c7aaL);
+	R1(A,B,C,D,X( 5), 5,0xd62f105dL);
+	R1(D,A,B,C,X(10), 9,0x02441453L);
+	R1(C,D,A,B,X(15),14,0xd8a1e681L);
+	R1(B,C,D,A,X( 4),20,0xe7d3fbc8L);
+	R1(A,B,C,D,X( 9), 5,0x21e1cde6L);
+	R1(D,A,B,C,X(14), 9,0xc33707d6L);
+	R1(C,D,A,B,X( 3),14,0xf4d50d87L);
+	R1(B,C,D,A,X( 8),20,0x455a14edL);
+	R1(A,B,C,D,X(13), 5,0xa9e3e905L);
+	R1(D,A,B,C,X( 2), 9,0xfcefa3f8L);
+	R1(C,D,A,B,X( 7),14,0x676f02d9L);
+	R1(B,C,D,A,X(12),20,0x8d2a4c8aL);
+	/* Round 2 */
+	R2(A,B,C,D,X( 5), 4,0xfffa3942L);
+	R2(D,A,B,C,X( 8),11,0x8771f681L);
+	R2(C,D,A,B,X(11),16,0x6d9d6122L);
+	R2(B,C,D,A,X(14),23,0xfde5380cL);
+	R2(A,B,C,D,X( 1), 4,0xa4beea44L);
+	R2(D,A,B,C,X( 4),11,0x4bdecfa9L);
+	R2(C,D,A,B,X( 7),16,0xf6bb4b60L);
+	R2(B,C,D,A,X(10),23,0xbebfbc70L);
+	R2(A,B,C,D,X(13), 4,0x289b7ec6L);
+	R2(D,A,B,C,X( 0),11,0xeaa127faL);
+	R2(C,D,A,B,X( 3),16,0xd4ef3085L);
+	R2(B,C,D,A,X( 6),23,0x04881d05L);
+	R2(A,B,C,D,X( 9), 4,0xd9d4d039L);
+	R2(D,A,B,C,X(12),11,0xe6db99e5L);
+	R2(C,D,A,B,X(15),16,0x1fa27cf8L);
+	R2(B,C,D,A,X( 2),23,0xc4ac5665L);
+	/* Round 3 */
+	R3(A,B,C,D,X( 0), 6,0xf4292244L);
+	R3(D,A,B,C,X( 7),10,0x432aff97L);
+	R3(C,D,A,B,X(14),15,0xab9423a7L);
+	R3(B,C,D,A,X( 5),21,0xfc93a039L);
+	R3(A,B,C,D,X(12), 6,0x655b59c3L);
+	R3(D,A,B,C,X( 3),10,0x8f0ccc92L);
+	R3(C,D,A,B,X(10),15,0xffeff47dL);
+	R3(B,C,D,A,X( 1),21,0x85845dd1L);
+	R3(A,B,C,D,X( 8), 6,0x6fa87e4fL);
+	R3(D,A,B,C,X(15),10,0xfe2ce6e0L);
+	R3(C,D,A,B,X( 6),15,0xa3014314L);
+	R3(B,C,D,A,X(13),21,0x4e0811a1L);
+	R3(A,B,C,D,X( 4), 6,0xf7537e82L);
+	R3(D,A,B,C,X(11),10,0xbd3af235L);
+	R3(C,D,A,B,X( 2),15,0x2ad7d2bbL);
+	R3(B,C,D,A,X( 9),21,0xeb86d391L);
+
+	A = c->A += A;
+	B = c->B += B;
+	C = c->C += C;
+	D = c->D += D;
+		}
+	}
+#endif
+
+#ifdef undef
+int printit(unsigned long *l)
+	{
+	int i,ii;
+
+	for (i=0; i<2; i++)
+		{
+		for (ii=0; ii<8; ii++)
+			{
+			fprintf(stderr,"%08lx ",l[i*8+ii]);
+			}
+		fprintf(stderr,"\n");
+		}
+	}
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/md5_locl.h linux-patched/net/ipsec/libcrypto/libmd5/md5_locl.h
--- linux/net/ipsec/libcrypto/libmd5/md5_locl.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/md5_locl.h	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,177 @@
+/* crypto/md5/md5_locl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#include "md5.h"
+#else
+#include <stdlib.h>
+#include <string.h>
+#include "md5.h"
+#endif
+
+#ifndef MD5_LONG_LOG2
+#define MD5_LONG_LOG2 2 /* default to 32 bits */
+#endif
+
+#ifdef MD5_ASM
+# if defined(__i386) || defined(_M_IX86) || defined(__INTEL__)
+#  define md5_block_host_order md5_block_asm_host_order
+# elif defined(__sparc) && defined(ULTRASPARC)
+   void md5_block_asm_data_order_aligned (MD5_CTX *c, const MD5_LONG *p,int num);
+#  define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned
+# endif
+#endif
+
+void md5_block_host_order (MD5_CTX *c, const void *p,int num);
+void md5_block_data_order (MD5_CTX *c, const void *p,int num);
+
+#if defined(__i386) || defined(_M_IX86) || defined(__INTEL__)
+/*
+ * *_block_host_order is expected to handle aligned data while
+ * *_block_data_order - unaligned. As algorithm and host (x86)
+ * are in this case of the same "endianness" these two are
+ * otherwise indistinguishable. But normally you don't want to
+ * call the same function because unaligned access in places
+ * where alignment is expected is usually a "Bad Thing". Indeed,
+ * on RISCs you get punished with BUS ERROR signal or *severe*
+ * performance degradation. Intel CPUs are in turn perfectly
+ * capable of loading unaligned data without such drastic side
+ * effect. Yes, they say it's slower than aligned load, but no
+ * exception is generated and therefore performance degradation
+ * is *incomparable* with RISCs. What we should weight here is
+ * costs of unaligned access against costs of aligning data.
+ * According to my measurements allowing unaligned access results
+ * in ~9% performance improvement on Pentium II operating at
+ * 266MHz. I won't be surprised if the difference will be higher
+ * on faster systems:-)
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#define md5_block_data_order md5_block_host_order
+#endif
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG		MD5_LONG
+#define HASH_LONG_LOG2		MD5_LONG_LOG2
+#define HASH_CTX		MD5_CTX
+#define HASH_CBLOCK		MD5_CBLOCK
+#define HASH_LBLOCK		MD5_LBLOCK
+#define HASH_UPDATE		MD5_Update
+#define HASH_TRANSFORM		MD5_Transform
+#define HASH_FINAL		MD5_Final
+#define	HASH_MAKE_STRING(c,s)	do {	\
+	unsigned long ll;		\
+	ll=(c)->A; HOST_l2c(ll,(s));	\
+	ll=(c)->B; HOST_l2c(ll,(s));	\
+	ll=(c)->C; HOST_l2c(ll,(s));	\
+	ll=(c)->D; HOST_l2c(ll,(s));	\
+	} while (0)
+#define HASH_BLOCK_HOST_ORDER	md5_block_host_order
+#if !defined(L_ENDIAN) || defined(md5_block_data_order)
+#define	HASH_BLOCK_DATA_ORDER	md5_block_data_order
+/*
+ * Little-endians (Intel and Alpha) feel better without this.
+ * It looks like memcpy does better job than generic
+ * md5_block_data_order on copying-n-aligning input data.
+ * But frankly speaking I didn't expect such result on Alpha.
+ * On the other hand I've got this with egcs-1.0.2 and if
+ * program is compiled with another (better?) compiler it
+ * might turn out other way around.
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#endif
+
+#include "md32_common.h"
+
+/*
+#define	F(x,y,z)	(((x) & (y))  |  ((~(x)) & (z)))
+#define	G(x,y,z)	(((x) & (z))  |  ((y) & (~(z))))
+*/
+
+/* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
+ * simplified to the code below.  Wei attributes these optimizations
+ * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
+ */
+#define	F(b,c,d)	((((c) ^ (d)) & (b)) ^ (d))
+#define	G(b,c,d)	((((b) ^ (c)) & (d)) ^ (c))
+#define	H(b,c,d)	((b) ^ (c) ^ (d))
+#define	I(b,c,d)	(((~(d)) | (b)) ^ (c))
+
+#define R0(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+F((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };\
+
+#define R1(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+G((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };
+
+#define R2(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+H((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };
+
+#define R3(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+I((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libmd5/md5_one.c linux-patched/net/ipsec/libcrypto/libmd5/md5_one.c
--- linux/net/ipsec/libcrypto/libmd5/md5_one.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libmd5/md5_one.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,97 @@
+/* crypto/md5/md5_one.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+
+#include "md5.h"
+
+unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md)
+	{
+	MD5_CTX c;
+	static unsigned char m[MD5_DIGEST_LENGTH];
+
+	if (md == NULL) md=m;
+	MD5_Init(&c);
+#ifndef CHARSET_EBCDIC
+	MD5_Update(&c,d,n);
+#else
+	{
+		char temp[1024];
+		unsigned long chunk;
+
+		while (n > 0)
+		{
+			chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
+			ebcdic2ascii(temp, d, chunk);
+			MD5_Update(&c,temp,chunk);
+			n -= chunk;
+			d += chunk;
+		}
+	}
+#endif
+	MD5_Final(md,&c);
+	memset(&c,0,sizeof(c)); /* security consideration */
+	return(md);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libserpent/Makefile linux-patched/net/ipsec/libcrypto/libserpent/Makefile
--- linux/net/ipsec/libcrypto/libserpent/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libserpent/Makefile	Tue Jul  8 15:21:05 2003
@@ -0,0 +1,20 @@
+CFLAGS=-O3 -fomit-frame-pointer -D__KERNEL__  -Wall $(EXTRA_CFLAGS)
+INC=-I../include 
+LIBOBJ=serpent.o serpent_cbc.o
+BLIB=libserpent.a
+
+.c.o:
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c $< -o $@
+
+$(BLIB): $(LIBOBJ)
+	/bin/rm -f $(BLIB)
+	ar cr $(BLIB) $(LIBOBJ)
+	-if test -s /bin/ranlib; then /bin/ranlib $(BLIB); \
+	else if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(BLIB); \
+	else exit 0; fi; fi
+
+test: test_main.o $(BLIB)
+	$(CC) -o $@ $^ 
+
+clean:
+	rm -f *.[oa] core $(TARGET) test
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libserpent/serpent.c linux-patched/net/ipsec/libcrypto/libserpent/serpent.c
--- linux/net/ipsec/libcrypto/libserpent/serpent.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libserpent/serpent.c	Tue Oct  1 14:47:14 2002
@@ -0,0 +1,995 @@
+
+/* Optimized implementation of the Serpent AES candidate algorithm
+ * Designed by Anderson, Biham and Knudsen and Implemented by 
+ * Gisle Sælensminde 2000. 
+ *
+ * The implementation is based on the pentium optimised sboxes of
+ * Dag Arne Osvik. Even these sboxes are designed to be optimal for x86 
+ * processors they are efficient on other processors as well, but the speedup 
+ * isn't so impressive compared to other implementations.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version. 
+ */
+
+#ifdef __KERNEL__
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <asm/byteorder.h>
+#else
+#include <sys/types.h>
+#include <asm/byteorder.h>
+#endif
+
+#include "serpent.h"
+
+#define rotl(reg, val) ((reg << val) | (reg >> (32 - val)))
+#define rotr(reg, val) ((reg >> val) | (reg << (32 - val)))
+ 
+#ifdef __cpu_to_be32
+#define BLOCK_SWAP
+#define io_swap(x)  __cpu_to_be32(x)
+#else
+#undef BLOCK_SWAP
+#endif
+
+/* The sbox functions. The first four parameters is the input bits, and 
+ * the last is a tempoary. These parameters are also used for output, but
+ * the bit order is permuted. The output bit order from S0 is
+ * (1 4 2 0 3), where 3 is the (now useless) tempoary. 
+ */
+
+#define S0(r0,r1,r2,r3,r4) \
+      r3 = r3 ^ r0; \
+      r4 = r1; \
+      r1 = r1 & r3; \
+      r4 = r4 ^ r2; \
+      r1 = r1 ^ r0; \
+      r0 = r0 | r3; \
+      r0 = r0 ^ r4; \
+      r4 = r4 ^ r3; \
+      r3 = r3 ^ r2; \
+      r2 = r2 | r1; \
+      r2 = r2 ^ r4; \
+      r4 = -1 ^ r4; \
+      r4 = r4 | r1; \
+      r1 = r1 ^ r3; \
+      r1 = r1 ^ r4; \
+      r3 = r3 | r0; \
+      r1 = r1 ^ r3; \
+      r4 = r4 ^ r3; 
+
+#define S1(r0,r1,r2,r3,r4) \
+      r1 = -1 ^ r1; \
+      r4 = r0; \
+      r0 = r0 ^ r1; \
+      r4 = r4 | r1; \
+      r4 = r4 ^ r3; \
+      r3 = r3 & r0; \
+      r2 = r2 ^ r4; \
+      r3 = r3 ^ r1; \
+      r3 = r3 | r2; \
+      r0 = r0 ^ r4; \
+      r3 = r3 ^ r0; \
+      r1 = r1 & r2; \
+      r0 = r0 | r1; \
+      r1 = r1 ^ r4; \
+      r0 = r0 ^ r2; \
+      r4 = r4 | r3; \
+      r0 = r0 ^ r4; \
+      r4 = -1 ^ r4; \
+      r1 = r1 ^ r3; \
+      r4 = r4 & r2; \
+      r1 = -1 ^ r1; \
+      r4 = r4 ^ r0; \
+      r1 = r1 ^ r4; 
+
+#define S2(r0,r1,r2,r3,r4) \
+      r4 = r0; \
+      r0 = r0 & r2; \
+      r0 = r0 ^ r3; \
+      r2 = r2 ^ r1; \
+      r2 = r2 ^ r0; \
+      r3 = r3 | r4; \
+      r3 = r3 ^ r1; \
+      r4 = r4 ^ r2; \
+      r1 = r3; \
+      r3 = r3 | r4; \
+      r3 = r3 ^ r0; \
+      r0 = r0 & r1; \
+      r4 = r4 ^ r0; \
+      r1 = r1 ^ r3; \
+      r1 = r1 ^ r4; \
+      r4 = -1 ^ r4; 
+
+#define S3(r0,r1,r2,r3,r4) \
+      r4 = r0 ; \
+      r0 = r0 | r3; \
+      r3 = r3 ^ r1; \
+      r1 = r1 & r4; \
+      r4 = r4 ^ r2; \
+      r2 = r2 ^ r3; \
+      r3 = r3 & r0; \
+      r4 = r4 | r1; \
+      r3 = r3 ^ r4; \
+      r0 = r0 ^ r1; \
+      r4 = r4 & r0; \
+      r1 = r1 ^ r3; \
+      r4 = r4 ^ r2; \
+      r1 = r1 | r0; \
+      r1 = r1 ^ r2; \
+      r0 = r0 ^ r3; \
+      r2 = r1; \
+      r1 = r1 | r3; \
+      r1 = r1 ^ r0; 
+
+#define S4(r0,r1,r2,r3,r4) \
+      r1 = r1 ^ r3; \
+      r3 = -1 ^ r3; \
+      r2 = r2 ^ r3; \
+      r3 = r3 ^ r0; \
+      r4 = r1; \
+      r1 = r1 & r3; \
+      r1 = r1 ^ r2; \
+      r4 = r4 ^ r3; \
+      r0 = r0 ^ r4; \
+      r2 = r2 & r4; \
+      r2 = r2 ^ r0; \
+      r0 = r0 & r1; \
+      r3 = r3 ^ r0; \
+      r4 = r4 | r1; \
+      r4 = r4 ^ r0; \
+      r0 = r0 | r3; \
+      r0 = r0 ^ r2; \
+      r2 = r2 & r3; \
+      r0 = -1 ^ r0; \
+      r4 = r4 ^ r2; 
+
+#define S5(r0,r1,r2,r3,r4) \
+      r0 = r0 ^ r1; \
+      r1 = r1 ^ r3; \
+      r3 = -1 ^ r3; \
+      r4 = r1; \
+      r1 = r1 & r0; \
+      r2 = r2 ^ r3; \
+      r1 = r1 ^ r2; \
+      r2 = r2 | r4; \
+      r4 = r4 ^ r3; \
+      r3 = r3 & r1; \
+      r3 = r3 ^ r0; \
+      r4 = r4 ^ r1; \
+      r4 = r4 ^ r2; \
+      r2 = r2 ^ r0; \
+      r0 = r0 & r3; \
+      r2 = -1 ^ r2; \
+      r0 = r0 ^ r4; \
+      r4 = r4 | r3; \
+      r2 = r2 ^ r4; 
+
+#define S6(r0,r1,r2,r3,r4) \
+      r2 = -1 ^ r2; \
+      r4 = r3; \
+      r3 = r3 & r0; \
+      r0 = r0 ^ r4; \
+      r3 = r3 ^ r2; \
+      r2 = r2 | r4; \
+      r1 = r1 ^ r3; \
+      r2 = r2 ^ r0; \
+      r0 = r0 | r1; \
+      r2 = r2 ^ r1; \
+      r4 = r4 ^ r0; \
+      r0 = r0 | r3; \
+      r0 = r0 ^ r2; \
+      r4 = r4 ^ r3; \
+      r4 = r4 ^ r0; \
+      r3 = -1 ^ r3; \
+      r2 = r2 & r4; \
+      r2 = r2 ^ r3; 
+
+#define S7(r0,r1,r2,r3,r4) \
+      r4 = r2; \
+      r2 = r2 & r1; \
+      r2 = r2 ^ r3; \
+      r3 = r3 & r1; \
+      r4 = r4 ^ r2; \
+      r2 = r2 ^ r1; \
+      r1 = r1 ^ r0; \
+      r0 = r0 | r4; \
+      r0 = r0 ^ r2; \
+      r3 = r3 ^ r1; \
+      r2 = r2 ^ r3; \
+      r3 = r3 & r0; \
+      r3 = r3 ^ r4; \
+      r4 = r4 ^ r2; \
+      r2 = r2 & r0; \
+      r4 = -1 ^ r4; \
+      r2 = r2 ^ r4; \
+      r4 = r4 & r0; \
+      r1 = r1 ^ r3; \
+      r4 = r4 ^ r1; 
+
+/* The inverse sboxes */
+
+#define I0(r0,r1,r2,r3,r4) \
+      r2 = r2 ^ -1; \
+      r4 = r1; \
+      r1 = r1 | r0; \
+      r4 = r4 ^ -1; \
+      r1 = r1 ^ r2; \
+      r2 = r2 | r4; \
+      r1 = r1 ^ r3; \
+      r0 = r0 ^ r4; \
+      r2 = r2 ^ r0; \
+      r0 = r0 & r3; \
+      r4 = r4 ^ r0; \
+      r0 = r0 | r1; \
+      r0 = r0 ^ r2; \
+      r3 = r3 ^ r4; \
+      r2 = r2 ^ r1; \
+      r3 = r3 ^ r0; \
+      r3 = r3 ^ r1; \
+      r2 = r2 & r3; \
+      r4 = r4 ^ r2; 
+ 
+#define I1(r0,r1,r2,r3,r4) \
+      r4 = r1; \
+      r1 = r1 ^ r3; \
+      r3 = r3 & r1; \
+      r4 = r4 ^ r2; \
+      r3 = r3 ^ r0; \
+      r0 = r0 | r1; \
+      r2 = r2 ^ r3; \
+      r0 = r0 ^ r4; \
+      r0 = r0 | r2; \
+      r1 = r1 ^ r3; \
+      r0 = r0 ^ r1; \
+      r1 = r1 | r3; \
+      r1 = r1 ^ r0; \
+      r4 = r4 ^ -1; \
+      r4 = r4 ^ r1; \
+      r1 = r1 | r0; \
+      r1 = r1 ^ r0; \
+      r1 = r1 | r4; \
+      r3 = r3 ^ r1; 
+
+#define I2(r0,r1,r2,r3,r4) \
+      r2 = r2 ^ r3; \
+      r3 = r3 ^ r0; \
+      r4 =  r3; \
+      r3 = r3 & r2; \
+      r3 = r3 ^ r1; \
+      r1 = r1 | r2; \
+      r1 = r1 ^ r4; \
+      r4 = r4 & r3; \
+      r2 = r2 ^ r3; \
+      r4 = r4 & r0; \
+      r4 = r4 ^ r2; \
+      r2 = r2 & r1; \
+      r2 = r2 | r0; \
+      r3 = r3 ^ -1; \
+      r2 = r2 ^ r3; \
+      r0 = r0 ^ r3; \
+      r0 = r0 & r1; \
+      r3 = r3 ^ r4; \
+      r3 = r3 ^ r0; 
+
+#define I3(r0,r1,r2,r3,r4) \
+      r4 =  r2; \
+      r2 = r2 ^ r1; \
+      r0 = r0 ^ r2; \
+      r4 = r4 & r2; \
+      r4 = r4 ^ r0; \
+      r0 = r0 & r1; \
+      r1 = r1 ^ r3; \
+      r3 = r3 | r4; \
+      r2 = r2 ^ r3; \
+      r0 = r0 ^ r3; \
+      r1 = r1 ^ r4; \
+      r3 = r3 & r2; \
+      r3 = r3 ^ r1; \
+      r1 = r1 ^ r0; \
+      r1 = r1 | r2; \
+      r0 = r0 ^ r3; \
+      r1 = r1 ^ r4; \
+      r0 = r0 ^ r1; 
+
+#define I4(r0,r1,r2,r3,r4) \
+      r4 =  r2; \
+      r2 = r2 & r3; \
+      r2 = r2 ^ r1; \
+      r1 = r1 | r3; \
+      r1 = r1 & r0; \
+      r4 = r4 ^ r2; \
+      r4 = r4 ^ r1; \
+      r1 = r1 & r2; \
+      r0 = r0 ^ -1; \
+      r3 = r3 ^ r4; \
+      r1 = r1 ^ r3; \
+      r3 = r3 & r0; \
+      r3 = r3 ^ r2; \
+      r0 = r0 ^ r1; \
+      r2 = r2 & r0; \
+      r3 = r3 ^ r0; \
+      r2 = r2 ^ r4; \
+      r2 = r2 | r3; \
+      r3 = r3 ^ r0; \
+      r2 = r2 ^ r1; 
+
+#define I5(r0,r1,r2,r3,r4) \
+      r1 = r1 ^ -1; \
+      r4 = r3; \
+      r2 = r2 ^ r1; \
+      r3 = r3 | r0; \
+      r3 = r3 ^ r2; \
+      r2 = r2 | r1; \
+      r2 = r2 & r0; \
+      r4 = r4 ^ r3; \
+      r2 = r2 ^ r4; \
+      r4 = r4 | r0; \
+      r4 = r4 ^ r1; \
+      r1 = r1 & r2; \
+      r1 = r1 ^ r3; \
+      r4 = r4 ^ r2; \
+      r3 = r3 & r4; \
+      r4 = r4 ^ r1; \
+      r3 = r3 ^ r0; \
+      r3 = r3 ^ r4; \
+      r4 = r4 ^ -1; 
+
+
+#define I6(r0,r1,r2,r3,r4) \
+      r0 = r0 ^ r2; \
+      r4 = r2; \
+      r2 = r2 & r0; \
+      r4 = r4 ^ r3; \
+      r2 = r2 ^ -1; \
+      r3 = r3 ^ r1; \
+      r2 = r2 ^ r3; \
+      r4 = r4 | r0; \
+      r0 = r0 ^ r2; \
+      r3 = r3 ^ r4; \
+      r4 = r4 ^ r1; \
+      r1 = r1 & r3; \
+      r1 = r1 ^ r0; \
+      r0 = r0 ^ r3; \
+      r0 = r0 | r2; \
+      r3 = r3 ^ r1; \
+      r4 = r4 ^ r0; 
+
+#define I7(r0,r1,r2,r3,r4) \
+      r4 = r2; \
+      r2 = r2 ^ r0; \
+      r0 = r0 & r3; \
+      r4 = r4 | r3; \
+      r2 = r2 ^ -1; \
+      r3 = r3 ^ r1; \
+      r1 = r1 | r0; \
+      r0 = r0 ^ r2; \
+      r2 = r2 & r4; \
+      r3 = r3 & r4; \
+      r1 = r1 ^ r2; \
+      r2 = r2 ^ r0; \
+      r0 = r0 | r2; \
+      r4 = r4 ^ r1; \
+      r0 = r0 ^ r3; \
+      r3 = r3 ^ r4; \
+      r4 = r4 | r0; \
+      r3 = r3 ^ r2; \
+      r4 = r4 ^ r2; 
+
+/* forward and inverse linear transformations */
+
+#define LINTRANS(r0,r1,r2,r3,r4) \
+      r0 = rotl(r0, 13); \
+      r2 = rotl(r2, 3); \
+      r3 = r3 ^ r2; \
+      r4 = r0 << 3; \
+      r1 = r1 ^ r0; \
+      r3 = r3 ^ r4; \
+      r1 = r1 ^ r2; \
+      r3 = rotl(r3, 7); \
+      r1 = rotl(r1, 1); \
+      r2 = r2 ^ r3; \
+      r4 = r1 << 7; \
+      r0 = r0 ^ r1; \
+      r2 = r2 ^ r4; \
+      r0 = r0 ^ r3; \
+      r2 = rotl(r2, 22); \
+      r0 = rotl(r0, 5);
+     
+#define ILINTRANS(r0,r1,r2,r3,r4) \
+      r2 = rotr(r2, 22); \
+      r0 = rotr(r0, 5); \
+      r2 = r2 ^ r3; \
+      r4 = r1 << 7; \
+      r0 = r0 ^ r1; \
+      r2 = r2 ^ r4; \
+      r0 = r0 ^ r3; \
+      r3 = rotr(r3, 7); \
+      r1 = rotr(r1, 1); \
+      r3 = r3 ^ r2; \
+      r4 = r0 << 3; \
+      r1 = r1 ^ r0; \
+      r3 = r3 ^ r4; \
+      r1 = r1 ^ r2; \
+      r2 = rotr(r2, 3); \
+      r0 = rotr(r0, 13); 
+
+
+#define KEYMIX(r0,r1,r2,r3,r4,IN) \
+      r0  = r0 ^ l_key[IN+8]; \
+      r1  = r1 ^ l_key[IN+9]; \
+      r2  = r2 ^ l_key[IN+10]; \
+      r3  = r3 ^ l_key[IN+11]; 
+
+#define GETKEY(r0, r1, r2, r3, IN) \
+      r0 = l_key[IN+8]; \
+      r1 = l_key[IN+9]; \
+      r2 = l_key[IN+10]; \
+      r3 = l_key[IN+11]; 
+
+#define SETKEY(r0, r1, r2, r3, IN) \
+      l_key[IN+8] = r0; \
+      l_key[IN+9] = r1; \
+      l_key[IN+10] = r2; \
+      l_key[IN+11] = r3;
+
+/* initialise the key schedule from the user supplied key   */
+
+int serpent_set_key(serpent_context *cx, const unsigned char *key, int key_len)
+{   const u32 *in_key = (const u32 *)key;
+    /* l_key - storage for the key schedule */
+    u32 *l_key   = cx->keyinfo;
+    u32  i,lk,r0,r1,r2,r3,r4;
+
+    if (key_len != 16 && key_len != 24 && key_len != 32)
+      return -1; /* unsupported key length */
+    
+    key_len *= 8;
+
+    i = 0; lk = (key_len + 31) / 32;
+    
+    while(i < lk)
+    {
+#ifdef  BLOCK_SWAP
+        l_key[i] = io_swap(in_key[lk - i - 1]);
+#else
+        l_key[i] = in_key[i];
+#endif  
+        i++;
+    }
+
+    if (key_len < 256)
+    {
+        while(i < 8)
+
+            l_key[i++] = 0;
+
+        i = key_len / 32; lk = 1 << key_len % 32; 
+
+        l_key[i] &= lk - 1;
+        l_key[i] |= lk;
+    }
+
+    for(i = 0; i < 132; ++i)
+    {
+        lk = l_key[i] ^ l_key[i + 3] ^ l_key[i + 5] 
+                                ^ l_key[i + 7] ^ 0x9e3779b9 ^ i;
+
+        l_key[i + 8] = (lk << 11) | (lk >> 21); 
+    }
+
+      GETKEY(r0, r1, r2, r3, 0);
+      S3(r0,r1,r2,r3,r4);
+      SETKEY(r1, r2, r3, r4, 0) 
+
+      GETKEY(r0, r1, r2, r3, 4);
+      S2(r0,r1,r2,r3,r4);
+      SETKEY(r2, r3, r1, r4, 4) 
+
+      GETKEY(r0, r1, r2, r3, 8);
+      S1(r0,r1,r2,r3,r4);
+      SETKEY(r3, r1, r2, r0, 8) 
+
+      GETKEY(r0, r1, r2, r3, 12);
+      S0(r0,r1,r2,r3,r4);
+      SETKEY(r1, r4, r2, r0, 12) 
+
+      GETKEY(r0, r1, r2, r3, 16);
+      S7(r0,r1,r2,r3,r4);
+      SETKEY(r2, r4, r3, r0, 16) 
+
+      GETKEY(r0, r1, r2, r3, 20);
+      S6(r0,r1,r2,r3,r4) 
+      SETKEY(r0, r1, r4, r2, 20) 
+
+      GETKEY(r0, r1, r2, r3, 24);
+      S5(r0,r1,r2,r3,r4);
+      SETKEY(r1, r3, r0, r2, 24) 
+
+      GETKEY(r0, r1, r2, r3, 28);
+      S4(r0,r1,r2,r3,r4) 
+      SETKEY(r1, r4, r0, r3, 28) 
+
+      GETKEY(r0, r1, r2, r3, 32);
+      S3(r0,r1,r2,r3,r4);
+      SETKEY(r1, r2, r3, r4, 32) 
+
+      GETKEY(r0, r1, r2, r3, 36);
+      S2(r0,r1,r2,r3,r4);
+      SETKEY(r2, r3, r1, r4, 36) 
+
+      GETKEY(r0, r1, r2, r3, 40);
+      S1(r0,r1,r2,r3,r4);
+      SETKEY(r3, r1, r2, r0, 40) 
+
+      GETKEY(r0, r1, r2, r3, 44);
+      S0(r0,r1,r2,r3,r4);
+      SETKEY(r1, r4, r2, r0, 44) 
+
+      GETKEY(r0, r1, r2, r3, 48);
+      S7(r0,r1,r2,r3,r4);
+      SETKEY(r2, r4, r3, r0, 48) 
+
+      GETKEY(r0, r1, r2, r3, 52);
+      S6(r0,r1,r2,r3,r4) 
+      SETKEY(r0, r1, r4, r2, 52) 
+
+      GETKEY(r0, r1, r2, r3, 56);
+      S5(r0,r1,r2,r3,r4);
+      SETKEY(r1, r3, r0, r2, 56) 
+
+      GETKEY(r0, r1, r2, r3, 60);
+      S4(r0,r1,r2,r3,r4) 
+      SETKEY(r1, r4, r0, r3, 60) 
+
+      GETKEY(r0, r1, r2, r3, 64);
+      S3(r0,r1,r2,r3,r4);
+      SETKEY(r1, r2, r3, r4, 64) 
+
+      GETKEY(r0, r1, r2, r3, 68);
+      S2(r0,r1,r2,r3,r4);
+      SETKEY(r2, r3, r1, r4, 68) 
+
+      GETKEY(r0, r1, r2, r3, 72);
+      S1(r0,r1,r2,r3,r4);
+      SETKEY(r3, r1, r2, r0, 72) 
+
+      GETKEY(r0, r1, r2, r3, 76);
+      S0(r0,r1,r2,r3,r4);
+      SETKEY(r1, r4, r2, r0, 76) 
+
+      GETKEY(r0, r1, r2, r3, 80);
+      S7(r0,r1,r2,r3,r4);
+      SETKEY(r2, r4, r3, r0, 80) 
+
+      GETKEY(r0, r1, r2, r3, 84);
+      S6(r0,r1,r2,r3,r4) 
+      SETKEY(r0, r1, r4, r2, 84) 
+
+      GETKEY(r0, r1, r2, r3, 88);
+      S5(r0,r1,r2,r3,r4);
+      SETKEY(r1, r3, r0, r2, 88) 
+
+      GETKEY(r0, r1, r2, r3, 92);
+      S4(r0,r1,r2,r3,r4) 
+      SETKEY(r1, r4, r0, r3, 92) 
+
+      GETKEY(r0, r1, r2, r3, 96);
+      S3(r0,r1,r2,r3,r4);
+      SETKEY(r1, r2, r3, r4, 96) 
+
+      GETKEY(r0, r1, r2, r3, 100);
+      S2(r0,r1,r2,r3,r4);
+      SETKEY(r2, r3, r1, r4, 100) 
+
+      GETKEY(r0, r1, r2, r3, 104);
+      S1(r0,r1,r2,r3,r4);
+      SETKEY(r3, r1, r2, r0, 104) 
+
+      GETKEY(r0, r1, r2, r3, 108);
+      S0(r0,r1,r2,r3,r4);
+      SETKEY(r1, r4, r2, r0, 108) 
+
+      GETKEY(r0, r1, r2, r3, 112);
+      S7(r0,r1,r2,r3,r4);
+      SETKEY(r2, r4, r3, r0, 112) 
+
+      GETKEY(r0, r1, r2, r3, 116);
+      S6(r0,r1,r2,r3,r4) 
+      SETKEY(r0, r1, r4, r2, 116) 
+
+      GETKEY(r0, r1, r2, r3, 120);
+      S5(r0,r1,r2,r3,r4);
+      SETKEY(r1, r3, r0, r2, 120) 
+
+      GETKEY(r0, r1, r2, r3, 124);
+      S4(r0,r1,r2,r3,r4) 
+      SETKEY(r1, r4, r0, r3, 124) 
+
+      GETKEY(r0, r1, r2, r3, 128);
+      S3(r0,r1,r2,r3,r4);
+      SETKEY(r1, r2, r3, r4, 128) 
+
+    return 0;
+};
+
+/* Encryption and decryption functions. The rounds are fully inlined. 
+ * The sboxes alters the bit order of the output, and the altered
+ * bit ordrer is used progressivly. */
+
+/* encrypt a block of text */
+
+int serpent_encrypt(serpent_context *cx, const u8 *in, 
+		    u8 *out)
+{    u32 *l_key = cx->keyinfo;
+     const u32 *in_blk = (const u32 *) in;
+     u32 *out_blk = (u32 *) out;
+     u32  r0,r1,r2,r3,r4;
+    
+#ifdef  BLOCK_SWAP
+    r0 = io_swap(in_blk[3]); r1 = io_swap(in_blk[2]); 
+    r2 = io_swap(in_blk[1]); r3 = io_swap(in_blk[0]);
+#else
+    r0 = in_blk[0]; r1 = in_blk[1]; r2 = in_blk[2]; r3 = in_blk[3];
+#endif
+
+      /* round 1  */
+      KEYMIX(r0,r1,r2,r3,r4,0);
+      S0(r0,r1,r2,r3,r4);
+      LINTRANS(r1,r4,r2,r0,r3);
+
+      /* round 2  */
+      KEYMIX(r1,r4,r2,r0,r3,4);
+      S1(r1,r4,r2,r0,r3);
+      LINTRANS(r0,r4,r2,r1,r3);
+
+      /* round 3  */
+      KEYMIX(r0,r4,r2,r1,r3,8);
+      S2(r0,r4,r2,r1,r3);
+      LINTRANS(r2,r1,r4,r3,r0);
+
+      /* round 4  */
+      KEYMIX(r2,r1,r4,r3,r0,12);
+      S3(r2,r1,r4,r3,r0);
+      LINTRANS(r1,r4,r3,r0,r2);
+
+      /* round 5  */
+      KEYMIX(r1,r4,r3,r0,r2,16);
+      S4(r1,r4,r3,r0,r2) 
+      LINTRANS(r4,r2,r1,r0,r3);
+
+      /* round 6  */
+      KEYMIX(r4,r2,r1,r0,r3,20);
+      S5(r4,r2,r1,r0,r3);
+      LINTRANS(r2,r0,r4,r1,r3);
+
+      /* round 7  */
+      KEYMIX(r2,r0,r4,r1,r3,24);
+      S6(r2,r0,r4,r1,r3) 
+      LINTRANS(r2,r0,r3,r4,r1);
+
+      /* round 8  */
+      KEYMIX(r2,r0,r3,r4,r1,28);
+      S7(r2,r0,r3,r4,r1);
+      LINTRANS(r3,r1,r4,r2,r0);
+
+      /* round 9  */
+      KEYMIX(r3,r1,r4,r2,r0,32);
+      S0(r3,r1,r4,r2,r0);
+      LINTRANS(r1,r0,r4,r3,r2);
+
+      /* round 10  */
+      KEYMIX(r1,r0,r4,r3,r2,36);
+      S1(r1,r0,r4,r3,r2);
+      LINTRANS(r3,r0,r4,r1,r2);
+
+      /* round 11  */
+      KEYMIX(r3,r0,r4,r1,r2,40);
+      S2(r3,r0,r4,r1,r2);
+      LINTRANS(r4,r1,r0,r2,r3);
+
+      /* round 12  */
+      KEYMIX(r4,r1,r0,r2,r3,44);
+      S3(r4,r1,r0,r2,r3);
+      LINTRANS(r1,r0,r2,r3,r4);
+
+      /* round 13  */
+      KEYMIX(r1,r0,r2,r3,r4,48);
+      S4(r1,r0,r2,r3,r4) 
+      LINTRANS(r0,r4,r1,r3,r2);
+
+      /* round 14  */
+      KEYMIX(r0,r4,r1,r3,r2,52);
+      S5(r0,r4,r1,r3,r2);
+      LINTRANS(r4,r3,r0,r1,r2);
+
+      /* round 15  */
+      KEYMIX(r4,r3,r0,r1,r2,56);
+      S6(r4,r3,r0,r1,r2) 
+      LINTRANS(r4,r3,r2,r0,r1);
+
+      /* round 16  */
+      KEYMIX(r4,r3,r2,r0,r1,60);
+      S7(r4,r3,r2,r0,r1);
+      LINTRANS(r2,r1,r0,r4,r3);
+
+      /* round 17  */
+      KEYMIX(r2,r1,r0,r4,r3,64);
+      S0(r2,r1,r0,r4,r3);
+      LINTRANS(r1,r3,r0,r2,r4);
+
+      /* round 18  */
+      KEYMIX(r1,r3,r0,r2,r4,68);
+      S1(r1,r3,r0,r2,r4);
+      LINTRANS(r2,r3,r0,r1,r4);
+
+      /* round 19  */
+      KEYMIX(r2,r3,r0,r1,r4,72);
+      S2(r2,r3,r0,r1,r4);
+      LINTRANS(r0,r1,r3,r4,r2);
+
+      /* round 20  */
+      KEYMIX(r0,r1,r3,r4,r2,76);
+      S3(r0,r1,r3,r4,r2);
+      LINTRANS(r1,r3,r4,r2,r0);
+
+      /* round 21  */
+      KEYMIX(r1,r3,r4,r2,r0,80);
+      S4(r1,r3,r4,r2,r0) 
+      LINTRANS(r3,r0,r1,r2,r4);
+
+      /* round 22  */
+      KEYMIX(r3,r0,r1,r2,r4,84);
+      S5(r3,r0,r1,r2,r4);
+      LINTRANS(r0,r2,r3,r1,r4);
+
+      /* round 23  */
+      KEYMIX(r0,r2,r3,r1,r4,88);
+      S6(r0,r2,r3,r1,r4) 
+      LINTRANS(r0,r2,r4,r3,r1);
+
+      /* round 24  */
+      KEYMIX(r0,r2,r4,r3,r1,92);
+      S7(r0,r2,r4,r3,r1);
+      LINTRANS(r4,r1,r3,r0,r2);
+
+      /* round 25  */
+      KEYMIX(r4,r1,r3,r0,r2,96);
+      S0(r4,r1,r3,r0,r2);
+      LINTRANS(r1,r2,r3,r4,r0);
+
+      /* round 26  */
+      KEYMIX(r1,r2,r3,r4,r0,100);
+      S1(r1,r2,r3,r4,r0);
+      LINTRANS(r4,r2,r3,r1,r0);
+
+      /* round 27  */
+      KEYMIX(r4,r2,r3,r1,r0,104);
+      S2(r4,r2,r3,r1,r0);
+      LINTRANS(r3,r1,r2,r0,r4);
+
+      /* round 28  */
+      KEYMIX(r3,r1,r2,r0,r4,108);
+      S3(r3,r1,r2,r0,r4);
+      LINTRANS(r1,r2,r0,r4,r3);
+
+      /* round 29  */
+      KEYMIX(r1,r2,r0,r4,r3,112);
+      S4(r1,r2,r0,r4,r3) 
+      LINTRANS(r2,r3,r1,r4,r0);
+
+      /* round 30  */
+      KEYMIX(r2,r3,r1,r4,r0,116);
+      S5(r2,r3,r1,r4,r0);
+      LINTRANS(r3,r4,r2,r1,r0);
+
+      /* round 31  */
+      KEYMIX(r3,r4,r2,r1,r0,120);
+      S6(r3,r4,r2,r1,r0) 
+      LINTRANS(r3,r4,r0,r2,r1);
+
+      /* round 32  */
+      KEYMIX(r3,r4,r0,r2,r1,124);
+      S7(r3,r4,r0,r2,r1);
+      KEYMIX(r0,r1,r2,r3,r4,128);
+
+    
+#ifdef  BLOCK_SWAP
+    out_blk[3] = io_swap(r0); out_blk[2] = io_swap(r1); 
+    out_blk[1] = io_swap(r2); out_blk[0] = io_swap(r3);
+#else
+    out_blk[0] = r0; out_blk[1] = r1; out_blk[2] = r2; out_blk[3] = r3;
+#endif
+    return 0;
+};
+
+/* decrypt a block of text  */
+
+int serpent_decrypt(serpent_context *cx, const u8 *in,
+		    u8 *out)
+{   u32 *l_key = cx->keyinfo;
+    const u32 *in_blk = (const u32 *)in;
+    u32 *out_blk = (u32 *)out;
+    u32  r0,r1,r2,r3,r4;
+    
+#ifdef  BLOCK_SWAP
+    r0 = io_swap(in_blk[3]); r1 = io_swap(in_blk[2]); 
+    r2 = io_swap(in_blk[1]); r3 = io_swap(in_blk[0]);
+#else
+    r0 = in_blk[0]; r1 = in_blk[1]; r2 = in_blk[2]; r3 = in_blk[3];
+#endif
+
+      /* round 1 */
+      KEYMIX(r0,r1,r2,r3,r4,128);
+      I7(r0,r1,r2,r3,r4);
+      KEYMIX(r3,r0,r1,r4,r2,124);
+
+      /* round 2  */
+      ILINTRANS(r3,r0,r1,r4,r2);
+      I6(r3,r0,r1,r4,r2);
+      KEYMIX(r0,r1,r2,r4,r3,120);
+
+      /* round 3  */
+      ILINTRANS(r0,r1,r2,r4,r3);
+      I5(r0,r1,r2,r4,r3);
+      KEYMIX(r1,r3,r4,r2,r0,116);
+
+      /* round 4  */
+      ILINTRANS(r1,r3,r4,r2,r0);
+      I4(r1,r3,r4,r2,r0);
+      KEYMIX(r1,r2,r4,r0,r3,112);
+
+      /* round 5  */
+      ILINTRANS(r1,r2,r4,r0,r3);
+      I3(r1,r2,r4,r0,r3);
+      KEYMIX(r4,r2,r0,r1,r3,108);
+
+      /* round 6  */
+      ILINTRANS(r4,r2,r0,r1,r3);
+      I2(r4,r2,r0,r1,r3);
+      KEYMIX(r2,r3,r0,r1,r4,104);
+
+      /* round 7  */
+      ILINTRANS(r2,r3,r0,r1,r4);
+      I1(r2,r3,r0,r1,r4);
+      KEYMIX(r4,r2,r1,r0,r3,100);
+
+      /* round 8  */
+      ILINTRANS(r4,r2,r1,r0,r3);
+      I0(r4,r2,r1,r0,r3);
+      KEYMIX(r4,r3,r2,r0,r1,96);
+
+      /* round 9  */
+      ILINTRANS(r4,r3,r2,r0,r1);
+      I7(r4,r3,r2,r0,r1);
+      KEYMIX(r0,r4,r3,r1,r2,92);
+
+      /* round 10  */
+      ILINTRANS(r0,r4,r3,r1,r2);
+      I6(r0,r4,r3,r1,r2);
+      KEYMIX(r4,r3,r2,r1,r0,88);
+
+      /* round 11  */
+      ILINTRANS(r4,r3,r2,r1,r0);
+      I5(r4,r3,r2,r1,r0);
+      KEYMIX(r3,r0,r1,r2,r4,84);
+
+      /* round 12  */
+      ILINTRANS(r3,r0,r1,r2,r4);
+      I4(r3,r0,r1,r2,r4);
+      KEYMIX(r3,r2,r1,r4,r0,80);
+
+      /* round 13  */
+      ILINTRANS(r3,r2,r1,r4,r0);
+      I3(r3,r2,r1,r4,r0);
+      KEYMIX(r1,r2,r4,r3,r0,76);
+
+      /* round 14  */
+      ILINTRANS(r1,r2,r4,r3,r0);
+      I2(r1,r2,r4,r3,r0);
+      KEYMIX(r2,r0,r4,r3,r1,72);
+
+      /* round 15  */
+      ILINTRANS(r2,r0,r4,r3,r1);
+      I1(r2,r0,r4,r3,r1);
+      KEYMIX(r1,r2,r3,r4,r0,68);
+
+      /* round 16  */
+      ILINTRANS(r1,r2,r3,r4,r0);
+      I0(r1,r2,r3,r4,r0);
+      KEYMIX(r1,r0,r2,r4,r3,64);
+
+      /* round 17  */
+      ILINTRANS(r1,r0,r2,r4,r3);
+      I7(r1,r0,r2,r4,r3);
+      KEYMIX(r4,r1,r0,r3,r2,60);
+
+      /* round 18  */
+      ILINTRANS(r4,r1,r0,r3,r2);
+      I6(r4,r1,r0,r3,r2);
+      KEYMIX(r1,r0,r2,r3,r4,56);
+
+      /* round 19  */
+      ILINTRANS(r1,r0,r2,r3,r4);
+      I5(r1,r0,r2,r3,r4);
+      KEYMIX(r0,r4,r3,r2,r1,52);
+
+      /* round 20  */
+      ILINTRANS(r0,r4,r3,r2,r1);
+      I4(r0,r4,r3,r2,r1);
+      KEYMIX(r0,r2,r3,r1,r4,48);
+
+      /* round 21  */
+      ILINTRANS(r0,r2,r3,r1,r4);
+      I3(r0,r2,r3,r1,r4);
+      KEYMIX(r3,r2,r1,r0,r4,44);
+
+      /* round 22  */
+      ILINTRANS(r3,r2,r1,r0,r4);
+      I2(r3,r2,r1,r0,r4);
+      KEYMIX(r2,r4,r1,r0,r3,40);
+
+      /* round 23  */
+      ILINTRANS(r2,r4,r1,r0,r3);
+      I1(r2,r4,r1,r0,r3);
+      KEYMIX(r3,r2,r0,r1,r4,36);
+
+      /* round 24  */
+      ILINTRANS(r3,r2,r0,r1,r4);
+      I0(r3,r2,r0,r1,r4);
+      KEYMIX(r3,r4,r2,r1,r0,32);
+
+      /* round 25  */
+      ILINTRANS(r3,r4,r2,r1,r0);
+      I7(r3,r4,r2,r1,r0);
+      KEYMIX(r1,r3,r4,r0,r2,28);
+
+      /* round 26  */
+      ILINTRANS(r1,r3,r4,r0,r2);
+      I6(r1,r3,r4,r0,r2);
+      KEYMIX(r3,r4,r2,r0,r1,24);
+
+      /* round 27  */
+      ILINTRANS(r3,r4,r2,r0,r1);
+      I5(r3,r4,r2,r0,r1);
+      KEYMIX(r4,r1,r0,r2,r3,20);
+
+      /* round 28  */
+      ILINTRANS(r4,r1,r0,r2,r3);
+      I4(r4,r1,r0,r2,r3);
+      KEYMIX(r4,r2,r0,r3,r1,16);
+
+      /* round 29  */
+      ILINTRANS(r4,r2,r0,r3,r1);
+      I3(r4,r2,r0,r3,r1);
+      KEYMIX(r0,r2,r3,r4,r1,12);
+
+      /* round 30  */
+      ILINTRANS(r0,r2,r3,r4,r1);
+      I2(r0,r2,r3,r4,r1);
+      KEYMIX(r2,r1,r3,r4,r0,8);
+
+      /* round 31  */
+      ILINTRANS(r2,r1,r3,r4,r0);
+      I1(r2,r1,r3,r4,r0);
+      KEYMIX(r0,r2,r4,r3,r1,4);
+
+      /* round 32  */
+      ILINTRANS(r0,r2,r4,r3,r1);
+      I0(r0,r2,r4,r3,r1);
+      KEYMIX(r0,r1,r2,r3,r4,0);
+    
+#ifdef  BLOCK_SWAP
+    out_blk[3] = io_swap(r0); out_blk[2] = io_swap(r1); 
+    out_blk[1] = io_swap(r2); out_blk[0] = io_swap(r3);
+#else
+    out_blk[0] = r0; out_blk[1] = r1; out_blk[2] = r2; out_blk[3] = r3;
+#endif
+    return 0;
+};
+
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libserpent/serpent.h linux-patched/net/ipsec/libcrypto/libserpent/serpent.h
--- linux/net/ipsec/libcrypto/libserpent/serpent.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libserpent/serpent.h	Thu Sep  5 04:43:55 2002
@@ -0,0 +1,17 @@
+#ifndef SERPENT_H
+#define SERPENT_H
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#define u32 u_int32_t
+#define u8 u_int8_t
+#endif
+struct serpent_context {
+	u32  keyinfo[140]; /* storage for the key schedule         */
+};
+typedef struct serpent_context serpent_context;
+int serpent_set_key(serpent_context *ctx, const u8 * in_key, int key_len);
+int serpent_decrypt(serpent_context *ctx, const u8 * in_blk, u8 * out_blk);
+int serpent_encrypt(serpent_context *ctx, const u8 * in_blk, u8 * out_blk);
+#endif /* SERPENT_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libserpent/serpent_cbc.c linux-patched/net/ipsec/libcrypto/libserpent/serpent_cbc.c
--- linux/net/ipsec/libcrypto/libserpent/serpent_cbc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libserpent/serpent_cbc.c	Thu Sep  5 04:43:55 2002
@@ -0,0 +1,8 @@
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#include "serpent_cbc.h"
+#include "cbc_generic.h"
+CBC_IMPL_BLK16(serpent_cbc_encrypt, serpent_context, u_int8_t *, serpent_encrypt, serpent_decrypt);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libserpent/serpent_cbc.h linux-patched/net/ipsec/libcrypto/libserpent/serpent_cbc.h
--- linux/net/ipsec/libcrypto/libserpent/serpent_cbc.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libserpent/serpent_cbc.h	Thu Sep  5 04:43:55 2002
@@ -0,0 +1,3 @@
+/* Glue header */
+#include "serpent.h"
+int serpent_cbc_encrypt(serpent_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libserpent/test_main.c linux-patched/net/ipsec/libcrypto/libserpent/test_main.c
--- linux/net/ipsec/libcrypto/libserpent/test_main.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libserpent/test_main.c	Thu Sep  5 04:43:55 2002
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <string.h>
+#include "serpent_cbc.h"
+#define BLOCK_SIZE	16
+#define KEY_SIZE 	128	/* bits */
+#define KEY 		"1234567890123456"
+#define STR 		"hola guaso como estaisss ... 012"
+#define STRSZ		(sizeof(STR)-1)
+
+#define BLKLEN 		BLOCK_SIZE
+#define CONTEXT_T  	serpent_context
+static int pretty_print(const unsigned char *buf, int count) {
+	int i=0;
+	for (;i<count;i++) printf ("%02hhx ", buf[i]);
+	putchar('\n');
+	return i;
+}
+//#define SIZE STRSZ/2
+#define SIZE STRSZ
+int main() {
+	int ret;
+	char buf0[SIZE+1], buf1[SIZE+1];
+	char IV[BLOCK_SIZE];
+	CONTEXT_T ac;	
+	serpent_set_key(&ac, (void *)KEY, KEY_SIZE);
+	memset(buf0, 0, sizeof (buf0));
+	memset(buf1, 0, sizeof (buf1));
+	serpent_cbc_encrypt(&ac, STR, buf0, SIZE, IV, 1);
+	pretty_print(buf0, SIZE);
+	printf("size=%d ret=%d\n%s\n", SIZE, ret, buf0);
+	ret=serpent_cbc_encrypt(&ac, buf0, buf1, SIZE, IV, 0);
+	printf("size=%d ret=%d\n%s\n", SIZE, ret, buf1);
+	return 0;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/Makefile linux-patched/net/ipsec/libcrypto/libsha1/Makefile
--- linux/net/ipsec/libcrypto/libsha1/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/Makefile	Thu Sep  5 04:32:56 2002
@@ -0,0 +1,112 @@
+#
+# SSLeay/crypto/sha/Makefile
+#
+
+DIR=    sha
+TOP=    ../..
+CC=     cc
+CPP=    $(CC) -E
+INCLUDES=
+CFLAG=-g -I ../include -D__KERNEL__ -I/usr/src/linux/include
+INSTALL_PREFIX=
+OPENSSLDIR=     /usr/local/ssl
+INSTALLTOP=/usr/local/ssl
+MAKE=           make -f Makefile.ssl
+MAKEDEPEND=	$(TOP)/util/domd $(TOP)
+MAKEFILE=       Makefile.ssl
+AR=             ar r
+RANLIB=		ranlib
+PERL=		perl
+
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+ASM-$(ARCH_ASM):=1
+ASM_X86:=$(ASM-i586)$(ASM-i686)
+ifneq ($(strip $(ASM_X86)),)
+SHA1_ASM_OBJ:=asm/sx86-elf.o
+override CFLAGS += -DSHA1_ASM
+endif
+
+GENERAL=Makefile
+TEST=shatest.c sha1test.c
+APPS=
+
+LIB=libsha1.a
+LIBSRC=sha_dgst.c sha1dgst.c sha1_one.c hmac_sha1.c
+LIBOBJ=sha_dgst.o sha1dgst.o sha1_one.o $(SHA1_ASM_OBJ) hmac_sha1.o
+
+SRC= $(LIBSRC)
+
+EXHEADER= sha.h
+HEADER= sha_locl.h $(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+#top:
+#	(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all:    lib
+
+lib:	$(LIB)
+
+$(LIB):    $(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	$(RANLIB) $(LIB)
+
+# elf
+asm/sx86-elf.o: asm/sx86unix.cpp
+	$(CPP) -DELF -x c asm/sx86unix.cpp | as -o asm/sx86-elf.o
+
+# solaris
+asm/sx86-sol.o: asm/sx86unix.cpp
+	$(CC) -E -DSOL asm/sx86unix.cpp | sed 's/^#.*//' > asm/sx86-sol.s
+	as -o asm/sx86-sol.o asm/sx86-sol.s
+	rm -f asm/sx86-sol.s
+
+# a.out
+asm/sx86-out.o: asm/sx86unix.cpp
+	$(CPP) -DOUT asm/sx86unix.cpp | as -o asm/sx86-out.o
+
+# bsdi
+asm/sx86bsdi.o: asm/sx86unix.cpp
+	$(CPP) -DBSDI asm/sx86unix.cpp | sed 's/ :/:/' | as -o asm/sx86bsdi.o
+
+asm/sx86unix.cpp: asm/sha1-586.pl ../perlasm/x86asm.pl
+	(cd asm; $(PERL) sha1-586.pl cpp $(PROCESSOR) >sx86unix.cpp)
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO
+
+links:
+	@$(TOP)/util/point.sh Makefile.ssl Makefile
+	@$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+	@$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+	@$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install:
+	@for i in $(EXHEADER) ; \
+	do  \
+	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	$(MAKEDEPEND) $(INCLUDES) $(DEPFLAG) $(PROGS) $(LIBSRC)
+
+dclean:
+	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	rm -f asm/sx86unix.cpp *.o *.obj $(LIB) tags core .pure .nfs* *.old *.bak fluff asm/*.o
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/asm/README linux-patched/net/ipsec/libcrypto/libsha1/asm/README
--- linux/net/ipsec/libcrypto/libsha1/asm/README	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/asm/README	Thu Sep  5 04:35:58 2002
@@ -0,0 +1 @@
+C2.pl works
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/asm/sha1-586.pl linux-patched/net/ipsec/libcrypto/libsha1/asm/sha1-586.pl
--- linux/net/ipsec/libcrypto/libsha1/asm/sha1-586.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/asm/sha1-586.pl	Thu Sep  5 04:35:58 2002
@@ -0,0 +1,538 @@
+#!/usr/local/bin/perl
+
+$normal=0;
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"sha1-586.pl",$ARGV[$#ARGV] eq "386");
+
+$A="eax";
+$B="ecx";
+$C="ebx";
+$D="edx";
+$E="edi";
+$T="esi";
+$tmp1="ebp";
+
+$off=9*4;
+
+@K=(0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6);
+
+&sha1_block_data("sha1_block_asm_data_order");
+
+&asm_finish();
+
+sub Nn
+	{
+	local($p)=@_;
+	local(%n)=($A,$T,$B,$A,$C,$B,$D,$C,$E,$D,$T,$E);
+	return($n{$p});
+	}
+
+sub Np
+	{
+	local($p)=@_;
+	local(%n)=($A,$T,$B,$A,$C,$B,$D,$C,$E,$D,$T,$E);
+	local(%n)=($A,$B,$B,$C,$C,$D,$D,$E,$E,$T,$T,$A);
+	return($n{$p});
+	}
+
+sub Na
+	{
+	local($n)=@_;
+	return( (($n   )&0x0f),
+		(($n+ 2)&0x0f),
+		(($n+ 8)&0x0f),
+		(($n+13)&0x0f),
+		(($n+ 1)&0x0f));
+	}
+
+sub X_expand
+	{
+	local($in)=@_;
+
+	&comment("First, load the words onto the stack in network byte order");
+	for ($i=0; $i<16; $i+=2)
+		{
+		&mov($A,&DWP(($i+0)*4,$in,"",0));# unless $i == 0;
+		 &mov($B,&DWP(($i+1)*4,$in,"",0));
+		&bswap($A);
+		 &bswap($B);
+		&mov(&swtmp($i+0),$A);
+		 &mov(&swtmp($i+1),$B);
+		}
+
+	&comment("We now have the X array on the stack");
+	&comment("starting at sp-4");
+	}
+
+# Rules of engagement
+# F is always trashable at the start, the running total.
+# E becomes the next F so it can be trashed after it has been 'accumulated'
+# F becomes A in the next round.  We don't need to access it much.
+# During the X update part, the result ends up in $X[$n0].
+
+sub BODY_00_15
+	{
+	local($pos,$K,$X,$n,$a,$b,$c,$d,$e,$f)=@_;
+
+return if $n & 1;
+	&comment("00_15 $n");
+
+	 &mov($f,$c);
+
+	&mov($tmp1,$a);
+	 &xor($f,$d);			# F2
+
+	&rotl($tmp1,5);			# A2
+
+	&and($f,$b);			# F3
+	 &add($tmp1,$e);
+
+	&rotr($b,1);			# B1	<- F
+	 &mov($e,&swtmp($n));		# G1
+
+	&rotr($b,1);			# B1	<- F
+	 &xor($f,$d);			# F4
+
+	&lea($tmp1,&DWP($K,$tmp1,$e,1));
+
+############################
+#	&BODY_40_59( 0,$K[2],$X,42,$A,$B,$C,$D,$E,$T);
+#	&BODY_40_59( 0,$K[2],$X,43,$T,$A,$B,$C,$D,$E);
+$n++;
+	local($n0,$n1,$n2,$n3,$np)=&Na($n);
+	($b,$c,$d,$e,$f,$a)=($a,$b,$c,$d,$e,$f);
+
+	 &mov($f,$c);
+
+	&add($a,$tmp1);		# MOVED DOWN
+	 &xor($f,$d);			# F2
+
+	&mov($tmp1,$a);
+	 &and($f,$b);			# F3
+
+	&rotl($tmp1,5);			# A2
+
+	&add($tmp1,$e);
+	 &mov($e,&swtmp($n));		# G1
+
+	&rotr($b,1);			# B1	<- F
+	 &xor($f,$d);			# F4
+
+	&rotr($b,1);			# B1	<- F
+	 &lea($tmp1,&DWP($K,$tmp1,$e,1));
+
+	&add($f,$tmp1);
+	}
+
+sub BODY_16_19
+	{
+	local($pos,$K,$X,$n,$a,$b,$c,$d,$e,$f)=@_;
+	local($n0,$n1,$n2,$n3,$np)=&Na($n);
+
+return if $n & 1;
+	&comment("16_19 $n");
+
+ &nop() if ($pos < 0);
+&mov($tmp1,&swtmp($n0));			# X1
+ &mov($f,&swtmp($n1));			# X2
+&xor($f,$tmp1);				# X3
+ &mov($tmp1,&swtmp($n2));		# X4
+&xor($f,$tmp1);				# X5
+ &mov($tmp1,&swtmp($n3));		# X6
+&xor($f,$tmp1);				# X7 - slot
+ &mov($tmp1,$c);			# F1
+&rotl($f,1);				# X8 - slot
+ &xor($tmp1,$d);			# F2
+&mov(&swtmp($n0),$f);			# X9 - anytime
+ &and($tmp1,$b);			# F3
+&lea($f,&DWP($K,$f,$e,1));		# tot=X+K+e
+ &xor($tmp1,$d);				# F4
+&mov($e,$a);				# A1
+ &add($f,$tmp1);			# tot+=F();
+
+&rotl($e,5);				# A2
+
+&rotr($b,1);				# B1	<- F
+ &add($f,$e);				# tot+=a
+
+############################
+#	&BODY_40_59( 0,$K[2],$X,42,$A,$B,$C,$D,$E,$T);
+#	&BODY_40_59( 0,$K[2],$X,43,$T,$A,$B,$C,$D,$E);
+$n++;
+	local($n0,$n1,$n2,$n3,$np)=&Na($n);
+	($b,$c,$d,$e,$f,$a)=($a,$b,$c,$d,$e,$f);
+
+
+&mov($f,&swtmp($n0));			# X1
+ &mov($tmp1,&swtmp($n1));		# X2
+&xor($f,$tmp1);				# X3
+ &mov($tmp1,&swtmp($n2));		# X4
+&xor($f,$tmp1);				# X5
+ &mov($tmp1,&swtmp($n3));		# X6
+&rotr($c,1); #&rotr($b,1);		# B1	<- F # MOVED DOWN
+ &xor($f,$tmp1);				# X7 - slot
+&rotl($f,1);				# X8 - slot
+ &mov($tmp1,$c);			# F1
+&xor($tmp1,$d);			# F2
+ &mov(&swtmp($n0),$f);			# X9 - anytime
+&and($tmp1,$b);			# F3
+ &lea($f,&DWP($K,$f,$e,1));		# tot=X+K+e
+
+&xor($tmp1,$d);				# F4
+ &mov($e,$a);				# A1
+
+&rotl($e,5);				# A2
+
+&rotr($b,1);				# B1	<- F
+ &add($f,$e);				# tot+=a
+
+&rotr($b,1);				# B1	<- F
+ &add($f,$tmp1);			# tot+=F();
+
+	}
+
+sub BODY_20_39
+	{
+	local($pos,$K,$X,$n,$a,$b,$c,$d,$e,$f)=@_;
+
+	&comment("20_39 $n");
+	local($n0,$n1,$n2,$n3,$np)=&Na($n);
+
+&mov($f,&swtmp($n0));			# X1
+ &mov($tmp1,&swtmp($n1));		# X2
+&xor($f,$tmp1);				# X3
+ &mov($tmp1,&swtmp($n2));		# X4
+&xor($f,$tmp1);				# X5
+ &mov($tmp1,&swtmp($n3));		# X6
+&xor($f,$tmp1);				# X7 - slot
+ &mov($tmp1,$b);			# F1
+&rotl($f,1);				# X8 - slot
+ &xor($tmp1,$c);			# F2
+&mov(&swtmp($n0),$f);			# X9 - anytime
+ &xor($tmp1,$d);			# F3
+
+&lea($f,&DWP($K,$f,$e,1));		# tot=X+K+e
+ &mov($e,$a);				# A1
+
+&rotl($e,5);				# A2
+
+if ($n != 79) # last loop	
+	{
+	&rotr($b,1);				# B1	<- F
+	 &add($e,$tmp1);			# tmp1=F()+a
+
+	&rotr($b,1);				# B2	<- F
+	 &add($f,$e);				# tot+=tmp1;
+	}
+else
+	{
+	&add($e,$tmp1);				# tmp1=F()+a
+	 &mov($tmp1,&wparam(0));
+
+	&rotr($b,1);				# B1	<- F
+	 &add($f,$e);				# tot+=tmp1;
+
+	&rotr($b,1);				# B2	<- F
+	}
+	}
+
+sub BODY_40_59
+	{
+	local($pos,$K,$X,$n,$a,$b,$c,$d,$e,$f)=@_;
+
+	&comment("40_59 $n");
+	return if $n & 1;
+	local($n0,$n1,$n2,$n3,$np)=&Na($n);
+
+&mov($f,&swtmp($n0));			# X1
+ &mov($tmp1,&swtmp($n1));		# X2
+&xor($f,$tmp1);				# X3
+ &mov($tmp1,&swtmp($n2));		# X4
+&xor($f,$tmp1);				# X5
+ &mov($tmp1,&swtmp($n3));		# X6
+&xor($f,$tmp1);				# X7 - slot
+ &mov($tmp1,$b);			# F1
+&rotl($f,1);				# X8 - slot
+ &or($tmp1,$c);				# F2
+&mov(&swtmp($n0),$f);			# X9 - anytime
+ &and($tmp1,$d);			# F3
+
+&lea($f,&DWP($K,$f,$e,1));		# tot=X+K+e
+ &mov($e,$b);				# F4
+
+&rotr($b,1);				# B1	<- F
+ &and($e,$c);				# F5
+
+&or($tmp1,$e);				# F6
+ &mov($e,$a);				# A1
+
+&rotl($e,5);				# A2
+
+&add($tmp1,$e);			# tmp1=F()+a
+
+############################
+#	&BODY_40_59( 0,$K[2],$X,42,$A,$B,$C,$D,$E,$T);
+#	&BODY_40_59( 0,$K[2],$X,43,$T,$A,$B,$C,$D,$E);
+$n++;
+	local($n0,$n1,$n2,$n3,$np)=&Na($n);
+	($b,$c,$d,$e,$f,$a)=($a,$b,$c,$d,$e,$f);
+
+ &mov($f,&swtmp($n0));			# X1
+&add($a,$tmp1);				# tot+=tmp1; # moved was add f,tmp1
+ &mov($tmp1,&swtmp($n1));		# X2
+&xor($f,$tmp1);				# X3
+ &mov($tmp1,&swtmp($n2));		# X4
+&xor($f,$tmp1);				# X5
+ &mov($tmp1,&swtmp($n3));		# X6
+&rotr($c,1);				# B2	<- F # moved was rotr b,1
+ &xor($f,$tmp1);			# X7 - slot
+&rotl($f,1);				# X8 - slot
+ &mov($tmp1,$b);			# F1
+&mov(&swtmp($n0),$f);			# X9 - anytime
+ &or($tmp1,$c);				# F2
+&lea($f,&DWP($K,$f,$e,1));		# tot=X+K+e
+ &mov($e,$b);				# F4
+&and($tmp1,$d);				# F3
+ &and($e,$c);				# F5
+
+&or($tmp1,$e);				# F6
+ &mov($e,$a);				# A1
+
+&rotl($e,5);				# A2
+
+&rotr($b,1);				# B1	<- F
+ &add($tmp1,$e);			# tmp1=F()+a
+
+&rotr($b,1);				# B2	<- F
+ &add($f,$tmp1);			# tot+=tmp1;
+	}
+
+sub BODY_60_79
+	{
+	&BODY_20_39(@_);
+	}
+
+sub sha1_block_host
+	{
+	local($name)=@_;
+
+	&function_begin_B($name,"");
+
+	# parameter 1 is the MD5_CTX structure.
+	# A	0
+	# B	4
+	# C	8
+	# D 	12
+	# E 	16
+
+	&mov("ecx",	&wparam(2));
+	 &push("esi");
+	&shl("ecx",6);
+	 &mov("esi",	&wparam(1));
+	&push("ebp");
+	 &add("ecx","esi");	# offset to leave on
+	&push("ebx");
+	 &mov("ebp",	&wparam(0));
+	&push("edi");
+	 &mov($D,	&DWP(12,"ebp","",0));
+	&stack_push(18+9);
+	 &mov($E,	&DWP(16,"ebp","",0));
+	&mov($C,	&DWP( 8,"ebp","",0));
+	 &mov(&swtmp(17),"ecx");
+
+	&comment("First we need to setup the X array");
+
+	for ($i=0; $i<16; $i+=2)
+		{
+		&mov($A,&DWP(($i+0)*4,"esi","",0));# unless $i == 0;
+		 &mov($B,&DWP(($i+1)*4,"esi","",0));
+		&mov(&swtmp($i+0),$A);
+		 &mov(&swtmp($i+1),$B);
+		}
+	&jmp(&label("shortcut"));
+	&function_end_B($name);
+	}
+
+
+sub sha1_block_data
+	{
+	local($name)=@_;
+
+	&function_begin_B($name,"");
+
+	# parameter 1 is the MD5_CTX structure.
+	# A	0
+	# B	4
+	# C	8
+	# D 	12
+	# E 	16
+
+	&mov("ecx",	&wparam(2));
+	 &push("esi");
+	&shl("ecx",6);
+	 &mov("esi",	&wparam(1));
+	&push("ebp");
+	 &add("ecx","esi");	# offset to leave on
+	&push("ebx");
+	 &mov("ebp",	&wparam(0));
+	&push("edi");
+	 &mov($D,	&DWP(12,"ebp","",0));
+	&stack_push(18+9);
+	 &mov($E,	&DWP(16,"ebp","",0));
+	&mov($C,	&DWP( 8,"ebp","",0));
+	 &mov(&swtmp(17),"ecx");
+
+	&comment("First we need to setup the X array");
+
+	&set_label("start") unless $normal;
+
+	&X_expand("esi");
+	 &mov(&wparam(1),"esi");
+
+	&set_label("shortcut", 0, 1);
+	&comment("");
+	&comment("Start processing");
+
+	# odd start
+	&mov($A,	&DWP( 0,"ebp","",0));
+	 &mov($B,	&DWP( 4,"ebp","",0));
+	$X="esp";
+	&BODY_00_15(-2,$K[0],$X, 0,$A,$B,$C,$D,$E,$T);
+	&BODY_00_15( 0,$K[0],$X, 1,$T,$A,$B,$C,$D,$E);
+	&BODY_00_15( 0,$K[0],$X, 2,$E,$T,$A,$B,$C,$D);
+	&BODY_00_15( 0,$K[0],$X, 3,$D,$E,$T,$A,$B,$C);
+	&BODY_00_15( 0,$K[0],$X, 4,$C,$D,$E,$T,$A,$B);
+	&BODY_00_15( 0,$K[0],$X, 5,$B,$C,$D,$E,$T,$A);
+	&BODY_00_15( 0,$K[0],$X, 6,$A,$B,$C,$D,$E,$T);
+	&BODY_00_15( 0,$K[0],$X, 7,$T,$A,$B,$C,$D,$E);
+	&BODY_00_15( 0,$K[0],$X, 8,$E,$T,$A,$B,$C,$D);
+	&BODY_00_15( 0,$K[0],$X, 9,$D,$E,$T,$A,$B,$C);
+	&BODY_00_15( 0,$K[0],$X,10,$C,$D,$E,$T,$A,$B);
+	&BODY_00_15( 0,$K[0],$X,11,$B,$C,$D,$E,$T,$A);
+	&BODY_00_15( 0,$K[0],$X,12,$A,$B,$C,$D,$E,$T);
+	&BODY_00_15( 0,$K[0],$X,13,$T,$A,$B,$C,$D,$E);
+	&BODY_00_15( 0,$K[0],$X,14,$E,$T,$A,$B,$C,$D);
+	&BODY_00_15( 1,$K[0],$X,15,$D,$E,$T,$A,$B,$C);
+	&BODY_16_19(-1,$K[0],$X,16,$C,$D,$E,$T,$A,$B);
+	&BODY_16_19( 0,$K[0],$X,17,$B,$C,$D,$E,$T,$A);
+	&BODY_16_19( 0,$K[0],$X,18,$A,$B,$C,$D,$E,$T);
+	&BODY_16_19( 1,$K[0],$X,19,$T,$A,$B,$C,$D,$E);
+
+	&BODY_20_39(-1,$K[1],$X,20,$E,$T,$A,$B,$C,$D);
+	&BODY_20_39( 0,$K[1],$X,21,$D,$E,$T,$A,$B,$C);
+	&BODY_20_39( 0,$K[1],$X,22,$C,$D,$E,$T,$A,$B);
+	&BODY_20_39( 0,$K[1],$X,23,$B,$C,$D,$E,$T,$A);
+	&BODY_20_39( 0,$K[1],$X,24,$A,$B,$C,$D,$E,$T);
+	&BODY_20_39( 0,$K[1],$X,25,$T,$A,$B,$C,$D,$E);
+	&BODY_20_39( 0,$K[1],$X,26,$E,$T,$A,$B,$C,$D);
+	&BODY_20_39( 0,$K[1],$X,27,$D,$E,$T,$A,$B,$C);
+	&BODY_20_39( 0,$K[1],$X,28,$C,$D,$E,$T,$A,$B);
+	&BODY_20_39( 0,$K[1],$X,29,$B,$C,$D,$E,$T,$A);
+	&BODY_20_39( 0,$K[1],$X,30,$A,$B,$C,$D,$E,$T);
+	&BODY_20_39( 0,$K[1],$X,31,$T,$A,$B,$C,$D,$E);
+	&BODY_20_39( 0,$K[1],$X,32,$E,$T,$A,$B,$C,$D);
+	&BODY_20_39( 0,$K[1],$X,33,$D,$E,$T,$A,$B,$C);
+	&BODY_20_39( 0,$K[1],$X,34,$C,$D,$E,$T,$A,$B);
+	&BODY_20_39( 0,$K[1],$X,35,$B,$C,$D,$E,$T,$A);
+	&BODY_20_39( 0,$K[1],$X,36,$A,$B,$C,$D,$E,$T);
+	&BODY_20_39( 0,$K[1],$X,37,$T,$A,$B,$C,$D,$E);
+	&BODY_20_39( 0,$K[1],$X,38,$E,$T,$A,$B,$C,$D);
+	&BODY_20_39( 1,$K[1],$X,39,$D,$E,$T,$A,$B,$C);
+
+	&BODY_40_59(-1,$K[2],$X,40,$C,$D,$E,$T,$A,$B);
+	&BODY_40_59( 0,$K[2],$X,41,$B,$C,$D,$E,$T,$A);
+	&BODY_40_59( 0,$K[2],$X,42,$A,$B,$C,$D,$E,$T);
+	&BODY_40_59( 0,$K[2],$X,43,$T,$A,$B,$C,$D,$E);
+	&BODY_40_59( 0,$K[2],$X,44,$E,$T,$A,$B,$C,$D);
+	&BODY_40_59( 0,$K[2],$X,45,$D,$E,$T,$A,$B,$C);
+	&BODY_40_59( 0,$K[2],$X,46,$C,$D,$E,$T,$A,$B);
+	&BODY_40_59( 0,$K[2],$X,47,$B,$C,$D,$E,$T,$A);
+	&BODY_40_59( 0,$K[2],$X,48,$A,$B,$C,$D,$E,$T);
+	&BODY_40_59( 0,$K[2],$X,49,$T,$A,$B,$C,$D,$E);
+	&BODY_40_59( 0,$K[2],$X,50,$E,$T,$A,$B,$C,$D);
+	&BODY_40_59( 0,$K[2],$X,51,$D,$E,$T,$A,$B,$C);
+	&BODY_40_59( 0,$K[2],$X,52,$C,$D,$E,$T,$A,$B);
+	&BODY_40_59( 0,$K[2],$X,53,$B,$C,$D,$E,$T,$A);
+	&BODY_40_59( 0,$K[2],$X,54,$A,$B,$C,$D,$E,$T);
+	&BODY_40_59( 0,$K[2],$X,55,$T,$A,$B,$C,$D,$E);
+	&BODY_40_59( 0,$K[2],$X,56,$E,$T,$A,$B,$C,$D);
+	&BODY_40_59( 0,$K[2],$X,57,$D,$E,$T,$A,$B,$C);
+	&BODY_40_59( 0,$K[2],$X,58,$C,$D,$E,$T,$A,$B);
+	&BODY_40_59( 1,$K[2],$X,59,$B,$C,$D,$E,$T,$A);
+
+	&BODY_60_79(-1,$K[3],$X,60,$A,$B,$C,$D,$E,$T);
+	&BODY_60_79( 0,$K[3],$X,61,$T,$A,$B,$C,$D,$E);
+	&BODY_60_79( 0,$K[3],$X,62,$E,$T,$A,$B,$C,$D);
+	&BODY_60_79( 0,$K[3],$X,63,$D,$E,$T,$A,$B,$C);
+	&BODY_60_79( 0,$K[3],$X,64,$C,$D,$E,$T,$A,$B);
+	&BODY_60_79( 0,$K[3],$X,65,$B,$C,$D,$E,$T,$A);
+	&BODY_60_79( 0,$K[3],$X,66,$A,$B,$C,$D,$E,$T);
+	&BODY_60_79( 0,$K[3],$X,67,$T,$A,$B,$C,$D,$E);
+	&BODY_60_79( 0,$K[3],$X,68,$E,$T,$A,$B,$C,$D);
+	&BODY_60_79( 0,$K[3],$X,69,$D,$E,$T,$A,$B,$C);
+	&BODY_60_79( 0,$K[3],$X,70,$C,$D,$E,$T,$A,$B);
+	&BODY_60_79( 0,$K[3],$X,71,$B,$C,$D,$E,$T,$A);
+	&BODY_60_79( 0,$K[3],$X,72,$A,$B,$C,$D,$E,$T);
+	&BODY_60_79( 0,$K[3],$X,73,$T,$A,$B,$C,$D,$E);
+	&BODY_60_79( 0,$K[3],$X,74,$E,$T,$A,$B,$C,$D);
+	&BODY_60_79( 0,$K[3],$X,75,$D,$E,$T,$A,$B,$C);
+	&BODY_60_79( 0,$K[3],$X,76,$C,$D,$E,$T,$A,$B);
+	&BODY_60_79( 0,$K[3],$X,77,$B,$C,$D,$E,$T,$A);
+	&BODY_60_79( 0,$K[3],$X,78,$A,$B,$C,$D,$E,$T);
+	&BODY_60_79( 2,$K[3],$X,79,$T,$A,$B,$C,$D,$E);
+
+	&comment("End processing");
+	&comment("");
+	# D is the tmp value
+
+	# E -> A
+	# T -> B
+	# A -> C
+	# B -> D
+	# C -> E
+	# D -> T
+
+	# The last 2 have been moved into the last loop
+	# &mov($tmp1,&wparam(0));
+
+	 &mov($D,	&DWP(12,$tmp1,"",0));
+	&add($D,$B);
+	 &mov($B,	&DWP( 4,$tmp1,"",0));
+	&add($B,$T);
+	 &mov($T,	$A);
+	&mov($A,	&DWP( 0,$tmp1,"",0));
+	 &mov(&DWP(12,$tmp1,"",0),$D);
+
+	&add($A,$E);
+	 &mov($E,	&DWP(16,$tmp1,"",0));
+	&add($E,$C);
+	 &mov($C,	&DWP( 8,$tmp1,"",0));
+	&add($C,$T);
+
+	 &mov(&DWP( 0,$tmp1,"",0),$A);
+	&mov("esi",&wparam(1));
+	 &mov(&DWP( 8,$tmp1,"",0),$C);
+ 	&add("esi",64);
+	 &mov("eax",&swtmp(17));
+	&mov(&DWP(16,$tmp1,"",0),$E);
+	 &cmp("esi","eax");
+	&mov(&DWP( 4,$tmp1,"",0),$B);
+	 &jl(&label("start"));
+
+	&stack_pop(18+9);
+	 &pop("edi");
+	&pop("ebx");
+	 &pop("ebp");
+	&pop("esi");
+	 &ret();
+
+	# it has to reside within sha1_block_asm_host_order body
+	# because it calls &jmp(&label("shortcut"));
+	&sha1_block_host("sha1_block_asm_host_order");
+
+	&function_end_B($name);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/hmac_sha1.c linux-patched/net/ipsec/libcrypto/libsha1/hmac_sha1.c
--- linux/net/ipsec/libcrypto/libsha1/hmac_sha1.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/hmac_sha1.c	Thu Sep  5 04:32:56 2002
@@ -0,0 +1,26 @@
+#include <linux/types.h>
+#include <linux/string.h>
+#include "hmac_generic.h"
+#include "sha.h"
+#include "hmac_sha1.h"
+
+#if 0
+#define SHA1_Final  SHA1Final
+#define SHA1_Init   SHA1Init
+#define SHA1_Update SHA1Update
+#endif
+void inline sha1_result(SHA1_CTX *ctx, __u8 * hash, int hashlen) {
+	if (hashlen==SHA1_HASHLEN)
+		SHA1_Final(hash, ctx);
+	else {
+		__u8 hash_buf[SHA1_HASHLEN];
+		SHA1_Final(hash_buf, ctx);
+		memcpy(hash, hash_buf, hashlen);
+	}
+}
+HMAC_SET_KEY_IMPL (sha1_hmac_set_key, 
+		sha1_hmac_context, SHA1_BLOCKSIZE, 
+		SHA1_Init, SHA1_Update)
+HMAC_HASH_IMPL (sha1_hmac_hash, 
+		sha1_hmac_context, SHA1_CTX, SHA1_HASHLEN,
+		SHA1_Update, sha1_result)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/hmac_sha1.h linux-patched/net/ipsec/libcrypto/libsha1/hmac_sha1.h
--- linux/net/ipsec/libcrypto/libsha1/hmac_sha1.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/hmac_sha1.h	Thu Sep  5 04:32:56 2002
@@ -0,0 +1,10 @@
+#include "sha.h"
+#define SHA1_CTX SHA_CTX
+typedef struct {
+	SHA1_CTX ictx,octx;
+} sha1_hmac_context;
+#define SHA1_BLOCKSIZE 64
+#define SHA1_HASHLEN   20
+
+void sha1_hmac_hash(sha1_hmac_context *hctx, const __u8 * dat, int len, __u8 * hash, int hashlen);
+void sha1_hmac_set_key(sha1_hmac_context *hctx, const __u8 * key, int keylen);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/sha.h linux-patched/net/ipsec/libcrypto/libsha1/sha.h
--- linux/net/ipsec/libcrypto/libsha1/sha.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/sha.h	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,127 @@
+/* crypto/sha/sha.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SHA_H
+#define HEADER_SHA_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if defined(NO_SHA) || (defined(NO_SHA0) && defined(NO_SHA1))
+#error SHA is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! SHA_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(WIN16) || defined(__LP32__)
+#define SHA_LONG unsigned long
+#elif defined(_CRAY) || defined(__ILP64__)
+#define SHA_LONG unsigned long
+#define SHA_LONG_LOG2 3
+#endif
+
+/* des.h-like hack <jjo-ipsec@mendoza.gov.ar> */
+#ifndef SHA_LONG
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#define SHA_LONG u_int32_t
+#endif
+
+#define SHA_LBLOCK	16
+#define SHA_CBLOCK	(SHA_LBLOCK*4)	/* SHA treats input data as a
+					 * contiguous array of 32 bit
+					 * wide big-endian values. */
+#define SHA_LAST_BLOCK  (SHA_CBLOCK-8)
+#define SHA_DIGEST_LENGTH 20
+
+typedef struct SHAstate_st
+	{
+	SHA_LONG h0,h1,h2,h3,h4;
+	SHA_LONG Nl,Nh;
+	SHA_LONG data[SHA_LBLOCK];
+	int num;
+	} SHA_CTX;
+
+#ifndef NO_SHA0
+void SHA_Init(SHA_CTX *c);
+void SHA_Update(SHA_CTX *c, const void *data, unsigned long len);
+void SHA_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA(const unsigned char *d, unsigned long n,unsigned char *md);
+void SHA_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+#ifndef NO_SHA1
+void SHA1_Init(SHA_CTX *c);
+void SHA1_Update(SHA_CTX *c, const void *data, unsigned long len);
+void SHA1_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md);
+void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/sha1_one.c linux-patched/net/ipsec/libcrypto/libsha1/sha1_one.c
--- linux/net/ipsec/libcrypto/libsha1/sha1_one.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/sha1_one.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,81 @@
+/* crypto/sha/sha1_one.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "sha.h"
+
+#ifndef NO_SHA1
+unsigned char *SHA1(const unsigned char *d, unsigned long n, unsigned char *md)
+	{
+	SHA_CTX c;
+	static unsigned char m[SHA_DIGEST_LENGTH];
+
+	if (md == NULL) md=m;
+	SHA1_Init(&c);
+	SHA1_Update(&c,d,n);
+	SHA1_Final(md,&c);
+	memset(&c,0,sizeof(c));
+	return(md);
+	}
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/sha1dgst.c linux-patched/net/ipsec/libcrypto/libsha1/sha1dgst.c
--- linux/net/ipsec/libcrypto/libsha1/sha1dgst.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/sha1dgst.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,78 @@
+/* crypto/sha/sha1dgst.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#if !defined(NO_SHA1) && !defined(NO_SHA)
+
+#undef  SHA_0
+#define SHA_1
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <sys/types.h>
+#include <string.h>
+#endif
+
+
+/* The implementation is in ../md32_common.h */
+
+#include "sha_locl.h"
+
+#endif
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/sha_dgst.c linux-patched/net/ipsec/libcrypto/libsha1/sha_dgst.c
--- linux/net/ipsec/libcrypto/libsha1/sha_dgst.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/sha_dgst.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,69 @@
+/* crypto/sha/sha1dgst.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#if !defined(NO_SHA0) && !defined(NO_SHA)
+
+#undef  SHA_1
+#define SHA_0
+
+/* The implementation is in ../md32_common.h */
+
+#include "sha_locl.h"
+
+#endif
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha1/sha_locl.h linux-patched/net/ipsec/libcrypto/libsha1/sha_locl.h
--- linux/net/ipsec/libcrypto/libsha1/sha_locl.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha1/sha_locl.h	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,476 @@
+/* crypto/sha/sha_locl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#include "sha.h"
+#else
+#include <stdlib.h>
+#include <string.h>
+
+#include "sha.h"
+#endif
+
+#ifndef SHA_LONG_LOG2
+#define SHA_LONG_LOG2	2	/* default to 32 bits */
+#endif
+
+#define DATA_ORDER_IS_BIG_ENDIAN
+
+#define HASH_LONG               SHA_LONG
+#define HASH_LONG_LOG2          SHA_LONG_LOG2
+#define HASH_CTX                SHA_CTX
+#define HASH_CBLOCK             SHA_CBLOCK
+#define HASH_LBLOCK             SHA_LBLOCK
+#define HASH_MAKE_STRING(c,s)   do {	\
+	unsigned long ll;		\
+	ll=(c)->h0; HOST_l2c(ll,(s));	\
+	ll=(c)->h1; HOST_l2c(ll,(s));	\
+	ll=(c)->h2; HOST_l2c(ll,(s));	\
+	ll=(c)->h3; HOST_l2c(ll,(s));	\
+	ll=(c)->h4; HOST_l2c(ll,(s));	\
+	} while (0)
+
+#if defined(SHA_0)
+
+# define HASH_UPDATE             	SHA_Update
+# define HASH_TRANSFORM          	SHA_Transform
+# define HASH_FINAL              	SHA_Final
+# define HASH_INIT			SHA_Init
+# define HASH_BLOCK_HOST_ORDER   	sha_block_host_order
+# define HASH_BLOCK_DATA_ORDER   	sha_block_data_order
+# define Xupdate(a,ix,ia,ib,ic,id)	(ix=(a)=(ia^ib^ic^id))
+
+  void sha_block_host_order (SHA_CTX *c, const void *p,int num);
+  void sha_block_data_order (SHA_CTX *c, const void *p,int num);
+
+#elif defined(SHA_1)
+
+# define HASH_UPDATE             	SHA1_Update
+# define HASH_TRANSFORM          	SHA1_Transform
+# define HASH_FINAL              	SHA1_Final
+# define HASH_INIT			SHA1_Init
+# define HASH_BLOCK_HOST_ORDER   	sha1_block_host_order
+# define HASH_BLOCK_DATA_ORDER   	sha1_block_data_order
+# if defined(__MWERKS__) && defined(__MC68K__)
+   /* Metrowerks for Motorola fails otherwise:-( <appro@fy.chalmers.se> */
+#  define Xupdate(a,ix,ia,ib,ic,id)	do { (a)=(ia^ib^ic^id);		\
+					     ix=(a)=ROTATE((a),1);	\
+					} while (0)
+# else
+#  define Xupdate(a,ix,ia,ib,ic,id)	( (a)=(ia^ib^ic^id),	\
+					  ix=(a)=ROTATE((a),1)	\
+					)
+# endif
+
+# ifdef SHA1_ASM
+#  if defined(__i386) || defined(_M_IX86) || defined(__INTEL__)
+#   define sha1_block_host_order		sha1_block_asm_host_order
+#   define DONT_IMPLEMENT_BLOCK_HOST_ORDER
+#   define sha1_block_data_order		sha1_block_asm_data_order
+#   define DONT_IMPLEMENT_BLOCK_DATA_ORDER
+#   define HASH_BLOCK_DATA_ORDER_ALIGNED	sha1_block_asm_data_order
+#  endif
+# endif
+  void sha1_block_host_order (SHA_CTX *c, const void *p,int num);
+  void sha1_block_data_order (SHA_CTX *c, const void *p,int num);
+
+#else
+# error "Either SHA_0 or SHA_1 must be defined."
+#endif
+
+#include "md32_common.h"
+
+#define INIT_DATA_h0 0x67452301UL
+#define INIT_DATA_h1 0xefcdab89UL
+#define INIT_DATA_h2 0x98badcfeUL
+#define INIT_DATA_h3 0x10325476UL
+#define INIT_DATA_h4 0xc3d2e1f0UL
+
+void HASH_INIT (SHA_CTX *c)
+	{
+	c->h0=INIT_DATA_h0;
+	c->h1=INIT_DATA_h1;
+	c->h2=INIT_DATA_h2;
+	c->h3=INIT_DATA_h3;
+	c->h4=INIT_DATA_h4;
+	c->Nl=0;
+	c->Nh=0;
+	c->num=0;
+	}
+
+#define K_00_19	0x5a827999UL
+#define K_20_39 0x6ed9eba1UL
+#define K_40_59 0x8f1bbcdcUL
+#define K_60_79 0xca62c1d6UL
+
+/* As  pointed out by Wei Dai <weidai@eskimo.com>, F() below can be
+ * simplified to the code in F_00_19.  Wei attributes these optimisations
+ * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
+ * #define F(x,y,z) (((x) & (y))  |  ((~(x)) & (z)))
+ * I've just become aware of another tweak to be made, again from Wei Dai,
+ * in F_40_59, (x&a)|(y&a) -> (x|y)&a
+ */
+#define	F_00_19(b,c,d)	((((c) ^ (d)) & (b)) ^ (d)) 
+#define	F_20_39(b,c,d)	((b) ^ (c) ^ (d))
+#define F_40_59(b,c,d)	(((b) & (c)) | (((b)|(c)) & (d))) 
+#define	F_60_79(b,c,d)	F_20_39(b,c,d)
+
+#define BODY_00_15(i,a,b,c,d,e,f,xi) \
+	(f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \
+	Xupdate(f,xi,xa,xb,xc,xd); \
+	(f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \
+	Xupdate(f,xi,xa,xb,xc,xd); \
+	(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \
+	Xupdate(f,xa,xa,xb,xc,xd); \
+	(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \
+	Xupdate(f,xa,xa,xb,xc,xd); \
+	(f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \
+	Xupdate(f,xa,xa,xb,xc,xd); \
+	(f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#ifdef X
+#undef X
+#endif
+#ifndef MD32_XARRAY
+  /*
+   * Originally X was an array. As it's automatic it's natural
+   * to expect RISC compiler to accomodate at least part of it in
+   * the register bank, isn't it? Unfortunately not all compilers
+   * "find" this expectation reasonable:-( On order to make such
+   * compilers generate better code I replace X[] with a bunch of
+   * X0, X1, etc. See the function body below...
+   *					<appro@fy.chalmers.se>
+   */
+# define X(i)	XX##i
+#else
+  /*
+   * However! Some compilers (most notably HP C) get overwhelmed by
+   * that many local variables so that we have to have the way to
+   * fall down to the original behavior.
+   */
+# define X(i)	XX[i]
+#endif
+
+#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER
+void HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, int num)
+	{
+	const SHA_LONG *W=d;
+	register unsigned long A,B,C,D,E,T;
+#ifndef MD32_XARRAY
+	unsigned long	XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
+			XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
+#else
+	SHA_LONG	XX[16];
+#endif
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+	for (;;)
+		{
+	BODY_00_15( 0,A,B,C,D,E,T,W[ 0]);
+	BODY_00_15( 1,T,A,B,C,D,E,W[ 1]);
+	BODY_00_15( 2,E,T,A,B,C,D,W[ 2]);
+	BODY_00_15( 3,D,E,T,A,B,C,W[ 3]);
+	BODY_00_15( 4,C,D,E,T,A,B,W[ 4]);
+	BODY_00_15( 5,B,C,D,E,T,A,W[ 5]);
+	BODY_00_15( 6,A,B,C,D,E,T,W[ 6]);
+	BODY_00_15( 7,T,A,B,C,D,E,W[ 7]);
+	BODY_00_15( 8,E,T,A,B,C,D,W[ 8]);
+	BODY_00_15( 9,D,E,T,A,B,C,W[ 9]);
+	BODY_00_15(10,C,D,E,T,A,B,W[10]);
+	BODY_00_15(11,B,C,D,E,T,A,W[11]);
+	BODY_00_15(12,A,B,C,D,E,T,W[12]);
+	BODY_00_15(13,T,A,B,C,D,E,W[13]);
+	BODY_00_15(14,E,T,A,B,C,D,W[14]);
+	BODY_00_15(15,D,E,T,A,B,C,W[15]);
+
+	BODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]);
+	BODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]);
+	BODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]);
+	BODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0));
+
+	BODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1));
+	BODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2));
+	BODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3));
+	BODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4));
+	BODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5));
+	BODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6));
+	BODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7));
+	BODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8));
+	BODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9));
+	BODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10));
+	BODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11));
+	BODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12));
+
+	BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));
+	BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));
+	BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));
+	BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));
+	BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));
+	BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));
+	BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));
+	BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));
+
+	BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));
+	BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));
+	BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));
+	BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));
+	BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));
+	BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));
+	BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));
+	BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));
+	BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));
+	BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));
+	BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));
+	BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));
+	BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));
+	BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));
+
+	BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));
+	BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));
+	BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));
+	BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));
+	BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));
+	BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));
+	BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));
+	BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));
+	BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));
+	BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));
+	BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));
+	BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));
+	BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));
+	BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));
+	BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));
+	BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));
+	
+	c->h0=(c->h0+E)&0xffffffffL; 
+	c->h1=(c->h1+T)&0xffffffffL;
+	c->h2=(c->h2+A)&0xffffffffL;
+	c->h3=(c->h3+B)&0xffffffffL;
+	c->h4=(c->h4+C)&0xffffffffL;
+
+	if (--num <= 0) break;
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+	W+=SHA_LBLOCK;
+		}
+	}
+#endif
+
+#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER
+void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, int num)
+	{
+	const unsigned char *data=p;
+	register unsigned long A,B,C,D,E,T,l;
+#ifndef MD32_XARRAY
+	unsigned long	XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
+			XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
+#else
+	SHA_LONG	XX[16];
+#endif
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+	for (;;)
+		{
+
+	HOST_c2l(data,l); X( 0)=l;		HOST_c2l(data,l); X( 1)=l;
+	BODY_00_15( 0,A,B,C,D,E,T,X( 0));	HOST_c2l(data,l); X( 2)=l;
+	BODY_00_15( 1,T,A,B,C,D,E,X( 1));	HOST_c2l(data,l); X( 3)=l;
+	BODY_00_15( 2,E,T,A,B,C,D,X( 2));	HOST_c2l(data,l); X( 4)=l;
+	BODY_00_15( 3,D,E,T,A,B,C,X( 3));	HOST_c2l(data,l); X( 5)=l;
+	BODY_00_15( 4,C,D,E,T,A,B,X( 4));	HOST_c2l(data,l); X( 6)=l;
+	BODY_00_15( 5,B,C,D,E,T,A,X( 5));	HOST_c2l(data,l); X( 7)=l;
+	BODY_00_15( 6,A,B,C,D,E,T,X( 6));	HOST_c2l(data,l); X( 8)=l;
+	BODY_00_15( 7,T,A,B,C,D,E,X( 7));	HOST_c2l(data,l); X( 9)=l;
+	BODY_00_15( 8,E,T,A,B,C,D,X( 8));	HOST_c2l(data,l); X(10)=l;
+	BODY_00_15( 9,D,E,T,A,B,C,X( 9));	HOST_c2l(data,l); X(11)=l;
+	BODY_00_15(10,C,D,E,T,A,B,X(10));	HOST_c2l(data,l); X(12)=l;
+	BODY_00_15(11,B,C,D,E,T,A,X(11));	HOST_c2l(data,l); X(13)=l;
+	BODY_00_15(12,A,B,C,D,E,T,X(12));	HOST_c2l(data,l); X(14)=l;
+	BODY_00_15(13,T,A,B,C,D,E,X(13));	HOST_c2l(data,l); X(15)=l;
+	BODY_00_15(14,E,T,A,B,C,D,X(14));
+	BODY_00_15(15,D,E,T,A,B,C,X(15));
+
+	BODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13));
+	BODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14));
+	BODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15));
+	BODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0));
+
+	BODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1));
+	BODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2));
+	BODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3));
+	BODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4));
+	BODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5));
+	BODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6));
+	BODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7));
+	BODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8));
+	BODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9));
+	BODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10));
+	BODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11));
+	BODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12));
+
+	BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));
+	BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));
+	BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));
+	BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));
+	BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));
+	BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));
+	BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));
+	BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));
+
+	BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));
+	BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));
+	BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));
+	BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));
+	BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));
+	BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));
+	BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));
+	BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));
+	BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));
+	BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));
+	BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));
+	BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));
+	BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));
+	BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));
+	BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));
+	BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));
+	BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));
+
+	BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));
+	BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));
+	BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));
+	BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));
+	BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));
+	BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));
+	BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));
+	BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));
+	BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));
+	BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));
+	BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));
+	BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));
+	BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));
+	BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));
+	BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));
+	BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));
+	BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));
+	BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));
+	
+	c->h0=(c->h0+E)&0xffffffffL; 
+	c->h1=(c->h1+T)&0xffffffffL;
+	c->h2=(c->h2+A)&0xffffffffL;
+	c->h3=(c->h3+B)&0xffffffffL;
+	c->h4=(c->h4+C)&0xffffffffL;
+
+	if (--num <= 0) break;
+
+	A=c->h0;
+	B=c->h1;
+	C=c->h2;
+	D=c->h3;
+	E=c->h4;
+
+		}
+	}
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha2/Makefile linux-patched/net/ipsec/libcrypto/libsha2/Makefile
--- linux/net/ipsec/libcrypto/libsha2/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha2/Makefile	Tue Jul  8 15:21:05 2003
@@ -0,0 +1,21 @@
+CFLAGS=-O3 -fomit-frame-pointer -I../include $(EXTRA_CFLAGS)
+
+LIBOBJ := hmac_sha2.o sha2.o
+
+BLIB := libsha2.a
+
+.S.o:
+	$(CC) $(AFLAGS) -c $< -o $@
+
+$(BLIB): $(LIBOBJ)
+	/bin/rm -f $(BLIB)
+	ar cr $(BLIB) $(LIBOBJ)
+	-if test -s /bin/ranlib; then /bin/ranlib $(BLIB); \
+	else if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(BLIB); \
+	else exit 0; fi; fi
+
+test: test_main.o $(BLIB)
+	$(CC) -o $@ $^ 
+
+clean:
+	rm -f *.[oa] core $(TARGET) test
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha2/hmac_sha2.c linux-patched/net/ipsec/libcrypto/libsha2/hmac_sha2.c
--- linux/net/ipsec/libcrypto/libsha2/hmac_sha2.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha2/hmac_sha2.c	Thu Sep  5 04:32:57 2002
@@ -0,0 +1,32 @@
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <sys/types.h>
+#include <string.h>
+#endif
+#include "hmac_generic.h"
+#include "sha2.h"
+#include "hmac_sha2.h"
+
+void inline sha256_result(sha256_context *ctx, u_int8_t * hash, int hashlen) {
+	sha256_final(ctx);
+	memcpy(hash, &ctx->sha_out[0], hashlen);
+}
+void inline sha512_result(sha512_context *ctx, u_int8_t * hash, int hashlen) {
+	sha512_final(ctx);
+	memcpy(hash, &ctx->sha_out[0], hashlen);
+}
+HMAC_SET_KEY_IMPL (sha256_hmac_set_key, 
+		sha256_hmac_context, SHA256_BLOCKSIZE, 
+		sha256_init, sha256_write)
+HMAC_HASH_IMPL (sha256_hmac_hash, 
+		sha256_hmac_context, sha256_context, SHA256_HASHLEN,
+		sha256_write, sha256_result)
+
+HMAC_SET_KEY_IMPL (sha512_hmac_set_key, 
+		sha512_hmac_context, SHA512_BLOCKSIZE, 
+		sha512_init, sha512_write)
+HMAC_HASH_IMPL (sha512_hmac_hash, 
+		sha512_hmac_context, sha512_context, SHA512_HASHLEN,
+		sha512_write, sha512_result)
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha2/hmac_sha2.h linux-patched/net/ipsec/libcrypto/libsha2/hmac_sha2.h
--- linux/net/ipsec/libcrypto/libsha2/hmac_sha2.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha2/hmac_sha2.h	Thu Sep  5 04:32:57 2002
@@ -0,0 +1,17 @@
+typedef struct {
+	sha256_context ictx,octx;
+} sha256_hmac_context;
+typedef struct {
+	sha512_context ictx,octx;
+} sha512_hmac_context;
+#define SHA256_BLOCKSIZE 64
+#define SHA256_HASHLEN   32
+#define SHA384_BLOCKSIZE 128	/* XXX ok? */
+#define SHA384_HASHLEN   48
+#define SHA512_BLOCKSIZE 128
+#define SHA512_HASHLEN   64
+
+void sha256_hmac_hash(sha256_hmac_context *hctx, const u_int8_t * dat, int len, u_int8_t * hash, int hashlen);
+void sha256_hmac_set_key(sha256_hmac_context *hctx, const u_int8_t * key, int keylen);
+void sha512_hmac_hash(sha512_hmac_context *hctx, const u_int8_t * dat, int len, u_int8_t * hash, int hashlen);
+void sha512_hmac_set_key(sha512_hmac_context *hctx, const u_int8_t * key, int keylen);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha2/sha2.c linux-patched/net/ipsec/libcrypto/libsha2/sha2.c
--- linux/net/ipsec/libcrypto/libsha2/sha2.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha2/sha2.c	Thu Sep  5 04:32:57 2002
@@ -0,0 +1,437 @@
+/*
+ *  sha512.c
+ *
+ *  Written by Jari Ruusu, April 16 2001
+ *
+ *  Copyright 2001 by Jari Ruusu.
+ *  Redistribution of this file is permitted under the GNU Public License.
+ */
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#include <linux/types.h>
+#else
+#include <string.h>
+#include <sys/types.h>
+#endif
+#include "sha2.h"
+
+/* Define one or more of these. If none is defined, you get all of them */
+#if !defined(SHA256_NEEDED)&&!defined(SHA512_NEEDED)&&!defined(SHA384_NEEDED)
+# define SHA256_NEEDED  1
+# define SHA512_NEEDED  1
+# define SHA384_NEEDED  1
+#endif
+
+#if defined(SHA256_NEEDED)
+static const u_int32_t sha256_hashInit[8] = {
+    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c,
+    0x1f83d9ab, 0x5be0cd19
+};
+static const u_int32_t sha256_K[64] = {
+    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+    0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+    0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+    0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+    0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+    0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+#endif
+
+#if defined(SHA512_NEEDED)
+static const u_int64_t sha512_hashInit[8] = {
+    0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
+    0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+    0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+#endif
+
+#if defined(SHA384_NEEDED)
+static const u_int64_t sha384_hashInit[8] = {
+    0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL,
+    0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
+    0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL
+};
+#endif
+
+#if defined(SHA512_NEEDED) || defined(SHA384_NEEDED)
+static const u_int64_t sha512_K[80] = {
+    0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+    0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+    0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+    0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+    0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+    0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+    0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+    0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+    0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+    0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+    0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+    0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+    0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+    0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+    0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+    0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+    0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+    0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+    0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+    0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+    0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+    0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+    0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+    0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+    0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+    0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+    0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+#endif
+
+#define Ch(x,y,z)   (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)  (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+#define R(x,y)      ((y) >> (x))
+
+#if defined(SHA256_NEEDED)
+void sha256_init(sha256_context *ctx)
+{
+    memcpy(&ctx->sha_H[0], &sha256_hashInit[0], sizeof(ctx->sha_H));
+    ctx->sha_blocks = 0;
+    ctx->sha_bufCnt = 0;
+}
+
+#define S(x,y)      (((y) >> (x)) | ((y) << (32 - (x))))
+#define uSig0(x)    ((S(2,(x))) ^ (S(13,(x))) ^ (S(22,(x))))
+#define uSig1(x)    ((S(6,(x))) ^ (S(11,(x))) ^ (S(25,(x))))
+#define lSig0(x)    ((S(7,(x))) ^ (S(18,(x))) ^ (R(3,(x))))
+#define lSig1(x)    ((S(17,(x))) ^ (S(19,(x))) ^ (R(10,(x))))
+
+static void sha256_transform(sha256_context *ctx, const unsigned char *datap)
+{
+    register int    j;
+    u_int32_t       a, b, c, d, e, f, g, h;
+    u_int32_t       T1, T2, W[64], Wm2, Wm15;
+
+    /* read the data, big endian byte order */
+    j = 0;
+    do {
+        W[j] = (((u_int32_t)(datap[0]))<<24) | (((u_int32_t)(datap[1]))<<16) |
+               (((u_int32_t)(datap[2]))<<8 ) | ((u_int32_t)(datap[3]));
+        datap += 4;
+    } while(++j < 16);
+    
+    /* initialize variables a...h */
+    a = ctx->sha_H[0];
+    b = ctx->sha_H[1];
+    c = ctx->sha_H[2];
+    d = ctx->sha_H[3];
+    e = ctx->sha_H[4];
+    f = ctx->sha_H[5];
+    g = ctx->sha_H[6];
+    h = ctx->sha_H[7];
+
+    /* apply compression function */
+    j = 0;
+    do {
+        if(j >= 16) {
+            Wm2 = W[j - 2];
+            Wm15 = W[j - 15];
+            W[j] = lSig1(Wm2) + W[j - 7] + lSig0(Wm15) + W[j - 16];
+        }
+        T1 = h + uSig1(e) + Ch(e,f,g) + sha256_K[j] + W[j];
+        T2 = uSig0(a) + Maj(a,b,c);
+        h = g; g = f; f = e;
+        e = d + T1;
+        d = c; c = b; b = a;
+        a = T1 + T2;
+    } while(++j < 64);
+
+    /* compute intermediate hash value */
+    ctx->sha_H[0] += a;
+    ctx->sha_H[1] += b;
+    ctx->sha_H[2] += c;
+    ctx->sha_H[3] += d;
+    ctx->sha_H[4] += e;
+    ctx->sha_H[5] += f;
+    ctx->sha_H[6] += g;
+    ctx->sha_H[7] += h;
+
+    ctx->sha_blocks++;
+}
+
+void sha256_write(sha256_context *ctx, const unsigned char *datap, int length)
+{
+    while(length > 0) {
+        if(!ctx->sha_bufCnt) {
+            while(length >= sizeof(ctx->sha_out)) {
+                sha256_transform(ctx, datap);
+                datap += sizeof(ctx->sha_out);
+                length -= sizeof(ctx->sha_out);
+            }
+            if(!length) return;
+        }
+        ctx->sha_out[ctx->sha_bufCnt] = *datap++;
+        length--;
+        if(++ctx->sha_bufCnt == sizeof(ctx->sha_out)) {
+            sha256_transform(ctx, &ctx->sha_out[0]);
+            ctx->sha_bufCnt = 0;
+        }
+    }
+}
+
+void sha256_final(sha256_context *ctx)
+{
+    register int    j;
+    u_int64_t       bitLength;
+    u_int32_t       i;
+    unsigned char   padByte, *datap;
+
+    bitLength = (ctx->sha_blocks << 9) | (ctx->sha_bufCnt << 3);
+    padByte = 0x80;
+    sha256_write(ctx, &padByte, 1);
+
+    /* pad extra space with zeroes */
+    padByte = 0;
+    while(ctx->sha_bufCnt != 56) {
+        sha256_write(ctx, &padByte, 1);
+    }
+
+    /* write bit length, big endian byte order */
+    ctx->sha_out[56] = bitLength >> 56;
+    ctx->sha_out[57] = bitLength >> 48;
+    ctx->sha_out[58] = bitLength >> 40;
+    ctx->sha_out[59] = bitLength >> 32;
+    ctx->sha_out[60] = bitLength >> 24;
+    ctx->sha_out[61] = bitLength >> 16;
+    ctx->sha_out[62] = bitLength >> 8;
+    ctx->sha_out[63] = bitLength;
+    sha256_transform(ctx, &ctx->sha_out[0]);
+    
+    /* return results in ctx->sha_out[0...31] */
+    datap = &ctx->sha_out[0];
+    j = 0;
+    do {
+        i = ctx->sha_H[j];
+        datap[0] = i >> 24;
+        datap[1] = i >> 16;
+        datap[2] = i >> 8;
+        datap[3] = i;
+        datap += 4;
+    } while(++j < 8);
+
+    /* clear sensitive information */
+    memset(&ctx->sha_out[32], 0, sizeof(sha256_context) - 32);
+}
+
+void sha256_hash_buffer(unsigned char *ib, int ile, unsigned char *ob, int ole)
+{
+    sha256_context ctx;
+
+    if(ole < 1) return;
+    memset(ob, 0, ole);
+    if(ole > 32) ole = 32;
+    sha256_init(&ctx);
+    sha256_write(&ctx, ib, ile);
+    sha256_final(&ctx);
+    memcpy(ob, &ctx.sha_out[0], ole);
+    memset(&ctx, 0, sizeof(ctx));
+}
+
+#endif
+
+#if defined(SHA512_NEEDED)
+void sha512_init(sha512_context *ctx)
+{
+    memcpy(&ctx->sha_H[0], &sha512_hashInit[0], sizeof(ctx->sha_H));
+    ctx->sha_blocks = 0;
+    ctx->sha_blocksMSB = 0;
+    ctx->sha_bufCnt = 0;
+}
+#endif
+
+#if defined(SHA512_NEEDED) || defined(SHA384_NEEDED)
+#undef S
+#undef uSig0
+#undef uSig1
+#undef lSig0
+#undef lSig1
+#define S(x,y)      (((y) >> (x)) | ((y) << (64 - (x))))
+#define uSig0(x)    ((S(28,(x))) ^ (S(34,(x))) ^ (S(39,(x))))
+#define uSig1(x)    ((S(14,(x))) ^ (S(18,(x))) ^ (S(41,(x))))
+#define lSig0(x)    ((S(1,(x))) ^ (S(8,(x))) ^ (R(7,(x))))
+#define lSig1(x)    ((S(19,(x))) ^ (S(61,(x))) ^ (R(6,(x))))
+
+static void sha512_transform(sha512_context *ctx, const unsigned char *datap)
+{
+    register int    j;
+    u_int64_t       a, b, c, d, e, f, g, h;
+    u_int64_t       T1, T2, W[80], Wm2, Wm15;
+
+    /* read the data, big endian byte order */
+    j = 0;
+    do {
+        W[j] = (((u_int64_t)(datap[0]))<<56) | (((u_int64_t)(datap[1]))<<48) |
+               (((u_int64_t)(datap[2]))<<40) | (((u_int64_t)(datap[3]))<<32) |
+               (((u_int64_t)(datap[4]))<<24) | (((u_int64_t)(datap[5]))<<16) |
+               (((u_int64_t)(datap[6]))<<8 ) | ((u_int64_t)(datap[7]));
+        datap += 8;
+    } while(++j < 16);
+    
+    /* initialize variables a...h */
+    a = ctx->sha_H[0];
+    b = ctx->sha_H[1];
+    c = ctx->sha_H[2];
+    d = ctx->sha_H[3];
+    e = ctx->sha_H[4];
+    f = ctx->sha_H[5];
+    g = ctx->sha_H[6];
+    h = ctx->sha_H[7];
+
+    /* apply compression function */
+    j = 0;
+    do {
+        if(j >= 16) {
+            Wm2 = W[j - 2];
+            Wm15 = W[j - 15];
+            W[j] = lSig1(Wm2) + W[j - 7] + lSig0(Wm15) + W[j - 16];
+        }
+        T1 = h + uSig1(e) + Ch(e,f,g) + sha512_K[j] + W[j];
+        T2 = uSig0(a) + Maj(a,b,c);
+        h = g; g = f; f = e;
+        e = d + T1;
+        d = c; c = b; b = a;
+        a = T1 + T2;
+    } while(++j < 80);
+
+    /* compute intermediate hash value */
+    ctx->sha_H[0] += a;
+    ctx->sha_H[1] += b;
+    ctx->sha_H[2] += c;
+    ctx->sha_H[3] += d;
+    ctx->sha_H[4] += e;
+    ctx->sha_H[5] += f;
+    ctx->sha_H[6] += g;
+    ctx->sha_H[7] += h;
+
+    ctx->sha_blocks++;
+    if(!ctx->sha_blocks) ctx->sha_blocksMSB++;
+}
+
+void sha512_write(sha512_context *ctx, const unsigned char *datap, int length)
+{
+    while(length > 0) {
+        if(!ctx->sha_bufCnt) {
+            while(length >= sizeof(ctx->sha_out)) {
+                sha512_transform(ctx, datap);
+                datap += sizeof(ctx->sha_out);
+                length -= sizeof(ctx->sha_out);
+            }
+            if(!length) return;
+        }
+        ctx->sha_out[ctx->sha_bufCnt] = *datap++;
+        length--;
+        if(++ctx->sha_bufCnt == sizeof(ctx->sha_out)) {
+            sha512_transform(ctx, &ctx->sha_out[0]);
+            ctx->sha_bufCnt = 0;
+        }
+    }
+}
+
+void sha512_final(sha512_context *ctx)
+{
+    register int    j;
+    u_int64_t       bitLength, bitLengthMSB;
+    u_int64_t       i;
+    unsigned char   padByte, *datap;
+
+    bitLength = (ctx->sha_blocks << 10) | (ctx->sha_bufCnt << 3);
+    bitLengthMSB = (ctx->sha_blocksMSB << 10) | (ctx->sha_blocks >> 54);
+    padByte = 0x80;
+    sha512_write(ctx, &padByte, 1);
+
+    /* pad extra space with zeroes */
+    padByte = 0;
+    while(ctx->sha_bufCnt != 112) {
+        sha512_write(ctx, &padByte, 1);
+    }
+
+    /* write bit length, big endian byte order */
+    ctx->sha_out[112] = bitLengthMSB >> 56;
+    ctx->sha_out[113] = bitLengthMSB >> 48;
+    ctx->sha_out[114] = bitLengthMSB >> 40;
+    ctx->sha_out[115] = bitLengthMSB >> 32;
+    ctx->sha_out[116] = bitLengthMSB >> 24;
+    ctx->sha_out[117] = bitLengthMSB >> 16;
+    ctx->sha_out[118] = bitLengthMSB >> 8;
+    ctx->sha_out[119] = bitLengthMSB;
+    ctx->sha_out[120] = bitLength >> 56;
+    ctx->sha_out[121] = bitLength >> 48;
+    ctx->sha_out[122] = bitLength >> 40;
+    ctx->sha_out[123] = bitLength >> 32;
+    ctx->sha_out[124] = bitLength >> 24;
+    ctx->sha_out[125] = bitLength >> 16;
+    ctx->sha_out[126] = bitLength >> 8;
+    ctx->sha_out[127] = bitLength;
+    sha512_transform(ctx, &ctx->sha_out[0]);
+    
+    /* return results in ctx->sha_out[0...63] */
+    datap = &ctx->sha_out[0];
+    j = 0;
+    do {
+        i = ctx->sha_H[j];
+        datap[0] = i >> 56;
+        datap[1] = i >> 48;
+        datap[2] = i >> 40;
+        datap[3] = i >> 32;
+        datap[4] = i >> 24;
+        datap[5] = i >> 16;
+        datap[6] = i >> 8;
+        datap[7] = i;
+        datap += 8;
+    } while(++j < 8);
+
+    /* clear sensitive information */
+    memset(&ctx->sha_out[64], 0, sizeof(sha512_context) - 64);
+}
+
+void sha512_hash_buffer(unsigned char *ib, int ile, unsigned char *ob, int ole)
+{
+    sha512_context ctx;
+
+    if(ole < 1) return;
+    memset(ob, 0, ole);
+    if(ole > 64) ole = 64;
+    sha512_init(&ctx);
+    sha512_write(&ctx, ib, ile);
+    sha512_final(&ctx);
+    memcpy(ob, &ctx.sha_out[0], ole);
+    memset(&ctx, 0, sizeof(ctx));
+}
+#endif
+
+#if defined(SHA384_NEEDED)
+void sha384_init(sha512_context *ctx)
+{
+    memcpy(&ctx->sha_H[0], &sha384_hashInit[0], sizeof(ctx->sha_H));
+    ctx->sha_blocks = 0;
+    ctx->sha_blocksMSB = 0;
+    ctx->sha_bufCnt = 0;
+}
+
+void sha384_hash_buffer(unsigned char *ib, int ile, unsigned char *ob, int ole)
+{
+    sha512_context ctx;
+
+    if(ole < 1) return;
+    memset(ob, 0, ole);
+    if(ole > 48) ole = 48;
+    sha384_init(&ctx);
+    sha512_write(&ctx, ib, ile);
+    sha512_final(&ctx);
+    memcpy(ob, &ctx.sha_out[0], ole);
+    memset(&ctx, 0, sizeof(ctx));
+}
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libsha2/sha2.h linux-patched/net/ipsec/libcrypto/libsha2/sha2.h
--- linux/net/ipsec/libcrypto/libsha2/sha2.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libsha2/sha2.h	Thu Sep  5 04:32:57 2002
@@ -0,0 +1,52 @@
+#ifndef _SHA2_H
+#define _SHA2_H
+/*
+ *  sha512.h
+ *
+ *  Written by Jari Ruusu, April 16 2001
+ *
+ *  Copyright 2001 by Jari Ruusu.
+ *  Redistribution of this file is permitted under the GNU Public License.
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+
+typedef struct {
+    unsigned char   sha_out[64];    /* results are here, bytes 0...31 */
+    u_int32_t       sha_H[8];
+    u_int64_t       sha_blocks;
+    int             sha_bufCnt;
+} sha256_context;
+
+typedef struct {
+    unsigned char   sha_out[128];   /* results are here, bytes 0...63 */
+    u_int64_t       sha_H[8];
+    u_int64_t       sha_blocks;
+    u_int64_t       sha_blocksMSB;
+    int             sha_bufCnt;
+} sha512_context;
+
+/* no sha384_context, use sha512_context */
+
+/* 256 bit hash, provides 128 bits of security against collision attacks */
+extern void sha256_init(sha256_context *);
+extern void sha256_write(sha256_context *, const unsigned char *, int);
+extern void sha256_final(sha256_context *);
+extern void sha256_hash_buffer(unsigned char *, int, unsigned char *, int);
+
+/* 512 bit hash, provides 256 bits of security against collision attacks */
+extern void sha512_init(sha512_context *);
+extern void sha512_write(sha512_context *, const unsigned char *, int);
+extern void sha512_final(sha512_context *);
+extern void sha512_hash_buffer(unsigned char *, int, unsigned char *, int);
+
+/* 384 bit hash, provides 192 bits of security against collision attacks */
+extern void sha384_init(sha512_context *);
+/* no sha384_write(), use sha512_write() */
+/* no sha384_final(), use sha512_final(), result in ctx->sha_out[0...47]  */
+extern void sha384_hash_buffer(unsigned char *, int, unsigned char *, int);
+#endif /* _SHA2_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libtwofish/Makefile linux-patched/net/ipsec/libcrypto/libtwofish/Makefile
--- linux/net/ipsec/libcrypto/libtwofish/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libtwofish/Makefile	Tue Jul  8 15:21:05 2003
@@ -0,0 +1,21 @@
+CFLAGS=-O3 -fomit-frame-pointer -D__KERNEL__  -Wall $(EXTRA_CFLAGS)
+INC=-I../include 
+
+LIBOBJ=twofish.o twofish_cbc.o
+BLIB=libtwofish.a
+
+.c.o:
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(INC) -c $< -o $@
+
+$(BLIB): $(LIBOBJ)
+	/bin/rm -f $(BLIB)
+	ar cr $(BLIB) $(LIBOBJ)
+	-if test -s /bin/ranlib; then /bin/ranlib $(BLIB); \
+	else if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(BLIB); \
+	else exit 0; fi; fi
+
+test: test_main.o $(BLIB)
+	$(CC) -o $@ $^ 
+
+clean:
+	rm -f *.[oa] core $(TARGET) test
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libtwofish/test_main.c linux-patched/net/ipsec/libcrypto/libtwofish/test_main.c
--- linux/net/ipsec/libcrypto/libtwofish/test_main.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libtwofish/test_main.c	Thu Sep  5 04:41:17 2002
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <string.h>
+#include "twofish_cbc.h"
+#define BLOCK_SIZE	16
+#define KEY_SIZE 	128	/* bits */
+#define KEY 		"1234567890123456"
+#define STR 		"hola guaso como estaisss ... 012"
+#define STRSZ		(sizeof(STR)-1)
+
+#define BLKLEN 		BLOCK_SIZE
+#define CONTEXT_T  	twofish_context
+static int pretty_print(const unsigned char *buf, int count) {
+	int i=0;
+	for (;i<count;i++) printf ("%02hhx ", buf[i]);
+	putchar('\n');
+	return i;
+}
+//#define SIZE STRSZ/2
+#define SIZE STRSZ
+int main() {
+	int ret;
+	char buf0[SIZE+1], buf1[SIZE+1];
+	char IV[BLOCK_SIZE];
+	CONTEXT_T ac;	
+	twofish_set_key(&ac, (void *)KEY, KEY_SIZE);
+	memset(buf0, 0, sizeof (buf0));
+	memset(buf1, 0, sizeof (buf1));
+	twofish_cbc_encrypt(&ac, STR, buf0, SIZE, IV, 1);
+	pretty_print(buf0, SIZE);
+	printf("size=%d ret=%d\n%s\n", SIZE, ret, buf0);
+	ret=twofish_cbc_encrypt(&ac, buf0, buf1, SIZE, IV, 0);
+	printf("size=%d ret=%d\n%s\n", SIZE, ret, buf1);
+	return 0;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libtwofish/twofish.c linux-patched/net/ipsec/libcrypto/libtwofish/twofish.c
--- linux/net/ipsec/libcrypto/libtwofish/twofish.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libtwofish/twofish.c	Thu Sep  5 04:41:18 2002
@@ -0,0 +1,861 @@
+/* NOTE: This implementation has been changed from the original
+ * source. See ChangeLog for more information.
+ * Maintained by Marc Mutz <Marc@Mutz.com>
+ */
+
+/* Twofish for GPG
+ * By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
+ * 256-bit key length added March 20, 1999
+ * Some modifications to reduce the text size by Werner Koch, April, 1998
+ *
+ * The original author has disclaimed all copyright interest in this
+ * code and thus putting it in the public domain.
+ *
+ * This code is a "clean room" implementation, written from the paper
+ * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey,
+ * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available
+ * through http://www.counterpane.com/twofish.html
+ *
+ * For background information on multiplication in finite fields, used for
+ * the matrix operations in the key schedule, see the book _Contemporary
+ * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the
+ * Third Edition.
+ *
+ * Only the 128- and 256-bit key sizes are supported.  This code is intended
+ * for GNU C on a 32-bit system, but it should work almost anywhere.  Loops
+ * are unrolled, precomputation tables are used, etc., for maximum speed at
+ * some cost in memory consumption. */
+
+#ifdef __KERNEL__
+#include <linux/init.h>
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#define u8 u_int8_t
+#define u32 u_int32_t
+#endif
+
+#if 0 /* shouldn't this be #ifdef rotl32 ?
+       * Look at wordops.h: It includes asm/wordops.h.
+       * Anyway, we have to search in the macros for rot's,
+       * since they seem to be defined in a generic way. */
+#define rotl rotl32
+#define rotr rotr32
+#else
+#define rotl generic_rotl32
+#define rotr generic_rotr32
+#endif
+
+#include "twofish.h"
+/* The large precomputed tables for the Twofish cipher (twofish.c)
+ * Taken from the same source as twofish.c
+ * Marc Mutz <Marc@Mutz.com>
+ */
+
+/* These two tables are the q0 and q1 permutations, exactly as described in
+ * the Twofish paper. */
+
+static const u8 q0[256] = {
+   0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78,
+   0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
+   0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30,
+   0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
+   0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE,
+   0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
+   0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45,
+   0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
+   0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF,
+   0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
+   0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED,
+   0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
+   0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B,
+   0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
+   0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F,
+   0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
+   0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17,
+   0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
+   0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68,
+   0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
+   0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42,
+   0x4A, 0x5E, 0xC1, 0xE0
+};
+
+static const u8 q1[256] = {
+   0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B,
+   0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
+   0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B,
+   0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
+   0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54,
+   0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
+   0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7,
+   0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
+   0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF,
+   0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
+   0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D,
+   0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
+   0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21,
+   0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
+   0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E,
+   0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
+   0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44,
+   0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
+   0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B,
+   0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
+   0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56,
+   0x55, 0x09, 0xBE, 0x91
+};
+
+/* These MDS tables are actually tables of MDS composed with q0 and q1,
+ * because it is only ever used that way and we can save some time by
+ * precomputing.  Of course the main saving comes from precomputing the
+ * GF(2^8) multiplication involved in the MDS matrix multiply; by looking
+ * things up in these tables we reduce the matrix multiply to four lookups
+ * and three XORs.  Semi-formally, the definition of these tables is:
+ * mds[0][i] = MDS (q1[i] 0 0 0)^T  mds[1][i] = MDS (0 q0[i] 0 0)^T
+ * mds[2][i] = MDS (0 0 q1[i] 0)^T  mds[3][i] = MDS (0 0 0 q0[i])^T
+ * where ^T means "transpose", the matrix multiply is performed in GF(2^8)
+ * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described
+ * by Schneier et al, and I'm casually glossing over the byte/word
+ * conversion issues. */
+
+static const u32 mds[4][256] = {
+   {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B,
+    0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B,
+    0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32,
+    0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
+    0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA,
+    0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B,
+    0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1,
+    0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
+    0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490,
+    0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154,
+    0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0,
+    0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
+    0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228,
+    0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7,
+    0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3,
+    0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
+    0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477,
+    0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF,
+    0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C,
+    0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
+    0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA,
+    0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D,
+    0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72,
+    0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
+    0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76,
+    0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321,
+    0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39,
+    0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
+    0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D,
+    0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E,
+    0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5,
+    0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
+    0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7,
+    0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544,
+    0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E,
+    0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
+    0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A,
+    0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B,
+    0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2,
+    0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
+    0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504,
+    0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756,
+    0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91},
+
+   {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252,
+    0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A,
+    0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020,
+    0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
+    0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444,
+    0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424,
+    0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A,
+    0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
+    0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383,
+    0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A,
+    0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9,
+    0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
+    0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1,
+    0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898,
+    0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414,
+    0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
+    0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1,
+    0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989,
+    0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5,
+    0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
+    0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E,
+    0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E,
+    0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202,
+    0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
+    0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565,
+    0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A,
+    0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808,
+    0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
+    0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A,
+    0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969,
+    0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505,
+    0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
+    0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D,
+    0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343,
+    0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF,
+    0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
+    0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F,
+    0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646,
+    0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6,
+    0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
+    0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A,
+    0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7,
+    0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8},
+
+   {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B,
+    0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F,
+    0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A,
+    0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
+    0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70,
+    0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3,
+    0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB,
+    0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
+    0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4,
+    0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41,
+    0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C,
+    0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
+    0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622,
+    0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18,
+    0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035,
+    0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
+    0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84,
+    0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E,
+    0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F,
+    0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
+    0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558,
+    0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40,
+    0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA,
+    0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
+    0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF,
+    0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773,
+    0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D,
+    0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
+    0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C,
+    0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19,
+    0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086,
+    0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
+    0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74,
+    0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755,
+    0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691,
+    0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
+    0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4,
+    0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53,
+    0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E,
+    0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
+    0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705,
+    0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7,
+    0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF},
+
+   {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98,
+    0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866,
+    0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643,
+    0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
+    0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9,
+    0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C,
+    0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3,
+    0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
+    0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F,
+    0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25,
+    0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF,
+    0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
+    0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4,
+    0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E,
+    0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA,
+    0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
+    0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12,
+    0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A,
+    0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D,
+    0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
+    0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A,
+    0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C,
+    0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B,
+    0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
+    0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B,
+    0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3,
+    0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE,
+    0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
+    0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85,
+    0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA,
+    0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E,
+    0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
+    0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33,
+    0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC,
+    0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718,
+    0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
+    0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8,
+    0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872,
+    0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882,
+    0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
+    0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10,
+    0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6,
+    0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8}
+};
+
+/* The exp_to_poly and poly_to_exp tables are used to perform efficient
+ * operations in GF(2^8) represented as GF(2)[x]/w(x) where
+ * w(x)=x^8+x^6+x^3+x^2+1.  We care about doing that because it's part of the
+ * definition of the RS matrix in the key schedule.  Elements of that field
+ * are polynomials of degree not greater than 7 and all coefficients 0 or 1,
+ * which can be represented naturally by bytes (just substitute x=2).  In that
+ * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8)
+ * multiplication is inefficient without hardware support.  To multiply
+ * faster, I make use of the fact x is a generator for the nonzero elements,
+ * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for
+ * some n in 0..254.  Note that that caret is exponentiation in GF(2^8),
+ * *not* polynomial notation.  So if I want to compute pq where p and q are
+ * in GF(2^8), I can just say:
+ *    1. if p=0 or q=0 then pq=0
+ *    2. otherwise, find m and n such that p=x^m and q=x^n
+ *    3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq
+ * The translations in steps 2 and 3 are looked up in the tables
+ * poly_to_exp (for step 2) and exp_to_poly (for step 3).  To see this
+ * in action, look at the CALC_S macro.  As additional wrinkles, note that
+ * one of my operands is always a constant, so the poly_to_exp lookup on it
+ * is done in advance; I included the original values in the comments so
+ * readers can have some chance of recognizing that this *is* the RS matrix
+ * from the Twofish paper.  I've only included the table entries I actually
+ * need; I never do a lookup on a variable input of zero and the biggest
+ * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll
+ * never sum to more than 491.	I'm repeating part of the exp_to_poly table
+ * so that I don't have to do mod-255 reduction in the exponent arithmetic.
+ * Since I know my constant operands are never zero, I only have to worry
+ * about zero values in the variable operand, and I do it with a simple
+ * conditional branch.	I know conditionals are expensive, but I couldn't
+ * see a non-horrible way of avoiding them, and I did manage to group the
+ * statements so that each if covers four group multiplications. */
+
+static const u8 poly_to_exp[255] = {
+   0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19,
+   0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A,
+   0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C,
+   0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B,
+   0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47,
+   0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D,
+   0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8,
+   0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C,
+   0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83,
+   0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48,
+   0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26,
+   0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E,
+   0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3,
+   0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9,
+   0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A,
+   0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D,
+   0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75,
+   0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84,
+   0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64,
+   0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49,
+   0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF,
+   0x85, 0xC8, 0xA1
+};
+
+static const u8 exp_to_poly[492] = {
+   0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2,
+   0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03,
+   0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6,
+   0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A,
+   0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63,
+   0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C,
+   0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07,
+   0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88,
+   0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12,
+   0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7,
+   0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C,
+   0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8,
+   0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25,
+   0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A,
+   0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE,
+   0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC,
+   0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E,
+   0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92,
+   0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89,
+   0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB,
+   0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1,
+   0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D,
+   0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC,
+   0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3,
+   0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52,
+   0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0,
+   0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1,
+   0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A,
+   0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11,
+   0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51,
+   0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66,
+   0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB,
+   0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19,
+   0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D,
+   0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56,
+   0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE,
+   0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9,
+   0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE,
+   0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41,
+   0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E,
+   0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB
+};
+
+
+/* The table constants are indices of
+ * S-box entries, preprocessed through q0 and q1. */
+static const u8 calc_sb_tbl[512] = {
+    0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4,
+    0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8,
+    0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B,
+    0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B,
+    0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD,
+    0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1,
+    0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B,
+    0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F,
+    0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B,
+    0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D,
+    0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E,
+    0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5,
+    0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14,
+    0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3,
+    0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54,
+    0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51,
+    0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A,
+    0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96,
+    0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10,
+    0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C,
+    0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7,
+    0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70,
+    0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB,
+    0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8,
+    0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF,
+    0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC,
+    0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF,
+    0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2,
+    0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82,
+    0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9,
+    0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97,
+    0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17,
+    0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D,
+    0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3,
+    0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C,
+    0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E,
+    0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F,
+    0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49,
+    0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21,
+    0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9,
+    0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD,
+    0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01,
+    0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F,
+    0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48,
+    0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E,
+    0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19,
+    0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57,
+    0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64,
+    0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE,
+    0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5,
+    0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44,
+    0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69,
+    0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15,
+    0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E,
+    0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34,
+    0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC,
+    0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B,
+    0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB,
+    0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52,
+    0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9,
+    0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4,
+    0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2,
+    0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56,
+    0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91
+};
+
+/* Macro to perform one column of the RS matrix multiplication.  The
+ * parameters a, b, c, and d are the four bytes of output; i is the index
+ * of the key bytes, and w, x, y, and z, are the column of constants from
+ * the RS matrix, preprocessed through the poly_to_exp table. */
+
+#define CALC_S(a, b, c, d, i, w, x, y, z) \
+   if (key[i]) { \
+      tmp = poly_to_exp[key[i] - 1]; \
+      (a) ^= exp_to_poly[tmp + (w)]; \
+      (b) ^= exp_to_poly[tmp + (x)]; \
+      (c) ^= exp_to_poly[tmp + (y)]; \
+      (d) ^= exp_to_poly[tmp + (z)]; \
+   }
+
+/* Macros to calculate the key-dependent S-boxes for a 128-bit key using
+ * the S vector from CALC_S.  CALC_SB_2 computes a single entry in all
+ * four S-boxes, where i is the index of the entry to compute, and a and b
+ * are the index numbers preprocessed through the q0 and q1 tables
+ * respectively. */
+
+#define CALC_SB_2(i, a, b) \
+   ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \
+   ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \
+   ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \
+   ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh]
+
+/* Macro exactly like CALC_SB_2, but for 192-bit keys. */
+
+#define CALC_SB192_2(i, a, b) \
+   ctx->s[0][i] = mds[0][q0[q0[(b) ^ sa] ^ se] ^ si]; \
+   ctx->s[1][i] = mds[1][q0[q1[(b) ^ sb] ^ sf] ^ sj]; \
+   ctx->s[2][i] = mds[2][q1[q0[(a) ^ sc] ^ sg] ^ sk]; \
+   ctx->s[3][i] = mds[3][q1[q1[(a) ^ sd] ^ sh] ^ sl];
+
+/* Macro exactly like CALC_SB_2, but for 256-bit keys. */
+
+#define CALC_SB256_2(i, a, b) \
+   ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \
+   ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \
+   ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \
+   ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp];
+
+/* Macros to calculate the whitening and round subkeys.  CALC_K_2 computes the
+ * last two stages of the h() function for a given index (either 2i or 2i+1).
+ * a, b, c, and d are the four bytes going into the last two stages.  For
+ * 128-bit keys, this is the entire h() function and a and c are the index
+ * preprocessed through q0 and q1 respectively; for longer keys they are the
+ * output of previous stages.  j is the index of the first key byte to use.
+ * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2
+ * twice, doing the Psuedo-Hadamard Transform, and doing the necessary
+ * rotations.  Its parameters are: a, the array to write the results into,
+ * j, the index of the first output entry, k and l, the preprocessed indices
+ * for index 2i, and m and n, the preprocessed indices for index 2i+1.
+ * CALC_K192_2 expands CALC_K_2 to handle 192-bit keys, by doing an
+ * additional lookup-and-XOR stage.  The parameters a, b, c and d are the
+ * four bytes going into the last three stages.  For 192-bit keys, c = d
+ * are the index preprocessed through q0, and a = b are the index
+ * preprocessed through q1; j is the index of the first key byte to use.
+ * CALC_K192 is identical to CALC_K but for using the CALC_K192_2 macro
+ * instead of CALC_K_2.
+ * CALC_K256_2 expands CALC_K192_2 to handle 256-bit keys, by doing an
+ * additional lookup-and-XOR stage.  The parameters a and b are the index
+ * preprocessed through q0 and q1 respectively; j is the index of the first
+ * key byte to use.  CALC_K256 is identical to CALC_K but for using the
+ * CALC_K256_2 macro instead of CALC_K_2. */
+
+#define CALC_K_2(a, b, c, d, j) \
+     mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \
+   ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \
+   ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \
+   ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]]
+
+#define CALC_K(a, j, k, l, m, n) \
+   x = CALC_K_2 (k, l, k, l, 0); \
+   y = CALC_K_2 (m, n, m, n, 4); \
+   y = (y << 8) + (y >> 24); \
+   x += y; y += x; ctx->a[j] = x; \
+   ctx->a[(j) + 1] = (y << 9) + (y >> 23)
+
+#define CALC_K192_2(a, b, c, d, j) \
+   CALC_K_2 (q0[a ^ key[(j) + 16]], \
+	     q1[b ^ key[(j) + 17]], \
+	     q0[c ^ key[(j) + 18]], \
+	     q1[d ^ key[(j) + 19]], j)
+
+#define CALC_K192(a, j, k, l, m, n) \
+   x = CALC_K192_2 (l, l, k, k, 0); \
+   y = CALC_K192_2 (n, n, m, m, 4); \
+   y = (y << 8) + (y >> 24); \
+   x += y; y += x; ctx->a[j] = x; \
+   ctx->a[(j) + 1] = (y << 9) + (y >> 23)
+
+#define CALC_K256_2(a, b, j) \
+   CALC_K192_2 (q1[b ^ key[(j) + 24]], \
+	        q1[a ^ key[(j) + 25]], \
+	        q0[a ^ key[(j) + 26]], \
+	        q0[b ^ key[(j) + 27]], j)
+
+#define CALC_K256(a, j, k, l, m, n) \
+   x = CALC_K256_2 (k, l, 0); \
+   y = CALC_K256_2 (m, n, 4); \
+   y = (y << 8) + (y >> 24); \
+   x += y; y += x; ctx->a[j] = x; \
+   ctx->a[(j) + 1] = (y << 9) + (y >> 23)
+
+/* Perform the key setup. */
+
+int twofish_set_key (TWOFISH_context *ctx,
+			    const unsigned char *key, int key_len)
+{
+
+	int i, j, k;
+
+	/* Temporaries for CALC_K. */
+	u32 x, y;
+
+	/* The S vector used to key the S-boxes, split up into individual bytes.
+	 * 128-bit keys use only sa through sh; 256-bit use all of them. */
+	u8 sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0;
+	u8 si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0;
+
+	/* Temporary for CALC_S. */
+	u8 tmp;
+
+	/* Check key length. */
+	if (key_len != 16 && key_len != 24 && key_len != 32)
+		return -1; /* unsupported key length */
+
+	/* Compute the first two words of the S vector.  The magic numbers are
+	 * the entries of the RS matrix, preprocessed through poly_to_exp. The
+	 * numbers in the comments are the original (polynomial form) matrix
+	 * entries. */
+	CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */
+	CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */
+	CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */
+	CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */
+	CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */
+	CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */
+	CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */
+	CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */
+	CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */
+	CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */
+	CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */
+	CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */
+	CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */
+	CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */
+	CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */
+	CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */
+
+	if (key_len == 24 || key_len == 32) { /* 192- or 256-bit key */
+		/* Calculate the third word of the S vector */
+		CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */
+		CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */
+		CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */
+		CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */
+		CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */
+		CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */
+		CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */
+		CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */
+	}
+
+	if (key_len == 32) { /* 256-bit key */
+		/* Calculate the fourth word of the S vector */
+		CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */
+		CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */
+		CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */
+		CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */
+		CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */
+		CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */
+		CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */
+		CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */
+
+		/* Compute the S-boxes. */
+		for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
+			CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
+		}
+
+		/* Calculate whitening and round subkeys.  The constants are
+		 * indices of subkeys, preprocessed through q0 and q1. */
+		CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
+		CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
+		CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
+		CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
+		CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
+		CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
+		CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
+		CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
+		CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
+		CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
+		CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71);
+		CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
+		CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F);
+		CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
+		CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
+		CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F);
+		CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
+		CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
+		CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00);
+		CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
+	} else if (key_len == 24) { /* 192-bit key */
+		/* Compute the S-boxes. */
+		for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
+		        CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
+		}
+
+		/* Calculate whitening and round subkeys.  The constants are
+		 * indices of subkeys, preprocessed through q0 and q1. */
+		CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
+		CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
+		CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
+		CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
+		CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
+		CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
+		CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
+		CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
+		CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
+		CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
+		CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71);
+		CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
+		CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F);
+		CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
+		CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
+		CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F);
+		CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
+		CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
+		CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00);
+		CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
+	} else { /* 128-bit key */
+		/* Compute the S-boxes. */
+		for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
+			CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
+		}
+
+		/* Calculate whitening and round subkeys.  The constants are
+		 * indices of subkeys, preprocessed through q0 and q1. */
+		CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3);
+		CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
+		CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
+		CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
+		CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
+		CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B);
+		CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
+		CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
+		CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
+		CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD);
+		CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71);
+		CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
+		CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F);
+		CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B);
+		CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA);
+		CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F);
+		CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
+		CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
+		CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00);
+		CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
+	}
+
+	return 0;
+}
+
+/* Macros to compute the g() function in the encryption and decryption
+ * rounds.  G1 is the straight g() function; G2 includes the 8-bit
+ * rotation for the high 32-bit word. */
+
+#define G1(a) \
+     (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \
+   ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24])
+
+#define G2(b) \
+     (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \
+   ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24])
+
+/* Encryption and decryption Feistel rounds.  Each one calls the two g()
+ * macros, does the PHT, and performs the XOR and the appropriate bit
+ * rotations.  The parameters are the round number (used to select subkeys),
+ * and the four 32-bit chunks of the text. */
+
+#define ENCROUND(n, a, b, c, d) \
+   x = G1 (a); y = G2 (b); \
+   x += y; y += x + ctx->k[2 * (n) + 1]; \
+   (c) ^= x + ctx->k[2 * (n)]; \
+   (c) = ((c) >> 1) + ((c) << 31); \
+   (d) = (((d) << 1)+((d) >> 31)) ^ y
+
+#define DECROUND(n, a, b, c, d) \
+   x = G1 (a); y = G2 (b); \
+   x += y; y += x; \
+   (d) ^= y + ctx->k[2 * (n) + 1]; \
+   (d) = ((d) >> 1) + ((d) << 31); \
+   (c) = (((c) << 1)+((c) >> 31)); \
+   (c) ^= (x + ctx->k[2 * (n)])
+
+/* Encryption and decryption cycles; each one is simply two Feistel rounds
+ * with the 32-bit chunks re-ordered to simulate the "swap" */
+
+#define ENCCYCLE(n) \
+   ENCROUND (2 * (n), a, b, c, d); \
+   ENCROUND (2 * (n) + 1, c, d, a, b)
+
+#define DECCYCLE(n) \
+   DECROUND (2 * (n) + 1, c, d, a, b); \
+   DECROUND (2 * (n), a, b, c, d)
+
+/* Macros to convert the input and output bytes into 32-bit words,
+ * and simultaneously perform the whitening step.  INPACK packs word
+ * number n into the variable named by x, using whitening subkey number m.
+ * OUTUNPACK unpacks word number n from the variable named by x, using
+ * whitening subkey number m. */
+
+#define INPACK(n, x, m) \
+   x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \
+     ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m]
+
+#define OUTUNPACK(n, x, m) \
+   x ^= ctx->w[m]; \
+   out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \
+   out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24
+
+/* Encrypt one block.  in and out may be the same. */
+
+int twofish_encrypt (TWOFISH_context *ctx,
+			    const u8 *in, u8 *out)
+{
+	/* The four 32-bit chunks of the text. */
+	u32 a, b, c, d;
+	
+	/* Temporaries used by the round function. */
+	u32 x, y;
+	
+	/* Input whitening and packing. */
+	INPACK (0, a, 0);
+	INPACK (1, b, 1);
+	INPACK (2, c, 2);
+	INPACK (3, d, 3);
+	
+	/* Encryption Feistel cycles. */
+	ENCCYCLE (0);
+	ENCCYCLE (1);
+	ENCCYCLE (2);
+	ENCCYCLE (3);
+	ENCCYCLE (4);
+	ENCCYCLE (5);
+	ENCCYCLE (6);
+	ENCCYCLE (7);
+	
+	/* Output whitening and unpacking. */
+	OUTUNPACK (0, c, 4);
+	OUTUNPACK (1, d, 5);
+	OUTUNPACK (2, a, 6);
+	OUTUNPACK (3, b, 7);
+	
+	return 0;
+}
+
+/* Decrypt one block.  in and out may be the same. */
+
+int twofish_decrypt (TWOFISH_context *ctx,
+			    const u8 *in, u8 *out)
+{
+	/* The four 32-bit chunks of the text. */
+	u32 a, b, c, d;
+	
+	/* Temporaries used by the round function. */
+	u32 x, y;
+	
+	/* Input whitening and packing. */
+	INPACK (0, c, 4);
+	INPACK (1, d, 5);
+	INPACK (2, a, 6);
+	INPACK (3, b, 7);
+	
+	/* Encryption Feistel cycles. */
+	DECCYCLE (7);
+	DECCYCLE (6);
+	DECCYCLE (5);
+	DECCYCLE (4);
+	DECCYCLE (3);
+	DECCYCLE (2);
+	DECCYCLE (1);
+	DECCYCLE (0);
+
+	/* Output whitening and unpacking. */
+	OUTUNPACK (0, a, 0);
+	OUTUNPACK (1, b, 1);
+	OUTUNPACK (2, c, 2);
+	OUTUNPACK (3, d, 3);
+
+	return 0;
+}
+
+/* eof */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libtwofish/twofish.h linux-patched/net/ipsec/libcrypto/libtwofish/twofish.h
--- linux/net/ipsec/libcrypto/libtwofish/twofish.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libtwofish/twofish.h	Thu Sep  5 04:41:18 2002
@@ -0,0 +1,20 @@
+#ifndef TWOFISH_H
+#define TWOFISH_H
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+/* Structure for an expanded Twofish key.  s contains the key-dependent
+ * S-boxes composed with the MDS matrix; w contains the eight "whitening"
+ * subkeys, K[0] through K[7].	k holds the remaining, "round" subkeys.  Note
+ * that k[i] corresponds to what the Twofish paper calls K[i+8]. */
+typedef struct {
+   u_int32_t s[4][256], w[8], k[32];
+} TWOFISH_context;
+
+typedef TWOFISH_context twofish_context;
+int twofish_set_key(twofish_context *tf_ctx, const u_int8_t * in_key, int key_len);
+int twofish_encrypt(twofish_context *tf_ctx, const u_int8_t * in, u_int8_t * out);
+int twofish_decrypt(twofish_context * tf_ctx, const u_int8_t * in, u_int8_t * out);
+#endif /* TWOFISH_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libtwofish/twofish_cbc.c linux-patched/net/ipsec/libcrypto/libtwofish/twofish_cbc.c
--- linux/net/ipsec/libcrypto/libtwofish/twofish_cbc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libtwofish/twofish_cbc.c	Thu Sep  5 04:41:18 2002
@@ -0,0 +1,8 @@
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#include "twofish_cbc.h"
+#include "cbc_generic.h"
+CBC_IMPL_BLK16(twofish_cbc_encrypt, twofish_context, u_int8_t *, twofish_encrypt, twofish_decrypt);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/libtwofish/twofish_cbc.h linux-patched/net/ipsec/libcrypto/libtwofish/twofish_cbc.h
--- linux/net/ipsec/libcrypto/libtwofish/twofish_cbc.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/libtwofish/twofish_cbc.h	Thu Sep  5 04:41:18 2002
@@ -0,0 +1,3 @@
+/* Glue header */
+#include "twofish.h"
+int twofish_cbc_encrypt(twofish_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t* iv, int encrypt);
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/LICENSE linux-patched/net/ipsec/libcrypto/perlasm/LICENSE
--- linux/net/ipsec/libcrypto/perlasm/LICENSE	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/LICENSE	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,127 @@
+
+  LICENSE ISSUES
+  ==============
+
+  The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+  the OpenSSL License and the original SSLeay license apply to the toolkit.
+  See below for the actual license texts. Actually both licenses are BSD-style
+  Open Source licenses. In case of any license issues related to OpenSSL
+  please contact openssl-core@openssl.org.
+
+  OpenSSL License
+  ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  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 acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/alpha.pl linux-patched/net/ipsec/libcrypto/perlasm/alpha.pl
--- linux/net/ipsec/libcrypto/perlasm/alpha.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/alpha.pl	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,434 @@
+#!/usr/local/bin/perl
+
+package alpha;
+use Carp qw(croak cluck);
+
+$label="100";
+
+$n_debug=0;
+$smear_regs=1;
+$reg_alloc=1;
+
+$align="3";
+$com_start="#";
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels,@_); }
+
+# General registers
+
+%regs=(	'r0',	'$0',
+	'r1',	'$1',
+	'r2',	'$2',
+	'r3',	'$3',
+	'r4',	'$4',
+	'r5',	'$5',
+	'r6',	'$6',
+	'r7',	'$7',
+	'r8',	'$8',
+	'r9',	'$22',
+	'r10',	'$23',
+	'r11',	'$24',
+	'r12',	'$25',
+	'r13',	'$27',
+	'r14',	'$28',
+	'r15',	'$21', # argc == 5
+	'r16',	'$20', # argc == 4
+	'r17',	'$19', # argc == 3
+	'r18',	'$18', # argc == 2
+	'r19',	'$17', # argc == 1
+	'r20',	'$16', # argc == 0
+	'r21',	'$9',  # save 0
+	'r22',	'$10', # save 1
+	'r23',	'$11', # save 2
+	'r24',	'$12', # save 3
+	'r25',	'$13', # save 4
+	'r26',	'$14', # save 5
+
+	'a0',	'$16',
+	'a1',	'$17',
+	'a2',	'$18',
+	'a3',	'$19',
+	'a4',	'$20',
+	'a5',	'$21',
+
+	's0',	'$9',
+	's1',	'$10',
+	's2',	'$11',
+	's3',	'$12',
+	's4',	'$13',
+	's5',	'$14',
+	'zero',	'$31',
+	'sp',	'$30',
+	);
+
+$main'reg_s0="r21";
+$main'reg_s1="r22";
+$main'reg_s2="r23";
+$main'reg_s3="r24";
+$main'reg_s4="r25";
+$main'reg_s5="r26";
+
+@reg=(  '$0', '$1' ,'$2' ,'$3' ,'$4' ,'$5' ,'$6' ,'$7' ,'$8',
+	'$22','$23','$24','$25','$20','$21','$27','$28');
+
+
+sub main'sub	{ &out3("subq",@_); }
+sub main'add	{ &out3("addq",@_); }
+sub main'mov	{ &out3("bis",$_[0],$_[0],$_[1]); }
+sub main'or	{ &out3("bis",@_); }
+sub main'bis	{ &out3("bis",@_); }
+sub main'br	{ &out1("br",@_); }
+sub main'ld	{ &out2("ldq",@_); }
+sub main'st	{ &out2("stq",@_); }
+sub main'cmpult	{ &out3("cmpult",@_); }
+sub main'cmplt	{ &out3("cmplt",@_); }
+sub main'bgt	{ &out2("bgt",@_); }
+sub main'ble	{ &out2("ble",@_); }
+sub main'blt	{ &out2("blt",@_); }
+sub main'mul	{ &out3("mulq",@_); }
+sub main'muh	{ &out3("umulh",@_); }
+
+$main'QWS=8;
+
+sub main'asm_add
+	{
+	push(@out,@_);
+	}
+
+sub main'asm_finish
+	{
+	&main'file_end();
+	print &main'asm_get_output();
+	}
+
+sub main'asm_init
+	{
+	($type,$fn)=@_;
+	$filename=$fn;
+
+	&main'asm_init_output();
+	&main'comment("Don't even think of reading this code");
+	&main'comment("It was automatically generated by $filename");
+	&main'comment("Which is a perl program used to generate the alpha assember.");
+	&main'comment("eric <eay\@cryptsoft.com>");
+	&main'comment("");
+
+	$filename =~ s/\.pl$//;
+	&main'file($filename);
+	}
+
+sub conv
+	{
+	local($r)=@_;
+	local($v);
+
+	return($regs{$r}) if defined($regs{$r});
+	return($r);
+	}
+
+sub main'QWPw
+	{
+	local($off,$reg)=@_;
+
+	return(&main'QWP($off*8,$reg));
+	}
+
+sub main'QWP
+	{
+	local($off,$reg)=@_;
+
+	$ret="$off(".&conv($reg).")";
+	return($ret);
+	}
+
+sub out3
+	{
+	local($name,$p1,$p2,$p3)=@_;
+
+	$p1=&conv($p1);
+	$p2=&conv($p2);
+	$p3=&conv($p3);
+	push(@out,"\t$name\t");
+	$l=length($p1)+1;
+	push(@out,$p1.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	$l=length($p2)+1;
+	push(@out,$p2.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	push(@out,&conv($p3)."\n");
+	}
+
+sub out2
+	{
+	local($name,$p1,$p2,$p3)=@_;
+
+	$p1=&conv($p1);
+	$p2=&conv($p2);
+	push(@out,"\t$name\t");
+	$l=length($p1)+1;
+	push(@out,$p1.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	push(@out,&conv($p2)."\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+
+	$p1=&conv($p1);
+	push(@out,"\t$name\t".$p1."\n");
+	}
+
+sub out0
+	{
+	push(@out,"\t$_[0]\n");
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+ # DEC Alpha assember
+ # Generated from perl scripts contains in SSLeay
+	.file	1 "$file.s"
+	.set noat
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func)=@_;
+
+print STDERR "$func\n";
+	local($tmp)=<<"EOF";
+	.text
+	.align $align
+	.globl $func
+	.ent $func
+${func}:
+${func}..ng:
+	.frame \$30,0,\$26,0
+	.prologue 0
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	ret	\$31,(\$26),1
+	.end $func
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	ret	\$31,(\$26),1
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	push(@out,"\t.end $func\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	if ($num < 6)
+		{
+		$num=20-$num;
+		return("r$num");
+		}
+	else
+		{ return(&main'QWP($stack+$num*8,"sp")); }
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*8;
+	&main'sub("sp",$num*8,"sp");
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*8;
+	&main'add("sp",$num*8,"sp");
+	}
+
+sub main'swtmp
+	{
+	return(&main'QWP(($_[0])*8,"sp"));
+	}
+
+# Should use swtmp, which is above sp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'QWP(-($num+1)*4,"esp","",0));
+#	}
+
+sub main'comment
+	{
+	foreach (@_)
+		{
+		if (/^\s*$/)
+			{ push(@out,"\n"); }
+		else
+			{ push(@out,"\t$com_start $_ $com_end\n"); }
+		}
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=$label;
+		$label++;
+		}
+	return('$'.$label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=$label;
+		$label++;
+		}
+#	push(@out,".align $align\n") if ($_[1] != 0);
+	push(@out,'$'."$label{$_[0]}:\n");
+	}
+
+sub main'file_end
+	{
+	}
+
+sub main'data_word
+	{
+	push(@out,"\t.long $_[0]\n");
+	}
+
+@pool_free=();
+@pool_taken=();
+$curr_num=0;
+$max=0;
+
+sub main'init_pool
+	{
+	local($args)=@_;
+	local($i);
+
+	@pool_free=();
+	for ($i=(14+(6-$args)); $i >= 0; $i--)
+		{
+		push(@pool_free,"r$i");
+		}
+	print STDERR "START :register pool:@pool_free\n";
+	$curr_num=$max=0;
+	}
+
+sub main'fin_pool
+	{
+	printf STDERR "END %2d:register pool:@pool_free\n",$max;
+	}
+
+sub main'GR
+	{
+	local($r)=@_;
+	local($i,@n,$_);
+
+	foreach (@pool_free)
+		{
+		if ($r ne $_)
+			{ push(@n,$_); }
+		else
+			{
+			$curr_num++;
+			$max=$curr_num if ($curr_num > $max);
+			}
+		}
+	@pool_free=@n;
+print STDERR "GR:@pool_free\n" if $reg_alloc;
+	return(@_);
+	}
+
+sub main'NR
+	{
+	local($num)=@_;
+	local(@ret);
+
+	$num=1 if $num == 0;
+	($#pool_free >= ($num-1)) || croak "out of registers: want $num, have @pool_free";
+	while ($num > 0)
+		{
+		push(@ret,pop @pool_free);
+		$curr_num++;
+		$max=$curr_num if ($curr_num > $max);
+		$num--
+		}
+	print STDERR "nr @ret\n" if $n_debug;
+print STDERR "NR:@pool_free\n" if $reg_alloc;
+	return(@ret);
+
+	}
+
+sub main'FR
+	{
+	local(@r)=@_;
+	local(@a,$v,$w);
+
+	print STDERR "fr @r\n" if $n_debug;
+#	cluck "fr @r";
+	for $w (@pool_free)
+		{
+		foreach $v (@r)
+			{
+			croak "double register free of $v (@pool_free)" if $w eq $v;
+			}
+		}
+	foreach $v (@r)
+		{
+		croak "bad argument to FR" if ($v !~ /^r\d+$/);
+		if ($smear_regs)
+			{ unshift(@pool_free,$v); }
+		else	{ push(@pool_free,$v); }
+		$curr_num--;
+		}
+print STDERR "FR:@pool_free\n" if $reg_alloc;
+	}
+1;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/cbc.pl linux-patched/net/ipsec/libcrypto/perlasm/cbc.pl
--- linux/net/ipsec/libcrypto/perlasm/cbc.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/cbc.pl	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,342 @@
+#!/usr/local/bin/perl
+
+# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
+# des_cblock (*input);
+# des_cblock (*output);
+# long length;
+# des_key_schedule schedule;
+# des_cblock (*ivec);
+# int enc;
+#
+# calls 
+# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+#
+
+#&cbc("des_ncbc_encrypt","des_encrypt",0);
+#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
+#	1,4,5,3,5,-1);
+#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
+#	0,4,5,3,5,-1);
+#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
+#	0,6,7,3,4,5);
+#
+# When doing a cipher that needs bigendian order,
+# for encrypt, the iv is kept in bigendian form,
+# while for decrypt, it is kept in little endian.
+sub cbc
+	{
+	local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
+	# name is the function name
+	# enc_func and dec_func and the functions to call for encrypt/decrypt
+	# swap is true if byte order needs to be reversed
+	# iv_off is parameter number for the iv 
+	# enc_off is parameter number for the encrypt/decrypt flag
+	# p1,p2,p3 are the offsets for parameters to be passed to the
+	# underlying calls.
+
+	&function_begin_B($name,"");
+	&comment("");
+
+	$in="esi";
+	$out="edi";
+	$count="ebp";
+
+	&push("ebp");
+	&push("ebx");
+	&push("esi");
+	&push("edi");
+
+	$data_off=4;
+	$data_off+=4 if ($p1 > 0);
+	$data_off+=4 if ($p2 > 0);
+	$data_off+=4 if ($p3 > 0);
+
+	&mov($count,	&wparam(2));	# length
+
+	&comment("getting iv ptr from parameter $iv_off");
+	&mov("ebx",	&wparam($iv_off));	# Get iv ptr
+
+	&mov($in,	&DWP(0,"ebx","",0));#	iv[0]
+	&mov($out,	&DWP(4,"ebx","",0));#	iv[1]
+
+	&push($out);
+	&push($in);
+	&push($out);	# used in decrypt for iv[1]
+	&push($in);	# used in decrypt for iv[0]
+
+	&mov("ebx",	"esp");		# This is the address of tin[2]
+
+	&mov($in,	&wparam(0));	# in
+	&mov($out,	&wparam(1));	# out
+
+	# We have loaded them all, how lets push things
+	&comment("getting encrypt flag from parameter $enc_off");
+	&mov("ecx",	&wparam($enc_off));	# Get enc flag
+	if ($p3 > 0)
+		{
+		&comment("get and push parameter $p3");
+		if ($enc_off != $p3)
+			{ &mov("eax",	&wparam($p3)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p2 > 0)
+		{
+		&comment("get and push parameter $p2");
+		if ($enc_off != $p2)
+			{ &mov("eax",	&wparam($p2)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p1 > 0)
+		{
+		&comment("get and push parameter $p1");
+		if ($enc_off != $p1)
+			{ &mov("eax",	&wparam($p1)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	&push("ebx");		# push data/iv
+
+	&cmp("ecx",0);
+	&jz(&label("decrypt"));
+
+	&and($count,0xfffffff8);
+	&mov("eax",	&DWP($data_off,"esp","",0));	# load iv[0]
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	# load iv[1]
+
+	&jz(&label("encrypt_finish"));
+
+	#############################################################
+
+	&set_label("encrypt_loop");
+	# encrypt start 
+	# "eax" and "ebx" hold iv (or the last cipher text)
+
+	&mov("ecx",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("edx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	# eax and ebx are the next iv.
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("encrypt_loop"));
+
+###################################################################3
+	&set_label("encrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+	&xor("ecx","ecx");
+	&xor("edx","edx");
+	&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
+	&jmp_ptr($count);
+
+&set_label("ej7");
+	&xor("edx",		"edx") if $ppro; # ppro friendly
+	&movb(&HB("edx"),	&BP(6,$in,"",0));
+	&shl("edx",8);
+&set_label("ej6");
+	&movb(&HB("edx"),	&BP(5,$in,"",0));
+&set_label("ej5");
+	&movb(&LB("edx"),	&BP(4,$in,"",0));
+&set_label("ej4");
+	&mov("ecx",		&DWP(0,$in,"",0));
+	&jmp(&label("ejend"));
+&set_label("ej3");
+	&movb(&HB("ecx"),	&BP(2,$in,"",0));
+	&xor("ecx",		"ecx") if $ppro; # ppro friendly
+	&shl("ecx",8);
+&set_label("ej2");
+	&movb(&HB("ecx"),	&BP(1,$in,"",0));
+&set_label("ej1");
+	&movb(&LB("ecx"),	&BP(0,$in,"",0));
+&set_label("ejend");
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	&jmp(&label("finish"));
+
+	#############################################################
+	#############################################################
+	&set_label("decrypt",1);
+	# decrypt start 
+	&and($count,0xfffffff8);
+	# The next 2 instructions are only for if the jz is taken
+	&mov("eax",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("ebx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+	&jz(&label("decrypt_finish"));
+
+	&set_label("decrypt_loop");
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+	&mov(&DWP(0,$out,"",0),"ecx");
+	&mov(&DWP(4,$out,"",0),"edx");
+
+	&mov(&DWP($data_off+8,"esp","",0),	"eax");	# save iv
+	&mov(&DWP($data_off+12,"esp","",0),	"ebx");	#
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("decrypt_loop"));
+############################ ENDIT #######################3
+	&set_label("decrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	# this is for when we exit
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+&set_label("dj7");
+	&rotr("edx",	16);
+	&movb(&BP(6,$out,"",0),	&LB("edx"));
+	&shr("edx",16);
+&set_label("dj6");
+	&movb(&BP(5,$out,"",0),	&HB("edx"));
+&set_label("dj5");
+	&movb(&BP(4,$out,"",0),	&LB("edx"));
+&set_label("dj4");
+	&mov(&DWP(0,$out,"",0),	"ecx");
+	&jmp(&label("djend"));
+&set_label("dj3");
+	&rotr("ecx",	16);
+	&movb(&BP(2,$out,"",0),	&LB("ecx"));
+	&shl("ecx",16);
+&set_label("dj2");
+	&movb(&BP(1,$in,"",0),	&HB("ecx"));
+&set_label("dj1");
+	&movb(&BP(0,$in,"",0),	&LB("ecx"));
+&set_label("djend");
+
+	# final iv is still in eax:ebx
+	&jmp(&label("finish"));
+
+
+############################ FINISH #######################3
+	&set_label("finish",1);
+	&mov("ecx",	&wparam($iv_off));	# Get iv ptr
+
+	#################################################
+	$total=16+4;
+	$total+=4 if ($p1 > 0);
+	$total+=4 if ($p2 > 0);
+	$total+=4 if ($p3 > 0);
+	&add("esp",$total);
+
+	&mov(&DWP(0,"ecx","",0),	"eax");	# save iv
+	&mov(&DWP(4,"ecx","",0),	"ebx");	# save iv
+
+	&function_end_A($name);
+
+	&set_label("cbc_enc_jmp_table",1);
+	&data_word("0");
+	&data_word(&label("ej1"));
+	&data_word(&label("ej2"));
+	&data_word(&label("ej3"));
+	&data_word(&label("ej4"));
+	&data_word(&label("ej5"));
+	&data_word(&label("ej6"));
+	&data_word(&label("ej7"));
+	&set_label("cbc_dec_jmp_table",1);
+	&data_word("0");
+	&data_word(&label("dj1"));
+	&data_word(&label("dj2"));
+	&data_word(&label("dj3"));
+	&data_word(&label("dj4"));
+	&data_word(&label("dj5"));
+	&data_word(&label("dj6"));
+	&data_word(&label("dj7"));
+
+	&function_end_B($name);
+	
+	}
+
+1;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/readme linux-patched/net/ipsec/libcrypto/perlasm/readme
--- linux/net/ipsec/libcrypto/perlasm/readme	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/readme	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,124 @@
+The perl scripts in this directory are my 'hack' to generate
+multiple different assembler formats via the one origional script.
+
+The way to use this library is to start with adding the path to this directory
+and then include it.
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+The first thing we do is setup the file and type of assember
+
+&asm_init($ARGV[0],$0);
+
+The first argument is the 'type'.  Currently
+'cpp', 'sol', 'a.out', 'elf' or 'win32'.
+Argument 2 is the file name.
+
+The reciprocal function is
+&asm_finish() which should be called at the end.
+
+There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
+and x86unix.pl which is the unix (gas) version.
+
+Functions of interest are:
+&external_label("des_SPtrans");	declare and external variable
+&LB(reg);			Low byte for a register
+&HB(reg);			High byte for a register
+&BP(off,base,index,scale)	Byte pointer addressing
+&DWP(off,base,index,scale)	Word pointer addressing
+&stack_push(num)		Basically a 'sub esp, num*4' with extra
+&stack_pop(num)			inverse of stack_push
+&function_begin(name,extra)	Start a function with pushing of
+				edi, esi, ebx and ebp.  extra is extra win32
+				external info that may be required.
+&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
+&function_end(name)		Call at end of function.
+&function_end_A(name)		Standard pop and ret, for use inside functions
+&function_end_B(name)		Call at end but with poping or 'ret'.
+&swtmp(num)			Address on stack temp word.
+&wparam(num)			Parameter number num, that was push
+				in C convention.  This all works over pushes
+				and pops.
+&comment("hello there")		Put in a comment.
+&label("loop")			Refer to a label, normally a jmp target.
+&set_label("loop")		Set a label at this point.
+&data_word(word)		Put in a word of data.
+
+So how does this all hold together?  Given
+
+int calc(int len, int *data)
+	{
+	int i,j=0;
+
+	for (i=0; i<len; i++)
+		{
+		j+=other(data[i]);
+		}
+	}
+
+So a very simple version of this function could be coded as
+
+	push(@INC,"perlasm","../../perlasm");
+	require "x86asm.pl";
+	
+	&asm_init($ARGV[0],"cacl.pl");
+
+	&external_label("other");
+
+	$tmp1=	"eax";
+	$j=	"edi";
+	$data=	"esi";
+	$i=	"ebp";
+
+	&comment("a simple function");
+	&function_begin("calc");
+	&mov(	$data,		&wparam(1)); # data
+	&xor(	$j,		$j);
+	&xor(	$i,		$i);
+
+	&set_label("loop");
+	&cmp(	$i,		&wparam(0));
+	&jge(	&label("end"));
+
+	&mov(	$tmp1,		&DWP(0,$data,$i,4));
+	&push(	$tmp1);
+	&call(	"other");
+	&add(	$j,		"eax");
+	&pop(	$tmp1);
+	&inc(	$i);
+	&jmp(	&label("loop"));
+
+	&set_label("end");
+	&mov(	"eax",		$j);
+
+	&function_end("calc");
+
+	&asm_finish();
+
+The above example is very very unoptimised but gives an idea of how
+things work.
+
+There is also a cbc mode function generator in cbc.pl
+
+&cbc(	$name,
+	$encrypt_function_name,
+	$decrypt_function_name,
+	$true_if_byte_swap_needed,
+	$parameter_number_for_iv,
+	$parameter_number_for_encrypt_flag,
+	$first_parameter_to_pass,
+	$second_parameter_to_pass,
+	$third_parameter_to_pass);
+
+So for example, given
+void BF_encrypt(BF_LONG *data,BF_KEY *key);
+void BF_decrypt(BF_LONG *data,BF_KEY *key);
+void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
+        BF_KEY *ks, unsigned char *iv, int enc);
+
+&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
+
+&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
+&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/version linux-patched/net/ipsec/libcrypto/perlasm/version
--- linux/net/ipsec/libcrypto/perlasm/version	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/version	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,5 @@
+$Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+
+This version of perlasm was copied from the openssl 0.9.6c distribution
+
+The license applying to it is enclose in the LICENSE file
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/x86asm.pl linux-patched/net/ipsec/libcrypto/perlasm/x86asm.pl
--- linux/net/ipsec/libcrypto/perlasm/x86asm.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/x86asm.pl	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,118 @@
+#!/usr/local/bin/perl
+
+# require 'x86asm.pl';
+# &asm_init("cpp","des-586.pl");
+# XXX
+# XXX
+# main'asm_finish
+
+sub main'asm_finish
+	{
+	&file_end();
+	&asm_finish_cpp() if $cpp;
+	print &asm_get_output();
+	}
+
+sub main'asm_init
+	{
+	($type,$fn,$i386)=@_;
+	$filename=$fn;
+
+	$cpp=$sol=$aout=$win32=$gaswin=0;
+	if (	($type eq "elf"))
+		{ require "x86unix.pl"; }
+	elsif (	($type eq "a.out"))
+		{ $aout=1; require "x86unix.pl"; }
+	elsif (	($type eq "gaswin"))
+		{ $gaswin=1; $aout=1; require "x86unix.pl"; }
+	elsif (	($type eq "sol"))
+		{ $sol=1; require "x86unix.pl"; }
+	elsif (	($type eq "cpp"))
+		{ $cpp=1; require "x86unix.pl"; }
+	elsif (	($type eq "win32"))
+		{ $win32=1; require "x86ms.pl"; }
+	elsif (	($type eq "win32n"))
+		{ $win32=1; require "x86nasm.pl"; }
+	else
+		{
+		print STDERR <<"EOF";
+Pick one target type from
+	elf	- linux, FreeBSD etc
+	a.out	- old linux
+	sol	- x86 solaris
+	cpp	- format so x86unix.cpp can be used
+	win32	- Windows 95/Windows NT
+	win32n	- Windows 95/Windows NT NASM format
+EOF
+		exit(1);
+		}
+
+	&asm_init_output();
+
+&comment("Don't even think of reading this code");
+&comment("It was automatically generated by $filename");
+&comment("Which is a perl program used to generate the x86 assember for");
+&comment("any of elf, a.out, BSDI, Win32, gaswin (for GNU as on Win32) or Solaris");
+&comment("eric <eay\@cryptsoft.com>");
+&comment("");
+
+	$filename =~ s/\.pl$//;
+	&file($filename);
+	}
+
+sub asm_finish_cpp
+	{
+	return unless $cpp;
+
+	local($tmp,$i);
+	foreach $i (&get_labels())
+		{
+		$tmp.="#define $i _$i\n";
+		}
+	print <<"EOF";
+/* Run the C pre-processor over this file with one of the following defined
+ * ELF - elf object files,
+ * OUT - a.out object files,
+ * BSDI - BSDI style a.out object files
+ * SOL - Solaris style elf
+ */
+
+#define TYPE(a,b)       .type   a,b
+#define SIZE(a,b)       .size   a,b
+
+#if defined(OUT) || (defined(BSDI) && !defined(ELF))
+$tmp
+#endif
+
+#ifdef OUT
+#define OK	1
+#define ALIGN	4
+#endif
+
+#if defined(BSDI) && !defined(ELF)
+#define OK              1
+#define ALIGN           4
+#undef SIZE
+#undef TYPE
+#define SIZE(a,b)
+#define TYPE(a,b)
+#endif
+
+#if defined(ELF) || defined(SOL)
+#define OK              1
+#define ALIGN           16
+#endif
+
+#ifndef OK
+You need to define one of
+ELF - elf systems - linux-elf, NetBSD and DG-UX
+OUT - a.out systems - linux-a.out and FreeBSD
+SOL - solaris systems, which are elf with strange comment lines
+BSDI - a.out with a very primative version of as.
+#endif
+
+/* Let the Assembler begin :-) */
+EOF
+	}
+
+1;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/x86ms.pl linux-patched/net/ipsec/libcrypto/perlasm/x86ms.pl
--- linux/net/ipsec/libcrypto/perlasm/x86ms.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/x86ms.pl	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,365 @@
+#!/usr/local/bin/perl
+
+package x86ms;
+
+$label="L000";
+
+%lb=(	'eax',	'al',
+	'ebx',	'bl',
+	'ecx',	'cl',
+	'edx',	'dl',
+	'ax',	'al',
+	'bx',	'bl',
+	'cx',	'cl',
+	'dx',	'dl',
+	);
+
+%hb=(	'eax',	'ah',
+	'ebx',	'bh',
+	'ecx',	'ch',
+	'edx',	'dh',
+	'ax',	'ah',
+	'bx',	'bh',
+	'cx',	'ch',
+	'dx',	'dh',
+	);
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels,@_); }
+
+sub main'LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main'HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main'BP
+	{
+	&get_mem("BYTE",@_);
+	}
+
+sub main'DWP
+	{
+	&get_mem("DWORD",@_);
+	}
+
+sub main'BC
+	{
+	return @_;
+	}
+
+sub main'DWC
+	{
+	return @_;
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*4;
+	&main'sub("esp",$num*4);
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*4;
+	&main'add("esp",$num*4);
+	}
+
+sub get_mem
+	{
+	local($size,$addr,$reg1,$reg2,$idx)=@_;
+	local($t,$post);
+	local($ret)="$size PTR ";
+
+	$addr =~ s/^\s+//;
+	if ($addr =~ /^(.+)\+(.+)$/)
+		{
+		$reg2=&conv($1);
+		$addr="_$2";
+		}
+	elsif ($addr =~ /^[_a-zA-Z]/)
+		{
+		$addr="_$addr";
+		}
+
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	if (($addr ne "") && ($addr ne 0))
+		{
+		if ($addr !~ /^-/)
+			{ $ret.=$addr; }
+		else	{ $post=$addr; }
+		}
+	if ($reg2 ne "")
+		{
+		$t="";
+		$t="*$idx" if ($idx != 0);
+		$reg1="+".$reg1 if ("$reg1$post" ne "");
+		$ret.="[$reg2$t$reg1$post]";
+		}
+	else
+		{
+		$ret.="[$reg1$post]"
+		}
+	return($ret);
+	}
+
+sub main'mov	{ &out2("mov",@_); }
+sub main'movb	{ &out2("mov",@_); }
+sub main'and	{ &out2("and",@_); }
+sub main'or	{ &out2("or",@_); }
+sub main'shl	{ &out2("shl",@_); }
+sub main'shr	{ &out2("shr",@_); }
+sub main'xor	{ &out2("xor",@_); }
+sub main'xorb	{ &out2("xor",@_); }
+sub main'add	{ &out2("add",@_); }
+sub main'adc	{ &out2("adc",@_); }
+sub main'sub	{ &out2("sub",@_); }
+sub main'rotl	{ &out2("rol",@_); }
+sub main'rotr	{ &out2("ror",@_); }
+sub main'exch	{ &out2("xchg",@_); }
+sub main'cmp	{ &out2("cmp",@_); }
+sub main'lea	{ &out2("lea",@_); }
+sub main'mul	{ &out1("mul",@_); }
+sub main'div	{ &out1("div",@_); }
+sub main'dec	{ &out1("dec",@_); }
+sub main'inc	{ &out1("inc",@_); }
+sub main'jmp	{ &out1("jmp",@_); }
+sub main'jmp_ptr { &out1p("jmp",@_); }
+sub main'je	{ &out1("je",@_); }
+sub main'jle	{ &out1("jle",@_); }
+sub main'jz	{ &out1("jz",@_); }
+sub main'jge	{ &out1("jge",@_); }
+sub main'jl	{ &out1("jl",@_); }
+sub main'jb	{ &out1("jb",@_); }
+sub main'jc	{ &out1("jc",@_); }
+sub main'jnc	{ &out1("jnc",@_); }
+sub main'jnz	{ &out1("jnz",@_); }
+sub main'jne	{ &out1("jne",@_); }
+sub main'jno	{ &out1("jno",@_); }
+sub main'push	{ &out1("push",@_); $stack+=4; }
+sub main'pop	{ &out1("pop",@_); $stack-=4; }
+sub main'bswap	{ &out1("bswap",@_); &using486(); }
+sub main'not	{ &out1("not",@_); }
+sub main'call	{ &out1("call",'_'.$_[0]); }
+sub main'ret	{ &out0("ret"); }
+sub main'nop	{ &out0("nop"); }
+
+sub out2
+	{
+	local($name,$p1,$p2)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t");
+	$t=&conv($p1).",";
+	$l=length($t);
+	push(@out,$t);
+	$l=4-($l+9)/8;
+	push(@out,"\t" x $l);
+	push(@out,&conv($p2));
+	push(@out,"\n");
+	}
+
+sub out0
+	{
+	local($name)=@_;
+
+	push(@out,"\t$name\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub conv
+	{
+	local($p)=@_;
+
+	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+	return $p;
+	}
+
+sub using486
+	{
+	return if $using486;
+	$using486++;
+	grep(s/\.386/\.486/,@out);
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+	TITLE	$file.asm
+        .386
+.model FLAT
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func,$extra)=@_;
+
+	push(@labels,$func);
+
+	local($tmp)=<<"EOF";
+_TEXT	SEGMENT
+PUBLIC	_$func
+$extra
+_$func PROC NEAR
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main'function_begin_B
+	{
+	local($func,$extra)=@_;
+
+	local($tmp)=<<"EOF";
+_TEXT	SEGMENT
+PUBLIC	_$func
+$extra
+_$func PROC NEAR
+EOF
+	push(@out,$tmp);
+	$stack=4;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+_$func ENDP
+_TEXT	ENDS
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+_$func ENDP
+_TEXT	ENDS
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'file_end
+	{
+	push(@out,"END\n");
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	return(&main'DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main'swtmp
+	{
+	return(&main'DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'DWP(-(($num+1)*4),"esp","",0));
+#	}
+
+sub main'comment
+	{
+	foreach (@_)
+		{
+		push(@out,"\t; $_\n");
+		}
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="\$${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="${label}${_[0]}";
+		$label++;
+		}
+	if((defined $_[2]) && ($_[2] == 1))
+		{
+		push(@out,"$label{$_[0]}::\n");
+		}
+	else
+		{
+		push(@out,"$label{$_[0]}:\n");
+		}
+	}
+
+sub main'data_word
+	{
+	push(@out,"\tDD\t$_[0]\n");
+	}
+
+sub out1p
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t ".&conv($p1)."\n");
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/x86nasm.pl linux-patched/net/ipsec/libcrypto/perlasm/x86nasm.pl
--- linux/net/ipsec/libcrypto/perlasm/x86nasm.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/x86nasm.pl	Thu Sep  5 04:26:32 2002
@@ -0,0 +1,366 @@
+#!/usr/local/bin/perl
+
+package x86nasm;
+
+$label="L000";
+
+%lb=(	'eax',	'al',
+	'ebx',	'bl',
+	'ecx',	'cl',
+	'edx',	'dl',
+	'ax',	'al',
+	'bx',	'bl',
+	'cx',	'cl',
+	'dx',	'dl',
+	);
+
+%hb=(	'eax',	'ah',
+	'ebx',	'bh',
+	'ecx',	'ch',
+	'edx',	'dh',
+	'ax',	'ah',
+	'bx',	'bh',
+	'cx',	'ch',
+	'dx',	'dh',
+	);
+
+%regs=(	'eax',	'eax',
+	'ebx',	'ebx',
+	'ecx',	'ecx',
+	'edx',	'edx',
+	'esi',	'esi',
+	'edi',	'edi',
+	'ebp',	'ebp',
+	'esp',	'esp',
+	'mm0',  'mm0',
+	'mm1',  'mm1',
+	);
+
+sub main::asm_init_output { @out=(); }
+sub main::asm_get_output { return(@out); }
+sub main::get_labels { return(@labels); }
+
+sub main::external_label
+{
+	push(@labels,@_);
+	foreach (@_) {
+		push(@out, "extern\t_$_\n");
+	}
+}
+
+sub main::LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main::HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main::BP
+	{
+	&get_mem("BYTE",@_);
+	}
+
+sub main::DWP
+	{
+	&get_mem("DWORD",@_);
+	}
+
+sub main::BC
+	{
+	return "BYTE @_";
+	}
+
+sub main::DWC
+	{
+	return "DWORD @_";
+	}
+
+sub main::stack_push
+	{
+	my($num)=@_;
+	$stack+=$num*4;
+	&main::sub("esp",$num*4);
+	}
+
+sub main::stack_pop
+	{
+	my($num)=@_;
+	$stack-=$num*4;
+	&main::add("esp",$num*4);
+	}
+
+sub get_mem
+	{
+	my($size,$addr,$reg1,$reg2,$idx)=@_;
+	my($t,$post);
+	my($ret)="[";
+	$addr =~ s/^\s+//;
+	if ($addr =~ /^(.+)\+(.+)$/)
+		{
+		if (defined($regs{$reg2})) {
+		    $addr=join('+', &conv($1), "_$2");
+		} else {
+		    $reg2=&conv($1);
+		    $addr="_$2";
+		}
+		}
+	elsif ($addr =~ /^[_a-zA-Z]/)
+		{
+		$addr="_$addr";
+		}
+
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	if (($addr ne "") && ($addr ne 0))
+		{
+		if ($addr !~ /^-/)
+			{ $ret.="${addr}+"; }
+		else	{ $post=$addr; }
+		}
+	if ($reg2 ne "")
+		{
+		$t="";
+		$t="*$idx" if ($idx != 0);
+		$reg1="+".$reg1 if ("$reg1$post" ne "");
+		$ret.="$reg2$t$reg1$post]";
+		}
+	else
+		{
+		$ret.="$reg1$post]"
+		}
+	return($ret);
+	}
+
+sub main::mov	{ &out2("mov",@_); }
+sub main::movb	{ &out2("mov",@_); }
+sub main::and	{ &out2("and",@_); }
+sub main::or	{ &out2("or",@_); }
+sub main::shl	{ &out2("shl",@_); }
+sub main::shr	{ &out2("shr",@_); }
+sub main::xor	{ &out2("xor",@_); }
+sub main::xorb	{ &out2("xor",@_); }
+sub main::add	{ &out2("add",@_); }
+sub main::adc	{ &out2("adc",@_); }
+sub main::sub	{ &out2("sub",@_); }
+sub main::rotl	{ &out2("rol",@_); }
+sub main::rotr	{ &out2("ror",@_); }
+sub main::exch	{ &out2("xchg",@_); }
+sub main::cmp	{ &out2("cmp",@_); }
+sub main::lea	{ &out2("lea",@_); }
+sub main::mul	{ &out1("mul",@_); }
+sub main::div	{ &out1("div",@_); }
+sub main::dec	{ &out1("dec",@_); }
+sub main::inc	{ &out1("inc",@_); }
+sub main::jmp	{ &out1("jmp",@_); }
+sub main::jmp_ptr { &out1p("jmp",@_); }
+
+# This is a bit of a kludge: declare all branches as NEAR.
+sub main::je	{ &out1("je NEAR",@_); }
+sub main::jle	{ &out1("jle NEAR",@_); }
+sub main::jz	{ &out1("jz NEAR",@_); }
+sub main::jge	{ &out1("jge NEAR",@_); }
+sub main::jl	{ &out1("jl NEAR",@_); }
+sub main::jb	{ &out1("jb NEAR",@_); }
+sub main::jc	{ &out1("jc NEAR",@_); }
+sub main::jnc	{ &out1("jnc NEAR",@_); }
+sub main::jnz	{ &out1("jnz NEAR",@_); }
+sub main::jne	{ &out1("jne NEAR",@_); }
+sub main::jno	{ &out1("jno NEAR",@_); }
+
+sub main::push	{ &out1("push",@_); $stack+=4; }
+sub main::pop	{ &out1("pop",@_); $stack-=4; }
+sub main::bswap	{ &out1("bswap",@_); &using486(); }
+sub main::not	{ &out1("not",@_); }
+sub main::call	{ &out1("call",'_'.$_[0]); }
+sub main::ret	{ &out0("ret"); }
+sub main::nop	{ &out0("nop"); }
+
+sub out2
+	{
+	my($name,$p1,$p2)=@_;
+	my($l,$t);
+
+	push(@out,"\t$name\t");
+	$t=&conv($p1).",";
+	$l=length($t);
+	push(@out,$t);
+	$l=4-($l+9)/8;
+	push(@out,"\t" x $l);
+	push(@out,&conv($p2));
+	push(@out,"\n");
+	}
+
+sub out0
+	{
+	my($name)=@_;
+
+	push(@out,"\t$name\n");
+	}
+
+sub out1
+	{
+	my($name,$p1)=@_;
+	my($l,$t);
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub conv
+	{
+	my($p)=@_;
+	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+	return $p;
+	}
+
+sub using486
+	{
+	return if $using486;
+	$using486++;
+	grep(s/\.386/\.486/,@out);
+	}
+
+sub main::file
+	{
+	push(@out, "segment .text\n");
+	}
+
+sub main::function_begin
+	{
+	my($func,$extra)=@_;
+
+	push(@labels,$func);
+	my($tmp)=<<"EOF";
+global	_$func
+_$func:
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main::function_begin_B
+	{
+	my($func,$extra)=@_;
+	my($tmp)=<<"EOF";
+global	_$func
+_$func:
+EOF
+	push(@out,$tmp);
+	$stack=4;
+	}
+
+sub main::function_end
+	{
+	my($func)=@_;
+
+	my($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main::function_end_B
+	{
+	$stack=0;
+	%label=();
+	}
+
+sub main::function_end_A
+	{
+	my($func)=@_;
+
+	my($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main::file_end
+	{
+	}
+
+sub main::wparam
+	{
+	my($num)=@_;
+
+	return(&main::DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main::swtmp
+	{
+	return(&main::DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main::wtmp
+#	{
+#	my($num)=@_;
+#
+#	return(&main::DWP(-(($num+1)*4),"esp","",0));
+#	}
+
+sub main::comment
+	{
+	foreach (@_)
+		{
+		push(@out,"\t; $_\n");
+		}
+	}
+
+sub main::label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="\$${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main::set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="${label}${_[0]}";
+		$label++;
+		}
+	push(@out,"$label{$_[0]}:\n");
+	}
+
+sub main::data_word
+	{
+	push(@out,"\tDD\t$_[0]\n");
+	}
+
+sub out1p
+	{
+	my($name,$p1)=@_;
+	my($l,$t);
+
+	push(@out,"\t$name\t ".&conv($p1)."\n");
+	}
+
+##
+## Additional functions required for MMX and other ops
+##
+sub main::testb { &out2('test', @_) }
+sub main::movzx { &out2('movzx', @_) }
+sub main::movd { &out2('movd', @_) }
+sub main::emms { &out0('emms', @_) }
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libcrypto/perlasm/x86unix.pl linux-patched/net/ipsec/libcrypto/perlasm/x86unix.pl
--- linux/net/ipsec/libcrypto/perlasm/x86unix.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libcrypto/perlasm/x86unix.pl	Sat Oct 26 20:24:16 2002
@@ -0,0 +1,470 @@
+#!/usr/local/bin/perl
+
+package x86unix;
+
+$label="L000";
+
+$align=($main::aout)?"4":"16";
+$under=($main::aout)?"_":"";
+$com_start=($main::sol)?"/":"#";
+
+sub main::asm_init_output { @out=(); }
+sub main::asm_get_output { return(@out); }
+sub main::get_labels { return(@labels); }
+sub main::external_label { push(@labels,@_); }
+
+if ($main::cpp)
+	{
+	$align="ALIGN";
+	$under="";
+	$com_start='/*';
+	$com_end='*/';
+	}
+
+%lb=(	'eax',	'%al',
+	'ebx',	'%bl',
+	'ecx',	'%cl',
+	'edx',	'%dl',
+	'ax',	'%al',
+	'bx',	'%bl',
+	'cx',	'%cl',
+	'dx',	'%dl',
+	);
+
+%hb=(	'eax',	'%ah',
+	'ebx',	'%bh',
+	'ecx',	'%ch',
+	'edx',	'%dh',
+	'ax',	'%ah',
+	'bx',	'%bh',
+	'cx',	'%ch',
+	'dx',	'%dh',
+	);
+
+%regs=(	'eax',	'%eax',
+	'ebx',	'%ebx',
+	'ecx',	'%ecx',
+	'edx',	'%edx',
+	'esi',	'%esi',
+	'edi',	'%edi',
+	'ebp',	'%ebp',
+	'esp',	'%esp',
+	'mm0',  '%mm0',
+	'mm1',  '%mm1',
+	);
+
+%reg_val=(
+	'eax',	0x00,
+	'ebx',	0x03,
+	'ecx',	0x01,
+	'edx',	0x02,
+	'esi',	0x06,
+	'edi',	0x07,
+	'ebp',	0x05,
+	'esp',	0x04,
+	);
+
+sub main::LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main::HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main::DWP
+	{
+	local($addr,$reg1,$reg2,$idx)=@_;
+
+	$ret="";
+	$addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/;
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+	if ($reg2 ne "")
+		{
+		if($idx ne "")
+		    { $ret.="($reg1,$reg2,$idx)"; }
+		else
+		    { $ret.="($reg1,$reg2)"; }
+	        }
+	else
+		{ $ret.="($reg1)" }
+	return($ret);
+	}
+
+sub main::BP
+	{
+	return(&main::DWP(@_));
+	}
+
+sub main::BC
+	{
+	return @_;
+	}
+
+sub main::DWC
+	{
+	return @_;
+	}
+
+#sub main::BP
+#	{
+#	local($addr,$reg1,$reg2,$idx)=@_;
+#
+#	$ret="";
+#
+#	$addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
+#	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+#	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+#	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+#	if ($reg2 ne "")
+#		{ $ret.="($reg1,$reg2,$idx)"; }
+#	else
+#		{ $ret.="($reg1)" }
+#	return($ret);
+#	}
+
+sub main::mov	{ &out2("movl",@_); }
+sub main::movb	{ &out2("movb",@_); }
+sub main::and	{ &out2("andl",@_); }
+sub main::or	{ &out2("orl",@_); }
+sub main::shl	{ &out2("sall",@_); }
+sub main::shr	{ &out2("shrl",@_); }
+sub main::xor	{ &out2("xorl",@_); }
+sub main::xorb	{ &out2("xorb",@_); }
+sub main::add	{ &out2("addl",@_); }
+sub main::adc	{ &out2("adcl",@_); }
+sub main::sub	{ &out2("subl",@_); }
+sub main::rotl	{ &out2("roll",@_); }
+sub main::rotr	{ &out2("rorl",@_); }
+sub main::exch	{ &out2("xchg",@_); }
+sub main::cmp	{ &out2("cmpl",@_); }
+sub main::lea	{ &out2("leal",@_); }
+sub main::mul	{ &out1("mull",@_); }
+sub main::div	{ &out1("divl",@_); }
+sub main::jmp	{ &out1("jmp",@_); }
+sub main::jmp_ptr { &out1p("jmp",@_); }
+sub main::je	{ &out1("je",@_); }
+sub main::jle	{ &out1("jle",@_); }
+sub main::jne	{ &out1("jne",@_); }
+sub main::jnz	{ &out1("jnz",@_); }
+sub main::jz	{ &out1("jz",@_); }
+sub main::jge	{ &out1("jge",@_); }
+sub main::jl	{ &out1("jl",@_); }
+sub main::jb	{ &out1("jb",@_); }
+sub main::jc	{ &out1("jc",@_); }
+sub main::jnc	{ &out1("jnc",@_); }
+sub main::jno	{ &out1("jno",@_); }
+sub main::dec	{ &out1("decl",@_); }
+sub main::inc	{ &out1("incl",@_); }
+sub main::push	{ &out1("pushl",@_); $stack+=4; }
+sub main::pop	{ &out1("popl",@_); $stack-=4; }
+sub main::not	{ &out1("notl",@_); }
+sub main::call	{ &out1("call",$under.$_[0]); }
+sub main::ret	{ &out0("ret"); }
+sub main::nop	{ &out0("nop"); }
+
+# The bswapl instruction is new for the 486. Emulate if i386.
+sub main::bswap
+	{
+	if ($main::i386)
+		{
+		&main::comment("bswapl @_");
+		&main::exch(main::HB(@_),main::LB(@_));
+		&main::rotr(@_,16);
+		&main::exch(main::HB(@_),main::LB(@_));
+		}
+	else
+		{
+		&out1("bswapl",@_);
+		}
+	}
+
+sub out2
+	{
+	local($name,$p1,$p2)=@_;
+	local($l,$ll,$t);
+	local(%special)=(	"roll",0xD1C0,"rorl",0xD1C8,
+				"rcll",0xD1D0,"rcrl",0xD1D8,
+				"shll",0xD1E0,"shrl",0xD1E8,
+				"sarl",0xD1F8);
+	
+	if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
+		{
+		$op=$special{$name}|$reg_val{$p1};
+		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
+		$tmp2=sprintf(".byte %d\t",$op     &0xff);
+		push(@out,$tmp1);
+		push(@out,$tmp2);
+
+		$p2=&conv($p2);
+		$p1=&conv($p1);
+		&main::comment("$name $p2 $p1");
+		return;
+		}
+
+	push(@out,"\t$name\t");
+	$t=&conv($p2).",";
+	$l=length($t);
+	push(@out,$t);
+	$ll=4-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+	push(@out,&conv($p1)."\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+	local(%special)=("bswapl",0x0FC8);
+
+	if ((defined($special{$name})) && defined($regs{$p1}))
+		{
+		$op=$special{$name}|$reg_val{$p1};
+		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
+		$tmp2=sprintf(".byte %d\t",$op     &0xff);
+		push(@out,$tmp1);
+		push(@out,$tmp2);
+
+		$p2=&conv($p2);
+		$p1=&conv($p1);
+		&main::comment("$name $p2 $p1");
+		return;
+		}
+
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub out1p
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t*".&conv($p1)."\n");
+	}
+
+sub out0
+	{
+	push(@out,"\t$_[0]\n");
+	}
+
+sub conv
+	{
+	local($p)=@_;
+
+#	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+
+	$p=$regs{$p} if (defined($regs{$p}));
+
+	$p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
+	$p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
+	return $p;
+	}
+
+sub main::file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+	.file	"$file.s"
+	.version	"01.01"
+EOF
+	push(@out,$tmp);
+	}
+
+sub main::function_begin
+	{
+	local($func)=@_;
+
+	&main::external_label($func);
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+	.align $align
+.globl $func
+EOF
+	push(@out,$tmp);
+	if ($main::cpp)
+		{ $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
+	elsif ($main::gaswin)
+		{ $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+	else	{ $tmp=push(@out,"\t.type\t$func,\@function\n"); }
+	push(@out,"$func:\n");
+	$tmp=<<"EOF";
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main::function_begin_B
+	{
+	local($func,$extra)=@_;
+
+	&main::external_label($func);
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+	.align $align
+.globl $func
+EOF
+	push(@out,$tmp);
+	if ($main::cpp)
+		{ push(@out,"\tTYPE($func,\@function)\n"); }
+	elsif ($main::gaswin)
+		{ $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+	else	{ push(@out,"\t.type	$func,\@function\n"); }
+	push(@out,"$func:\n");
+	$stack=4;
+	}
+
+sub main::function_end
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.${func}_end:
+EOF
+	push(@out,$tmp);
+	if ($main::cpp)
+		{ push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
+	elsif ($main::gaswin)
+                { $tmp=push(@out,"\t.align 4\n"); }
+	else	{ push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
+	push(@out,".ident	\"$func\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main::function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main::function_end_B
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	push(@out,".L_${func}_end:\n");
+	if ($main::cpp)
+		{ push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
+        elsif ($main::gaswin)
+                { push(@out,"\t.align 4\n"); }
+	else	{ push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
+	push(@out,".ident	\"desasm.pl\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main::wparam
+	{
+	local($num)=@_;
+
+	return(&main::DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main::stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*4;
+	&main::sub("esp",$num*4);
+	}
+
+sub main::stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*4;
+	&main::add("esp",$num*4);
+	}
+
+sub main::swtmp
+	{
+	return(&main::DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main::wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main::DWP(-($num+1)*4,"esp","",0));
+#	}
+
+sub main::comment
+	{
+	foreach (@_)
+		{
+		if (/^\s*$/)
+			{ push(@out,"\n"); }
+		else
+			{ push(@out,"\t$com_start $_ $com_end\n"); }
+		}
+	}
+
+sub main::label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=".${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main::set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=".${label}${_[0]}";
+		$label++;
+		}
+	push(@out,".align $align\n") if ($_[1] != 0);
+	push(@out,"$label{$_[0]}:\n");
+	}
+
+sub main::file_end
+	{
+	}
+
+sub main::data_word
+	{
+	push(@out,"\t.long $_[0]\n");
+	}
+
+##
+## Additional functions required for MMX and other ops
+##
+sub main::testb { &out2('testb', @_) }
+sub main::movzx { &out2('movzx', @_) }
+sub main::movd { &out2('movd', @_) }
+sub main::emms { &out0('emms', @_) }
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/Makefile linux-patched/net/ipsec/libdes/Makefile
--- linux/net/ipsec/libdes/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/Makefile	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,268 @@
+include ../Makefile.inc
+
+
+# You must select the correct terminal control system to be used to
+# turn character echo off when reading passwords.  There a 5 systems
+# SGTTY   - the old BSD system
+# TERMIO  - most system V boxes
+# TERMIOS - SGI (ala IRIX).
+# VMS     - the DEC operating system
+# MSDOS   - we all know what it is :-)
+# read_pwd.c makes a reasonable guess at what is correct.
+
+# Targets
+# make          - twidle the options yourself :-)
+# make cc       - standard cc options
+# make gcc      - standard gcc options
+# make x86-elf  - linux-elf etc
+# make x86-out  - linux-a.out, FreeBSD etc
+# make x86-solaris
+# make x86-bdsi
+
+# If you are on a DEC Alpha, edit des.h and change the DES_LONG
+# define to 'unsigned int'.  I have seen this give a %20 speedup.
+
+OPTS0= -DLIBDES_LIT -DRAND -DTERMIO #-DNOCONST
+
+# Version 1.94 has changed the strings_to_key function so that it is
+# now compatible with MITs when the string is longer than 8 characters.
+# If you wish to keep the old version, uncomment the following line.
+# This will affect the -E/-D options on des(1).
+#OPTS1= -DOLD_STR_TO_KEY
+
+# There are 4 possible performance options
+# -DDES_PTR
+# -DDES_RISC1
+# -DDES_RISC2 (only one of DES_RISC1 and DES_RISC2)
+# -DDES_UNROLL
+# after the initial build, run 'des_opts' to see which options are best
+# for your platform.  There are some listed in options.txt
+#OPTS2= -DDES_PTR 
+#OPTS3= -DDES_RISC1 # or DES_RISC2
+#OPTS4= -DDES_UNROLL
+
+OPTS= $(OPTS0) $(OPTS1) $(OPTS2) $(OPTS3) $(OPTS4)
+
+MAKE=make -f Makefile
+#CC=cc
+#CFLAG= -O
+
+#CC=gcc
+#CFLAG= -O4 -funroll-loops -fomit-frame-pointer
+# normally overridden by FreeS/WAN Makefiles anyway
+CFLAG= -O3 -fomit-frame-pointer
+
+CFLAGS=$(OPTS) $(CFLAG)
+CPP=$(CC) -E
+AS=as
+
+# Assember version of des_encrypt*().
+DES_ENC=des_enc.o fcrypt_b.o		# normal C version
+#DES_ENC=asm/dx86-elf.o	asm/yx86-elf.o	# elf format x86
+#DES_ENC=asm/dx86-out.o	asm/yx86-out.o	# a.out format x86
+#DES_ENC=asm/dx86-sol.o	asm/yx86-sol.o	# solaris format x86 
+#DES_ENC=asm/dx86bsdi.o	asm/yx86basi.o	# bsdi format x86 
+
+LIBDIR=${DESTDIR}/usr/local/lib
+BINDIR=${DESTDIR}/usr/local/bin
+INCDIR=${DESTDIR}/usr/local/include
+MANDIR=${DESTDIR}/usr/local/man
+MAN1=1
+MAN3=3
+SHELL=/bin/sh
+OBJ_LIT=cbc_enc.o ecb_enc.o $(DES_ENC) fcrypt.o set_key.o
+OBJ_FULL=cbc_cksm.o $(OBJ_LIT) pcbc_enc.o \
+	xcbc_enc.o qud_cksm.o \
+	cfb64ede.o cfb64enc.o cfb_enc.o ecb3_enc.o \
+	enc_read.o enc_writ.o ofb64ede.o ofb64enc.o ofb_enc.o  \
+	rand_key.o read_pwd.o read2pwd.o rpc_enc.o  str2key.o supp.o
+
+GENERAL_LIT=COPYRIGHT INSTALL README VERSION Makefile des_crypt.man \
+	des.doc options.txt asm
+GENERAL_FULL=$(GENERAL_LIT) FILES Imakefile times vms.com KERBEROS MODES.DES \
+	des.man DES.pm DES.pod DES.xs Makefile.PL dess.S des3s.S \
+	Makefile.uni typemap t Makefile.ssl makefile.bc Makefile.lit \
+	des.org des_locl.org
+TESTING_LIT=	destest speed des_opts
+TESTING_FULL=	rpw $(TESTING_LIT)
+TESTING_SRC_LIT=destest.c speed.c des_opts.c
+TESTING_SRC_FULL=rpw.c $(TESTING_SRC_LIT)
+HEADERS_LIT=des_ver.h des.h des_locl.h podd.h sk.h spr.h
+HEADERS_FULL= $(HEADERS_LIT) rpc_des.h
+LIBDES_LIT=cbc_enc.c ecb_enc.c fcrypt.c set_key.c des_enc.c fcrypt_b.c
+LIBDES_FULL= cbc_cksm.c pcbc_enc.c qud_cksm.c \
+	cfb64ede.c cfb64enc.c cfb_enc.c ecb3_enc.c \
+	enc_read.c enc_writ.c ofb64ede.c ofb64enc.c ofb_enc.c  \
+	rand_key.c rpc_enc.c  str2key.c  supp.c \
+	xcbc_enc.c $(LIBDES_LIT) read_pwd.c read2pwd.c
+
+PERL=	des.pl testdes.pl doIP doPC1 doPC2 PC1 PC2 shifts.pl
+
+OBJ=	$(OBJ_LIT)
+GENERAL=$(GENERAL_LIT)
+TESTING=$(TESTING_LIT)
+TESTING_SRC=$(TESTING_SRC_LIT)
+HEADERS=$(HEADERS_LIT)
+LIBDES=	$(LIBDES_LIT)
+
+ALL=	$(GENERAL) $(TESTING_SRC) $(LIBDES) $(PERL) $(HEADERS)
+
+DLIB=	libdes.a
+
+.PHONY:	all cc gcc x86-elf x86-out x86-solaris x86-bsdi test tar_lit \
+	tar shar depend clean dclean install check checkprograms
+
+programs: $(DLIB)
+
+all: $(DLIB) $(TESTING)
+
+cc:
+	$(MAKE) CC=cc CFLAGS="-O $(OPTS) $(CFLAG)" all
+
+gcc:
+	$(MAKE) CC=gcc CFLAGS="-O3 -fomit-frame-pointer $(OPTS) $(CFLAG)" all
+
+x86-elf:
+	$(MAKE) DES_ENC='asm/dx86-elf.o asm/yx86-elf.o' CC='$(CC)' CFLAGS="-DELF $(OPTS) $(CFLAG)" all
+
+x86-out:
+	$(MAKE) DES_ENC='asm/dx86-out.o asm/yx86-out.o' CC='$(CC)' CFLAGS="-DOUT $(OPTS) $(CFLAG)" all
+
+x86-solaris:
+	$(MAKE) DES_ENC='asm/dx86-sol.o asm/yx86-sol.o' CC='$(CC)' CFLAGS="-DSOL $(OPTS) $(CFLAG)" all
+
+x86-bsdi:
+	$(MAKE) DES_ENC='asm/dx86bsdi.o asm/yx86bsdi.o' CC='$(CC)' CFLAGS="-DBSDI $(OPTS) $(CFLAG)" all
+
+# elf
+asm/dx86-elf.o: asm/dx86unix.S
+	$(CPP) -DELF asm/dx86unix.S | $(AS) -o asm/dx86-elf.o
+
+asm/yx86-elf.o: asm/yx86unix.S
+	$(CPP) -DELF asm/yx86unix.S | $(AS) -o asm/yx86-elf.o
+
+# solaris
+asm/dx86-sol.o: asm/dx86unix.S
+	$(CC) -E -DSOL asm/dx86unix.S | sed 's/^#.*//' > asm/dx86-sol.s
+	as -o asm/dx86-sol.o asm/dx86-sol.s
+	rm -f asm/dx86-sol.s
+
+asm/yx86-sol.o: asm/yx86unix.S
+	$(CC) -E -DSOL asm/yx86unix.S | sed 's/^#.*//' > asm/yx86-sol.s
+	as -o asm/yx86-sol.o asm/yx86-sol.s
+	rm -f asm/yx86-sol.s
+
+# a.out
+asm/dx86-out.o: asm/dx86unix.S
+	$(CPP) -DOUT asm/dx86unix.S | $(AS) -o asm/dx86-out.o
+
+asm/yx86-out.o: asm/yx86unix.S
+	$(CPP) -DOUT asm/yx86unix.S | $(AS) -o asm/yx86-out.o
+
+# bsdi
+asm/dx86bsdi.o: asm/dx86unix.S
+	$(CPP) -DBSDI asm/dx86unix.S | $(AS) -o asm/dx86bsdi.o
+
+asm/yx86bsdi.o: asm/yx86unix.S
+	$(CPP) -DBSDI asm/yx86unix.S | $(AS) -o asm/yx86bsdi.o
+
+asm/dx86unix.S:
+	(cd asm; perl des-586.pl cpp >dx86unix.S)
+
+asm/yx86unix.S:
+	(cd asm; perl crypt586.pl cpp >yx86unix.S)
+
+test:	all
+	./destest
+
+$(DLIB): $(OBJ)
+	/bin/rm -f $(DLIB)
+	ar cr $(DLIB) $(OBJ)
+	-if test -s /bin/ranlib; then /bin/ranlib $(DLIB); \
+	else if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(DLIB); \
+	else exit 0; fi; fi
+
+des_opts: des_opts.o $(DLIB)
+	$(CC) $(CFLAGS) -o des_opts des_opts.o $(DLIB)
+
+destest: destest.o $(DLIB)
+	$(CC) $(CFLAGS) -o destest destest.o $(DLIB)
+
+rpw: rpw.o $(DLIB)
+	$(CC) $(CFLAGS) -o rpw rpw.o $(DLIB)
+
+speed: speed.o $(DLIB)
+	$(CC) $(CFLAGS) -o speed speed.o $(DLIB)
+
+des: des.o $(DLIB)
+	$(CC) $(CFLAGS) -o des des.o $(DLIB)
+
+tags:
+	ctags $(TESTING_SRC) $(LIBDES)
+
+tar_lit:
+	/bin/mv Makefile Makefile.tmp
+	/bin/cp Makefile.lit Makefile
+	tar chf libdes-l.tar $(LIBDES_LIT) $(HEADERS_LIT) \
+		$(GENERAL_LIT) $(TESTING_SRC_LIT)
+	/bin/rm -f Makefile
+	/bin/mv Makefile.tmp Makefile
+
+tar:
+	tar chf libdes.tar $(ALL)
+
+shar:
+	shar $(ALL) >libdes.shar
+
+depend:
+	makedepend $(LIBDES) $(TESTING_SRC)
+
+clean:
+	/bin/rm -f *.o tags core $(TESTING) $(DLIB) .nfs* *.old *.bak asm/*.o \
+		asm/*.S
+
+dclean:
+	sed -e '/^# DO NOT DELETE THIS LINE/ q' Makefile >Makefile.new
+	mv -f Makefile.new Makefile
+
+# Eric is probably going to choke when he next looks at this --tjh
+install:
+	if test $(INSTALLTOP); then \
+	    echo SSL style install; \
+	    cp $(DLIB) $(INSTALLTOP)/lib; \
+	    if test -s /bin/ranlib; then \
+	        /bin/ranlib $(INSTALLTOP)/lib/$(DLIB); \
+	    else \
+		if test -s /usr/bin/ranlib; then \
+		/usr/bin/ranlib $(INSTALLTOP)/lib/$(DLIB); \
+	    fi; fi; \
+	    chmod 644 $(INSTALLTOP)/lib/$(DLIB); \
+	    cp des.h $(INSTALLTOP)/include; \
+	    chmod 644 $(INSTALLTOP)/include/des.h; \
+	else \
+	    echo Standalone install; \
+	    mkdir -p ${LIBDIR}; \
+	    cp $(DLIB) $(LIBDIR)/$(DLIB); \
+	    if test -s /bin/ranlib; then \
+	      /bin/ranlib $(LIBDIR)/$(DLIB); \
+	    else \
+	      if test -s /usr/bin/ranlib; then \
+		/usr/bin/ranlib $(LIBDIR)/$(DLIB); \
+	      fi; \
+	    fi; \
+	    chmod 644 $(LIBDIR)/$(DLIB); \
+	    mkdir -p ${MANDIR}/man${MAN3}; \
+	    cp des_crypt.man $(MANDIR)/man$(MAN3)/des_crypt.$(MAN3); \
+	    chmod 644 $(MANDIR)/man$(MAN3)/des_crypt.$(MAN3); \
+	    mkdir -p ${INCDIR}; \
+	    cp des.h $(INCDIR)/des.h; \
+	    chmod 644 $(INCDIR)/des.h; \
+	fi
+
+check:
+	echo no checks in lib right now.
+
+checkprograms:
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/crypt586.pl linux-patched/net/ipsec/libdes/asm/crypt586.pl
--- linux/net/ipsec/libdes/asm/crypt586.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/crypt586.pl	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,204 @@
+#!/usr/local/bin/perl
+#
+# The inner loop instruction sequence and the IP/FP modifications are from
+# Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk>
+# I've added the stuff needed for crypt() but I've not worried about making
+# things perfect.
+#
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"crypt586.pl");
+
+$L="edi";
+$R="esi";
+
+&external_label("des_SPtrans");
+&fcrypt_body("fcrypt_body");
+&asm_finish();
+
+sub fcrypt_body
+	{
+	local($name,$do_ip)=@_;
+
+	&function_begin($name,"EXTRN   _des_SPtrans:DWORD");
+
+	&comment("");
+	&comment("Load the 2 words");
+	$ks="ebp";
+
+	&xor(	$L,	$L);
+	&xor(	$R,	$R);
+	&mov($ks,&wparam(1));
+
+	&push(25); # add a variable
+
+	&set_label("start");
+	for ($i=0; $i<16; $i+=2)
+		{
+		&comment("");
+		&comment("Round $i");
+		&D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
+
+		&comment("");
+		&comment("Round ".sprintf("%d",$i+1));
+		&D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
+		}
+	 &mov("ebx",	&swtmp(0));
+	&mov("eax",	$L);
+	 &dec("ebx");
+	&mov($L,	$R);
+	 &mov($R,	"eax");
+	&mov(&swtmp(0),	"ebx");
+	 &jnz(&label("start"));
+
+	&comment("");
+	&comment("FP");
+	&mov("edx",&wparam(0));
+
+	&FP_new($R,$L,"eax",3);
+	&mov(&DWP(0,"edx","",0),"eax");
+	&mov(&DWP(4,"edx","",0),$L);
+
+	&pop("ecx");	# remove variable
+
+	&function_end($name);
+	}
+
+sub D_ENCRYPT
+	{
+	local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_;
+
+	&mov(	$u,		&wparam(2));			# 2
+	&mov(	$t,		$R);
+	&shr(	$t,		16);				# 1
+	&mov(	$tmp2,		&wparam(3));			# 2
+	&xor(	$t,		$R);				# 1
+
+	&and(	$u,		$t);				# 2
+	&and(	$t,		$tmp2);				# 2
+
+	&mov(	$tmp1,		$u);
+	&shl(	$tmp1,		16); 				# 1
+	&mov(	$tmp2,		$t);
+	&shl(	$tmp2,		16); 				# 1
+	&xor(	$u,		$tmp1);				# 2
+	&xor(	$t,		$tmp2);				# 2
+	&mov(	$tmp1,		&DWP(&n2a($S*4),$ks,"",0));	# 2
+	&xor(	$u,		$tmp1);
+	&mov(	$tmp2,		&DWP(&n2a(($S+1)*4),$ks,"",0));	# 2
+	&xor(	$u,		$R);
+	&xor(	$t,		$R);
+	&xor(	$t,		$tmp2);
+
+	&and(	$u,		"0xfcfcfcfc"	);		# 2
+	&xor(	$tmp1,		$tmp1);				# 1
+	&and(	$t,		"0xcfcfcfcf"	);		# 2
+	&xor(	$tmp2,		$tmp2);	
+	&movb(	&LB($tmp1),	&LB($u)	);
+	&movb(	&LB($tmp2),	&HB($u)	);
+	&rotr(	$t,		4		);
+	&mov(	$ks,		&DWP("      $desSP",$tmp1,"",0));
+	&movb(	&LB($tmp1),	&LB($t)	);
+	&xor(	$L,		$ks);
+	&mov(	$ks,		&DWP("0x200+$desSP",$tmp2,"",0));
+	&xor(	$L,		$ks);
+	&movb(	&LB($tmp2),	&HB($t)	);
+	&shr(	$u,		16);
+	&mov(	$ks,		&DWP("0x100+$desSP",$tmp1,"",0));
+	&xor(	$L,		$ks); 
+	&movb(	&LB($tmp1),	&HB($u)	);
+	&shr(	$t,		16);
+	&mov(	$ks,		&DWP("0x300+$desSP",$tmp2,"",0));
+	&xor(	$L,		$ks);
+	&mov(	$ks,		&wparam(1));
+	&movb(	&LB($tmp2),	&HB($t)	);
+	&and(	$u,		"0xff"	);
+	&and(	$t,		"0xff"	);
+	&mov(	$tmp1,		&DWP("0x600+$desSP",$tmp1,"",0));
+	&xor(	$L,		$tmp1);
+	&mov(	$tmp1,		&DWP("0x700+$desSP",$tmp2,"",0));
+	&xor(	$L,		$tmp1);
+	&mov(	$tmp1,		&DWP("0x400+$desSP",$u,"",0));
+	&xor(	$L,		$tmp1);
+	&mov(	$tmp1,		&DWP("0x500+$desSP",$t,"",0));
+	&xor(	$L,		$tmp1);
+	}
+
+sub n2a
+	{
+	sprintf("%d",$_[0]);
+	}
+
+# now has a side affect of rotating $a by $shift
+sub R_PERM_OP
+	{
+	local($a,$b,$tt,$shift,$mask,$last)=@_;
+
+	&rotl(	$a,		$shift		) if ($shift != 0);
+	&mov(	$tt,		$a		);
+	&xor(	$a,		$b		);
+	&and(	$a,		$mask		);
+	if ($notlast eq $b)
+		{
+		&xor(	$b,		$a		);
+		&xor(	$tt,		$a		);
+		}
+	else
+		{
+		&xor(	$tt,		$a		);
+		&xor(	$b,		$a		);
+		}
+	&comment("");
+	}
+
+sub IP_new
+	{
+	local($l,$r,$tt,$lr)=@_;
+
+	&R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l);
+	&R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l);
+	&R_PERM_OP($l,$tt,$r,14,"0x33333333",$r);
+	&R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r);
+	&R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r);
+	
+	if ($lr != 3)
+		{
+		if (($lr-3) < 0)
+			{ &rotr($tt,	3-$lr); }
+		else	{ &rotl($tt,	$lr-3); }
+		}
+	if ($lr != 2)
+		{
+		if (($lr-2) < 0)
+			{ &rotr($r,	2-$lr); }
+		else	{ &rotl($r,	$lr-2); }
+		}
+	}
+
+sub FP_new
+	{
+	local($l,$r,$tt,$lr)=@_;
+
+	if ($lr != 2)
+		{
+		if (($lr-2) < 0)
+			{ &rotl($r,	2-$lr); }
+		else	{ &rotr($r,	$lr-2); }
+		}
+	if ($lr != 3)
+		{
+		if (($lr-3) < 0)
+			{ &rotl($l,	3-$lr); }
+		else	{ &rotr($l,	$lr-3); }
+		}
+
+	&R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r);
+	&R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r);
+	&R_PERM_OP($l,$r,$tt,10,"0x33333333",$l);
+	&R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l);
+	&R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r);
+	&rotr($tt	, 4);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/des-586.pl linux-patched/net/ipsec/libdes/asm/des-586.pl
--- linux/net/ipsec/libdes/asm/des-586.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/des-586.pl	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,251 @@
+#!/usr/local/bin/perl
+#
+# The inner loop instruction sequence and the IP/FP modifications are from
+# Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk>
+#
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+require "cbc.pl";
+require "desboth.pl";
+
+# base code is in microsft
+# op dest, source
+# format.
+#
+
+&asm_init($ARGV[0],"des-586.pl");
+
+$L="edi";
+$R="esi";
+
+&external_label("des_SPtrans");
+&des_encrypt("des_encrypt",1);
+&des_encrypt("des_encrypt2",0);
+&des_encrypt3("des_encrypt3",1);
+&des_encrypt3("des_decrypt3",0);
+&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
+&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
+
+&asm_finish();
+
+sub des_encrypt
+	{
+	local($name,$do_ip)=@_;
+
+	&function_begin_B($name,"EXTRN   _des_SPtrans:DWORD");
+
+	&push("esi");
+	&push("edi");
+
+	&comment("");
+	&comment("Load the 2 words");
+	$ks="ebp";
+
+	if ($do_ip)
+		{
+		&mov($R,&wparam(0));
+		 &xor(	"ecx",		"ecx"		);
+
+		&push("ebx");
+		&push("ebp");
+
+		&mov("eax",&DWP(0,$R,"",0));
+		 &mov("ebx",&wparam(2));	# get encrypt flag
+		&mov($L,&DWP(4,$R,"",0));
+		&comment("");
+		&comment("IP");
+		&IP_new("eax",$L,$R,3);
+		}
+	else
+		{
+		&mov("eax",&wparam(0));
+		 &xor(	"ecx",		"ecx"		);
+
+		&push("ebx");
+		&push("ebp");
+
+		&mov($R,&DWP(0,"eax","",0));
+		 &mov("ebx",&wparam(2));	# get encrypt flag
+		&rotl($R,3);
+		&mov($L,&DWP(4,"eax","",0));
+		&rotl($L,3);
+		}
+
+	&mov(	$ks,		&wparam(1)	);
+	&cmp("ebx","0");
+	&je(&label("start_decrypt"));
+
+	for ($i=0; $i<16; $i+=2)
+		{
+		&comment("");
+		&comment("Round $i");
+		&D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
+
+		&comment("");
+		&comment("Round ".sprintf("%d",$i+1));
+		&D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
+		}
+	&jmp(&label("end"));
+
+	&set_label("start_decrypt");
+
+	for ($i=15; $i>0; $i-=2)
+		{
+		&comment("");
+		&comment("Round $i");
+		&D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
+		&comment("");
+		&comment("Round ".sprintf("%d",$i-1));
+		&D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
+		}
+
+	&set_label("end");
+
+	if ($do_ip)
+		{
+		&comment("");
+		&comment("FP");
+		&mov("edx",&wparam(0));
+		&FP_new($L,$R,"eax",3);
+
+		&mov(&DWP(0,"edx","",0),"eax");
+		&mov(&DWP(4,"edx","",0),$R);
+		}
+	else
+		{
+		&comment("");
+		&comment("Fixup");
+		&rotr($L,3);		# r
+		 &mov("eax",&wparam(0));
+		&rotr($R,3);		# l
+		 &mov(&DWP(0,"eax","",0),$L);
+		 &mov(&DWP(4,"eax","",0),$R);
+		}
+
+	&pop("ebp");
+	&pop("ebx");
+	&pop("edi");
+	&pop("esi");
+	&ret();
+
+	&function_end_B($name);
+	}
+
+sub D_ENCRYPT
+	{
+	local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_;
+
+	 &mov(	$u,		&DWP(&n2a($S*4),$ks,"",0));
+	&xor(	$tmp1,		$tmp1);
+	 &mov(	$t,		&DWP(&n2a(($S+1)*4),$ks,"",0));
+	&xor(	$u,		$R);
+	 &xor(	$t,		$R);
+	&and(	$u,		"0xfcfcfcfc"	);
+	 &and(	$t,		"0xcfcfcfcf"	);
+	&movb(	&LB($tmp1),	&LB($u)	);
+	 &movb(	&LB($tmp2),	&HB($u)	);
+	&rotr(	$t,		4		);
+	&mov(	$ks,		&DWP("      $desSP",$tmp1,"",0));
+	 &movb(	&LB($tmp1),	&LB($t)	);
+	&xor(	$L,		$ks);
+	 &mov(	$ks,		&DWP("0x200+$desSP",$tmp2,"",0));
+	&xor(	$L,		$ks); ######
+	 &movb(	&LB($tmp2),	&HB($t)	);
+	&shr(	$u,		16);
+	 &mov(	$ks,		&DWP("0x100+$desSP",$tmp1,"",0));
+	&xor(	$L,		$ks); ######
+	 &movb(	&LB($tmp1),	&HB($u)	);
+	&shr(	$t,		16);
+	 &mov(	$ks,		&DWP("0x300+$desSP",$tmp2,"",0));
+	&xor(	$L,		$ks);
+	 &mov(	$ks,		&wparam(1)	);
+	&movb(	&LB($tmp2),	&HB($t)	);
+	 &and(	$u,		"0xff"	);
+	&and(	$t,		"0xff"	);
+	 &mov(	$tmp1,		&DWP("0x600+$desSP",$tmp1,"",0));
+	&xor(	$L,		$tmp1);
+	 &mov(	$tmp1,		&DWP("0x700+$desSP",$tmp2,"",0));
+	&xor(	$L,		$tmp1);
+	 &mov(	$tmp1,		&DWP("0x400+$desSP",$u,"",0));
+	&xor(	$L,		$tmp1);
+	 &mov(	$tmp1,		&DWP("0x500+$desSP",$t,"",0));
+	&xor(	$L,		$tmp1);
+	}
+
+sub n2a
+	{
+	sprintf("%d",$_[0]);
+	}
+
+# now has a side affect of rotating $a by $shift
+sub R_PERM_OP
+	{
+	local($a,$b,$tt,$shift,$mask,$last)=@_;
+
+	&rotl(	$a,		$shift		) if ($shift != 0);
+	&mov(	$tt,		$a		);
+	&xor(	$a,		$b		);
+	&and(	$a,		$mask		);
+	if (!$last eq $b)
+		{
+		&xor(	$b,		$a		);
+		&xor(	$tt,		$a		);
+		}
+	else
+		{
+		&xor(	$tt,		$a		);
+		&xor(	$b,		$a		);
+		}
+	&comment("");
+	}
+
+sub IP_new
+	{
+	local($l,$r,$tt,$lr)=@_;
+
+	&R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l);
+	&R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l);
+	&R_PERM_OP($l,$tt,$r,14,"0x33333333",$r);
+	&R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r);
+	&R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r);
+	
+	if ($lr != 3)
+		{
+		if (($lr-3) < 0)
+			{ &rotr($tt,	3-$lr); }
+		else	{ &rotl($tt,	$lr-3); }
+		}
+	if ($lr != 2)
+		{
+		if (($lr-2) < 0)
+			{ &rotr($r,	2-$lr); }
+		else	{ &rotl($r,	$lr-2); }
+		}
+	}
+
+sub FP_new
+	{
+	local($l,$r,$tt,$lr)=@_;
+
+	if ($lr != 2)
+		{
+		if (($lr-2) < 0)
+			{ &rotl($r,	2-$lr); }
+		else	{ &rotr($r,	$lr-2); }
+		}
+	if ($lr != 3)
+		{
+		if (($lr-3) < 0)
+			{ &rotl($l,	3-$lr); }
+		else	{ &rotr($l,	$lr-3); }
+		}
+
+	&R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r);
+	&R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r);
+	&R_PERM_OP($l,$r,$tt,10,"0x33333333",$l);
+	&R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l);
+	&R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r);
+	&rotr($tt	, 4);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/des686.pl linux-patched/net/ipsec/libdes/asm/des686.pl
--- linux/net/ipsec/libdes/asm/des686.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/des686.pl	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,230 @@
+#!/usr/local/bin/perl
+
+$prog="des686.pl";
+
+# base code is in microsft
+# op dest, source
+# format.
+#
+
+# WILL NOT WORK ANYMORE WITH desboth.pl
+require "desboth.pl";
+
+if (	($ARGV[0] eq "elf"))
+	{ require "x86unix.pl"; }
+elsif (	($ARGV[0] eq "a.out"))
+	{ $aout=1; require "x86unix.pl"; }
+elsif (	($ARGV[0] eq "sol"))
+	{ $sol=1; require "x86unix.pl"; }
+elsif ( ($ARGV[0] eq "cpp"))
+	{ $cpp=1; require "x86unix.pl"; }
+elsif (	($ARGV[0] eq "win32"))
+	{ require "x86ms.pl"; }
+else
+	{
+	print STDERR <<"EOF";
+Pick one target type from
+	elf	- linux, FreeBSD etc
+	a.out	- old linux
+	sol	- x86 solaris
+	cpp	- format so x86unix.cpp can be used
+	win32	- Windows 95/Windows NT
+EOF
+	exit(1);
+	}
+
+&comment("Don't even think of reading this code");
+&comment("It was automatically generated by $prog");
+&comment("Which is a perl program used to generate the x86 assember for");
+&comment("any of elf, a.out, Win32, or Solaris");
+&comment("It can be found in SSLeay 0.6.5+ or in libdes 3.26+");
+&comment("eric <eay\@cryptsoft.com>");
+&comment("");
+
+&file("dx86xxxx");
+
+$L="edi";
+$R="esi";
+
+&des_encrypt("des_encrypt",1);
+&des_encrypt("des_encrypt2",0);
+
+&des_encrypt3("des_encrypt3",1);
+&des_encrypt3("des_decrypt3",0);
+
+&file_end();
+
+sub des_encrypt
+	{
+	local($name,$do_ip)=@_;
+
+	&function_begin($name,"EXTRN   _des_SPtrans:DWORD");
+
+	&comment("");
+	&comment("Load the 2 words");
+	&mov("eax",&wparam(0));
+	&mov($L,&DWP(0,"eax","",0));
+	&mov($R,&DWP(4,"eax","",0));
+
+	$ksp=&wparam(1);
+
+	if ($do_ip)
+		{
+		&comment("");
+		&comment("IP");
+		&IP_new($L,$R,"eax");
+		}
+
+	&comment("");
+	&comment("fixup rotate");
+	&rotl($R,3);
+	&rotl($L,3);
+	&exch($L,$R);
+
+	&comment("");
+	&comment("load counter, key_schedule and enc flag");
+	&mov("eax",&wparam(2));	# get encrypt flag
+	&mov("ebp",&wparam(1));	# get ks
+	&cmp("eax","0");
+	&je(&label("start_decrypt"));
+
+	# encrypting part
+
+	for ($i=0; $i<16; $i+=2)
+		{
+		&comment("");
+		&comment("Round $i");
+		&D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
+
+		&comment("");
+		&comment("Round ".sprintf("%d",$i+1));
+		&D_ENCRYPT($R,$L,($i+1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
+		}
+	&jmp(&label("end"));
+
+	&set_label("start_decrypt");
+
+	for ($i=15; $i>0; $i-=2)
+		{
+		&comment("");
+		&comment("Round $i");
+		&D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
+		&comment("");
+		&comment("Round ".sprintf("%d",$i-1));
+		&D_ENCRYPT($R,$L,($i-1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
+		}
+
+	&set_label("end");
+
+	&comment("");
+	&comment("Fixup");
+	&rotr($L,3);		# r
+	&rotr($R,3);		# l
+
+	if ($do_ip)
+		{
+		&comment("");
+		&comment("FP");
+		&FP_new($R,$L,"eax");
+		}
+
+	&mov("eax",&wparam(0));
+	&mov(&DWP(0,"eax","",0),$L);
+	&mov(&DWP(4,"eax","",0),$R);
+
+	&function_end($name);
+	}
+
+
+# The logic is to load R into 2 registers and operate on both at the same time.
+# We also load the 2 R's into 2 more registers so we can do the 'move word down a byte'
+# while also masking the other copy and doing a lookup.  We then also accumulate the
+# L value in 2 registers then combine them at the end.
+sub D_ENCRYPT
+	{
+	local($L,$R,$S,$ks,$desSP,$u,$t,$tmp1,$tmp2,$tmp3)=@_;
+
+	&mov(	$u,		&DWP(&n2a($S*4),$ks,"",0));
+	&mov(	$t,		&DWP(&n2a(($S+1)*4),$ks,"",0));
+	&xor(	$u,		$R		);
+	&xor(	$t,		$R		);
+	&rotr(	$t,		4		);
+
+	# the numbers at the end of the line are origional instruction order
+	&mov(	$tmp2,		$u		);			# 1 2
+	&mov(	$tmp1,		$t		);			# 1 1
+	&and(	$tmp2,		"0xfc"		);			# 1 4
+	&and(	$tmp1,		"0xfc"		);			# 1 3
+	&shr(	$t,		8		);			# 1 5
+	&xor(	$L,		&DWP("0x100+$desSP",$tmp1,"",0));	# 1 7
+	&shr(	$u,		8		);			# 1 6
+	&mov(	$tmp1,		&DWP("      $desSP",$tmp2,"",0));	# 1 8
+
+	&mov(	$tmp2,		$u		);			# 2 2
+	&xor(	$L,		$tmp1		);			# 1 9
+	&and(	$tmp2,		"0xfc"		);			# 2 4
+	&mov(	$tmp1,		$t		);			# 2 1
+	&and(	$tmp1,		"0xfc"		);			# 2 3
+	&shr(	$t,		8		);			# 2 5
+	&xor(	$L,		&DWP("0x300+$desSP",$tmp1,"",0));	# 2 7
+	&shr(	$u,		8		);			# 2 6
+	&mov(	$tmp1,		&DWP("0x200+$desSP",$tmp2,"",0));	# 2 8
+	&mov(	$tmp2,		$u		);			# 3 2
+
+	&xor(	$L,		$tmp1		);			# 2 9
+	&and(	$tmp2,		"0xfc"		);			# 3 4
+
+	&mov(	$tmp1,		$t		);			# 3 1 
+	&shr(	$u,		8		);			# 3 6
+	&and(	$tmp1,		"0xfc"		);			# 3 3
+	&shr(	$t,		8		);			# 3 5
+	&xor(	$L,		&DWP("0x500+$desSP",$tmp1,"",0));	# 3 7
+	&mov(	$tmp1,		&DWP("0x400+$desSP",$tmp2,"",0));	# 3 8
+
+	&and(	$t,		"0xfc"		);			# 4 1
+	&xor(	$L,		$tmp1		);			# 3 9
+
+	&and(	$u,		"0xfc"		);			# 4 2
+	&xor(	$L,		&DWP("0x700+$desSP",$t,"",0));		# 4 3
+	&xor(	$L,		&DWP("0x600+$desSP",$u,"",0));		# 4 4
+	}
+
+sub PERM_OP
+	{
+	local($a,$b,$tt,$shift,$mask)=@_;
+
+	&mov(	$tt,		$a		);
+	&shr(	$tt,		$shift		);
+	&xor(	$tt,		$b		);
+	&and(	$tt,		$mask		);
+	&xor(	$b,		$tt		);
+	&shl(	$tt,		$shift		);
+	&xor(	$a,		$tt		);
+	}
+
+sub IP_new
+	{
+	local($l,$r,$tt)=@_;
+
+	&PERM_OP($r,$l,$tt, 4,"0x0f0f0f0f");
+	&PERM_OP($l,$r,$tt,16,"0x0000ffff");
+	&PERM_OP($r,$l,$tt, 2,"0x33333333");
+	&PERM_OP($l,$r,$tt, 8,"0x00ff00ff");
+	&PERM_OP($r,$l,$tt, 1,"0x55555555");
+	}
+
+sub FP_new
+	{
+	local($l,$r,$tt)=@_;
+
+	&PERM_OP($l,$r,$tt, 1,"0x55555555");
+        &PERM_OP($r,$l,$tt, 8,"0x00ff00ff");
+        &PERM_OP($l,$r,$tt, 2,"0x33333333");
+        &PERM_OP($r,$l,$tt,16,"0x0000ffff");
+        &PERM_OP($l,$r,$tt, 4,"0x0f0f0f0f");
+	}
+
+sub n2a
+	{
+	sprintf("%d",$_[0]);
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/desboth.pl linux-patched/net/ipsec/libdes/asm/desboth.pl
--- linux/net/ipsec/libdes/asm/desboth.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/desboth.pl	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,79 @@
+#!/usr/local/bin/perl
+
+$L="edi";
+$R="esi";
+
+sub des_encrypt3
+	{
+	local($name,$enc)=@_;
+
+	&function_begin_B($name,"");
+	&push("ebx");
+	&mov("ebx",&wparam(0));
+
+	&push("ebp");
+	&push("esi");
+
+	&push("edi");
+
+	&comment("");
+	&comment("Load the data words");
+	&mov($L,&DWP(0,"ebx","",0));
+	&mov($R,&DWP(4,"ebx","",0));
+	&stack_push(3);
+
+	&comment("");
+	&comment("IP");
+	&IP_new($L,$R,"edx",0);
+
+	# put them back
+	
+	if ($enc)
+		{
+		&mov(&DWP(4,"ebx","",0),$R);
+		 &mov("eax",&wparam(1));
+		&mov(&DWP(0,"ebx","",0),"edx");
+		 &mov("edi",&wparam(2));
+		 &mov("esi",&wparam(3));
+		}
+	else
+		{
+		&mov(&DWP(4,"ebx","",0),$R);
+		 &mov("esi",&wparam(1));
+		&mov(&DWP(0,"ebx","",0),"edx");
+		 &mov("edi",&wparam(2));
+		 &mov("eax",&wparam(3));
+		}
+	&mov(&swtmp(2),	(($enc)?"1":"0"));
+	&mov(&swtmp(1),	"eax");
+	&mov(&swtmp(0),	"ebx");
+	&call("des_encrypt2");
+	&mov(&swtmp(2),	(($enc)?"0":"1"));
+	&mov(&swtmp(1),	"edi");
+	&mov(&swtmp(0),	"ebx");
+	&call("des_encrypt2");
+	&mov(&swtmp(2),	(($enc)?"1":"0"));
+	&mov(&swtmp(1),	"esi");
+	&mov(&swtmp(0),	"ebx");
+	&call("des_encrypt2");
+
+	&stack_pop(3);
+	&mov($L,&DWP(0,"ebx","",0));
+	&mov($R,&DWP(4,"ebx","",0));
+
+	&comment("");
+	&comment("FP");
+	&FP_new($L,$R,"eax",0);
+
+	&mov(&DWP(0,"ebx","",0),"eax");
+	&mov(&DWP(4,"ebx","",0),$R);
+
+	&pop("edi");
+	&pop("esi");
+	&pop("ebp");
+	&pop("ebx");
+	&ret();
+	&function_end_B($name);
+	}
+
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/perlasm/cbc.pl linux-patched/net/ipsec/libdes/asm/perlasm/cbc.pl
--- linux/net/ipsec/libdes/asm/perlasm/cbc.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/perlasm/cbc.pl	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,342 @@
+#!/usr/local/bin/perl
+
+# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
+# des_cblock (*input);
+# des_cblock (*output);
+# long length;
+# des_key_schedule schedule;
+# des_cblock (*ivec);
+# int enc;
+#
+# calls 
+# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+#
+
+#&cbc("des_ncbc_encrypt","des_encrypt",0);
+#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
+#	1,4,5,3,5,-1);
+#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
+#	0,4,5,3,5,-1);
+#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
+#	0,6,7,3,4,5);
+#
+# When doing a cipher that needs bigendian order,
+# for encrypt, the iv is kept in bigendian form,
+# while for decrypt, it is kept in little endian.
+sub cbc
+	{
+	local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
+	# name is the function name
+	# enc_func and dec_func and the functions to call for encrypt/decrypt
+	# swap is true if byte order needs to be reversed
+	# iv_off is parameter number for the iv 
+	# enc_off is parameter number for the encrypt/decrypt flag
+	# p1,p2,p3 are the offsets for parameters to be passed to the
+	# underlying calls.
+
+	&function_begin_B($name,"");
+	&comment("");
+
+	$in="esi";
+	$out="edi";
+	$count="ebp";
+
+	&push("ebp");
+	&push("ebx");
+	&push("esi");
+	&push("edi");
+
+	$data_off=4;
+	$data_off+=4 if ($p1 > 0);
+	$data_off+=4 if ($p2 > 0);
+	$data_off+=4 if ($p3 > 0);
+
+	&mov($count,	&wparam(2));	# length
+
+	&comment("getting iv ptr from parameter $iv_off");
+	&mov("ebx",	&wparam($iv_off));	# Get iv ptr
+
+	&mov($in,	&DWP(0,"ebx","",0));#	iv[0]
+	&mov($out,	&DWP(4,"ebx","",0));#	iv[1]
+
+	&push($out);
+	&push($in);
+	&push($out);	# used in decrypt for iv[1]
+	&push($in);	# used in decrypt for iv[0]
+
+	&mov("ebx",	"esp");		# This is the address of tin[2]
+
+	&mov($in,	&wparam(0));	# in
+	&mov($out,	&wparam(1));	# out
+
+	# We have loaded them all, how lets push things
+	&comment("getting encrypt flag from parameter $enc_off");
+	&mov("ecx",	&wparam($enc_off));	# Get enc flag
+	if ($p3 > 0)
+		{
+		&comment("get and push parameter $p3");
+		if ($enc_off != $p3)
+			{ &mov("eax",	&wparam($p3)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p2 > 0)
+		{
+		&comment("get and push parameter $p2");
+		if ($enc_off != $p2)
+			{ &mov("eax",	&wparam($p2)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p1 > 0)
+		{
+		&comment("get and push parameter $p1");
+		if ($enc_off != $p1)
+			{ &mov("eax",	&wparam($p1)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	&push("ebx");		# push data/iv
+
+	&cmp("ecx",0);
+	&jz(&label("decrypt"));
+
+	&and($count,0xfffffff8);
+	&mov("eax",	&DWP($data_off,"esp","",0));	# load iv[0]
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	# load iv[1]
+
+	&jz(&label("encrypt_finish"));
+
+	#############################################################
+
+	&set_label("encrypt_loop");
+	# encrypt start 
+	# "eax" and "ebx" hold iv (or the last cipher text)
+
+	&mov("ecx",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("edx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	# eax and ebx are the next iv.
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("encrypt_loop"));
+
+###################################################################3
+	&set_label("encrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+	&xor("ecx","ecx");
+	&xor("edx","edx");
+	&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
+	&jmp_ptr($count);
+
+&set_label("ej7");
+	&xor("edx",		"edx") if $ppro; # ppro friendly
+	&movb(&HB("edx"),	&BP(6,$in,"",0));
+	&shl("edx",8);
+&set_label("ej6");
+	&movb(&HB("edx"),	&BP(5,$in,"",0));
+&set_label("ej5");
+	&movb(&LB("edx"),	&BP(4,$in,"",0));
+&set_label("ej4");
+	&mov("ecx",		&DWP(0,$in,"",0));
+	&jmp(&label("ejend"));
+&set_label("ej3");
+	&movb(&HB("ecx"),	&BP(2,$in,"",0));
+	&xor("ecx",		"ecx") if $ppro; # ppro friendly
+	&shl("ecx",8);
+&set_label("ej2");
+	&movb(&HB("ecx"),	&BP(1,$in,"",0));
+&set_label("ej1");
+	&movb(&LB("ecx"),	&BP(0,$in,"",0));
+&set_label("ejend");
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	&jmp(&label("finish"));
+
+	#############################################################
+	#############################################################
+	&set_label("decrypt",1);
+	# decrypt start 
+	&and($count,0xfffffff8);
+	# The next 2 instructions are only for if the jz is taken
+	&mov("eax",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("ebx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+	&jz(&label("decrypt_finish"));
+
+	&set_label("decrypt_loop");
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+	&mov(&DWP(0,$out,"",0),"ecx");
+	&mov(&DWP(4,$out,"",0),"edx");
+
+	&mov(&DWP($data_off+8,"esp","",0),	"eax");	# save iv
+	&mov(&DWP($data_off+12,"esp","",0),	"ebx");	#
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("decrypt_loop"));
+############################ ENDIT #######################3
+	&set_label("decrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	# this is for when we exit
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+&set_label("dj7");
+	&rotr("edx",	16);
+	&movb(&BP(6,$out,"",0),	&LB("edx"));
+	&shr("edx",16);
+&set_label("dj6");
+	&movb(&BP(5,$out,"",0),	&HB("edx"));
+&set_label("dj5");
+	&movb(&BP(4,$out,"",0),	&LB("edx"));
+&set_label("dj4");
+	&mov(&DWP(0,$out,"",0),	"ecx");
+	&jmp(&label("djend"));
+&set_label("dj3");
+	&rotr("ecx",	16);
+	&movb(&BP(2,$out,"",0),	&LB("ecx"));
+	&shl("ecx",16);
+&set_label("dj2");
+	&movb(&BP(1,$in,"",0),	&HB("ecx"));
+&set_label("dj1");
+	&movb(&BP(0,$in,"",0),	&LB("ecx"));
+&set_label("djend");
+
+	# final iv is still in eax:ebx
+	&jmp(&label("finish"));
+
+
+############################ FINISH #######################3
+	&set_label("finish",1);
+	&mov("ecx",	&wparam($iv_off));	# Get iv ptr
+
+	#################################################
+	$total=16+4;
+	$total+=4 if ($p1 > 0);
+	$total+=4 if ($p2 > 0);
+	$total+=4 if ($p3 > 0);
+	&add("esp",$total);
+
+	&mov(&DWP(0,"ecx","",0),	"eax");	# save iv
+	&mov(&DWP(4,"ecx","",0),	"ebx");	# save iv
+
+	&function_end_A($name);
+
+	&set_label("cbc_enc_jmp_table",1);
+	&data_word("0");
+	&data_word(&label("ej1"));
+	&data_word(&label("ej2"));
+	&data_word(&label("ej3"));
+	&data_word(&label("ej4"));
+	&data_word(&label("ej5"));
+	&data_word(&label("ej6"));
+	&data_word(&label("ej7"));
+	&set_label("cbc_dec_jmp_table",1);
+	&data_word("0");
+	&data_word(&label("dj1"));
+	&data_word(&label("dj2"));
+	&data_word(&label("dj3"));
+	&data_word(&label("dj4"));
+	&data_word(&label("dj5"));
+	&data_word(&label("dj6"));
+	&data_word(&label("dj7"));
+
+	&function_end_B($name);
+	
+	}
+
+1;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/perlasm/readme linux-patched/net/ipsec/libdes/asm/perlasm/readme
--- linux/net/ipsec/libdes/asm/perlasm/readme	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/perlasm/readme	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,124 @@
+The perl scripts in this directory are my 'hack' to generate
+multiple different assembler formats via the one origional script.
+
+The way to use this library is to start with adding the path to this directory
+and then include it.
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+The first thing we do is setup the file and type of assember
+
+&asm_init($ARGV[0],$0);
+
+The first argument is the 'type'.  Currently
+'cpp', 'sol', 'a.out', 'elf' or 'win32'.
+Argument 2 is the file name.
+
+The reciprocal function is
+&asm_finish() which should be called at the end.
+
+There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
+and x86unix.pl which is the unix (gas) version.
+
+Functions of interest are:
+&external_label("des_SPtrans");	declare and external variable
+&LB(reg);			Low byte for a register
+&HB(reg);			High byte for a register
+&BP(off,base,index,scale)	Byte pointer addressing
+&DWP(off,base,index,scale)	Word pointer addressing
+&stack_push(num)		Basically a 'sub esp, num*4' with extra
+&stack_pop(num)			inverse of stack_push
+&function_begin(name,extra)	Start a function with pushing of
+				edi, esi, ebx and ebp.  extra is extra win32
+				external info that may be required.
+&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
+&function_end(name)		Call at end of function.
+&function_end_A(name)		Standard pop and ret, for use inside functions
+&function_end_B(name)		Call at end but with poping or 'ret'.
+&swtmp(num)			Address on stack temp word.
+&wparam(num)			Parameter number num, that was push
+				in C convention.  This all works over pushes
+				and pops.
+&comment("hello there")		Put in a comment.
+&label("loop")			Refer to a label, normally a jmp target.
+&set_label("loop")		Set a label at this point.
+&data_word(word)		Put in a word of data.
+
+So how does this all hold together?  Given
+
+int calc(int len, int *data)
+	{
+	int i,j=0;
+
+	for (i=0; i<len; i++)
+		{
+		j+=other(data[i]);
+		}
+	}
+
+So a very simple version of this function could be coded as
+
+	push(@INC,"perlasm","../../perlasm");
+	require "x86asm.pl";
+	
+	&asm_init($ARGV[0],"cacl.pl");
+
+	&external_label("other");
+
+	$tmp1=	"eax";
+	$j=	"edi";
+	$data=	"esi";
+	$i=	"ebp";
+
+	&comment("a simple function");
+	&function_begin("calc");
+	&mov(	$data,		&wparam(1)); # data
+	&xor(	$j,		$j);
+	&xor(	$i,		$i);
+
+	&set_label("loop");
+	&cmp(	$i,		&wparam(0));
+	&jge(	&label("end"));
+
+	&mov(	$tmp1,		&DWP(0,$data,$i,4));
+	&push(	$tmp1);
+	&call(	"other");
+	&add(	$j,		"eax");
+	&pop(	$tmp1);
+	&inc(	$i);
+	&jmp(	&label("loop"));
+
+	&set_label("end");
+	&mov(	"eax",		$j);
+
+	&function_end("calc");
+
+	&asm_finish();
+
+The above example is very very unoptimised but gives an idea of how
+things work.
+
+There is also a cbc mode function generator in cbc.pl
+
+&cbc(	$name,
+	$encrypt_function_name,
+	$decrypt_function_name,
+	$true_if_byte_swap_needed,
+	$parameter_number_for_iv,
+	$parameter_number_for_encrypt_flag,
+	$first_parameter_to_pass,
+	$second_parameter_to_pass,
+	$third_parameter_to_pass);
+
+So for example, given
+void BF_encrypt(BF_LONG *data,BF_KEY *key);
+void BF_decrypt(BF_LONG *data,BF_KEY *key);
+void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
+        BF_KEY *ks, unsigned char *iv, int enc);
+
+&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
+
+&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
+&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/perlasm/x86asm.pl linux-patched/net/ipsec/libdes/asm/perlasm/x86asm.pl
--- linux/net/ipsec/libdes/asm/perlasm/x86asm.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/perlasm/x86asm.pl	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,111 @@
+#!/usr/local/bin/perl
+
+# require 'x86asm.pl';
+# &asm_init("cpp","des-586.pl");
+# XXX
+# XXX
+# main'asm_finish
+
+sub main'asm_finish
+	{
+	&file_end();
+	&asm_finish_cpp() if $cpp;
+	print &asm_get_output();
+	}
+
+sub main'asm_init
+	{
+	($type,$fn)=@_;
+	$filename=$fn;
+
+	$cpp=$sol=$aout=$win32=0;
+	if (	($type eq "elf"))
+		{ require "x86unix.pl"; }
+	elsif (	($type eq "a.out"))
+		{ $aout=1; require "x86unix.pl"; }
+	elsif (	($type eq "sol"))
+		{ $sol=1; require "x86unix.pl"; }
+	elsif (	($type eq "cpp"))
+		{ $cpp=1; require "x86unix.pl"; }
+	elsif (	($type eq "win32"))
+		{ $win32=1; require "x86ms.pl"; }
+	else
+		{
+		print STDERR <<"EOF";
+Pick one target type from
+	elf	- linux, FreeBSD etc
+	a.out	- old linux
+	sol	- x86 solaris
+	cpp	- format so x86unix.cpp can be used
+	win32	- Windows 95/Windows NT
+EOF
+		exit(1);
+		}
+
+	&asm_init_output();
+
+&comment("Don't even think of reading this code");
+&comment("It was automatically generated by $filename");
+&comment("Which is a perl program used to generate the x86 assember for");
+&comment("any of elf, a.out, BSDI,Win32, or Solaris");
+&comment("eric <eay\@cryptsoft.com>");
+&comment("");
+
+	$filename =~ s/\.pl$//;
+	&file($filename);
+	}
+
+sub asm_finish_cpp
+	{
+	return unless $cpp;
+
+	local($tmp,$i);
+	foreach $i (&get_labels())
+		{
+		$tmp.="#define $i _$i\n";
+		}
+	print <<"EOF";
+/* Run the C pre-processor over this file with one of the following defined
+ * ELF - elf object files,
+ * OUT - a.out object files,
+ * BSDI - BSDI style a.out object files
+ * SOL - Solaris style elf
+ */
+
+#define TYPE(a,b)       .type   a,b
+#define SIZE(a,b)       .size   a,b
+
+#if defined(OUT) || defined(BSDI)
+$tmp
+#endif
+
+#ifdef OUT
+#define OK	1
+#define ALIGN	4
+#endif
+
+#ifdef BSDI
+#define OK              1
+#define ALIGN           4
+#undef SIZE
+#undef TYPE
+#endif
+
+#if defined(ELF) || defined(SOL)
+#define OK              1
+#define ALIGN           16
+#endif
+
+#ifndef OK
+You need to define one of
+ELF - elf systems - linux-elf, NetBSD and DG-UX
+OUT - a.out systems - linux-a.out and FreeBSD
+SOL - solaris systems, which are elf with strange comment lines
+BSDI - a.out with a very primative version of as.
+#endif
+
+/* Let the Assembler begin :-) */
+EOF
+	}
+
+1;
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/perlasm/x86ms.pl linux-patched/net/ipsec/libdes/asm/perlasm/x86ms.pl
--- linux/net/ipsec/libdes/asm/perlasm/x86ms.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/perlasm/x86ms.pl	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,345 @@
+#!/usr/local/bin/perl
+
+package x86ms;
+
+$label="L000";
+
+%lb=(	'eax',	'al',
+	'ebx',	'bl',
+	'ecx',	'cl',
+	'edx',	'dl',
+	'ax',	'al',
+	'bx',	'bl',
+	'cx',	'cl',
+	'dx',	'dl',
+	);
+
+%hb=(	'eax',	'ah',
+	'ebx',	'bh',
+	'ecx',	'ch',
+	'edx',	'dh',
+	'ax',	'ah',
+	'bx',	'bh',
+	'cx',	'ch',
+	'dx',	'dh',
+	);
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels,@_); }
+
+sub main'LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main'HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main'BP
+	{
+	&get_mem("BYTE",@_);
+	}
+
+sub main'DWP
+	{
+	&get_mem("DWORD",@_);
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*4;
+	&main'sub("esp",$num*4);
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*4;
+	&main'add("esp",$num*4);
+	}
+
+sub get_mem
+	{
+	local($size,$addr,$reg1,$reg2,$idx)=@_;
+	local($t,$post);
+	local($ret)="$size PTR ";
+
+	$addr =~ s/^\s+//;
+	if ($addr =~ /^(.+)\+(.+)$/)
+		{
+		$reg2=&conv($1);
+		$addr="_$2";
+		}
+	elsif ($addr =~ /^[_a-zA-Z]/)
+		{
+		$addr="_$addr";
+		}
+
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	if (($addr ne "") && ($addr ne 0))
+		{
+		if ($addr !~ /^-/)
+			{ $ret.=$addr; }
+		else	{ $post=$addr; }
+		}
+	if ($reg2 ne "")
+		{
+		$t="";
+		$t="*$idx" if ($idx != 0);
+		$reg1="+".$reg1 if ("$reg1$post" ne "");
+		$ret.="[$reg2$t$reg1$post]";
+		}
+	else
+		{
+		$ret.="[$reg1$post]"
+		}
+	return($ret);
+	}
+
+sub main'mov	{ &out2("mov",@_); }
+sub main'movb	{ &out2("mov",@_); }
+sub main'and	{ &out2("and",@_); }
+sub main'or	{ &out2("or",@_); }
+sub main'shl	{ &out2("shl",@_); }
+sub main'shr	{ &out2("shr",@_); }
+sub main'xor	{ &out2("xor",@_); }
+sub main'xorb	{ &out2("xor",@_); }
+sub main'add	{ &out2("add",@_); }
+sub main'adc	{ &out2("adc",@_); }
+sub main'sub	{ &out2("sub",@_); }
+sub main'rotl	{ &out2("rol",@_); }
+sub main'rotr	{ &out2("ror",@_); }
+sub main'exch	{ &out2("xchg",@_); }
+sub main'cmp	{ &out2("cmp",@_); }
+sub main'lea	{ &out2("lea",@_); }
+sub main'mul	{ &out1("mul",@_); }
+sub main'div	{ &out1("div",@_); }
+sub main'dec	{ &out1("dec",@_); }
+sub main'inc	{ &out1("inc",@_); }
+sub main'jmp	{ &out1("jmp",@_); }
+sub main'jmp_ptr { &out1p("jmp",@_); }
+sub main'je	{ &out1("je",@_); }
+sub main'jle	{ &out1("jle",@_); }
+sub main'jz	{ &out1("jz",@_); }
+sub main'jge	{ &out1("jge",@_); }
+sub main'jl	{ &out1("jl",@_); }
+sub main'jb	{ &out1("jb",@_); }
+sub main'jnz	{ &out1("jnz",@_); }
+sub main'jne	{ &out1("jne",@_); }
+sub main'push	{ &out1("push",@_); $stack+=4; }
+sub main'pop	{ &out1("pop",@_); $stack-=4; }
+sub main'bswap	{ &out1("bswap",@_); &using486(); }
+sub main'not	{ &out1("not",@_); }
+sub main'call	{ &out1("call",'_'.$_[0]); }
+sub main'ret	{ &out0("ret"); }
+sub main'nop	{ &out0("nop"); }
+
+sub out2
+	{
+	local($name,$p1,$p2)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t");
+	$t=&conv($p1).",";
+	$l=length($t);
+	push(@out,$t);
+	$l=4-($l+9)/8;
+	push(@out,"\t" x $l);
+	push(@out,&conv($p2));
+	push(@out,"\n");
+	}
+
+sub out0
+	{
+	local($name)=@_;
+
+	push(@out,"\t$name\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub conv
+	{
+	local($p)=@_;
+
+	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+	return $p;
+	}
+
+sub using486
+	{
+	return if $using486;
+	$using486++;
+	grep(s/\.386/\.486/,@out);
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+	TITLE	$file.asm
+        .386
+.model FLAT
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func,$extra)=@_;
+
+	push(@labels,$func);
+
+	local($tmp)=<<"EOF";
+_TEXT	SEGMENT
+PUBLIC	_$func
+$extra
+_$func PROC NEAR
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main'function_begin_B
+	{
+	local($func,$extra)=@_;
+
+	local($tmp)=<<"EOF";
+_TEXT	SEGMENT
+PUBLIC	_$func
+$extra
+_$func PROC NEAR
+EOF
+	push(@out,$tmp);
+	$stack=4;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+_$func ENDP
+_TEXT	ENDS
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+_$func ENDP
+_TEXT	ENDS
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'file_end
+	{
+	push(@out,"END\n");
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	return(&main'DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main'swtmp
+	{
+	return(&main'DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'DWP(-(($num+1)*4),"esp","",0));
+#	}
+
+sub main'comment
+	{
+	foreach (@_)
+		{
+		push(@out,"\t; $_\n");
+		}
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="\$${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="${label}${_[0]}";
+		$label++;
+		}
+	push(@out,"$label{$_[0]}:\n");
+	}
+
+sub main'data_word
+	{
+	push(@out,"\tDD\t$_[0]\n");
+	}
+
+sub out1p
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t ".&conv($p1)."\n");
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/asm/perlasm/x86unix.pl linux-patched/net/ipsec/libdes/asm/perlasm/x86unix.pl
--- linux/net/ipsec/libdes/asm/perlasm/x86unix.pl	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/asm/perlasm/x86unix.pl	Wed Oct 16 01:43:20 2002
@@ -0,0 +1,402 @@
+#!/usr/local/bin/perl
+
+package x86unix;
+
+$label="L000";
+
+$align=($main'aout)?"4":"16";
+$under=($main'aout)?"_":"";
+$com_start=($main'sol)?"/":"#";
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels,@_); }
+
+if ($main'cpp)
+	{
+	$align="ALIGN";
+	$under="";
+	$com_start='/*';
+	$com_end='*/';
+	}
+
+%lb=(	'eax',	'%al',
+	'ebx',	'%bl',
+	'ecx',	'%cl',
+	'edx',	'%dl',
+	'ax',	'%al',
+	'bx',	'%bl',
+	'cx',	'%cl',
+	'dx',	'%dl',
+	);
+
+%hb=(	'eax',	'%ah',
+	'ebx',	'%bh',
+	'ecx',	'%ch',
+	'edx',	'%dh',
+	'ax',	'%ah',
+	'bx',	'%bh',
+	'cx',	'%ch',
+	'dx',	'%dh',
+	);
+
+%regs=(	'eax',	'%eax',
+	'ebx',	'%ebx',
+	'ecx',	'%ecx',
+	'edx',	'%edx',
+	'esi',	'%esi',
+	'edi',	'%edi',
+	'ebp',	'%ebp',
+	'esp',	'%esp',
+	);
+
+%reg_val=(
+	'eax',	0x00,
+	'ebx',	0x03,
+	'ecx',	0x01,
+	'edx',	0x02,
+	'esi',	0x06,
+	'edi',	0x07,
+	'ebp',	0x05,
+	'esp',	0x04,
+	);
+
+sub main'LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main'HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main'DWP
+	{
+	local($addr,$reg1,$reg2,$idx)=@_;
+
+	$ret="";
+	$addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+	if ($reg2 ne "")
+		{ $ret.="($reg1,$reg2,$idx)"; }
+	else
+		{ $ret.="($reg1)" }
+	return($ret);
+	}
+
+sub main'BP
+	{
+	return(&main'DWP(@_));
+	}
+
+#sub main'BP
+#	{
+#	local($addr,$reg1,$reg2,$idx)=@_;
+#
+#	$ret="";
+#
+#	$addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
+#	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+#	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+#	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+#	if ($reg2 ne "")
+#		{ $ret.="($reg1,$reg2,$idx)"; }
+#	else
+#		{ $ret.="($reg1)" }
+#	return($ret);
+#	}
+
+sub main'mov	{ &out2("movl",@_); }
+sub main'movb	{ &out2("movb",@_); }
+sub main'and	{ &out2("andl",@_); }
+sub main'or	{ &out2("orl",@_); }
+sub main'shl	{ &out2("sall",@_); }
+sub main'shr	{ &out2("shrl",@_); }
+sub main'xor	{ &out2("xorl",@_); }
+sub main'xorb	{ &out2("xorb",@_); }
+sub main'add	{ &out2("addl",@_); }
+sub main'adc	{ &out2("adcl",@_); }
+sub main'sub	{ &out2("subl",@_); }
+sub main'rotl	{ &out2("roll",@_); }
+sub main'rotr	{ &out2("rorl",@_); }
+sub main'exch	{ &out2("xchg",@_); }
+sub main'cmp	{ &out2("cmpl",@_); }
+sub main'lea	{ &out2("leal",@_); }
+sub main'mul	{ &out1("mull",@_); }
+sub main'div	{ &out1("divl",@_); }
+sub main'jmp	{ &out1("jmp",@_); }
+sub main'jmp_ptr { &out1p("jmp",@_); }
+sub main'je	{ &out1("je",@_); }
+sub main'jle	{ &out1("jle",@_); }
+sub main'jne	{ &out1("jne",@_); }
+sub main'jnz	{ &out1("jnz",@_); }
+sub main'jz	{ &out1("jz",@_); }
+sub main'jge	{ &out1("jge",@_); }
+sub main'jl	{ &out1("jl",@_); }
+sub main'jb	{ &out1("jb",@_); }
+sub main'dec	{ &out1("decl",@_); }
+sub main'inc	{ &out1("incl",@_); }
+sub main'push	{ &out1("pushl",@_); $stack+=4; }
+sub main'pop	{ &out1("popl",@_); $stack-=4; }
+sub main'bswap	{ &out1("bswapl",@_); }
+sub main'not	{ &out1("notl",@_); }
+sub main'call	{ &out1("call",$under.$_[0]); }
+sub main'ret	{ &out0("ret"); }
+sub main'nop	{ &out0("nop"); }
+
+sub out2
+	{
+	local($name,$p1,$p2)=@_;
+	local($l,$ll,$t);
+	local(%special)=(	"roll",0xD1C0,"rorl",0xD1C8,
+				"rcll",0xD1D0,"rcrl",0xD1D8,
+				"shll",0xD1E0,"shrl",0xD1E8,
+				"sarl",0xD1F8);
+	
+	if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
+		{
+		$op=$special{$name}|$reg_val{$p1};
+		$tmp1=sprintf ".byte %d\n",($op>>8)&0xff;
+		$tmp2=sprintf ".byte %d\t",$op     &0xff;
+		push(@out,$tmp1);
+		push(@out,$tmp2);
+
+		$p2=&conv($p2);
+		$p1=&conv($p1);
+		&main'comment("$name $p2 $p1");
+		return;
+		}
+
+	push(@out,"\t$name\t");
+	$t=&conv($p2).",";
+	$l=length($t);
+	push(@out,$t);
+	$ll=4-($l+9)/8;
+	$tmp1=sprintf "\t" x $ll;
+	push(@out,$tmp1);
+	push(@out,&conv($p1)."\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub out1p
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t*".&conv($p1)."\n");
+	}
+
+sub out0
+	{
+	push(@out,"\t$_[0]\n");
+	}
+
+sub conv
+	{
+	local($p)=@_;
+
+#	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+
+	$p=$regs{$p} if (defined($regs{$p}));
+
+	$p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
+	$p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
+	return $p;
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+	.file	"$file.s"
+	.version	"01.01"
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+	.align $align
+.globl $func
+EOF
+	push(@out,$tmp);
+	if ($main'cpp)
+		{ $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
+	else	{ $tmp=push(@out,"\t.type\t$func,\@function\n"); }
+	push(@out,"$func:\n");
+	$tmp=<<"EOF";
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main'function_begin_B
+	{
+	local($func,$extra)=@_;
+
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+	.align $align
+.globl $func
+EOF
+	push(@out,$tmp);
+	if ($main'cpp)
+		{ push(@out,"\tTYPE($func,\@function)\n"); }
+	else	{ push(@out,"\t.type	$func,\@function\n"); }
+	push(@out,"$func:\n");
+	$stack=4;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.${func}_end:
+EOF
+	push(@out,$tmp);
+	if ($main'cpp)
+		{ push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
+	else	{ push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
+	push(@out,".ident	\"$func\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	push(@out,".${func}_end:\n");
+	if ($main'cpp)
+		{ push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
+	else	{ push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
+	push(@out,".ident	\"desasm.pl\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	return(&main'DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*4;
+	&main'sub("esp",$num*4);
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*4;
+	&main'add("esp",$num*4);
+	}
+
+sub main'swtmp
+	{
+	return(&main'DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'DWP(-($num+1)*4,"esp","",0));
+#	}
+
+sub main'comment
+	{
+	foreach (@_)
+		{
+		if (/^\s*$/)
+			{ push(@out,"\n"); }
+		else
+			{ push(@out,"\t$com_start $_ $com_end\n"); }
+		}
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=".${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=".${label}${_[0]}";
+		$label++;
+		}
+	push(@out,".align $align\n") if ($_[1] != 0);
+	push(@out,"$label{$_[0]}:\n");
+	}
+
+sub main'file_end
+	{
+	}
+
+sub main'data_word
+	{
+	push(@out,"\t.long $_[0]\n");
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/cbc_enc.c linux-patched/net/ipsec/libdes/cbc_enc.c
--- linux/net/ipsec/libdes/cbc_enc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/cbc_enc.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,135 @@
+/* crypto/des/cbc_enc.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_locl.h"
+
+void des_cbc_encrypt(input, output, length, schedule, ivec, enc)
+des_cblock (*input);
+des_cblock (*output);
+long length;
+des_key_schedule schedule;
+des_cblock (*ivec);
+int enc;
+	{
+	register DES_LONG tin0,tin1;
+	register DES_LONG tout0,tout1,xor0,xor1;
+	register unsigned char *in,*out;
+	register long l=length;
+	DES_LONG tin[2];
+	unsigned char *iv;
+
+	in=(unsigned char *)input;
+	out=(unsigned char *)output;
+	iv=(unsigned char *)ivec;
+
+	if (enc)
+		{
+		c2l(iv,tout0);
+		c2l(iv,tout1);
+		for (l-=8; l>=0; l-=8)
+			{
+			c2l(in,tin0);
+			c2l(in,tin1);
+			tin0^=tout0; tin[0]=tin0;
+			tin1^=tout1; tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+			tout0=tin[0]; l2c(tout0,out);
+			tout1=tin[1]; l2c(tout1,out);
+			}
+		if (l != -8)
+			{
+			c2ln(in,tin0,tin1,l+8);
+			tin0^=tout0; tin[0]=tin0;
+			tin1^=tout1; tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+			tout0=tin[0]; l2c(tout0,out);
+			tout1=tin[1]; l2c(tout1,out);
+			}
+		}
+	else
+		{
+		c2l(iv,xor0);
+		c2l(iv,xor1);
+		for (l-=8; l>=0; l-=8)
+			{
+			c2l(in,tin0); tin[0]=tin0;
+			c2l(in,tin1); tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2c(tout0,out);
+			l2c(tout1,out);
+			xor0=tin0;
+			xor1=tin1;
+			}
+		if (l != -8)
+			{
+			c2l(in,tin0); tin[0]=tin0;
+			c2l(in,tin1); tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2cn(tout0,tout1,out,l+8);
+		/*	xor0=tin0;
+			xor1=tin1; */
+			}
+		}
+	tin0=tin1=tout0=tout1=xor0=xor1=0;
+	tin[0]=tin[1]=0;
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/des.h linux-patched/net/ipsec/libdes/des.h
--- linux/net/ipsec/libdes/des.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/des.h	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,305 @@
+/* crypto/des/des.org */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 
+ *
+ * Always modify des.org since des.h is automatically generated from
+ * it during SSLeay configuration.
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
+#ifndef HEADER_DES_H
+#define HEADER_DES_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+#ifndef DES_LONG
+/* RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $ */
+/* This conditional for FreeS/WAN project. */
+#ifdef __alpha
+#define DES_LONG unsigned int
+#else
+#define DES_LONG unsigned long
+#endif
+#endif
+
+typedef unsigned char des_cblock[8];
+typedef struct des_ks_struct
+	{
+	union	{
+		des_cblock _;
+		/* make sure things are correct size on machines with
+		 * 8 byte longs */
+		DES_LONG pad[2];
+		} ks;
+#undef _
+#define _	ks._
+	} des_key_schedule[16];
+
+#define DES_KEY_SZ 	(sizeof(des_cblock))
+#define DES_SCHEDULE_SZ (sizeof(des_key_schedule))
+
+#define DES_ENCRYPT	1
+#define DES_DECRYPT	0
+
+#define DES_CBC_MODE	0
+#define DES_PCBC_MODE	1
+
+#define des_ecb2_encrypt(i,o,k1,k2,e) \
+	des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+	des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+	des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+	des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#define C_Block des_cblock
+#define Key_schedule des_key_schedule
+#ifdef KERBEROS
+#define ENCRYPT DES_ENCRYPT
+#define DECRYPT DES_DECRYPT
+#endif
+#define KEY_SZ DES_KEY_SZ
+#define string_to_key des_string_to_key
+#define read_pw_string des_read_pw_string
+#define random_key des_random_key
+#define pcbc_encrypt des_pcbc_encrypt
+#define set_key des_set_key
+#define key_sched des_key_sched
+#define ecb_encrypt des_ecb_encrypt
+#define cbc_encrypt des_cbc_encrypt
+#define ncbc_encrypt des_ncbc_encrypt
+#define xcbc_encrypt des_xcbc_encrypt
+#define cbc_cksum des_cbc_cksum
+#define quad_cksum des_quad_cksum
+
+/* For compatibility with the MIT lib - eay 20/05/92 */
+typedef des_key_schedule bit_64;
+#define des_fixup_key_parity des_set_odd_parity
+#define des_check_key_parity check_parity
+
+extern int des_check_key;	/* defaults to false */
+extern int des_rw_mode;		/* defaults to DES_PCBC_MODE */
+
+/* The next line is used to disable full ANSI prototypes, if your
+ * compiler has problems with the prototypes, make sure this line always
+ * evaluates to true :-) */
+#if defined(MSDOS) || defined(__STDC__)
+#undef NOPROTO
+#endif
+#ifndef NOPROTO
+char *des_options(void);
+void des_ecb3_encrypt(des_cblock *input,des_cblock *output,
+	des_key_schedule ks1,des_key_schedule ks2,
+	des_key_schedule ks3, int enc);
+DES_LONG des_cbc_cksum(des_cblock *input,des_cblock *output,
+	long length,des_key_schedule schedule,des_cblock *ivec);
+void des_cbc_encrypt(des_cblock *input,des_cblock *output,long length,
+	des_key_schedule schedule,des_cblock *ivec,int enc);
+void des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length,
+	des_key_schedule schedule,des_cblock *ivec,int enc);
+void des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length,
+	des_key_schedule schedule,des_cblock *ivec,
+	des_cblock *inw,des_cblock *outw,int enc);
+void des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits,
+	long length,des_key_schedule schedule,des_cblock *ivec,int enc);
+void des_ecb_encrypt(des_cblock *input,des_cblock *output,
+	des_key_schedule ks,int enc);
+void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc);
+void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc);
+void des_encrypt3(DES_LONG *data, des_key_schedule ks1,
+	des_key_schedule ks2, des_key_schedule ks3);
+void des_decrypt3(DES_LONG *data, des_key_schedule ks1,
+	des_key_schedule ks2, des_key_schedule ks3);
+void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, 
+	long length, des_key_schedule ks1, des_key_schedule ks2, 
+	des_key_schedule ks3, des_cblock *ivec, int enc);
+void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out,
+	long length, des_key_schedule ks1, des_key_schedule ks2,
+	des_key_schedule ks3, des_cblock *ivec, int *num, int enc);
+void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out,
+	long length, des_key_schedule ks1, des_key_schedule ks2,
+	des_key_schedule ks3, des_cblock *ivec, int *num);
+
+void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white),
+	des_cblock (*out_white));
+
+int des_enc_read(int fd,char *buf,int len,des_key_schedule sched,
+	des_cblock *iv);
+int des_enc_write(int fd,char *buf,int len,des_key_schedule sched,
+	des_cblock *iv);
+char *des_fcrypt(const char *buf,const char *salt, char *ret);
+#ifdef PERL5
+char *des_crypt(const char *buf,const char *salt);
+#else
+/* some stupid compilers complain because I have declared char instead
+ * of const char */
+#ifndef __KERNEL__
+#ifdef HEADER_DES_LOCL_H
+char *crypt(const char *buf,const char *salt);
+#else /* HEADER_DES_LOCL_H */
+char *crypt(void);
+#endif /* HEADER_DES_LOCL_H */
+#endif /* __KERNEL__ */
+#endif /* PERL5 */
+void des_ofb_encrypt(unsigned char *in,unsigned char *out,
+	int numbits,long length,des_key_schedule schedule,des_cblock *ivec);
+void des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length,
+	des_key_schedule schedule,des_cblock *ivec,int enc);
+DES_LONG des_quad_cksum(des_cblock *input,des_cblock *output,
+	long length,int out_count,des_cblock *seed);
+void des_random_seed(des_cblock key);
+void des_random_key(des_cblock ret);
+int des_read_password(des_cblock *key,char *prompt,int verify);
+int des_read_2passwords(des_cblock *key1,des_cblock *key2,
+	char *prompt,int verify);
+int des_read_pw_string(char *buf,int length,char *prompt,int verify);
+void des_set_odd_parity(des_cblock *key);
+int des_is_weak_key(des_cblock *key);
+int des_set_key(des_cblock *key,des_key_schedule schedule);
+int des_key_sched(des_cblock *key,des_key_schedule schedule);
+void des_string_to_key(char *str,des_cblock *key);
+void des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2);
+void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length,
+	des_key_schedule schedule, des_cblock *ivec, int *num, int enc);
+void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length,
+	des_key_schedule schedule, des_cblock *ivec, int *num);
+int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify);
+
+/* Extra functions from Mark Murray <mark@grondar.za> */
+/* The following functions are not in the normal unix build or the
+ * SSLeay build.  When using the SSLeay build, use RAND_seed()
+ * and RAND_bytes() instead. */
+int des_new_random_key(des_cblock *key);
+void des_init_random_number_generator(des_cblock *key);
+void des_set_random_generator_seed(des_cblock *key);
+void des_set_sequence_number(des_cblock new_sequence_number);
+void des_generate_random_block(des_cblock *block);
+
+#else
+
+char *des_options();
+void des_ecb3_encrypt();
+DES_LONG des_cbc_cksum();
+void des_cbc_encrypt();
+void des_ncbc_encrypt();
+void des_xcbc_encrypt();
+void des_cfb_encrypt();
+void des_ede3_cfb64_encrypt();
+void des_ede3_ofb64_encrypt();
+void des_ecb_encrypt();
+void des_encrypt();
+void des_encrypt2();
+void des_encrypt3();
+void des_decrypt3();
+void des_ede3_cbc_encrypt();
+int des_enc_read();
+int des_enc_write();
+char *des_fcrypt();
+#ifdef PERL5
+char *des_crypt();
+#else
+char *crypt();
+#endif
+void des_ofb_encrypt();
+void des_pcbc_encrypt();
+DES_LONG des_quad_cksum();
+void des_random_seed();
+void des_random_key();
+int des_read_password();
+int des_read_2passwords();
+int des_read_pw_string();
+void des_set_odd_parity();
+int des_is_weak_key();
+int des_set_key();
+int des_key_sched();
+void des_string_to_key();
+void des_string_to_2keys();
+void des_cfb64_encrypt();
+void des_ofb64_encrypt();
+int des_read_pw();
+void des_xwhite_in2out();
+
+/* Extra functions from Mark Murray <mark@grondar.za> */
+/* The following functions are not in the normal unix build or the
+ * SSLeay build.  When using the SSLeay build, use RAND_seed()
+ * and RAND_bytes() instead. */
+#ifdef FreeBSD
+int des_new_random_key();
+void des_init_random_number_generator();
+void des_set_random_generator_seed();
+void des_set_sequence_number();
+void des_generate_random_block();
+#endif
+
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/des_enc.c linux-patched/net/ipsec/libdes/des_enc.c
--- linux/net/ipsec/libdes/des_enc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/des_enc.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,502 @@
+/* crypto/des/des_enc.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_locl.h"
+
+void des_encrypt(data, ks, enc)
+DES_LONG *data;
+des_key_schedule ks;
+int enc;
+	{
+	register DES_LONG l,r,t,u;
+#ifdef DES_PTR
+	register unsigned char *des_SP=(unsigned char *)des_SPtrans;
+#endif
+#ifndef DES_UNROLL
+	register int i;
+#endif
+	register DES_LONG *s;
+
+	r=data[0];
+	l=data[1];
+
+	IP(r,l);
+	/* Things have been modified so that the initial rotate is
+	 * done outside the loop.  This required the
+	 * des_SPtrans values in sp.h to be rotated 1 bit to the right.
+	 * One perl script later and things have a 5% speed up on a sparc2.
+	 * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
+	 * for pointing this out. */
+	/* clear the top bits on machines with 8byte longs */
+	/* shift left by 2 */
+	r=ROTATE(r,29)&0xffffffffL;
+	l=ROTATE(l,29)&0xffffffffL;
+
+	s=(DES_LONG *)ks;
+	/* I don't know if it is worth the effort of loop unrolling the
+	 * inner loop */
+	if (enc)
+		{
+#ifdef DES_UNROLL
+		D_ENCRYPT(l,r, 0); /*  1 */
+		D_ENCRYPT(r,l, 2); /*  2 */
+		D_ENCRYPT(l,r, 4); /*  3 */
+		D_ENCRYPT(r,l, 6); /*  4 */
+		D_ENCRYPT(l,r, 8); /*  5 */
+		D_ENCRYPT(r,l,10); /*  6 */
+		D_ENCRYPT(l,r,12); /*  7 */
+		D_ENCRYPT(r,l,14); /*  8 */
+		D_ENCRYPT(l,r,16); /*  9 */
+		D_ENCRYPT(r,l,18); /*  10 */
+		D_ENCRYPT(l,r,20); /*  11 */
+		D_ENCRYPT(r,l,22); /*  12 */
+		D_ENCRYPT(l,r,24); /*  13 */
+		D_ENCRYPT(r,l,26); /*  14 */
+		D_ENCRYPT(l,r,28); /*  15 */
+		D_ENCRYPT(r,l,30); /*  16 */
+#else
+		for (i=0; i<32; i+=8)
+			{
+			D_ENCRYPT(l,r,i+0); /*  1 */
+			D_ENCRYPT(r,l,i+2); /*  2 */
+			D_ENCRYPT(l,r,i+4); /*  3 */
+			D_ENCRYPT(r,l,i+6); /*  4 */
+			}
+#endif
+		}
+	else
+		{
+#ifdef DES_UNROLL
+		D_ENCRYPT(l,r,30); /* 16 */
+		D_ENCRYPT(r,l,28); /* 15 */
+		D_ENCRYPT(l,r,26); /* 14 */
+		D_ENCRYPT(r,l,24); /* 13 */
+		D_ENCRYPT(l,r,22); /* 12 */
+		D_ENCRYPT(r,l,20); /* 11 */
+		D_ENCRYPT(l,r,18); /* 10 */
+		D_ENCRYPT(r,l,16); /*  9 */
+		D_ENCRYPT(l,r,14); /*  8 */
+		D_ENCRYPT(r,l,12); /*  7 */
+		D_ENCRYPT(l,r,10); /*  6 */
+		D_ENCRYPT(r,l, 8); /*  5 */
+		D_ENCRYPT(l,r, 6); /*  4 */
+		D_ENCRYPT(r,l, 4); /*  3 */
+		D_ENCRYPT(l,r, 2); /*  2 */
+		D_ENCRYPT(r,l, 0); /*  1 */
+#else
+		for (i=30; i>0; i-=8)
+			{
+			D_ENCRYPT(l,r,i-0); /* 16 */
+			D_ENCRYPT(r,l,i-2); /* 15 */
+			D_ENCRYPT(l,r,i-4); /* 14 */
+			D_ENCRYPT(r,l,i-6); /* 13 */
+			}
+#endif
+		}
+
+	/* rotate and clear the top bits on machines with 8byte longs */
+	l=ROTATE(l,3)&0xffffffffL;
+	r=ROTATE(r,3)&0xffffffffL;
+
+	FP(r,l);
+	data[0]=l;
+	data[1]=r;
+	l=r=t=u=0;
+	}
+
+void des_encrypt2(data, ks, enc)
+DES_LONG *data;
+des_key_schedule ks;
+int enc;
+	{
+	register DES_LONG l,r,t,u;
+#ifdef DES_PTR
+	register unsigned char *des_SP=(unsigned char *)des_SPtrans;
+#endif
+#ifndef DES_UNROLL
+	register int i;
+#endif
+	register DES_LONG *s;
+
+	r=data[0];
+	l=data[1];
+
+	/* Things have been modified so that the initial rotate is
+	 * done outside the loop.  This required the
+	 * des_SPtrans values in sp.h to be rotated 1 bit to the right.
+	 * One perl script later and things have a 5% speed up on a sparc2.
+	 * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
+	 * for pointing this out. */
+	/* clear the top bits on machines with 8byte longs */
+	r=ROTATE(r,29)&0xffffffffL;
+	l=ROTATE(l,29)&0xffffffffL;
+
+	s=(DES_LONG *)ks;
+	/* I don't know if it is worth the effort of loop unrolling the
+	 * inner loop */
+	if (enc)
+		{
+#ifdef DES_UNROLL
+		D_ENCRYPT(l,r, 0); /*  1 */
+		D_ENCRYPT(r,l, 2); /*  2 */
+		D_ENCRYPT(l,r, 4); /*  3 */
+		D_ENCRYPT(r,l, 6); /*  4 */
+		D_ENCRYPT(l,r, 8); /*  5 */
+		D_ENCRYPT(r,l,10); /*  6 */
+		D_ENCRYPT(l,r,12); /*  7 */
+		D_ENCRYPT(r,l,14); /*  8 */
+		D_ENCRYPT(l,r,16); /*  9 */
+		D_ENCRYPT(r,l,18); /*  10 */
+		D_ENCRYPT(l,r,20); /*  11 */
+		D_ENCRYPT(r,l,22); /*  12 */
+		D_ENCRYPT(l,r,24); /*  13 */
+		D_ENCRYPT(r,l,26); /*  14 */
+		D_ENCRYPT(l,r,28); /*  15 */
+		D_ENCRYPT(r,l,30); /*  16 */
+#else
+		for (i=0; i<32; i+=8)
+			{
+			D_ENCRYPT(l,r,i+0); /*  1 */
+			D_ENCRYPT(r,l,i+2); /*  2 */
+			D_ENCRYPT(l,r,i+4); /*  3 */
+			D_ENCRYPT(r,l,i+6); /*  4 */
+			}
+#endif
+		}
+	else
+		{
+#ifdef DES_UNROLL
+		D_ENCRYPT(l,r,30); /* 16 */
+		D_ENCRYPT(r,l,28); /* 15 */
+		D_ENCRYPT(l,r,26); /* 14 */
+		D_ENCRYPT(r,l,24); /* 13 */
+		D_ENCRYPT(l,r,22); /* 12 */
+		D_ENCRYPT(r,l,20); /* 11 */
+		D_ENCRYPT(l,r,18); /* 10 */
+		D_ENCRYPT(r,l,16); /*  9 */
+		D_ENCRYPT(l,r,14); /*  8 */
+		D_ENCRYPT(r,l,12); /*  7 */
+		D_ENCRYPT(l,r,10); /*  6 */
+		D_ENCRYPT(r,l, 8); /*  5 */
+		D_ENCRYPT(l,r, 6); /*  4 */
+		D_ENCRYPT(r,l, 4); /*  3 */
+		D_ENCRYPT(l,r, 2); /*  2 */
+		D_ENCRYPT(r,l, 0); /*  1 */
+#else
+		for (i=30; i>0; i-=8)
+			{
+			D_ENCRYPT(l,r,i-0); /* 16 */
+			D_ENCRYPT(r,l,i-2); /* 15 */
+			D_ENCRYPT(l,r,i-4); /* 14 */
+			D_ENCRYPT(r,l,i-6); /* 13 */
+			}
+#endif
+		}
+	/* rotate and clear the top bits on machines with 8byte longs */
+	data[0]=ROTATE(l,3)&0xffffffffL;
+	data[1]=ROTATE(r,3)&0xffffffffL;
+	l=r=t=u=0;
+	}
+
+void des_encrypt3(data,ks1,ks2,ks3)
+DES_LONG *data;
+des_key_schedule ks1;
+des_key_schedule ks2;
+des_key_schedule ks3;
+	{
+	register DES_LONG l,r;
+
+	l=data[0];
+	r=data[1];
+	IP(l,r);
+	data[0]=l;
+	data[1]=r;
+	des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT);
+	des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT);
+	des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT);
+	l=data[0];
+	r=data[1];
+	FP(r,l);
+	data[0]=l;
+	data[1]=r;
+	}
+
+void des_decrypt3(data,ks1,ks2,ks3)
+DES_LONG *data;
+des_key_schedule ks1;
+des_key_schedule ks2;
+des_key_schedule ks3;
+	{
+	register DES_LONG l,r;
+
+	l=data[0];
+	r=data[1];
+	IP(l,r);
+	data[0]=l;
+	data[1]=r;
+	des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT);
+	des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT);
+	des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT);
+	l=data[0];
+	r=data[1];
+	FP(r,l);
+	data[0]=l;
+	data[1]=r;
+	}
+
+#ifndef DES_DEFAULT_OPTIONS
+
+void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
+des_cblock (*input);
+des_cblock (*output);
+long length;
+des_key_schedule schedule;
+des_cblock (*ivec);
+int enc;
+	{
+	register DES_LONG tin0,tin1;
+	register DES_LONG tout0,tout1,xor0,xor1;
+	register unsigned char *in,*out;
+	register long l=length;
+	DES_LONG tin[2];
+	unsigned char *iv;
+
+	in=(unsigned char *)input;
+	out=(unsigned char *)output;
+	iv=(unsigned char *)ivec;
+
+	if (enc)
+		{
+		c2l(iv,tout0);
+		c2l(iv,tout1);
+		for (l-=8; l>=0; l-=8)
+			{
+			c2l(in,tin0);
+			c2l(in,tin1);
+			tin0^=tout0; tin[0]=tin0;
+			tin1^=tout1; tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+			tout0=tin[0]; l2c(tout0,out);
+			tout1=tin[1]; l2c(tout1,out);
+			}
+		if (l != -8)
+			{
+			c2ln(in,tin0,tin1,l+8);
+			tin0^=tout0; tin[0]=tin0;
+			tin1^=tout1; tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+			tout0=tin[0]; l2c(tout0,out);
+			tout1=tin[1]; l2c(tout1,out);
+			}
+		iv=(unsigned char *)ivec;
+		l2c(tout0,iv);
+		l2c(tout1,iv);
+		}
+	else
+		{
+		c2l(iv,xor0);
+		c2l(iv,xor1);
+		for (l-=8; l>=0; l-=8)
+			{
+			c2l(in,tin0); tin[0]=tin0;
+			c2l(in,tin1); tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2c(tout0,out);
+			l2c(tout1,out);
+			xor0=tin0;
+			xor1=tin1;
+			}
+		if (l != -8)
+			{
+			c2l(in,tin0); tin[0]=tin0;
+			c2l(in,tin1); tin[1]=tin1;
+			des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
+			tout0=tin[0]^xor0;
+			tout1=tin[1]^xor1;
+			l2cn(tout0,tout1,out,l+8);
+			xor0=tin0;
+			xor1=tin1;
+			}
+
+		iv=(unsigned char *)ivec;
+		l2c(xor0,iv);
+		l2c(xor1,iv);
+		}
+	tin0=tin1=tout0=tout1=xor0=xor1=0;
+	tin[0]=tin[1]=0;
+	}
+
+void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc)
+des_cblock (*input);
+des_cblock (*output);
+long length;
+des_key_schedule ks1;
+des_key_schedule ks2;
+des_key_schedule ks3;
+des_cblock (*ivec);
+int enc;
+	{
+	register DES_LONG tin0,tin1;
+	register DES_LONG tout0,tout1,xor0,xor1;
+	register unsigned char *in,*out;
+	register long l=length;
+	DES_LONG tin[2];
+	unsigned char *iv;
+
+	in=(unsigned char *)input;
+	out=(unsigned char *)output;
+	iv=(unsigned char *)ivec;
+
+	if (enc)
+		{
+		c2l(iv,tout0);
+		c2l(iv,tout1);
+		for (l-=8; l>=0; l-=8)
+			{
+			c2l(in,tin0);
+			c2l(in,tin1);
+			tin0^=tout0;
+			tin1^=tout1;
+
+			tin[0]=tin0;
+			tin[1]=tin1;
+			des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3);
+			tout0=tin[0];
+			tout1=tin[1];
+
+			l2c(tout0,out);
+			l2c(tout1,out);
+			}
+		if (l != -8)
+			{
+			c2ln(in,tin0,tin1,l+8);
+			tin0^=tout0;
+			tin1^=tout1;
+
+			tin[0]=tin0;
+			tin[1]=tin1;
+			des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3);
+			tout0=tin[0];
+			tout1=tin[1];
+
+			l2c(tout0,out);
+			l2c(tout1,out);
+			}
+		iv=(unsigned char *)ivec;
+		l2c(tout0,iv);
+		l2c(tout1,iv);
+		}
+	else
+		{
+		register DES_LONG t0,t1;
+
+		c2l(iv,xor0);
+		c2l(iv,xor1);
+		for (l-=8; l>=0; l-=8)
+			{
+			c2l(in,tin0);
+			c2l(in,tin1);
+
+			t0=tin0;
+			t1=tin1;
+
+			tin[0]=tin0;
+			tin[1]=tin1;
+			des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3);
+			tout0=tin[0];
+			tout1=tin[1];
+
+			tout0^=xor0;
+			tout1^=xor1;
+			l2c(tout0,out);
+			l2c(tout1,out);
+			xor0=t0;
+			xor1=t1;
+			}
+		if (l != -8)
+			{
+			c2l(in,tin0);
+			c2l(in,tin1);
+			
+			t0=tin0;
+			t1=tin1;
+
+			tin[0]=tin0;
+			tin[1]=tin1;
+			des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3);
+			tout0=tin[0];
+			tout1=tin[1];
+		
+			tout0^=xor0;
+			tout1^=xor1;
+			l2cn(tout0,tout1,out,l+8);
+			xor0=t0;
+			xor1=t1;
+			}
+
+		iv=(unsigned char *)ivec;
+		l2c(xor0,iv);
+		l2c(xor1,iv);
+		}
+	tin0=tin1=tout0=tout1=xor0=xor1=0;
+	tin[0]=tin[1]=0;
+	}
+
+#endif /* DES_DEFAULT_OPTIONS */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/des_locl.h linux-patched/net/ipsec/libdes/des_locl.h
--- linux/net/ipsec/libdes/des_locl.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/des_locl.h	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,515 @@
+/* crypto/des/des_locl.org */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * Always modify des_locl.org since des_locl.h is automatically generated from
+ * it during SSLeay configuration.
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
+#ifndef HEADER_DES_LOCL_H
+#define HEADER_DES_LOCL_H
+
+#if defined(WIN32) || defined(WIN16)
+#ifndef MSDOS
+#define MSDOS
+#endif
+#endif
+
+#include "des.h"
+
+#ifndef DES_DEFAULT_OPTIONS
+/* the following is tweaked from a config script, that is why it is a
+ * protected undef/define */
+#ifndef DES_PTR
+#define DES_PTR
+#endif
+
+/* This helps C compiler generate the correct code for multiple functional
+ * units.  It reduces register dependancies at the expense of 2 more
+ * registers */
+#ifndef DES_RISC1
+#define DES_RISC1
+#endif
+
+#ifndef DES_RISC2
+#undef DES_RISC2
+#endif
+
+#if defined(DES_RISC1) && defined(DES_RISC2)
+YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
+#endif
+
+/* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+#ifndef DES_UNROLL
+#define DES_UNROLL
+#endif
+
+/* These default values were supplied by
+ * Peter Gutman <pgut001@cs.auckland.ac.nz>
+ * They are only used if nothing else has been defined */
+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)
+/* Special defines which change the way the code is built depending on the
+   CPU and OS.  For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
+   even newer MIPS CPU's, but at the moment one size fits all for
+   optimization options.  Older Sparc's work better with only UNROLL, but
+   there's no way to tell at compile time what it is you're running on */
+ 
+#if defined( sun )		/* Newer Sparc's */
+  #define DES_PTR
+  #define DES_RISC1
+  #define DES_UNROLL
+#elif defined( __ultrix )	/* Older MIPS */
+  #define DES_PTR
+  #define DES_RISC2
+  #define DES_UNROLL
+#elif defined( __osf1__ )	/* Alpha */
+  #define DES_PTR
+  #define DES_RISC2
+#elif defined ( _AIX )		/* RS6000 */
+  /* Unknown */
+#elif defined( __hpux )		/* HP-PA */
+  /* Unknown */
+#elif defined( __aux )		/* 68K */
+  /* Unknown */
+#elif defined( __dgux )		/* 88K (but P6 in latest boxes) */
+  #define DES_UNROLL
+#elif defined( __sgi )		/* Newer MIPS */
+  #define DES_PTR
+  #define DES_RISC2
+  #define DES_UNROLL
+#elif defined( i386 )		/* x86 boxes, should be gcc */
+  #define DES_PTR
+  #define DES_RISC1
+  #define DES_UNROLL
+#endif /* Systems-specific speed defines */
+#endif
+
+#endif /* DES_DEFAULT_OPTIONS */
+
+#ifdef MSDOS		/* Visual C++ 2.1 (Windows NT/95) */
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <io.h>
+#ifndef RAND
+#define RAND
+#endif
+#undef NOPROTO
+#endif
+
+#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS)
+#ifndef __KERNEL__
+#include <string.h>
+#else
+#include <linux/string.h>
+#endif
+#endif
+
+#ifndef RAND
+#define RAND
+#endif
+
+#ifdef linux
+#undef RAND
+#endif
+
+#ifdef MSDOS
+#define getpid() 2
+#define RAND
+#undef NOPROTO
+#endif
+
+#if defined(NOCONST)
+#define const
+#endif
+
+#ifdef __STDC__
+#undef NOPROTO
+#endif
+
+#ifdef RAND
+#define srandom(s) srand(s)
+#define random rand
+#endif
+
+#define ITERATIONS 16
+#define HALF_ITERATIONS 8
+
+/* used in des_read and des_write */
+#define MAXWRITE	(1024*16)
+#define BSIZE		(MAXWRITE+4)
+
+#define c2l(c,l)	(l =((DES_LONG)(*((c)++)))    , \
+			 l|=((DES_LONG)(*((c)++)))<< 8L, \
+			 l|=((DES_LONG)(*((c)++)))<<16L, \
+			 l|=((DES_LONG)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#define c2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \
+			case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \
+			case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \
+			case 5: l2|=((DES_LONG)(*(--(c))));     \
+			case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \
+			case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \
+			case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \
+			case 1: l1|=((DES_LONG)(*(--(c))));     \
+				} \
+			}
+
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* replacements for htonl and ntohl since I have no idea what to do
+ * when faced with machines with 8 byte longs. */
+#define HDRSIZE 4
+
+#define n2l(c,l)	(l =((DES_LONG)(*((c)++)))<<24L, \
+			 l|=((DES_LONG)(*((c)++)))<<16L, \
+			 l|=((DES_LONG)(*((c)++)))<< 8L, \
+			 l|=((DES_LONG)(*((c)++))))
+
+#define l2n(l,c)	(*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)     )&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#define l2cn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \
+				} \
+			}
+
+#if defined(WIN32)
+#define	ROTATE(a,n)	(_lrotr(a,n))
+#else
+#define	ROTATE(a,n)	(((a)>>(n))+((a)<<(32-(n))))
+#endif
+
+/* Don't worry about the LOAD_DATA() stuff, that is used by
+ * fcrypt() to add it's little bit to the front */
+
+#ifdef DES_FCRYPT
+
+#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \
+	{ DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); }
+
+#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \
+	t=R^(R>>16L); \
+	u=t&E0; t&=E1; \
+	tmp=(u<<16); u^=R^s[S  ]; u^=tmp; \
+	tmp=(t<<16); t^=R^s[S+1]; t^=tmp
+#else
+#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g)
+#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \
+	u=R^s[S  ]; \
+	t=R^s[S+1]
+#endif
+
+/* The changes to this macro may help or hinder, depending on the
+ * compiler and the achitecture.  gcc2 always seems to do well :-).
+ * Inspired by Dana How <how@isl.stanford.edu>
+ * DO NOT use the alternative version on machines with 8 byte longs.
+ * It does not seem to work on the Alpha, even when DES_LONG is 4
+ * bytes, probably an issue of accessing non-word aligned objects :-( */
+#ifdef DES_PTR
+
+/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there
+ * is no reason to not xor all the sub items together.  This potentially
+ * saves a register since things can be xored directly into L */
+
+#if defined(DES_RISC1) || defined(DES_RISC2)
+#ifdef DES_RISC1
+#define D_ENCRYPT(LL,R,S) { \
+	unsigned int u1,u2,u3; \
+	LOAD_DATA(R,S,u,t,E0,E1,u1); \
+	u2=(int)u>>8L; \
+	u1=(int)u&0xfc; \
+	u2&=0xfc; \
+	t=ROTATE(t,4); \
+	u>>=16L; \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP      +u1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \
+	u3=(int)(u>>8L); \
+	u1=(int)u&0xfc; \
+	u3&=0xfc; \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \
+	u2=(int)t>>8L; \
+	u1=(int)t&0xfc; \
+	u2&=0xfc; \
+	t>>=16L; \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \
+	u3=(int)t>>8L; \
+	u1=(int)t&0xfc; \
+	u3&=0xfc; \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); }
+#endif
+#ifdef DES_RISC2
+#define D_ENCRYPT(LL,R,S) { \
+	unsigned int u1,u2,s1,s2; \
+	LOAD_DATA(R,S,u,t,E0,E1,u1); \
+	u2=(int)u>>8L; \
+	u1=(int)u&0xfc; \
+	u2&=0xfc; \
+	t=ROTATE(t,4); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP      +u1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \
+	s1=(int)(u>>16L); \
+	s2=(int)(u>>24L); \
+	s1&=0xfc; \
+	s2&=0xfc; \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \
+	u2=(int)t>>8L; \
+	u1=(int)t&0xfc; \
+	u2&=0xfc; \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \
+	s1=(int)(t>>16L); \
+	s2=(int)(t>>24L); \
+	s1&=0xfc; \
+	s2&=0xfc; \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \
+	LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); }
+#endif
+#else
+#define D_ENCRYPT(LL,R,S) { \
+	LOAD_DATA_tmp(R,S,u,t,E0,E1); \
+	t=ROTATE(t,4); \
+	LL^= \
+	*(DES_LONG *)((unsigned char *)des_SP      +((u     )&0xfc))^ \
+	*(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \
+	*(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \
+	*(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \
+	*(DES_LONG *)((unsigned char *)des_SP+0x100+((t     )&0xfc))^ \
+	*(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \
+	*(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \
+	*(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); }
+#endif
+
+#else /* original version */
+
+#if defined(DES_RISC1) || defined(DES_RISC2)
+#ifdef DES_RISC1
+#define D_ENCRYPT(LL,R,S) {\
+	unsigned int u1,u2,u3; \
+	LOAD_DATA(R,S,u,t,E0,E1,u1); \
+	u>>=2L; \
+	t=ROTATE(t,6); \
+	u2=(int)u>>8L; \
+	u1=(int)u&0x3f; \
+	u2&=0x3f; \
+	u>>=16L; \
+	LL^=des_SPtrans[0][u1]; \
+	LL^=des_SPtrans[2][u2]; \
+	u3=(int)u>>8L; \
+	u1=(int)u&0x3f; \
+	u3&=0x3f; \
+	LL^=des_SPtrans[4][u1]; \
+	LL^=des_SPtrans[6][u3]; \
+	u2=(int)t>>8L; \
+	u1=(int)t&0x3f; \
+	u2&=0x3f; \
+	t>>=16L; \
+	LL^=des_SPtrans[1][u1]; \
+	LL^=des_SPtrans[3][u2]; \
+	u3=(int)t>>8L; \
+	u1=(int)t&0x3f; \
+	u3&=0x3f; \
+	LL^=des_SPtrans[5][u1]; \
+	LL^=des_SPtrans[7][u3]; }
+#endif
+#ifdef DES_RISC2
+#define D_ENCRYPT(LL,R,S) {\
+	unsigned int u1,u2,s1,s2; \
+	LOAD_DATA(R,S,u,t,E0,E1,u1); \
+	u>>=2L; \
+	t=ROTATE(t,6); \
+	u2=(int)u>>8L; \
+	u1=(int)u&0x3f; \
+	u2&=0x3f; \
+	LL^=des_SPtrans[0][u1]; \
+	LL^=des_SPtrans[2][u2]; \
+	s1=(int)u>>16L; \
+	s2=(int)u>>24L; \
+	s1&=0x3f; \
+	s2&=0x3f; \
+	LL^=des_SPtrans[4][s1]; \
+	LL^=des_SPtrans[6][s2]; \
+	u2=(int)t>>8L; \
+	u1=(int)t&0x3f; \
+	u2&=0x3f; \
+	LL^=des_SPtrans[1][u1]; \
+	LL^=des_SPtrans[3][u2]; \
+	s1=(int)t>>16; \
+	s2=(int)t>>24L; \
+	s1&=0x3f; \
+	s2&=0x3f; \
+	LL^=des_SPtrans[5][s1]; \
+	LL^=des_SPtrans[7][s2]; }
+#endif
+
+#else
+
+#define D_ENCRYPT(LL,R,S) {\
+	LOAD_DATA_tmp(R,S,u,t,E0,E1); \
+	t=ROTATE(t,4); \
+	LL^=\
+		des_SPtrans[0][(u>> 2L)&0x3f]^ \
+		des_SPtrans[2][(u>>10L)&0x3f]^ \
+		des_SPtrans[4][(u>>18L)&0x3f]^ \
+		des_SPtrans[6][(u>>26L)&0x3f]^ \
+		des_SPtrans[1][(t>> 2L)&0x3f]^ \
+		des_SPtrans[3][(t>>10L)&0x3f]^ \
+		des_SPtrans[5][(t>>18L)&0x3f]^ \
+		des_SPtrans[7][(t>>26L)&0x3f]; }
+#endif
+#endif
+
+	/* IP and FP
+	 * The problem is more of a geometric problem that random bit fiddling.
+	 0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6
+	 8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4
+	16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2
+	24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0
+
+	32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7
+	40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5
+	48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3
+	56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1
+
+	The output has been subject to swaps of the form
+	0 1 -> 3 1 but the odd and even bits have been put into
+	2 3    2 0
+	different words.  The main trick is to remember that
+	t=((l>>size)^r)&(mask);
+	r^=t;
+	l^=(t<<size);
+	can be used to swap and move bits between words.
+
+	So l =  0  1  2  3  r = 16 17 18 19
+	        4  5  6  7      20 21 22 23
+	        8  9 10 11      24 25 26 27
+	       12 13 14 15      28 29 30 31
+	becomes (for size == 2 and mask == 0x3333)
+	   t =   2^16  3^17 -- --   l =  0  1 16 17  r =  2  3 18 19
+		 6^20  7^21 -- --        4  5 20 21       6  7 22 23
+		10^24 11^25 -- --        8  9 24 25      10 11 24 25
+		14^28 15^29 -- --       12 13 28 29      14 15 28 29
+
+	Thanks for hints from Richard Outerbridge - he told me IP&FP
+	could be done in 15 xor, 10 shifts and 5 ands.
+	When I finally started to think of the problem in 2D
+	I first got ~42 operations without xors.  When I remembered
+	how to use xors :-) I got it to its final state.
+	*/
+#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
+	(b)^=(t),\
+	(a)^=((t)<<(n)))
+
+#define IP(l,r) \
+	{ \
+	register DES_LONG tt; \
+	PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \
+	PERM_OP(l,r,tt,16,0x0000ffffL); \
+	PERM_OP(r,l,tt, 2,0x33333333L); \
+	PERM_OP(l,r,tt, 8,0x00ff00ffL); \
+	PERM_OP(r,l,tt, 1,0x55555555L); \
+	}
+
+#define FP(l,r) \
+	{ \
+	register DES_LONG tt; \
+	PERM_OP(l,r,tt, 1,0x55555555L); \
+	PERM_OP(r,l,tt, 8,0x00ff00ffL); \
+	PERM_OP(l,r,tt, 2,0x33333333L); \
+	PERM_OP(r,l,tt,16,0x0000ffffL); \
+	PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \
+	}
+
+extern const DES_LONG des_SPtrans[8][64];
+
+#ifndef NOPROTO
+void fcrypt_body(DES_LONG *out,des_key_schedule ks,
+	DES_LONG Eswap0, DES_LONG Eswap1);
+#else
+void fcrypt_body();
+#endif
+
+#endif
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/des_opts.c linux-patched/net/ipsec/libdes/des_opts.c
--- linux/net/ipsec/libdes/des_opts.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/des_opts.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,620 @@
+/* crypto/des/des_opts.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* define PART1, PART2, PART3 or PART4 to build only with a few of the options.
+ * This is for machines with 64k code segment size restrictions. */
+
+#ifndef MSDOS
+#define TIMES
+#endif
+
+#include <stdio.h>
+#ifndef MSDOS
+#include <unistd.h>
+#else
+#include <io.h>
+extern void exit();
+#endif
+#include <signal.h>
+#ifndef VMS
+#ifndef _IRIX
+#include <time.h>
+#endif
+#ifdef TIMES
+#include <sys/types.h>
+#include <sys/times.h>
+#endif
+#else /* VMS */
+#include <types.h>
+struct tms {
+	time_t tms_utime;
+	time_t tms_stime;
+	time_t tms_uchild;	/* I dunno...  */
+	time_t tms_uchildsys;	/* so these names are a guess :-) */
+	}
+#endif
+#ifndef TIMES
+#include <sys/timeb.h>
+#endif
+
+#ifdef sun
+#include <limits.h>
+#include <sys/param.h>
+#endif
+
+#include "des.h"
+#include "spr.h"
+
+#define DES_DEFAULT_OPTIONS
+
+#if !defined(PART1) && !defined(PART2) && !defined(PART3) && !defined(PART4)
+#define PART1
+#define PART2
+#define PART3
+#define PART4
+#endif
+
+#ifdef PART1
+
+#undef DES_UNROLL
+#undef DES_RISC1
+#undef DES_RISC2
+#undef DES_PTR
+#undef D_ENCRYPT
+#define des_encrypt  des_encrypt_u4_cisc_idx
+#define des_encrypt2 des_encrypt2_u4_cisc_idx
+#define des_encrypt3 des_encrypt3_u4_cisc_idx
+#define des_decrypt3 des_decrypt3_u4_cisc_idx
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#define DES_UNROLL
+#undef DES_RISC1
+#undef DES_RISC2
+#undef DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u16_cisc_idx
+#define des_encrypt2 des_encrypt2_u16_cisc_idx
+#define des_encrypt3 des_encrypt3_u16_cisc_idx
+#define des_decrypt3 des_decrypt3_u16_cisc_idx
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#undef DES_UNROLL
+#define DES_RISC1
+#undef DES_RISC2
+#undef DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u4_risc1_idx
+#define des_encrypt2 des_encrypt2_u4_risc1_idx
+#define des_encrypt3 des_encrypt3_u4_risc1_idx
+#define des_decrypt3 des_decrypt3_u4_risc1_idx
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#endif
+
+#ifdef PART2
+
+#undef DES_UNROLL
+#undef DES_RISC1
+#define DES_RISC2
+#undef DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u4_risc2_idx
+#define des_encrypt2 des_encrypt2_u4_risc2_idx
+#define des_encrypt3 des_encrypt3_u4_risc2_idx
+#define des_decrypt3 des_decrypt3_u4_risc2_idx
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#define DES_UNROLL
+#define DES_RISC1
+#undef DES_RISC2
+#undef DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u16_risc1_idx
+#define des_encrypt2 des_encrypt2_u16_risc1_idx
+#define des_encrypt3 des_encrypt3_u16_risc1_idx
+#define des_decrypt3 des_decrypt3_u16_risc1_idx
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#define DES_UNROLL
+#undef DES_RISC1
+#define DES_RISC2
+#undef DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u16_risc2_idx
+#define des_encrypt2 des_encrypt2_u16_risc2_idx
+#define des_encrypt3 des_encrypt3_u16_risc2_idx
+#define des_decrypt3 des_decrypt3_u16_risc2_idx
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#endif
+
+#ifdef PART3
+
+#undef DES_UNROLL
+#undef DES_RISC1
+#undef DES_RISC2
+#define DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u4_cisc_ptr
+#define des_encrypt2 des_encrypt2_u4_cisc_ptr
+#define des_encrypt3 des_encrypt3_u4_cisc_ptr
+#define des_decrypt3 des_decrypt3_u4_cisc_ptr
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#define DES_UNROLL
+#undef DES_RISC1
+#undef DES_RISC2
+#define DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u16_cisc_ptr
+#define des_encrypt2 des_encrypt2_u16_cisc_ptr
+#define des_encrypt3 des_encrypt3_u16_cisc_ptr
+#define des_decrypt3 des_decrypt3_u16_cisc_ptr
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#undef DES_UNROLL
+#define DES_RISC1
+#undef DES_RISC2
+#define DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u4_risc1_ptr
+#define des_encrypt2 des_encrypt2_u4_risc1_ptr
+#define des_encrypt3 des_encrypt3_u4_risc1_ptr
+#define des_decrypt3 des_decrypt3_u4_risc1_ptr
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#endif
+
+#ifdef PART4
+
+#undef DES_UNROLL
+#undef DES_RISC1
+#define DES_RISC2
+#define DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u4_risc2_ptr
+#define des_encrypt2 des_encrypt2_u4_risc2_ptr
+#define des_encrypt3 des_encrypt3_u4_risc2_ptr
+#define des_decrypt3 des_decrypt3_u4_risc2_ptr
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#define DES_UNROLL
+#define DES_RISC1
+#undef DES_RISC2
+#define DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u16_risc1_ptr
+#define des_encrypt2 des_encrypt2_u16_risc1_ptr
+#define des_encrypt3 des_encrypt3_u16_risc1_ptr
+#define des_decrypt3 des_decrypt3_u16_risc1_ptr
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#define DES_UNROLL
+#undef DES_RISC1
+#define DES_RISC2
+#define DES_PTR
+#undef D_ENCRYPT
+#undef des_encrypt
+#undef des_encrypt2
+#undef des_encrypt3
+#undef des_decrypt3
+#define des_encrypt  des_encrypt_u16_risc2_ptr
+#define des_encrypt2 des_encrypt2_u16_risc2_ptr
+#define des_encrypt3 des_encrypt3_u16_risc2_ptr
+#define des_decrypt3 des_decrypt3_u16_risc2_ptr
+#undef HEADER_DES_LOCL_H
+#include "des_enc.c"
+
+#endif
+
+/* The following if from times(3) man page.  It may need to be changed */
+#ifndef HZ
+# ifndef CLK_TCK
+#  ifndef _BSD_CLK_TCK_ /* FreeBSD fix */
+#   ifndef VMS
+#    define HZ	100.0
+#   else /* VMS */
+#    define HZ	100.0
+#   endif
+#  else /* _BSD_CLK_TCK_ */
+#   define HZ ((double)_BSD_CLK_TCK_)
+#  endif
+# else /* CLK_TCK */
+#  define HZ ((double)CLK_TCK)
+# endif
+#endif
+
+#define BUFSIZE	((long)1024)
+long run=0;
+
+#ifndef NOPROTO
+double Time_F(int s);
+#else
+double Time_F();
+#endif
+
+#ifdef SIGALRM
+#if defined(__STDC__) || defined(sgi)
+#define SIGRETTYPE void
+#else
+#define SIGRETTYPE int
+#endif
+
+#ifndef NOPROTO
+SIGRETTYPE sig_done(int sig);
+#else
+SIGRETTYPE sig_done();
+#endif
+
+SIGRETTYPE sig_done(sig)
+int sig;
+	{
+	signal(SIGALRM,sig_done);
+	run=0;
+#ifdef LINT
+	sig=sig;
+#endif
+	}
+#endif
+
+#define START	0
+#define STOP	1
+
+double Time_F(s)
+int s;
+	{
+	double ret;
+#ifdef TIMES
+	static struct tms tstart,tend;
+
+	if (s == START)
+		{
+		times(&tstart);
+		return(0);
+		}
+	else
+		{
+		times(&tend);
+		ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ;
+		return((ret == 0.0)?1e-6:ret);
+		}
+#else /* !times() */
+	static struct timeb tstart,tend;
+	long i;
+
+	if (s == START)
+		{
+		ftime(&tstart);
+		return(0);
+		}
+	else
+		{
+		ftime(&tend);
+		i=(long)tend.millitm-(long)tstart.millitm;
+		ret=((double)(tend.time-tstart.time))+((double)i)/1000.0;
+		return((ret == 0.0)?1e-6:ret);
+		}
+#endif
+	}
+
+#ifdef SIGALRM
+#define print_name(name) fprintf(stderr,"Doing %s's for 10 seconds\n",name); alarm(10);
+#else
+#define print_name(name) fprintf(stderr,"Doing %s %ld times\n",name,cb);
+#endif
+	
+#define time_it(func,name,index) \
+	print_name(name); \
+	Time_F(START); \
+	for (count=0,run=1; COND(cb); count++) \
+		{ \
+		unsigned long d[2]; \
+		func(d,&(sch[0]),DES_ENCRYPT); \
+		} \
+	tm[index]=Time_F(STOP); \
+	fprintf(stderr,"%ld %s's in %.2f second\n",count,name,tm[index]); \
+	tm[index]=((double)COUNT(cb))/tm[index];
+
+#define print_it(name,index) \
+	fprintf(stderr,"%s bytes per sec = %12.2f (%5.1fuS)\n",name, \
+		tm[index]*8,1.0e6/tm[index]);
+
+int main(argc,argv)
+int argc;
+char **argv;
+	{
+	long count;
+	static unsigned char buf[BUFSIZE];
+	static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0};
+	static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
+	static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+	des_key_schedule sch,sch2,sch3;
+	double d,tm[16],max=0;
+	int rank[16];
+	char *str[16];
+	int max_idx=0,i,num=0,j;
+#ifndef SIGALARM
+	long ca,cb,cc,cd,ce;
+#endif
+
+	for (i=0; i<12; i++)
+		{
+		tm[i]=0.0;
+		rank[i]=0;
+		}
+
+#ifndef TIMES
+	fprintf(stderr,"To get the most acurate results, try to run this\n");
+	fprintf(stderr,"program when this computer is idle.\n");
+#endif
+
+	des_set_key((C_Block *)key,sch);
+	des_set_key((C_Block *)key2,sch2);
+	des_set_key((C_Block *)key3,sch3);
+
+#ifndef SIGALRM
+	fprintf(stderr,"First we calculate the approximate speed ...\n");
+	des_set_key((C_Block *)key,sch);
+	count=10;
+	do	{
+		long i;
+		unsigned long data[2];
+
+		count*=2;
+		Time_F(START);
+		for (i=count; i; i--)
+			des_encrypt(data,&(sch[0]),DES_ENCRYPT);
+		d=Time_F(STOP);
+		} while (d < 3.0);
+	ca=count;
+	cb=count*3;
+	cc=count*3*8/BUFSIZE+1;
+	cd=count*8/BUFSIZE+1;
+
+	ce=count/20+1;
+#define COND(d) (count != (d))
+#define COUNT(d) (d)
+#else
+#define COND(c) (run)
+#define COUNT(d) (count)
+        signal(SIGALRM,sig_done);
+        alarm(10);
+#endif
+
+#ifdef PART1
+	time_it(des_encrypt_u4_cisc_idx,  "des_encrypt_u4_cisc_idx  ", 0);
+	time_it(des_encrypt_u16_cisc_idx, "des_encrypt_u16_cisc_idx ", 1);
+	time_it(des_encrypt_u4_risc1_idx, "des_encrypt_u4_risc1_idx ", 2);
+	num+=3;
+#endif
+#ifdef PART2
+	time_it(des_encrypt_u16_risc1_idx,"des_encrypt_u16_risc1_idx", 3);
+	time_it(des_encrypt_u4_risc2_idx, "des_encrypt_u4_risc2_idx ", 4);
+	time_it(des_encrypt_u16_risc2_idx,"des_encrypt_u16_risc2_idx", 5);
+	num+=3;
+#endif
+#ifdef PART3
+	time_it(des_encrypt_u4_cisc_ptr,  "des_encrypt_u4_cisc_ptr  ", 6);
+	time_it(des_encrypt_u16_cisc_ptr, "des_encrypt_u16_cisc_ptr ", 7);
+	time_it(des_encrypt_u4_risc1_ptr, "des_encrypt_u4_risc1_ptr ", 8);
+	num+=3;
+#endif
+#ifdef PART4
+	time_it(des_encrypt_u16_risc1_ptr,"des_encrypt_u16_risc1_ptr", 9);
+	time_it(des_encrypt_u4_risc2_ptr, "des_encrypt_u4_risc2_ptr ",10);
+	time_it(des_encrypt_u16_risc2_ptr,"des_encrypt_u16_risc2_ptr",11);
+	num+=3;
+#endif
+
+#ifdef PART1
+	str[0]=" 4  c i";
+	print_it("des_encrypt_u4_cisc_idx  ",0);
+	max=tm[0];
+	max_idx=0;
+	str[1]="16  c i";
+	print_it("des_encrypt_u16_cisc_idx ",1);
+	if (max < tm[1]) { max=tm[1]; max_idx=1; }
+	str[2]=" 4 r1 i";
+	print_it("des_encrypt_u4_risc1_idx ",2);
+	if (max < tm[2]) { max=tm[2]; max_idx=2; }
+#endif
+#ifdef PART2
+	str[3]="16 r1 i";
+	print_it("des_encrypt_u16_risc1_idx",3);
+	if (max < tm[3]) { max=tm[3]; max_idx=3; }
+	str[4]=" 4 r2 i";
+	print_it("des_encrypt_u4_risc2_idx ",4);
+	if (max < tm[4]) { max=tm[4]; max_idx=4; }
+	str[5]="16 r2 i";
+	print_it("des_encrypt_u16_risc2_idx",5);
+	if (max < tm[5]) { max=tm[5]; max_idx=5; }
+#endif
+#ifdef PART3
+	str[6]=" 4  c p";
+	print_it("des_encrypt_u4_cisc_ptr  ",6);
+	if (max < tm[6]) { max=tm[6]; max_idx=6; }
+	str[7]="16  c p";
+	print_it("des_encrypt_u16_cisc_ptr ",7);
+	if (max < tm[7]) { max=tm[7]; max_idx=7; }
+	str[8]=" 4 r1 p";
+	print_it("des_encrypt_u4_risc1_ptr ",8);
+	if (max < tm[8]) { max=tm[8]; max_idx=8; }
+#endif
+#ifdef PART4
+	str[9]="16 r1 p";
+	print_it("des_encrypt_u16_risc1_ptr",9);
+	if (max < tm[9]) { max=tm[9]; max_idx=9; }
+	str[10]=" 4 r2 p";
+	print_it("des_encrypt_u4_risc2_ptr ",10);
+	if (max < tm[10]) { max=tm[10]; max_idx=10; }
+	str[11]="16 r2 p";
+	print_it("des_encrypt_u16_risc2_ptr",11);
+	if (max < tm[11]) { max=tm[11]; max_idx=11; }
+#endif
+	printf("options    des ecb/s\n");
+	printf("%s %12.2f 100.0%%\n",str[max_idx],tm[max_idx]);
+	d=tm[max_idx];
+	tm[max_idx]= -2.0;
+	max= -1.0;
+	for (;;)
+		{
+		for (i=0; i<12; i++)
+			{
+			if (max < tm[i]) { max=tm[i]; j=i; }
+			}
+		if (max < 0.0) break;
+		printf("%s %12.2f  %4.1f%%\n",str[j],tm[j],tm[j]/d*100.0);
+		tm[j]= -2.0;
+		max= -1.0;
+		}
+
+	switch (max_idx)
+		{
+	case 0:
+		printf("-DDES_DEFAULT_OPTIONS\n");
+		break;
+	case 1:
+		printf("-DDES_UNROLL\n");
+		break;
+	case 2:
+		printf("-DDES_RISC1\n");
+		break;
+	case 3:
+		printf("-DDES_UNROLL -DDES_RISC1\n");
+		break;
+	case 4:
+		printf("-DDES_RISC2\n");
+		break;
+	case 5:
+		printf("-DDES_UNROLL -DDES_RISC2\n");
+		break;
+	case 6:
+		printf("-DDES_PTR\n");
+		break;
+	case 7:
+		printf("-DDES_UNROLL -DDES_PTR\n");
+		break;
+	case 8:
+		printf("-DDES_RISC1 -DDES_PTR\n");
+		break;
+	case 9:
+		printf("-DDES_UNROLL -DDES_RISC1 -DDES_PTR\n");
+		break;
+	case 10:
+		printf("-DDES_RISC2 -DDES_PTR\n");
+		break;
+	case 11:
+		printf("-DDES_UNROLL -DDES_RISC2 -DDES_PTR\n");
+		break;
+		}
+	exit(0);
+#if defined(LINT) || defined(MSDOS)
+	return(0);
+#endif
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/des_ver.h linux-patched/net/ipsec/libdes/des_ver.h
--- linux/net/ipsec/libdes/des_ver.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/des_ver.h	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,60 @@
+/* crypto/des/des_ver.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+extern char *DES_version;	/* SSLeay version string */
+extern char *libdes_version;	/* old libdes version string */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/destest.c linux-patched/net/ipsec/libdes/destest.c
--- linux/net/ipsec/libdes/destest.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/destest.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,871 @@
+/* crypto/des/destest.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#if defined(WIN32) || defined(WIN16) || defined(WINDOWS)
+#ifndef MSDOS
+#define MSDOS
+#endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef MSDOS
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+#include <string.h>
+#include "des.h"
+
+/* tisk tisk - the test keys don't all have odd parity :-( */
+/* test data */
+#define NUM_TESTS 34
+static unsigned char key_data[NUM_TESTS][8]={
+	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
+	{0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
+	{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
+	{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
+	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10},
+	{0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57},
+	{0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E},
+	{0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86},
+	{0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E},
+	{0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6},
+	{0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE},
+	{0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6},
+	{0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE},
+	{0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16},
+	{0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F},
+	{0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46},
+	{0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E},
+	{0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76},
+	{0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07},
+	{0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F},
+	{0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7},
+	{0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF},
+	{0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6},
+	{0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF},
+	{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
+	{0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
+	{0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
+	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
+	{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
+	{0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}};
+
+static unsigned char plain_data[NUM_TESTS][8]={
+	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
+	{0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
+	{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
+	{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
+	{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
+	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
+	{0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42},
+	{0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA},
+	{0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72},
+	{0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A},
+	{0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2},
+	{0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A},
+	{0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2},
+	{0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A},
+	{0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02},
+	{0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A},
+	{0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32},
+	{0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA},
+	{0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62},
+	{0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2},
+	{0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA},
+	{0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92},
+	{0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A},
+	{0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2},
+	{0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A},
+	{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
+	{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
+	{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
+	{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
+	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+	{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
+
+static unsigned char cipher_data[NUM_TESTS][8]={
+	{0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7},
+	{0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58},
+	{0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B},
+	{0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33},
+	{0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D},
+	{0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD},
+	{0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7},
+	{0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4},
+	{0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B},
+	{0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71},
+	{0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A},
+	{0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A},
+	{0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95},
+	{0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B},
+	{0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09},
+	{0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A},
+	{0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F},
+	{0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88},
+	{0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77},
+	{0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A},
+	{0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56},
+	{0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56},
+	{0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56},
+	{0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC},
+	{0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A},
+	{0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41},
+	{0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93},
+	{0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00},
+	{0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06},
+	{0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7},
+	{0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51},
+	{0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE},
+	{0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D},
+	{0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2}};
+
+static unsigned char cipher_ecb2[NUM_TESTS-1][8]={
+	{0x92,0x95,0xB5,0x9B,0xB3,0x84,0x73,0x6E},
+	{0x19,0x9E,0x9D,0x6D,0xF3,0x9A,0xA8,0x16},
+	{0x2A,0x4B,0x4D,0x24,0x52,0x43,0x84,0x27},
+	{0x35,0x84,0x3C,0x01,0x9D,0x18,0xC5,0xB6},
+	{0x4A,0x5B,0x2F,0x42,0xAA,0x77,0x19,0x25},
+	{0xA0,0x6B,0xA9,0xB8,0xCA,0x5B,0x17,0x8A},
+	{0xAB,0x9D,0xB7,0xFB,0xED,0x95,0xF2,0x74},
+	{0x3D,0x25,0x6C,0x23,0xA7,0x25,0x2F,0xD6},
+	{0xB7,0x6F,0xAB,0x4F,0xBD,0xBD,0xB7,0x67},
+	{0x8F,0x68,0x27,0xD6,0x9C,0xF4,0x1A,0x10},
+	{0x82,0x57,0xA1,0xD6,0x50,0x5E,0x81,0x85},
+	{0xA2,0x0F,0x0A,0xCD,0x80,0x89,0x7D,0xFA},
+	{0xCD,0x2A,0x53,0x3A,0xDB,0x0D,0x7E,0xF3},
+	{0xD2,0xC2,0xBE,0x27,0xE8,0x1B,0x68,0xE3},
+	{0xE9,0x24,0xCF,0x4F,0x89,0x3C,0x5B,0x0A},
+	{0xA7,0x18,0xC3,0x9F,0xFA,0x9F,0xD7,0x69},
+	{0x77,0x2C,0x79,0xB1,0xD2,0x31,0x7E,0xB1},
+	{0x49,0xAB,0x92,0x7F,0xD0,0x22,0x00,0xB7},
+	{0xCE,0x1C,0x6C,0x7D,0x85,0xE3,0x4A,0x6F},
+	{0xBE,0x91,0xD6,0xE1,0x27,0xB2,0xE9,0x87},
+	{0x70,0x28,0xAE,0x8F,0xD1,0xF5,0x74,0x1A},
+	{0xAA,0x37,0x80,0xBB,0xF3,0x22,0x1D,0xDE},
+	{0xA6,0xC4,0xD2,0x5E,0x28,0x93,0xAC,0xB3},
+	{0x22,0x07,0x81,0x5A,0xE4,0xB7,0x1A,0xAD},
+	{0xDC,0xCE,0x05,0xE7,0x07,0xBD,0xF5,0x84},
+	{0x26,0x1D,0x39,0x2C,0xB3,0xBA,0xA5,0x85},
+	{0xB4,0xF7,0x0F,0x72,0xFB,0x04,0xF0,0xDC},
+	{0x95,0xBA,0xA9,0x4E,0x87,0x36,0xF2,0x89},
+	{0xD4,0x07,0x3A,0xF1,0x5A,0x17,0x82,0x0E},
+	{0xEF,0x6F,0xAF,0xA7,0x66,0x1A,0x7E,0x89},
+	{0xC1,0x97,0xF5,0x58,0x74,0x8A,0x20,0xE7},
+	{0x43,0x34,0xCF,0xDA,0x22,0xC4,0x86,0xC8},
+	{0x08,0xD7,0xB4,0xFB,0x62,0x9D,0x08,0x85}};
+
+static unsigned char cbc_key [8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
+static unsigned char cbc2_key[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87};
+static unsigned char cbc3_key[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
+static unsigned char cbc_iv  [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
+static char cbc_data[40]="7654321 Now is the time for \0001";
+
+static unsigned char cbc_ok[32]={
+	0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4,
+	0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb,
+	0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68,
+	0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4};
+
+static unsigned char xcbc_ok[32]={
+	0x86,0x74,0x81,0x0D,0x61,0xA4,0xA5,0x48,
+	0xB9,0x93,0x03,0xE1,0xB8,0xBB,0xBD,0xBD,
+	0x64,0x30,0x0B,0xB9,0x06,0x65,0x81,0x76,
+	0x04,0x1D,0x77,0x62,0x17,0xCA,0x2B,0xD2,
+	};
+
+static unsigned char cbc3_ok[32]={
+	0x3F,0xE3,0x01,0xC9,0x62,0xAC,0x01,0xD0,
+	0x22,0x13,0x76,0x3C,0x1C,0xBD,0x4C,0xDC,
+	0x79,0x96,0x57,0xC0,0x64,0xEC,0xF5,0xD4,
+	0x1C,0x67,0x38,0x12,0xCF,0xDE,0x96,0x75};
+
+static unsigned char pcbc_ok[32]={
+	0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4,
+	0x6d,0xec,0xb4,0x70,0xa0,0xe5,0x6b,0x15,
+	0xae,0xa6,0xbf,0x61,0xed,0x7d,0x9c,0x9f,
+	0xf7,0x17,0x46,0x3b,0x8a,0xb3,0xcc,0x88};
+
+static unsigned char cfb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
+static unsigned char cfb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef};
+static unsigned char cfb_buf1[40],cfb_buf2[40],cfb_tmp[8];
+static unsigned char plain[24]=
+	{
+	0x4e,0x6f,0x77,0x20,0x69,0x73,
+	0x20,0x74,0x68,0x65,0x20,0x74,
+	0x69,0x6d,0x65,0x20,0x66,0x6f,
+	0x72,0x20,0x61,0x6c,0x6c,0x20
+	};
+static unsigned char cfb_cipher8[24]= {
+	0xf3,0x1f,0xda,0x07,0x01,0x14, 0x62,0xee,0x18,0x7f,0x43,0xd8,
+	0x0a,0x7c,0xd9,0xb5,0xb0,0xd2, 0x90,0xda,0x6e,0x5b,0x9a,0x87 };
+static unsigned char cfb_cipher16[24]={
+	0xF3,0x09,0x87,0x87,0x7F,0x57, 0xF7,0x3C,0x36,0xB6,0xDB,0x70,
+	0xD8,0xD5,0x34,0x19,0xD3,0x86, 0xB2,0x23,0xB7,0xB2,0xAD,0x1B };
+static unsigned char cfb_cipher32[24]={
+	0xF3,0x09,0x62,0x49,0xA4,0xDF, 0xA4,0x9F,0x33,0xDC,0x7B,0xAD,
+	0x4C,0xC8,0x9F,0x64,0xE4,0x53, 0xE5,0xEC,0x67,0x20,0xDA,0xB6 };
+static unsigned char cfb_cipher48[24]={
+	0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x30,0xB5,0x15,0xEC,0xBB,0x85,
+	0x97,0x5A,0x13,0x8C,0x68,0x60, 0xE2,0x38,0x34,0x3C,0xDC,0x1F };
+static unsigned char cfb_cipher64[24]={
+	0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x6E,0x51,0xA6,0x9E,0x83,0x9B,
+	0x1A,0x92,0xF7,0x84,0x03,0x46, 0x71,0x33,0x89,0x8E,0xA6,0x22 };
+
+static unsigned char ofb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
+static unsigned char ofb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef};
+static unsigned char ofb_buf1[24],ofb_buf2[24],ofb_tmp[8];
+static unsigned char ofb_cipher[24]=
+	{
+	0xf3,0x09,0x62,0x49,0xc7,0xf4,0x6e,0x51,
+	0x35,0xf2,0x4a,0x24,0x2e,0xeb,0x3d,0x3f,
+	0x3d,0x6d,0x5b,0xe3,0x25,0x5a,0xf8,0xc3
+	};
+
+DES_LONG cbc_cksum_ret=0xB462FEF7L;
+unsigned char cbc_cksum_data[8]={0x1D,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4};
+
+#ifndef NOPROTO
+static char *pt(unsigned char *p);
+static int cfb_test(int bits, unsigned char *cfb_cipher);
+static int cfb64_test(unsigned char *cfb_cipher);
+static int ede_cfb64_test(unsigned char *cfb_cipher);
+#else
+static char *pt();
+static int cfb_test();
+static int cfb64_test();
+static int ede_cfb64_test();
+#endif
+
+int main(argc,argv)
+int argc;
+char *argv[];
+	{
+	int i,j,err=0;
+	des_cblock in,out,outin,iv3;
+	des_key_schedule ks,ks2,ks3;
+	unsigned char cbc_in[40];
+	unsigned char cbc_out[40];
+	DES_LONG cs;
+	unsigned char qret[4][4],cret[8];
+	DES_LONG lqret[4];
+	int num;
+	char *str;
+
+	printf("Doing ecb\n");
+	for (i=0; i<NUM_TESTS; i++)
+		{
+		if ((j=des_key_sched((C_Block *)(key_data[i]),ks)) != 0)
+			{
+			printf("Key error %2d:%d\n",i+1,j);
+			err=1;
+			}
+		memcpy(in,plain_data[i],8);
+		memset(out,0,8);
+		memset(outin,0,8);
+		des_ecb_encrypt((C_Block *)in,(C_Block *)out,ks,DES_ENCRYPT);
+		des_ecb_encrypt((C_Block *)out,(C_Block *)outin,ks,DES_DECRYPT);
+
+		if (memcmp(out,cipher_data[i],8) != 0)
+			{
+			printf("Encryption error %2d\nk=%s p=%s o=%s act=%s\n",
+				i+1,pt(key_data[i]),pt(in),pt(cipher_data[i]),
+				pt(out));
+			err=1;
+			}
+		if (memcmp(in,outin,8) != 0)
+			{
+			printf("Decryption error %2d\nk=%s p=%s o=%s act=%s\n",
+				i+1,pt(key_data[i]),pt(out),pt(in),pt(outin));
+			err=1;
+			}
+		}
+
+#ifndef LIBDES_LIT
+	printf("Doing ede ecb\n");
+	for (i=0; i<(NUM_TESTS-1); i++)
+		{
+		if ((j=des_key_sched((C_Block *)(key_data[i]),ks)) != 0)
+			{
+			err=1;
+			printf("Key error %2d:%d\n",i+1,j);
+			}
+		if ((j=des_key_sched((C_Block *)(key_data[i+1]),ks2)) != 0)
+			{
+			printf("Key error %2d:%d\n",i+2,j);
+			err=1;
+			}
+		if ((j=des_key_sched((C_Block *)(key_data[i+2]),ks3)) != 0)
+			{
+			printf("Key error %2d:%d\n",i+3,j);
+			err=1;
+			}
+		memcpy(in,plain_data[i],8);
+		memset(out,0,8);
+		memset(outin,0,8);
+		des_ecb2_encrypt((C_Block *)in,(C_Block *)out,ks,ks2,
+			DES_ENCRYPT);
+		des_ecb2_encrypt((C_Block *)out,(C_Block *)outin,ks,ks2,
+			DES_DECRYPT);
+
+		if (memcmp(out,cipher_ecb2[i],8) != 0)
+			{
+			printf("Encryption error %2d\nk=%s p=%s o=%s act=%s\n",
+				i+1,pt(key_data[i]),pt(in),pt(cipher_ecb2[i]),
+				pt(out));
+			err=1;
+			}
+		if (memcmp(in,outin,8) != 0)
+			{
+			printf("Decryption error %2d\nk=%s p=%s o=%s act=%s\n",
+				i+1,pt(key_data[i]),pt(out),pt(in),pt(outin));
+			err=1;
+			}
+		}
+#endif
+
+	printf("Doing cbc\n");
+	if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0)
+		{
+		printf("Key error %d\n",j);
+		err=1;
+		}
+	memset(cbc_out,0,40);
+	memset(cbc_in,0,40);
+	memcpy(iv3,cbc_iv,sizeof(cbc_iv));
+	des_ncbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out,
+		(long)strlen((char *)cbc_data)+1,ks,
+		(C_Block *)iv3,DES_ENCRYPT);
+	if (memcmp(cbc_out,cbc_ok,32) != 0)
+		printf("cbc_encrypt encrypt error\n");
+
+	memcpy(iv3,cbc_iv,sizeof(cbc_iv));
+	des_ncbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in,
+		(long)strlen((char *)cbc_data)+1,ks,
+		(C_Block *)iv3,DES_DECRYPT);
+	if (memcmp(cbc_in,cbc_data,strlen((char *)cbc_data)) != 0)
+		{
+		printf("cbc_encrypt decrypt error\n");
+		err=1;
+		}
+
+#ifndef LIBDES_LIT
+	printf("Doing desx cbc\n");
+	if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0)
+		{
+		printf("Key error %d\n",j);
+		err=1;
+		}
+	memset(cbc_out,0,40);
+	memset(cbc_in,0,40);
+	memcpy(iv3,cbc_iv,sizeof(cbc_iv));
+	des_xcbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out,
+		(long)strlen((char *)cbc_data)+1,ks,
+		(C_Block *)iv3,
+		(C_Block *)cbc2_key, (C_Block *)cbc3_key, DES_ENCRYPT);
+	if (memcmp(cbc_out,xcbc_ok,32) != 0)
+		{
+		printf("des_xcbc_encrypt encrypt error\n");
+		}
+	memcpy(iv3,cbc_iv,sizeof(cbc_iv));
+	des_xcbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in,
+		(long)strlen((char *)cbc_data)+1,ks,
+		(C_Block *)iv3,
+		(C_Block *)cbc2_key, (C_Block *)cbc3_key, DES_DECRYPT);
+	if (memcmp(cbc_in,cbc_data,strlen((char *)cbc_data)+1) != 0)
+		{
+		printf("des_xcbc_encrypt decrypt error\n");
+		err=1;
+		}
+#endif
+
+	printf("Doing ede cbc\n");
+	if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0)
+		{
+		printf("Key error %d\n",j);
+		err=1;
+		}
+	if ((j=des_key_sched((C_Block *)cbc2_key,ks2)) != 0)
+		{
+		printf("Key error %d\n",j);
+		err=1;
+		}
+	if ((j=des_key_sched((C_Block *)cbc3_key,ks3)) != 0)
+		{
+		printf("Key error %d\n",j);
+		err=1;
+		}
+	memset(cbc_out,0,40);
+	memset(cbc_in,0,40);
+	i=strlen((char *)cbc_data)+1;
+	/* i=((i+7)/8)*8; */
+	memcpy(iv3,cbc_iv,sizeof(cbc_iv));
+
+	des_ede3_cbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out,
+		16L,ks,ks2,ks3,(C_Block *)iv3,DES_ENCRYPT);
+	des_ede3_cbc_encrypt((C_Block *)&(cbc_data[16]),
+		(C_Block *)&(cbc_out[16]),
+		(long)i-16,ks,ks2,ks3,(C_Block *)iv3,DES_ENCRYPT);
+	if (memcmp(cbc_out,cbc3_ok,
+		(unsigned int)(strlen((char *)cbc_data)+1+7)/8*8) != 0)
+		{
+		printf("des_ede3_cbc_encrypt encrypt error\n");
+		err=1;
+		}
+
+	memcpy(iv3,cbc_iv,sizeof(cbc_iv));
+	des_ede3_cbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in,
+		(long)i,ks,ks2,ks3,(C_Block *)iv3,DES_DECRYPT);
+	if (memcmp(cbc_in,cbc_data,strlen(cbc_data)+1) != 0)
+		{
+		printf("des_ede3_cbc_encrypt decrypt error\n");
+		err=1;
+		}
+
+#ifndef LIBDES_LIT
+	printf("Doing pcbc\n");
+	if ((j=des_key_sched((C_Block *)cbc_key,ks)) != 0)
+		{
+		printf("Key error %d\n",j);
+		err=1;
+		}
+	memset(cbc_out,0,40);
+	memset(cbc_in,0,40);
+	des_pcbc_encrypt((C_Block *)cbc_data,(C_Block *)cbc_out,
+		(long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv,DES_ENCRYPT);
+	if (memcmp(cbc_out,pcbc_ok,32) != 0)
+		{
+		printf("pcbc_encrypt encrypt error\n");
+		err=1;
+		}
+	des_pcbc_encrypt((C_Block *)cbc_out,(C_Block *)cbc_in,
+		(long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv,DES_DECRYPT);
+	if (memcmp(cbc_in,cbc_data,strlen(cbc_data)+1) != 0)
+		{
+		printf("pcbc_encrypt decrypt error\n");
+		err=1;
+		}
+
+	printf("Doing ");
+	printf("cfb8 ");
+	err+=cfb_test(8,cfb_cipher8);
+	printf("cfb16 ");
+	err+=cfb_test(16,cfb_cipher16);
+	printf("cfb32 ");
+	err+=cfb_test(32,cfb_cipher32);
+	printf("cfb48 ");
+	err+=cfb_test(48,cfb_cipher48);
+	printf("cfb64 ");
+	err+=cfb_test(64,cfb_cipher64);
+
+	printf("cfb64() ");
+	err+=cfb64_test(cfb_cipher64);
+
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	for (i=0; i<sizeof(plain); i++)
+		des_cfb_encrypt(&(plain[i]),&(cfb_buf1[i]),
+			8,(long)1,ks,(C_Block *)cfb_tmp,DES_ENCRYPT);
+	if (memcmp(cfb_cipher8,cfb_buf1,sizeof(plain)) != 0)
+		{
+		printf("cfb_encrypt small encrypt error\n");
+		err=1;
+		}
+
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	for (i=0; i<sizeof(plain); i++)
+		des_cfb_encrypt(&(cfb_buf1[i]),&(cfb_buf2[i]),
+			8,(long)1,ks,(C_Block *)cfb_tmp,DES_DECRYPT);
+	if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0)
+		{
+		printf("cfb_encrypt small decrypt error\n");
+		err=1;
+		}
+
+	printf("ede_cfb64() ");
+	err+=ede_cfb64_test(cfb_cipher64);
+
+	printf("done\n");
+
+	printf("Doing ofb\n");
+	des_key_sched((C_Block *)ofb_key,ks);
+	memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv));
+	des_ofb_encrypt(plain,ofb_buf1,64,(long)sizeof(plain)/8,ks,
+		(C_Block *)ofb_tmp);
+	if (memcmp(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0)
+		{
+		printf("ofb_encrypt encrypt error\n");
+printf("%02X %02X %02X %02X %02X %02X %02X %02X\n",
+ofb_buf1[8+0], ofb_buf1[8+1], ofb_buf1[8+2], ofb_buf1[8+3],
+ofb_buf1[8+4], ofb_buf1[8+5], ofb_buf1[8+6], ofb_buf1[8+7]);
+printf("%02X %02X %02X %02X %02X %02X %02X %02X\n",
+ofb_buf1[8+0], ofb_cipher[8+1], ofb_cipher[8+2], ofb_cipher[8+3],
+ofb_buf1[8+4], ofb_cipher[8+5], ofb_cipher[8+6], ofb_cipher[8+7]);
+		err=1;
+		}
+	memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv));
+	des_ofb_encrypt(ofb_buf1,ofb_buf2,64,(long)sizeof(ofb_buf1)/8,ks,
+		(C_Block *)ofb_tmp);
+	if (memcmp(plain,ofb_buf2,sizeof(ofb_buf2)) != 0)
+		{
+		printf("ofb_encrypt decrypt error\n");
+printf("%02X %02X %02X %02X %02X %02X %02X %02X\n",
+ofb_buf2[8+0], ofb_buf2[8+1], ofb_buf2[8+2], ofb_buf2[8+3],
+ofb_buf2[8+4], ofb_buf2[8+5], ofb_buf2[8+6], ofb_buf2[8+7]);
+printf("%02X %02X %02X %02X %02X %02X %02X %02X\n",
+plain[8+0], plain[8+1], plain[8+2], plain[8+3],
+plain[8+4], plain[8+5], plain[8+6], plain[8+7]);
+		err=1;
+		}
+
+	printf("Doing ofb64\n");
+	des_key_sched((C_Block *)ofb_key,ks);
+	memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv));
+	memset(ofb_buf1,0,sizeof(ofb_buf1));
+	memset(ofb_buf2,0,sizeof(ofb_buf1));
+	num=0;
+	for (i=0; i<sizeof(plain); i++)
+		{
+		des_ofb64_encrypt(&(plain[i]),&(ofb_buf1[i]),1,ks,
+			(C_Block *)ofb_tmp,&num);
+		}
+	if (memcmp(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0)
+		{
+		printf("ofb64_encrypt encrypt error\n");
+		err=1;
+		}
+	memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv));
+	num=0;
+	des_ofb64_encrypt(ofb_buf1,ofb_buf2,(long)sizeof(ofb_buf1),ks,
+		(C_Block *)ofb_tmp,&num);
+	if (memcmp(plain,ofb_buf2,sizeof(ofb_buf2)) != 0)
+		{
+		printf("ofb64_encrypt decrypt error\n");
+		err=1;
+		}
+
+	printf("Doing ede_ofb64\n");
+	des_key_sched((C_Block *)ofb_key,ks);
+	memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv));
+	memset(ofb_buf1,0,sizeof(ofb_buf1));
+	memset(ofb_buf2,0,sizeof(ofb_buf1));
+	num=0;
+	for (i=0; i<sizeof(plain); i++)
+		{
+		des_ede3_ofb64_encrypt(&(plain[i]),&(ofb_buf1[i]),1,ks,ks,ks,
+			(C_Block *)ofb_tmp,&num);
+		}
+	if (memcmp(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0)
+		{
+		printf("ede_ofb64_encrypt encrypt error\n");
+		err=1;
+		}
+	memcpy(ofb_tmp,ofb_iv,sizeof(ofb_iv));
+	num=0;
+	des_ede3_ofb64_encrypt(ofb_buf1,ofb_buf2,(long)sizeof(ofb_buf1),ks,
+		ks,ks,(C_Block *)ofb_tmp,&num);
+	if (memcmp(plain,ofb_buf2,sizeof(ofb_buf2)) != 0)
+		{
+		printf("ede_ofb64_encrypt decrypt error\n");
+		err=1;
+		}
+
+	printf("Doing cbc_cksum\n");
+	des_key_sched((C_Block *)cbc_key,ks);
+	cs=des_cbc_cksum((C_Block *)cbc_data,(C_Block *)cret,
+		(long)strlen(cbc_data),ks,(C_Block *)cbc_iv);
+	if (cs != cbc_cksum_ret)
+		{
+		printf("bad return value (%08lX), should be %08lX\n",
+			(unsigned long)cs,(unsigned long)cbc_cksum_ret);
+		err=1;
+		}
+	if (memcmp(cret,cbc_cksum_data,8) != 0)
+		{
+		printf("bad cbc_cksum block returned\n");
+		err=1;
+		}
+
+	printf("Doing quad_cksum\n");
+	cs=quad_cksum((C_Block *)cbc_data,(C_Block *)qret,
+		(long)strlen(cbc_data),2,(C_Block *)cbc_iv);
+	for (i=0; i<4; i++)
+		{
+		lqret[i]=0;
+		memcpy(&(lqret[i]),&(qret[i][0]),4);
+		}
+	{ /* Big-endian fix */
+	static DES_LONG l=1;
+	static unsigned char *c=(unsigned char *)&l;
+	DES_LONG ll;
+
+	if (!c[0])
+		{
+		ll=lqret[0]^lqret[3];
+		lqret[0]^=ll;
+		lqret[3]^=ll;
+		ll=lqret[1]^lqret[2];
+		lqret[1]^=ll;
+		lqret[2]^=ll;
+		}
+	}
+	if (cs != 0x70d7a63aL)
+		{
+		printf("quad_cksum error, ret %08lx should be 70d7a63a\n",
+			(unsigned long)cs);
+		err=1;
+		}
+	if (lqret[0] != 0x327eba8dL)
+		{
+		printf("quad_cksum error, out[0] %08lx is not %08lx\n",
+			(unsigned long)lqret[0],0x327eba8dL);
+		err=1;
+		}
+	if (lqret[1] != 0x201a49ccL)
+		{
+		printf("quad_cksum error, out[1] %08lx is not %08lx\n",
+			(unsigned long)lqret[1],0x201a49ccL);
+		err=1;
+		}
+	if (lqret[2] != 0x70d7a63aL)
+		{
+		printf("quad_cksum error, out[2] %08lx is not %08lx\n",
+			(unsigned long)lqret[2],0x70d7a63aL);
+		err=1;
+		}
+	if (lqret[3] != 0x501c2c26L)
+		{
+		printf("quad_cksum error, out[3] %08lx is not %08lx\n",
+			(unsigned long)lqret[3],0x501c2c26L);
+		err=1;
+		}
+#endif
+
+	printf("input word alignment test");
+	for (i=0; i<4; i++)
+		{
+		printf(" %d",i);
+		des_ncbc_encrypt((C_Block *)&(cbc_out[i]),(C_Block *)cbc_in,
+			(long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv,
+			DES_ENCRYPT);
+		}
+	printf("\noutput word alignment test");
+	for (i=0; i<4; i++)
+		{
+		printf(" %d",i);
+		des_ncbc_encrypt((C_Block *)cbc_out,(C_Block *)&(cbc_in[i]),
+			(long)strlen(cbc_data)+1,ks,(C_Block *)cbc_iv,
+			DES_ENCRYPT);
+		}
+	printf("\n");
+	printf("fast crypt test ");
+	str=crypt("testing","ef");
+	if (strcmp("efGnQx2725bI2",str) != 0)
+		{
+		printf("fast crypt error, %s should be efGnQx2725bI2\n",str);
+		err=1;
+		}
+	str=crypt("bca76;23","yA");
+	if (strcmp("yA1Rp/1hZXIJk",str) != 0)
+		{
+		printf("fast crypt error, %s should be yA1Rp/1hZXIJk\n",str);
+		err=1;
+		}
+	printf("\n");
+	exit(err);
+	return(0);
+	}
+
+static char *pt(p)
+unsigned char *p;
+	{
+	static char bufs[10][20];
+	static int bnum=0;
+	char *ret;
+	int i;
+	static char *f="0123456789ABCDEF";
+
+	ret= &(bufs[bnum++][0]);
+	bnum%=10;
+	for (i=0; i<8; i++)
+		{
+		ret[i*2]=f[(p[i]>>4)&0xf];
+		ret[i*2+1]=f[p[i]&0xf];
+		}
+	ret[16]='\0';
+	return(ret);
+	}
+
+#ifndef LIBDES_LIT
+
+static int cfb_test(bits, cfb_cipher)
+int bits;
+unsigned char *cfb_cipher;
+	{
+	des_key_schedule ks;
+	int i,err=0;
+
+	des_key_sched((C_Block *)cfb_key,ks);
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	des_cfb_encrypt(plain,cfb_buf1,bits,(long)sizeof(plain),ks,
+		(C_Block *)cfb_tmp,DES_ENCRYPT);
+	if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0)
+		{
+		err=1;
+		printf("cfb_encrypt encrypt error\n");
+		for (i=0; i<24; i+=8)
+			printf("%s\n",pt(&(cfb_buf1[i])));
+		}
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	des_cfb_encrypt(cfb_buf1,cfb_buf2,bits,(long)sizeof(plain),ks,
+		(C_Block *)cfb_tmp,DES_DECRYPT);
+	if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0)
+		{
+		err=1;
+		printf("cfb_encrypt decrypt error\n");
+		for (i=0; i<24; i+=8)
+			printf("%s\n",pt(&(cfb_buf1[i])));
+		}
+	return(err);
+	}
+
+static int cfb64_test(cfb_cipher)
+unsigned char *cfb_cipher;
+	{
+	des_key_schedule ks;
+	int err=0,i,n;
+
+	des_key_sched((C_Block *)cfb_key,ks);
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	n=0;
+	des_cfb64_encrypt(plain,cfb_buf1,(long)12,ks,
+		(C_Block *)cfb_tmp,&n,DES_ENCRYPT);
+	des_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]),
+		(long)sizeof(plain)-12,ks,
+		(C_Block *)cfb_tmp,&n,DES_ENCRYPT);
+	if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0)
+		{
+		err=1;
+		printf("cfb_encrypt encrypt error\n");
+		for (i=0; i<24; i+=8)
+			printf("%s\n",pt(&(cfb_buf1[i])));
+		}
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	n=0;
+	des_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks,
+		(C_Block *)cfb_tmp,&n,DES_DECRYPT);
+	des_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]),
+		(long)sizeof(plain)-17,ks,
+		(C_Block *)cfb_tmp,&n,DES_DECRYPT);
+	if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0)
+		{
+		err=1;
+		printf("cfb_encrypt decrypt error\n");
+		for (i=0; i<24; i+=8)
+			printf("%s\n",pt(&(cfb_buf2[i])));
+		}
+	return(err);
+	}
+
+static int ede_cfb64_test(cfb_cipher)
+unsigned char *cfb_cipher;
+	{
+	des_key_schedule ks;
+	int err=0,i,n;
+
+	des_key_sched((C_Block *)cfb_key,ks);
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	n=0;
+	des_ede3_cfb64_encrypt(plain,cfb_buf1,(long)12,ks,ks,ks,
+		(C_Block *)cfb_tmp,&n,DES_ENCRYPT);
+	des_ede3_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]),
+		(long)sizeof(plain)-12,ks,ks,ks,
+		(C_Block *)cfb_tmp,&n,DES_ENCRYPT);
+	if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0)
+		{
+		err=1;
+		printf("ede_cfb_encrypt encrypt error\n");
+		for (i=0; i<24; i+=8)
+			printf("%s\n",pt(&(cfb_buf1[i])));
+		}
+	memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv));
+	n=0;
+	des_ede3_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks,ks,ks,
+		(C_Block *)cfb_tmp,&n,DES_DECRYPT);
+	des_ede3_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]),
+		(long)sizeof(plain)-17,ks,ks,ks,
+		(C_Block *)cfb_tmp,&n,DES_DECRYPT);
+	if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0)
+		{
+		err=1;
+		printf("ede_cfb_encrypt decrypt error\n");
+		for (i=0; i<24; i+=8)
+			printf("%s\n",pt(&(cfb_buf2[i])));
+		}
+	return(err);
+	}
+
+#endif
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/ecb_enc.c linux-patched/net/ipsec/libdes/ecb_enc.c
--- linux/net/ipsec/libdes/ecb_enc.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/ecb_enc.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,128 @@
+/* crypto/des/ecb_enc.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_locl.h"
+#include "spr.h"
+
+char *libdes_version="libdes v 3.24 - 20-Apr-1996 - eay";
+char *DES_version="DES part of SSLeay 0.8.2b 08-Jan-1998";
+
+/* RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $ */
+/* This function ifdef'ed out for FreeS/WAN project. */
+#ifdef notdef
+char *des_options()
+	{
+	static int init=1;
+	static char buf[32];
+
+	if (init)
+		{
+		char *ptr,*unroll,*risc,*size;
+
+		init=0;
+#ifdef DES_PTR
+		ptr="ptr";
+#else
+		ptr="idx";
+#endif
+#if defined(DES_RISC1) || defined(DES_RISC2)
+#ifdef DES_RISC1
+		risc="risc1";
+#endif
+#ifdef DES_RISC2
+		risc="risc2";
+#endif
+#else
+		risc="cisc";
+#endif
+#ifdef DES_UNROLL
+		unroll="16";
+#else
+		unroll="4";
+#endif
+		if (sizeof(DES_LONG) != sizeof(long))
+			size="int";
+		else
+			size="long";
+		sprintf(buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,size);
+		}
+	return(buf);
+	}
+#endif
+		
+
+void des_ecb_encrypt(input, output, ks, enc)
+des_cblock (*input);
+des_cblock (*output);
+des_key_schedule ks;
+int enc;
+	{
+	register DES_LONG l;
+	register unsigned char *in,*out;
+	DES_LONG ll[2];
+
+	in=(unsigned char *)input;
+	out=(unsigned char *)output;
+	c2l(in,l); ll[0]=l;
+	c2l(in,l); ll[1]=l;
+	des_encrypt(ll,ks,enc);
+	l=ll[0]; l2c(l,out);
+	l=ll[1]; l2c(l,out);
+	l=ll[0]=ll[1]=0;
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/fcrypt.c linux-patched/net/ipsec/libdes/fcrypt.c
--- linux/net/ipsec/libdes/fcrypt.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/fcrypt.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,152 @@
+/* NOCW */
+
+/* This version of crypt has been developed from my MIT compatable
+ * DES library.
+ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au
+ * Eric Young (eay@cryptsoft.com)
+ */
+
+/* Modification by Jens Kupferschmidt (Cu)
+ * I have included directive PARA for shared memory computers.
+ * I have included a directive LONGCRYPT to using this routine to cipher
+ * passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN
+ * definition is the maximum of lenght of password and can changed. I have
+ * defined 24.
+ */
+
+#include "des_locl.h"
+
+/* Added more values to handle illegal salt values the way normal
+ * crypt() implementations do.  The patch was sent by 
+ * Bjorn Gronvall <bg@sics.se>
+ */
+static unsigned const char con_salt[128]={
+0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
+0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,
+0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,
+0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,
+0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,
+0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01,
+0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
+0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A,
+0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,
+0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,
+0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,
+0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24,
+0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,
+0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,
+0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,
+0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,
+};
+
+static unsigned const char cov_2char[64]={
+0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
+0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,
+0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,
+0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,
+0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62,
+0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,
+0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,
+0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A
+};
+
+#ifndef NOPROTO
+void fcrypt_body(DES_LONG *out,des_key_schedule ks,
+	DES_LONG Eswap0, DES_LONG Eswap1);
+
+#ifdef PERL5
+char *des_crypt(const char *buf,const char *salt);
+#else
+char *crypt(const char *buf,const char *salt);
+#endif
+#else
+void fcrypt_body();
+#ifdef PERL5
+char *des_crypt();
+#else
+char *crypt();
+#endif
+#endif
+
+#ifdef PERL5
+char *des_crypt(buf,salt)
+#else
+char *crypt(buf,salt)
+#endif
+const char *buf;
+const char *salt;
+	{
+	static char buff[14];
+
+	return(des_fcrypt(buf,salt,buff));
+	}
+
+
+char *des_fcrypt(buf,salt,ret)
+const char *buf;
+const char *salt;
+char *ret;
+	{
+	unsigned int i,j,x,y;
+	DES_LONG Eswap0,Eswap1;
+	DES_LONG out[2],ll;
+	des_cblock key;
+	des_key_schedule ks;
+	unsigned char bb[9];
+	unsigned char *b=bb;
+	unsigned char c,u;
+
+	/* eay 25/08/92
+	 * If you call crypt("pwd","*") as often happens when you
+	 * have * as the pwd field in /etc/passwd, the function
+	 * returns *\0XXXXXXXXX
+	 * The \0 makes the string look like * so the pwd "*" would
+	 * crypt to "*".  This was found when replacing the crypt in
+	 * our shared libraries.  People found that the disbled
+	 * accounts effectivly had no passwd :-(. */
+	x=ret[0]=((salt[0] == '\0')?'A':salt[0]);
+	Eswap0=con_salt[x]<<2;
+	x=ret[1]=((salt[1] == '\0')?'A':salt[1]);
+	Eswap1=con_salt[x]<<6;
+
+/* EAY
+r=strlen(buf);
+r=(r+7)/8;
+*/
+	for (i=0; i<8; i++)
+		{
+		c= *(buf++);
+		if (!c) break;
+		key[i]=(c<<1);
+		}
+	for (; i<8; i++)
+		key[i]=0;
+
+	des_set_key((des_cblock *)(key),ks);
+	fcrypt_body(&(out[0]),ks,Eswap0,Eswap1);
+
+	ll=out[0]; l2c(ll,b);
+	ll=out[1]; l2c(ll,b);
+	y=0;
+	u=0x80;
+	bb[8]=0;
+	for (i=2; i<13; i++)
+		{
+		c=0;
+		for (j=0; j<6; j++)
+			{
+			c<<=1;
+			if (bb[y] & u) c|=1;
+			u>>=1;
+			if (!u)
+				{
+				y++;
+				u=0x80;
+				}
+			}
+		ret[i]=cov_2char[c];
+		}
+	ret[13]='\0';
+	return(ret);
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/fcrypt_b.c linux-patched/net/ipsec/libdes/fcrypt_b.c
--- linux/net/ipsec/libdes/fcrypt_b.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/fcrypt_b.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,148 @@
+/* crypto/des/fcrypt_b.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* #include <stdio.h> */
+
+/* This version of crypt has been developed from my MIT compatable
+ * DES library.
+ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au
+ * Eric Young (eay@cryptsoft.com)
+ */
+
+#define DES_FCRYPT
+#include "des_locl.h"
+#undef DES_FCRYPT
+
+#undef PERM_OP
+#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
+	(b)^=(t),\
+	(a)^=((t)<<(n)))
+
+#undef HPERM_OP
+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
+	(a)=(a)^(t)^(t>>(16-(n))))\
+
+void fcrypt_body(out, ks, Eswap0, Eswap1)
+DES_LONG *out;
+des_key_schedule ks;
+DES_LONG Eswap0;
+DES_LONG Eswap1;
+	{
+	register DES_LONG l,r,t,u;
+#ifdef DES_PTR
+	register unsigned char *des_SP=(unsigned char *)des_SPtrans;
+#endif
+	register DES_LONG *s;
+	register int j;
+	register DES_LONG E0,E1;
+
+	l=0;
+	r=0;
+
+	s=(DES_LONG *)ks;
+	E0=Eswap0;
+	E1=Eswap1;
+
+	for (j=0; j<25; j++)
+		{
+#ifdef DES_UNROLL
+		register int i;
+
+		for (i=0; i<32; i+=8)
+			{
+			D_ENCRYPT(l,r,i+0); /*  1 */
+			D_ENCRYPT(r,l,i+2); /*  2 */
+			D_ENCRYPT(l,r,i+4); /*  1 */
+			D_ENCRYPT(r,l,i+6); /*  2 */
+			}
+#else
+		D_ENCRYPT(l,r, 0); /*  1 */
+		D_ENCRYPT(r,l, 2); /*  2 */
+		D_ENCRYPT(l,r, 4); /*  3 */
+		D_ENCRYPT(r,l, 6); /*  4 */
+		D_ENCRYPT(l,r, 8); /*  5 */
+		D_ENCRYPT(r,l,10); /*  6 */
+		D_ENCRYPT(l,r,12); /*  7 */
+		D_ENCRYPT(r,l,14); /*  8 */
+		D_ENCRYPT(l,r,16); /*  9 */
+		D_ENCRYPT(r,l,18); /*  10 */
+		D_ENCRYPT(l,r,20); /*  11 */
+		D_ENCRYPT(r,l,22); /*  12 */
+		D_ENCRYPT(l,r,24); /*  13 */
+		D_ENCRYPT(r,l,26); /*  14 */
+		D_ENCRYPT(l,r,28); /*  15 */
+		D_ENCRYPT(r,l,30); /*  16 */
+#endif
+
+		t=l;
+		l=r;
+		r=t;
+		}
+	l=ROTATE(l,3)&0xffffffffL;
+	r=ROTATE(r,3)&0xffffffffL;
+
+	PERM_OP(l,r,t, 1,0x55555555L);
+	PERM_OP(r,l,t, 8,0x00ff00ffL);
+	PERM_OP(l,r,t, 2,0x33333333L);
+	PERM_OP(r,l,t,16,0x0000ffffL);
+	PERM_OP(l,r,t, 4,0x0f0f0f0fL);
+
+	out[0]=r;
+	out[1]=l;
+	}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/podd.h linux-patched/net/ipsec/libdes/podd.h
--- linux/net/ipsec/libdes/podd.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/podd.h	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,75 @@
+/* crypto/des/podd.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+static const unsigned char odd_parity[256]={
+  1,  1,  2,  2,  4,  4,  7,  7,  8,  8, 11, 11, 13, 13, 14, 14,
+ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
+ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
+ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
+ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
+ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
+ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
+112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
+128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
+145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
+161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
+176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
+193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
+208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
+224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
+241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254};
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/set_key.c linux-patched/net/ipsec/libdes/set_key.c
--- linux/net/ipsec/libdes/set_key.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/set_key.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,246 @@
+/* crypto/des/set_key.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* set_key.c v 1.4 eay 24/9/91
+ * 1.4 Speed up by 400% :-)
+ * 1.3 added register declarations.
+ * 1.2 unrolled make_key_sched a bit more
+ * 1.1 added norm_expand_bits
+ * 1.0 First working version
+ */
+#include "des_locl.h"
+#include "podd.h"
+#include "sk.h"
+
+#ifndef NOPROTO
+static int check_parity(des_cblock (*key));
+#else
+static int check_parity();
+#endif
+
+int des_check_key=0;
+
+void des_set_odd_parity(key)
+des_cblock (*key);
+	{
+	int i;
+
+	for (i=0; i<DES_KEY_SZ; i++)
+		(*key)[i]=odd_parity[(*key)[i]];
+	}
+
+static int check_parity(key)
+des_cblock (*key);
+	{
+	int i;
+
+	for (i=0; i<DES_KEY_SZ; i++)
+		{
+		if ((*key)[i] != odd_parity[(*key)[i]])
+			return(0);
+		}
+	return(1);
+	}
+
+/* Weak and semi week keys as take from
+ * %A D.W. Davies
+ * %A W.L. Price
+ * %T Security for Computer Networks
+ * %I John Wiley & Sons
+ * %D 1984
+ * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference
+ * (and actual cblock values).
+ */
+#define NUM_WEAK_KEY	16
+static des_cblock weak_keys[NUM_WEAK_KEY]={
+	/* weak keys */
+	{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
+	{0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
+	{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},
+	{0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0},
+	/* semi-weak keys */
+	{0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE},
+	{0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
+	{0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
+	{0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
+	{0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
+	{0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
+	{0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
+	{0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
+	{0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
+	{0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
+	{0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
+	{0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}};
+
+int des_is_weak_key(key)
+des_cblock (*key);
+	{
+	int i;
+
+	for (i=0; i<NUM_WEAK_KEY; i++)
+		/* Added == 0 to comparision, I obviously don't run
+		 * this section very often :-(, thanks to
+		 * engineering@MorningStar.Com for the fix
+		 * eay 93/06/29
+		 * Another problem, I was comparing only the first 4
+		 * bytes, 97/03/18 */
+		if (memcmp(weak_keys[i],key,sizeof(des_cblock)) == 0) return(1);
+	return(0);
+	}
+
+/* NOW DEFINED IN des_local.h
+ * See ecb_encrypt.c for a pseudo description of these macros. 
+ * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
+ * 	(b)^=(t),\
+ * 	(a)=((a)^((t)<<(n))))
+ */
+
+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
+	(a)=(a)^(t)^(t>>(16-(n))))
+
+/* return 0 if key parity is odd (correct),
+ * return -1 if key parity error,
+ * return -2 if illegal weak key.
+ */
+int des_set_key(key, schedule)
+des_cblock (*key);
+des_key_schedule schedule;
+	{
+	static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0};
+	register DES_LONG c,d,t,s,t2;
+	register unsigned char *in;
+	register DES_LONG *k;
+	register int i;
+
+	if (des_check_key)
+		{
+		if (!check_parity(key))
+			return(-1);
+
+		if (des_is_weak_key(key))
+			return(-2);
+		}
+
+	k=(DES_LONG *)schedule;
+	in=(unsigned char *)key;
+
+	c2l(in,c);
+	c2l(in,d);
+
+	/* do PC1 in 60 simple operations */ 
+/*	PERM_OP(d,c,t,4,0x0f0f0f0fL);
+	HPERM_OP(c,t,-2, 0xcccc0000L);
+	HPERM_OP(c,t,-1, 0xaaaa0000L);
+	HPERM_OP(c,t, 8, 0x00ff0000L);
+	HPERM_OP(c,t,-1, 0xaaaa0000L);
+	HPERM_OP(d,t,-8, 0xff000000L);
+	HPERM_OP(d,t, 8, 0x00ff0000L);
+	HPERM_OP(d,t, 2, 0x33330000L);
+	d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L);
+	d=(d>>8)|((c&0xf0000000L)>>4);
+	c&=0x0fffffffL; */
+
+	/* I now do it in 47 simple operations :-)
+	 * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
+	 * for the inspiration. :-) */
+	PERM_OP (d,c,t,4,0x0f0f0f0fL);
+	HPERM_OP(c,t,-2,0xcccc0000L);
+	HPERM_OP(d,t,-2,0xcccc0000L);
+	PERM_OP (d,c,t,1,0x55555555L);
+	PERM_OP (c,d,t,8,0x00ff00ffL);
+	PERM_OP (d,c,t,1,0x55555555L);
+	d=	(((d&0x000000ffL)<<16L)| (d&0x0000ff00L)     |
+		 ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L));
+	c&=0x0fffffffL;
+
+	for (i=0; i<ITERATIONS; i++)
+		{
+		if (shifts2[i])
+			{ c=((c>>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); }
+		else
+			{ c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); }
+		c&=0x0fffffffL;
+		d&=0x0fffffffL;
+		/* could be a few less shifts but I am to lazy at this
+		 * point in time to investigate */
+		s=	des_skb[0][ (c    )&0x3f                ]|
+			des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]|
+			des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]|
+			des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) |
+						  ((c>>22L)&0x38)];
+		t=	des_skb[4][ (d    )&0x3f                ]|
+			des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]|
+			des_skb[6][ (d>>15L)&0x3f                ]|
+			des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)];
+
+		/* table contained 0213 4657 */
+		t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL;
+		*(k++)=ROTATE(t2,30)&0xffffffffL;
+
+		t2=((s>>16L)|(t&0xffff0000L));
+		*(k++)=ROTATE(t2,26)&0xffffffffL;
+		}
+	return(0);
+	}
+
+int des_key_sched(key, schedule)
+des_cblock (*key);
+des_key_schedule schedule;
+	{
+	return(des_set_key(key,schedule));
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/sk.h linux-patched/net/ipsec/libdes/sk.h
--- linux/net/ipsec/libdes/sk.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/sk.h	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,204 @@
+/* crypto/des/sk.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+static const DES_LONG des_skb[8][64]={
+{
+/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
+0x00000000L,0x00000010L,0x20000000L,0x20000010L,
+0x00010000L,0x00010010L,0x20010000L,0x20010010L,
+0x00000800L,0x00000810L,0x20000800L,0x20000810L,
+0x00010800L,0x00010810L,0x20010800L,0x20010810L,
+0x00000020L,0x00000030L,0x20000020L,0x20000030L,
+0x00010020L,0x00010030L,0x20010020L,0x20010030L,
+0x00000820L,0x00000830L,0x20000820L,0x20000830L,
+0x00010820L,0x00010830L,0x20010820L,0x20010830L,
+0x00080000L,0x00080010L,0x20080000L,0x20080010L,
+0x00090000L,0x00090010L,0x20090000L,0x20090010L,
+0x00080800L,0x00080810L,0x20080800L,0x20080810L,
+0x00090800L,0x00090810L,0x20090800L,0x20090810L,
+0x00080020L,0x00080030L,0x20080020L,0x20080030L,
+0x00090020L,0x00090030L,0x20090020L,0x20090030L,
+0x00080820L,0x00080830L,0x20080820L,0x20080830L,
+0x00090820L,0x00090830L,0x20090820L,0x20090830L,
+},{
+/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
+0x00000000L,0x02000000L,0x00002000L,0x02002000L,
+0x00200000L,0x02200000L,0x00202000L,0x02202000L,
+0x00000004L,0x02000004L,0x00002004L,0x02002004L,
+0x00200004L,0x02200004L,0x00202004L,0x02202004L,
+0x00000400L,0x02000400L,0x00002400L,0x02002400L,
+0x00200400L,0x02200400L,0x00202400L,0x02202400L,
+0x00000404L,0x02000404L,0x00002404L,0x02002404L,
+0x00200404L,0x02200404L,0x00202404L,0x02202404L,
+0x10000000L,0x12000000L,0x10002000L,0x12002000L,
+0x10200000L,0x12200000L,0x10202000L,0x12202000L,
+0x10000004L,0x12000004L,0x10002004L,0x12002004L,
+0x10200004L,0x12200004L,0x10202004L,0x12202004L,
+0x10000400L,0x12000400L,0x10002400L,0x12002400L,
+0x10200400L,0x12200400L,0x10202400L,0x12202400L,
+0x10000404L,0x12000404L,0x10002404L,0x12002404L,
+0x10200404L,0x12200404L,0x10202404L,0x12202404L,
+},{
+/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
+0x00000000L,0x00000001L,0x00040000L,0x00040001L,
+0x01000000L,0x01000001L,0x01040000L,0x01040001L,
+0x00000002L,0x00000003L,0x00040002L,0x00040003L,
+0x01000002L,0x01000003L,0x01040002L,0x01040003L,
+0x00000200L,0x00000201L,0x00040200L,0x00040201L,
+0x01000200L,0x01000201L,0x01040200L,0x01040201L,
+0x00000202L,0x00000203L,0x00040202L,0x00040203L,
+0x01000202L,0x01000203L,0x01040202L,0x01040203L,
+0x08000000L,0x08000001L,0x08040000L,0x08040001L,
+0x09000000L,0x09000001L,0x09040000L,0x09040001L,
+0x08000002L,0x08000003L,0x08040002L,0x08040003L,
+0x09000002L,0x09000003L,0x09040002L,0x09040003L,
+0x08000200L,0x08000201L,0x08040200L,0x08040201L,
+0x09000200L,0x09000201L,0x09040200L,0x09040201L,
+0x08000202L,0x08000203L,0x08040202L,0x08040203L,
+0x09000202L,0x09000203L,0x09040202L,0x09040203L,
+},{
+/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
+0x00000000L,0x00100000L,0x00000100L,0x00100100L,
+0x00000008L,0x00100008L,0x00000108L,0x00100108L,
+0x00001000L,0x00101000L,0x00001100L,0x00101100L,
+0x00001008L,0x00101008L,0x00001108L,0x00101108L,
+0x04000000L,0x04100000L,0x04000100L,0x04100100L,
+0x04000008L,0x04100008L,0x04000108L,0x04100108L,
+0x04001000L,0x04101000L,0x04001100L,0x04101100L,
+0x04001008L,0x04101008L,0x04001108L,0x04101108L,
+0x00020000L,0x00120000L,0x00020100L,0x00120100L,
+0x00020008L,0x00120008L,0x00020108L,0x00120108L,
+0x00021000L,0x00121000L,0x00021100L,0x00121100L,
+0x00021008L,0x00121008L,0x00021108L,0x00121108L,
+0x04020000L,0x04120000L,0x04020100L,0x04120100L,
+0x04020008L,0x04120008L,0x04020108L,0x04120108L,
+0x04021000L,0x04121000L,0x04021100L,0x04121100L,
+0x04021008L,0x04121008L,0x04021108L,0x04121108L,
+},{
+/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
+0x00000000L,0x10000000L,0x00010000L,0x10010000L,
+0x00000004L,0x10000004L,0x00010004L,0x10010004L,
+0x20000000L,0x30000000L,0x20010000L,0x30010000L,
+0x20000004L,0x30000004L,0x20010004L,0x30010004L,
+0x00100000L,0x10100000L,0x00110000L,0x10110000L,
+0x00100004L,0x10100004L,0x00110004L,0x10110004L,
+0x20100000L,0x30100000L,0x20110000L,0x30110000L,
+0x20100004L,0x30100004L,0x20110004L,0x30110004L,
+0x00001000L,0x10001000L,0x00011000L,0x10011000L,
+0x00001004L,0x10001004L,0x00011004L,0x10011004L,
+0x20001000L,0x30001000L,0x20011000L,0x30011000L,
+0x20001004L,0x30001004L,0x20011004L,0x30011004L,
+0x00101000L,0x10101000L,0x00111000L,0x10111000L,
+0x00101004L,0x10101004L,0x00111004L,0x10111004L,
+0x20101000L,0x30101000L,0x20111000L,0x30111000L,
+0x20101004L,0x30101004L,0x20111004L,0x30111004L,
+},{
+/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
+0x00000000L,0x08000000L,0x00000008L,0x08000008L,
+0x00000400L,0x08000400L,0x00000408L,0x08000408L,
+0x00020000L,0x08020000L,0x00020008L,0x08020008L,
+0x00020400L,0x08020400L,0x00020408L,0x08020408L,
+0x00000001L,0x08000001L,0x00000009L,0x08000009L,
+0x00000401L,0x08000401L,0x00000409L,0x08000409L,
+0x00020001L,0x08020001L,0x00020009L,0x08020009L,
+0x00020401L,0x08020401L,0x00020409L,0x08020409L,
+0x02000000L,0x0A000000L,0x02000008L,0x0A000008L,
+0x02000400L,0x0A000400L,0x02000408L,0x0A000408L,
+0x02020000L,0x0A020000L,0x02020008L,0x0A020008L,
+0x02020400L,0x0A020400L,0x02020408L,0x0A020408L,
+0x02000001L,0x0A000001L,0x02000009L,0x0A000009L,
+0x02000401L,0x0A000401L,0x02000409L,0x0A000409L,
+0x02020001L,0x0A020001L,0x02020009L,0x0A020009L,
+0x02020401L,0x0A020401L,0x02020409L,0x0A020409L,
+},{
+/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
+0x00000000L,0x00000100L,0x00080000L,0x00080100L,
+0x01000000L,0x01000100L,0x01080000L,0x01080100L,
+0x00000010L,0x00000110L,0x00080010L,0x00080110L,
+0x01000010L,0x01000110L,0x01080010L,0x01080110L,
+0x00200000L,0x00200100L,0x00280000L,0x00280100L,
+0x01200000L,0x01200100L,0x01280000L,0x01280100L,
+0x00200010L,0x00200110L,0x00280010L,0x00280110L,
+0x01200010L,0x01200110L,0x01280010L,0x01280110L,
+0x00000200L,0x00000300L,0x00080200L,0x00080300L,
+0x01000200L,0x01000300L,0x01080200L,0x01080300L,
+0x00000210L,0x00000310L,0x00080210L,0x00080310L,
+0x01000210L,0x01000310L,0x01080210L,0x01080310L,
+0x00200200L,0x00200300L,0x00280200L,0x00280300L,
+0x01200200L,0x01200300L,0x01280200L,0x01280300L,
+0x00200210L,0x00200310L,0x00280210L,0x00280310L,
+0x01200210L,0x01200310L,0x01280210L,0x01280310L,
+},{
+/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
+0x00000000L,0x04000000L,0x00040000L,0x04040000L,
+0x00000002L,0x04000002L,0x00040002L,0x04040002L,
+0x00002000L,0x04002000L,0x00042000L,0x04042000L,
+0x00002002L,0x04002002L,0x00042002L,0x04042002L,
+0x00000020L,0x04000020L,0x00040020L,0x04040020L,
+0x00000022L,0x04000022L,0x00040022L,0x04040022L,
+0x00002020L,0x04002020L,0x00042020L,0x04042020L,
+0x00002022L,0x04002022L,0x00042022L,0x04042022L,
+0x00000800L,0x04000800L,0x00040800L,0x04040800L,
+0x00000802L,0x04000802L,0x00040802L,0x04040802L,
+0x00002800L,0x04002800L,0x00042800L,0x04042800L,
+0x00002802L,0x04002802L,0x00042802L,0x04042802L,
+0x00000820L,0x04000820L,0x00040820L,0x04040820L,
+0x00000822L,0x04000822L,0x00040822L,0x04040822L,
+0x00002820L,0x04002820L,0x00042820L,0x04042820L,
+0x00002822L,0x04002822L,0x00042822L,0x04042822L,
+}};
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/speed.c linux-patched/net/ipsec/libdes/speed.c
--- linux/net/ipsec/libdes/speed.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/speed.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,329 @@
+/* crypto/des/speed.c */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* 11-Sep-92 Andrew Daviel   Support for Silicon Graphics IRIX added */
+/* 06-Apr-92 Luke Brennan    Support for VMS and add extra signal calls */
+
+#ifndef MSDOS
+#define TIMES
+#endif
+
+#include <stdio.h>
+#ifndef MSDOS
+#include <unistd.h>
+#else
+#include <io.h>
+extern int exit();
+#endif
+#include <signal.h>
+#ifndef VMS
+#ifndef _IRIX
+#include <time.h>
+#endif
+#ifdef TIMES
+#include <sys/types.h>
+#include <sys/times.h>
+#endif
+#else /* VMS */
+#include <types.h>
+struct tms {
+	time_t tms_utime;
+	time_t tms_stime;
+	time_t tms_uchild;	/* I dunno...  */
+	time_t tms_uchildsys;	/* so these names are a guess :-) */
+	}
+#endif
+#ifndef TIMES
+#include <sys/timeb.h>
+#endif
+
+#ifdef sun
+#include <limits.h>
+#include <sys/param.h>
+#endif
+
+#include "des.h"
+
+/* The following if from times(3) man page.  It may need to be changed */
+#ifndef HZ
+# ifndef CLK_TCK
+#  ifndef _BSD_CLK_TCK_ /* FreeBSD fix */
+#   ifndef VMS
+#    define HZ	100.0
+#   else /* VMS */
+#    define HZ	100.0
+#   endif
+#  else /* _BSD_CLK_TCK_ */
+#   define HZ ((double)_BSD_CLK_TCK_)
+#  endif
+# else /* CLK_TCK */
+#  define HZ ((double)CLK_TCK)
+# endif
+#endif
+
+#define BUFSIZE	((long)1024)
+long run=0;
+
+#ifndef NOPROTO
+double Time_F(int s);
+#else
+double Time_F();
+#endif
+
+#ifdef SIGALRM
+#if defined(__STDC__) || defined(sgi) || defined(_AIX)
+#define SIGRETTYPE void
+#else
+#define SIGRETTYPE int
+#endif
+
+#ifndef NOPROTO
+SIGRETTYPE sig_done(int sig);
+#else
+SIGRETTYPE sig_done();
+#endif
+
+SIGRETTYPE sig_done(sig)
+int sig;
+	{
+	signal(SIGALRM,sig_done);
+	run=0;
+#ifdef LINT
+	sig=sig;
+#endif
+	}
+#endif
+
+#define START	0
+#define STOP	1
+
+double Time_F(s)
+int s;
+	{
+	double ret;
+#ifdef TIMES
+	static struct tms tstart,tend;
+
+	if (s == START)
+		{
+		times(&tstart);
+		return(0);
+		}
+	else
+		{
+		times(&tend);
+		ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ;
+		return((ret == 0.0)?1e-6:ret);
+		}
+#else /* !times() */
+	static struct timeb tstart,tend;
+	long i;
+
+	if (s == START)
+		{
+		ftime(&tstart);
+		return(0);
+		}
+	else
+		{
+		ftime(&tend);
+		i=(long)tend.millitm-(long)tstart.millitm;
+		ret=((double)(tend.time-tstart.time))+((double)i)/1e3;
+		return((ret == 0.0)?1e-6:ret);
+		}
+#endif
+	}
+
+int main(argc,argv)
+int argc;
+char **argv;
+	{
+	long count;
+	static unsigned char buf[BUFSIZE];
+	static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0};
+	static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
+	static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+	des_key_schedule sch,sch2,sch3;
+	double a,b,c,d,e;
+#ifndef SIGALRM
+	long ca,cb,cc,cd,ce;
+#endif
+
+#ifndef TIMES
+	printf("To get the most acurate results, try to run this\n");
+	printf("program when this computer is idle.\n");
+#endif
+
+	des_set_key((C_Block *)key2,sch2);
+	des_set_key((C_Block *)key3,sch3);
+
+#ifndef SIGALRM
+	printf("First we calculate the approximate speed ...\n");
+	des_set_key((C_Block *)key,sch);
+	count=10;
+	do	{
+		long i;
+		DES_LONG data[2];
+
+		count*=2;
+		Time_F(START);
+		for (i=count; i; i--)
+			des_encrypt(data,&(sch[0]),DES_ENCRYPT);
+		d=Time_F(STOP);
+		} while (d < 3.0);
+	ca=count;
+	cb=count*3;
+	cc=count*3*8/BUFSIZE+1;
+	cd=count*8/BUFSIZE+1;
+	ce=count/20+1;
+	printf("Doing set_key %ld times\n",ca);
+#define COND(d)	(count != (d))
+#define COUNT(d) (d)
+#else
+#define COND(c)	(run)
+#define COUNT(d) (count)
+	signal(SIGALRM,sig_done);
+	printf("Doing set_key for 10 seconds\n");
+	alarm(10);
+#endif
+
+	Time_F(START);
+	for (count=0,run=1; COND(ca); count++)
+		des_set_key((C_Block *)key,sch);
+	d=Time_F(STOP);
+	printf("%ld set_key's in %.2f seconds\n",count,d);
+	a=((double)COUNT(ca))/d;
+
+#ifdef SIGALRM
+	printf("Doing des_encrypt's for 10 seconds\n");
+	alarm(10);
+#else
+	printf("Doing des_encrypt %ld times\n",cb);
+#endif
+	Time_F(START);
+	for (count=0,run=1; COND(cb); count++)
+		{
+		DES_LONG data[2];
+
+		des_encrypt(data,&(sch[0]),DES_ENCRYPT);
+		}
+	d=Time_F(STOP);
+	printf("%ld des_encrypt's in %.2f second\n",count,d);
+	b=((double)COUNT(cb)*8)/d;
+
+#ifdef SIGALRM
+	printf("Doing des_cbc_encrypt on %ld byte blocks for 10 seconds\n",
+		BUFSIZE);
+	alarm(10);
+#else
+	printf("Doing des_cbc_encrypt %ld times on %ld byte blocks\n",cc,
+		BUFSIZE);
+#endif
+	Time_F(START);
+	for (count=0,run=1; COND(cc); count++)
+		des_ncbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE,&(sch[0]),
+			(C_Block *)&(key[0]),DES_ENCRYPT);
+	d=Time_F(STOP);
+	printf("%ld des_cbc_encrypt's of %ld byte blocks in %.2f second\n",
+		count,BUFSIZE,d);
+	c=((double)COUNT(cc)*BUFSIZE)/d;
+
+#ifdef SIGALRM
+	printf("Doing des_ede_cbc_encrypt on %ld byte blocks for 10 seconds\n",
+		BUFSIZE);
+	alarm(10);
+#else
+	printf("Doing des_ede_cbc_encrypt %ld times on %ld byte blocks\n",cd,
+		BUFSIZE);
+#endif
+	Time_F(START);
+	for (count=0,run=1; COND(cd); count++)
+		des_ede3_cbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE,
+			&(sch[0]),
+			&(sch2[0]),
+			&(sch3[0]),
+			(C_Block *)&(key[0]),
+			DES_ENCRYPT);
+	d=Time_F(STOP);
+	printf("%ld des_ede_cbc_encrypt's of %ld byte blocks in %.2f second\n",
+		count,BUFSIZE,d);
+	d=((double)COUNT(cd)*BUFSIZE)/d;
+
+#ifdef SIGALRM
+	printf("Doing crypt for 10 seconds\n");
+	alarm(10);
+#else
+	printf("Doing crypt %ld times\n",ce);
+#endif
+	Time_F(START);
+	for (count=0,run=1; COND(ce); count++)
+		crypt("testing1","ef");
+	e=Time_F(STOP);
+	printf("%ld crypts in %.2f second\n",count,e);
+	e=((double)COUNT(ce))/e;
+
+	printf("set_key            per sec = %12.2f (%9.3fuS)\n",a,1.0e6/a);
+	printf("DES raw ecb bytes  per sec = %12.2f (%9.3fuS)\n",b,8.0e6/b);
+	printf("DES cbc bytes      per sec = %12.2f (%9.3fuS)\n",c,8.0e6/c);
+	printf("DES ede cbc bytes  per sec = %12.2f (%9.3fuS)\n",d,8.0e6/d);
+	printf("crypt              per sec = %12.2f (%9.3fuS)\n",e,1.0e6/e);
+	exit(0);
+#if defined(LINT) || defined(MSDOS)
+	return(0);
+#endif
+	}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libdes/spr.h linux-patched/net/ipsec/libdes/spr.h
--- linux/net/ipsec/libdes/spr.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libdes/spr.h	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,204 @@
+/* crypto/des/spr.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * 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 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 cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+const DES_LONG des_SPtrans[8][64]={
+{
+/* nibble 0 */
+0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L,
+0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L,
+0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L,
+0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L,
+0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L,
+0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L,
+0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L,
+0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L,
+0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L,
+0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L,
+0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L,
+0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L,
+0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L,
+0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L,
+0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L,
+0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L,
+},{
+/* nibble 1 */
+0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L,
+0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L,
+0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L,
+0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L,
+0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L,
+0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L,
+0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L,
+0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L,
+0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L,
+0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L,
+0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L,
+0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L,
+0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L,
+0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L,
+0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L,
+0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L,
+},{
+/* nibble 2 */
+0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L,
+0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L,
+0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L,
+0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L,
+0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L,
+0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L,
+0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L,
+0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L,
+0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L,
+0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L,
+0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L,
+0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L,
+0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L,
+0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L,
+0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L,
+0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L,
+},{
+/* nibble 3 */
+0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L,
+0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L,
+0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L,
+0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L,
+0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L,
+0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L,
+0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L,
+0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L,
+0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L,
+0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L,
+0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L,
+0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L,
+0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L,
+0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L,
+0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L,
+0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L,
+},{
+/* nibble 4 */
+0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L,
+0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L,
+0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L,
+0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L,
+0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L,
+0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L,
+0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L,
+0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L,
+0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L,
+0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L,
+0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L,
+0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L,
+0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L,
+0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L,
+0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L,
+0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L,
+},{
+/* nibble 5 */
+0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L,
+0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L,
+0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L,
+0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L,
+0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L,
+0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L,
+0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L,
+0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L,
+0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L,
+0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L,
+0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L,
+0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L,
+0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L,
+0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L,
+0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L,
+0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L,
+},{
+/* nibble 6 */
+0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L,
+0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L,
+0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L,
+0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L,
+0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L,
+0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L,
+0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L,
+0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L,
+0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L,
+0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L,
+0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L,
+0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L,
+0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L,
+0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L,
+0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L,
+0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L,
+},{
+/* nibble 7 */
+0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L,
+0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L,
+0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L,
+0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L,
+0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L,
+0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L,
+0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L,
+0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L,
+0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L,
+0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L,
+0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L,
+0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L,
+0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L,
+0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L,
+0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L,
+0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L,
+}};
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/Makefile linux-patched/net/ipsec/libfreeswan/Makefile
--- linux/net/ipsec/libfreeswan/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/Makefile	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,65 @@
+# FreeS/WAN library
+# Copyright (C) 1998-2002  Henry Spencer.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+
+
+
+include ../Makefile.inc
+include ../Makefile.ver
+
+
+
+ifndef TOPDIR
+TOPDIR  := /usr/src/linux
+endif
+
+L_TARGET := libkernel.a
+
+obj-y := addrtoa.o datatot.o goodmask.o \
+	pfkey_v2_build.o pfkey_v2_debug.o pfkey_v2_ext_bits.o pfkey_v2_parse.o \
+	prng.o rangetoa.o satoa.o \
+	subnetof.o subnettoa.o ultoa.o version.o
+
+HDRS=freeswan.h internal.h
+
+EXTRA_CFLAGS += -I. $(KLIPSCOMPILE)
+
+EXTRA_CFLAGS += -Wall 
+#EXTRA_CFLAGS += -Wconversion 
+#EXTRA_CFLAGS += -Wmissing-prototypes 
+EXTRA_CFLAGS += -Wpointer-arith 
+#EXTRA_CFLAGS += -Wcast-qual 
+#EXTRA_CFLAGS += -Wmissing-declarations 
+EXTRA_CFLAGS += -Wstrict-prototypes
+#EXTRA_CFLAGS += -pedantic
+#EXTRA_CFLAGS += -W
+#EXTRA_CFLAGS += -Wwrite-strings 
+#EXTRA_CFLAGS += -Wbad-function-cast 
+
+active-objs     := $(sort $(obj-y) $(obj-m))
+L_OBJS          := $(obj-y)
+M_OBJS          := $(obj-m)
+MIX_OBJS        := $(filter $(export-objs), $(active-objs))
+
+include $(TOPDIR)/Rules.make
+
+$(obj-y):	$(HDRS)
+
+# build version.c using version number from Makefile.ver
+version.c:	version.in.c
+	sed '/"/s/xxx/$(IPSECVERSION)/' version.in.c >$@
+
+clean:
+	rm -f $(L_TARGET) *.o try* core *.core version.c
+	( cd des && $(MAKE) clean )
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/addrtoa.c linux-patched/net/ipsec/libfreeswan/addrtoa.c
--- linux/net/ipsec/libfreeswan/addrtoa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/addrtoa.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,68 @@
+/*
+ * addresses to ASCII
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#define	NBYTES	4		/* bytes in an address */
+#define	PERBYTE	4		/* three digits plus a dot or NUL */
+#define	BUFLEN	(NBYTES*PERBYTE)
+
+#if BUFLEN != ADDRTOA_BUF
+#error	"ADDRTOA_BUF in freeswan.h inconsistent with addrtoa() code"
+#endif
+
+/*
+ - addrtoa - convert binary address to ASCII dotted decimal
+ */
+size_t				/* space needed for full conversion */
+addrtoa(addr, format, dst, dstlen)
+struct in_addr addr;
+int format;			/* character */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	unsigned long a = ntohl(addr.s_addr);
+	int i;
+	size_t n;
+	unsigned long byte;
+	char buf[BUFLEN];
+	char *p;
+
+	switch (format) {
+	case 0:
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	p = buf;
+	for (i = NBYTES-1; i >= 0; i--) {
+		byte = (a >> (i*8)) & 0xff;
+		p += ultoa(byte, 10, p, PERBYTE);
+		if (i != 0)
+			*(p-1) = '.';
+	}
+	n = p - buf;
+
+	if (dstlen > 0) {
+		if (n > dstlen)
+			buf[dstlen - 1] = '\0';
+		strcpy(dst, buf);
+	}
+	return n;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/addrtot.c linux-patched/net/ipsec/libfreeswan/addrtot.c
--- linux/net/ipsec/libfreeswan/addrtot.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/addrtot.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,230 @@
+/*
+ * addresses to text
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#define	IP4BYTES	4	/* bytes in an IPv4 address */
+#define	PERBYTE		4	/* three digits plus a dot or NUL */
+#define	IP6BYTES	16	/* bytes in an IPv6 address */
+
+/* forwards */
+static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp);
+static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp);
+static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp);
+static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp);
+static size_t reverse62(const unsigned char *s, size_t len, char *b, char **dp);
+
+/*
+ - addrtot - convert binary address to text (dotted decimal or IPv6 string)
+ */
+size_t				/* space needed for full conversion */
+addrtot(src, format, dst, dstlen)
+const ip_address *src;
+int format;			/* character */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	const unsigned char *b;
+	size_t n;
+	char buf[1+ADDRTOT_BUF+1];	/* :address: */
+	char *p;
+	int t = addrtypeof(src);
+#	define	TF(t, f)	(((t)<<8) | (f))
+
+	n = addrbytesptr(src, &b);
+	if (n == 0)
+		return 0;
+
+	switch (TF(t, format)) {
+	case TF(AF_INET, 0):
+		n = normal4(b, n, buf, &p);
+		break;
+	case TF(AF_INET6, 0):
+		n = normal6(b, n, buf, &p);
+		break;
+	case TF(AF_INET, 'r'):
+		n = reverse4(b, n, buf, &p);
+		break;
+	case TF(AF_INET6, 'r'):
+		n = reverse6(b, n, buf, &p);
+		break;
+	case TF(AF_INET6, 'R'):
+		n = reverse62(b, n, buf, &p);
+		break;
+	default:		/* including (AF_INET, 'R') */
+		return 0;
+		break;
+	}
+
+	if (dstlen > 0) {
+		if (dstlen < n)
+			p[dstlen - 1] = '\0';
+		strcpy(dst, p);
+	}
+	return n;
+}
+
+/*
+ - normal4 - normal IPv4 address-text conversion
+ */
+static size_t			/* size of text, including NUL */
+normal4(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf;			/* guaranteed large enough */
+char **dstp;			/* where to put result pointer */
+{
+	int i;
+	char *p;
+
+	if (srclen != IP4BYTES)	/* "can't happen" */
+		return 0;
+	p = buf;
+	for (i = 0; i < IP4BYTES; i++) {
+		p += ultot(srcp[i], 10, p, PERBYTE);
+		if (i != IP4BYTES - 1)
+			*(p-1) = '.';	/* overwrites the NUL */
+	}
+	*dstp = buf;
+	return p - buf;
+}
+
+/*
+ - normal6 - normal IPv6 address-text conversion
+ */
+static size_t			/* size of text, including NUL */
+normal6(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf;			/* guaranteed large enough, plus 2 */
+char **dstp;			/* where to put result pointer */
+{
+	int i;
+	unsigned long piece;
+	char *p;
+	char *q;
+
+	if (srclen != IP6BYTES)	/* "can't happen" */
+		return 0;
+	p = buf;
+	*p++ = ':';
+	for (i = 0; i < IP6BYTES/2; i++) {
+		piece = (srcp[2*i] << 8) + srcp[2*i + 1];
+		p += ultot(piece, 16, p, 5);	/* 5 = abcd + NUL */
+		*(p-1) = ':';	/* overwrites the NUL */
+	}
+	*p = '\0';
+	q = strstr(buf, ":0:0:");
+	if (q != NULL) {	/* zero squishing is possible */
+		p = q + 1;
+		while (*p == '0' && *(p+1) == ':')
+			p += 2;
+		q++;
+		*q++ = ':';	/* overwrite first 0 */
+		while (*p != '\0')
+			*q++ = *p++;
+		*q = '\0';
+		if (!(*(q-1) == ':' && *(q-2) == ':'))
+			*--q = '\0';	/* strip final : unless :: */
+		p = buf;
+		if (!(*p == ':' && *(p+1) == ':'))
+			p++;	/* skip initial : unless :: */
+	} else {
+		q = p;
+		*--q = '\0';	/* strip final : */
+		p = buf + 1;	/* skip initial : */
+	}
+	*dstp = p;
+	return q - p + 1;
+}
+
+/*
+ - reverse4 - IPv4 reverse-lookup conversion
+ */
+static size_t			/* size of text, including NUL */
+reverse4(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf;			/* guaranteed large enough */
+char **dstp;			/* where to put result pointer */
+{
+	int i;
+	char *p;
+
+	if (srclen != IP4BYTES)	/* "can't happen" */
+		return 0;
+	p = buf;
+	for (i = IP4BYTES-1; i >= 0; i--) {
+		p += ultot(srcp[i], 10, p, PERBYTE);
+		*(p-1) = '.';	/* overwrites the NUL */
+	}
+	strcpy(p, "IN-ADDR.ARPA.");
+	*dstp = buf;
+	return strlen(buf) + 1;
+}
+
+/*
+ - reverse62 - obsolete IPv6 reverse-lookup conversion (RFC 1886)
+ * A trifle inefficient, really shouldn't use ultot...
+ */
+static size_t			/* size of text, including NUL */
+reverse62(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf;			/* guaranteed large enough */
+char **dstp;			/* where to put result pointer */
+{
+	int i;
+	unsigned long piece;
+	char *p;
+
+	if (srclen != IP6BYTES)	/* "can't happen" */
+		return 0;
+	p = buf;
+	for (i = IP6BYTES-1; i >= 0; i--) {
+		piece = srcp[i];
+		p += ultot(piece&0xf, 16, p, 2);
+		*(p-1) = '.';
+		p += ultot(piece>>4, 16, p, 2);
+		*(p-1) = '.';
+	}
+	strcpy(p, "IP6.INT.");
+	*dstp = buf;
+	return strlen(buf) + 1;
+}
+
+/*
+ - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
+ */
+static size_t			/* size of text, including NUL */
+reverse6(srcp, srclen, buf, dstp)
+const unsigned char *srcp;
+size_t srclen;
+char *buf;			/* guaranteed large enough */
+char **dstp;			/* where to put result pointer */
+{
+	char *p;
+
+	if (srclen != IP6BYTES)	/* "can't happen" */
+		return 0;
+	strcpy(buf, "\\[x");
+	p = buf + strlen(buf);
+	(void) datatot((const char *)srcp, srclen, 16, p, IP6BYTES*2 + 1);
+	strcat(buf, "].IP6.ARPA.");	/* leave count implicit */
+	*dstp = buf;
+	return strlen(buf) + 1;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/addrtypeof.c linux-patched/net/ipsec/libfreeswan/addrtypeof.c
--- linux/net/ipsec/libfreeswan/addrtypeof.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/addrtypeof.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,94 @@
+/*
+ * extract parts of an ip_address
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - addrtypeof - get the type of an ip_address
+ */
+int
+addrtypeof(src)
+const ip_address *src;
+{
+	return src->u.v4.sin_family;
+}
+
+/*
+ - addrbytesptr - get pointer to the address bytes of an ip_address
+ */
+size_t				/* 0 for error */
+addrbytesptr(src, dstp)
+const ip_address *src;
+const unsigned char **dstp;	/* NULL means just a size query */
+{
+	const unsigned char *p;
+	size_t n;
+
+	switch (src->u.v4.sin_family) {
+	case AF_INET:
+		p = (const unsigned char *)&src->u.v4.sin_addr.s_addr;
+		n = 4;
+		break;
+	case AF_INET6:
+		p = (const unsigned char *)&src->u.v6.sin6_addr;
+		n = 16;
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	if (dstp != NULL)
+		*dstp = p;
+	return n;
+}
+
+/*
+ - addrlenof - get length of the address bytes of an ip_address
+ */
+size_t				/* 0 for error */
+addrlenof(src)
+const ip_address *src;
+{
+	return addrbytesptr(src, NULL);
+}
+
+/*
+ - addrbytesof - get the address bytes of an ip_address
+ */
+size_t				/* 0 for error */
+addrbytesof(src, dst, dstlen)
+const ip_address *src;
+unsigned char *dst;
+size_t dstlen;
+{
+	const unsigned char *p;
+	size_t n;
+	size_t ncopy;
+
+	n = addrbytesptr(src, &p);
+	if (n == 0)
+		return 0;
+
+	if (dstlen > 0) {
+		ncopy = n;
+		if (ncopy > dstlen)
+			ncopy = dstlen;
+		memcpy(dst, p, ncopy);
+	}
+	return n;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/anyaddr.c linux-patched/net/ipsec/libfreeswan/anyaddr.c
--- linux/net/ipsec/libfreeswan/anyaddr.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/anyaddr.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,146 @@
+/*
+ * special addresses
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/* these are mostly fallbacks for the no-IPv6-support-in-library case */
+#ifndef IN6ADDR_ANY_INIT
+#define	IN6ADDR_ANY_INIT	{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}
+#endif
+#ifndef IN6ADDR_LOOPBACK_INIT
+#define	IN6ADDR_LOOPBACK_INIT	{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
+#endif
+
+static struct in6_addr v6any = IN6ADDR_ANY_INIT;
+static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT;
+
+/*
+ - anyaddr - initialize to the any-address value
+ */
+err_t				/* NULL for success, else string literal */
+anyaddr(af, dst)
+int af;				/* address family */
+ip_address *dst;
+{
+	uint32_t v4any = htonl(INADDR_ANY);
+
+	switch (af) {
+	case AF_INET:
+		return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst);
+		break;
+	case AF_INET6:
+		return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst);
+		break;
+	default:
+		return "unknown address family in anyaddr/unspecaddr";
+		break;
+	}
+}
+
+/*
+ - unspecaddr - initialize to the unspecified-address value
+ */
+err_t				/* NULL for success, else string literal */
+unspecaddr(af, dst)
+int af;				/* address family */
+ip_address *dst;
+{
+	return anyaddr(af, dst);
+}
+
+/*
+ - loopbackaddr - initialize to the loopback-address value
+ */
+err_t				/* NULL for success, else string literal */
+loopbackaddr(af, dst)
+int af;				/* address family */
+ip_address *dst;
+{
+	uint32_t v4loop = htonl(INADDR_LOOPBACK);
+
+	switch (af) {
+	case AF_INET:
+		return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst);
+		break;
+	case AF_INET6:
+		return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst);
+		break;
+	default:
+		return "unknown address family in loopbackaddr";
+		break;
+	}
+}
+
+/*
+ - isanyaddr - test for the any-address value
+ */
+int
+isanyaddr(src)
+const ip_address *src;
+{
+	uint32_t v4any = htonl(INADDR_ANY);
+	int cmp;
+
+	switch (src->u.v4.sin_family) {
+	case AF_INET:
+		cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any));
+		break;
+	case AF_INET6:
+		cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any));
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	return (cmp == 0) ? 1 : 0;
+}
+
+/*
+ - isunspecaddr - test for the unspecified-address value
+ */
+int
+isunspecaddr(src)
+const ip_address *src;
+{
+	return isanyaddr(src);
+}
+
+/*
+ - isloopbackaddr - test for the loopback-address value
+ */
+int
+isloopbackaddr(src)
+const ip_address *src;
+{
+	uint32_t v4loop = htonl(INADDR_LOOPBACK);
+	int cmp;
+
+	switch (src->u.v4.sin_family) {
+	case AF_INET:
+		cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop));
+		break;
+	case AF_INET6:
+		cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop));
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	return (cmp == 0) ? 1 : 0;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/atoaddr.c linux-patched/net/ipsec/libfreeswan/atoaddr.c
--- linux/net/ipsec/libfreeswan/atoaddr.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/atoaddr.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,238 @@
+/*
+ * conversion from ASCII forms of addresses to internal ones
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ * Define NOLEADINGZEROS to interpret 032 as an error, not as 32.  There
+ * is deliberately no way to interpret it as 26 (i.e., as octal).
+ */
+
+/*
+ * Legal characters in a domain name.  Underscore technically is not,
+ * but is a common misunderstanding.
+ */
+static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
+				"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
+
+static const char *try8hex(const char *, size_t, struct in_addr *);
+static const char *try8hosthex(const char *, size_t, struct in_addr *);
+static const char *trydotted(const char *, size_t, struct in_addr *);
+static const char *getbyte(const char **, const char *, int *);
+
+/*
+ - atoaddr - convert ASCII name or dotted-decimal address to binary address
+ */
+const char *			/* NULL for success, else string literal */
+atoaddr(src, srclen, addrp)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+struct in_addr *addrp;
+{
+	struct hostent *h;
+	struct netent *ne = NULL;
+	const char *oops;
+#	define	HEXLEN	10	/* strlen("0x11223344") */
+#	ifndef ATOADDRBUF
+#	define	ATOADDRBUF	100
+#	endif
+	char namebuf[ATOADDRBUF];
+	char *p = namebuf;
+	char *q;
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+
+	/* might it be hex? */
+	if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'x'))
+		return try8hex(src+2, srclen-2, addrp);
+	if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'h'))
+		return try8hosthex(src+2, srclen-2, addrp);
+
+	/* try it as dotted decimal */
+	oops = trydotted(src, srclen, addrp);
+	if (oops == NULL)
+		return NULL;		/* it worked */
+	if (*oops != '?')
+		return oops;		/* it *was* probably meant as a d.q. */
+
+	/* try it as a name -- first, NUL-terminate it */
+	if (srclen > sizeof(namebuf)-1) {
+		p = (char *) MALLOC(srclen+1);
+		if (p == NULL)
+			return "unable to allocate temporary space for name";
+	}
+	p[0] = '\0';
+	strncat(p, src, srclen);
+
+	/* next, check that it's a vaguely legal name */
+	for (q = p; *q != '\0'; q++)
+		if (!isprint(*q))
+			return "unprintable character in name";
+	if (strspn(p, namechars) != srclen)
+		return "illegal (non-DNS-name) character in name";
+
+	/* try as host name, failing that as /etc/networks network name */
+	h = gethostbyname(p);
+	if (h == NULL)
+		ne = getnetbyname(p);
+	if (p != namebuf)
+		FREE(p);
+	if (h == NULL && ne == NULL)
+		return "name lookup failed";
+
+	if (h != NULL)
+		memcpy(&addrp->s_addr, h->h_addr, sizeof(addrp->s_addr));
+	else
+		addrp->s_addr = htonl(ne->n_net);
+	return NULL;
+}
+
+/*
+ - try8hosthex - try conversion as an eight-digit host-order hex number
+ */
+const char *			/* NULL for success, else string literal */
+try8hosthex(src, srclen, addrp)
+const char *src;
+size_t srclen;			/* should be 8 */
+struct in_addr *addrp;
+{
+	const char *oops;
+	unsigned long addr;
+
+	if (srclen != 8)
+		return "internal error, try8hex called with bad length";
+
+	oops = atoul(src, srclen, 16, &addr);
+	if (oops != NULL)
+		return oops;
+
+	addrp->s_addr = addr;
+	return NULL;
+}
+
+/*
+ - try8hex - try conversion as an eight-digit network-order hex number
+ */
+const char *			/* NULL for success, else string literal */
+try8hex(src, srclen, addrp)
+const char *src;
+size_t srclen;			/* should be 8 */
+struct in_addr *addrp;
+{
+	const char *oops;
+
+	oops = try8hosthex(src, srclen, addrp);
+	if (oops != NULL)
+		return oops;
+
+	addrp->s_addr = htonl(addrp->s_addr);
+	return NULL;
+}
+
+/*
+ - trydotted - try conversion as dotted decimal
+ *
+ * If the first char of a complaint is '?', that means "didn't look like
+ * dotted decimal at all".
+ */
+const char *			/* NULL for success, else string literal */
+trydotted(src, srclen, addrp)
+const char *src;
+size_t srclen;
+struct in_addr *addrp;
+{
+	const char *stop = src + srclen;	/* just past end */
+	int byte;
+	const char *oops;
+	unsigned long addr;
+	int i;
+#	define	NBYTES	4
+#	define	BYTE	8
+
+	addr = 0;
+	for (i = 0; i < NBYTES && src < stop; i++) {
+		oops = getbyte(&src, stop, &byte);
+		if (oops != NULL) {
+			if (*oops != '?')
+				return oops;	/* bad number */
+			if (i > 1)
+				return oops+1;	/* failed number */
+			return oops;		/* with leading '?' */
+		}
+		addr = (addr << BYTE) | byte;
+		if (i < 3 && src < stop && *src++ != '.') {
+			if (i == 0)
+				return "?syntax error in dotted-decimal address";
+			else
+				return "syntax error in dotted-decimal address";
+		}
+	}
+	addr <<= (NBYTES - i) * BYTE;
+	if (src != stop)
+		return "extra garbage on end of dotted-decimal address";
+
+	addrp->s_addr = htonl(addr);
+	return NULL;
+}
+
+/*
+ - getbyte - try to scan a byte in dotted decimal
+ * A subtlety here is that all this arithmetic on ASCII digits really is
+ * highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
+ * It's easier to just do it ourselves than set up for a call to atoul().
+ *
+ * If the first char of a complaint is '?', that means "didn't look like a
+ * number at all".
+ */
+const char *			/* NULL for success, else string literal */
+getbyte(srcp, stop, retp)
+const char **srcp;		/* *srcp is updated */
+const char *stop;		/* first untouchable char */
+int *retp;			/* return-value pointer */
+{
+	char c;
+	const char *p;
+	int no;
+
+	if (*srcp >= stop)
+		return "?empty number in dotted-decimal address";
+
+	if (stop - *srcp >= 3 && **srcp == '0' && CIEQ(*(*srcp+1), 'x'))
+		return "hex numbers not supported in dotted-decimal addresses";
+#ifdef NOLEADINGZEROS
+	if (stop - *srcp >= 2 && **srcp == '0' && isdigit(*(*srcp+1)))
+		return "octal numbers not supported in dotted-decimal addresses";
+#endif /* NOLEADINGZEROS */
+
+	/* must be decimal, if it's numeric at all */
+	no = 0;
+	p = *srcp;
+	while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
+		no = no*10 + (c - '0');
+		p++;
+	}
+	if (p == *srcp)
+		return "?non-numeric component in dotted-decimal address";
+	*srcp = p;
+	if (no > 255)
+		return "byte overflow in dotted-decimal address";
+	*retp = no;
+	return NULL;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/atoasr.c linux-patched/net/ipsec/libfreeswan/atoasr.c
--- linux/net/ipsec/libfreeswan/atoasr.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/atoasr.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,212 @@
+/*
+ * convert from ASCII form of address/subnet/range to binary
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - atoasr - convert ASCII to address, subnet, or range
+ */
+const char *			/* NULL for success, else string literal */
+atoasr(src, srclen, typep, addrsp)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+char *typep;			/* return type code:  'a', 's', 'r' */
+struct in_addr addrsp[2];
+{
+	const char *punct;
+	const char *stop;
+	const char *oops;
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+
+	/* subnet is easy to spot */
+	punct = memchr(src, '/', srclen);
+	if (punct != NULL) {
+		*typep = 's';
+		return atosubnet(src, srclen, &addrsp[0], &addrsp[1]);
+	}
+
+	/* try for a range */
+	stop = src + srclen;
+	for (punct = src; (punct = memchr(punct, '.', stop - punct)) != NULL;
+									punct++)
+		if (stop - punct > 3 && *(punct+1) == '.' && *(punct+2) == '.')
+			break;			/* NOTE BREAK OUT */
+	if (punct == NULL) {
+		/* didn't find the range delimiter, must be plain address */
+		*typep = 'a';
+		return atoaddr(src, srclen, &addrsp[0]);
+	}
+
+	/* looks like a range */
+	*typep = 'r';
+	if (stop - punct > 4 && *(punct+3) == '.')
+		punct++;		/* first dot is trailing dot of name */
+	oops = atoaddr(src, punct - src, &addrsp[0]);
+	if (oops != NULL)
+		return oops;
+	oops = atoaddr(punct+3, stop - (punct+3), &addrsp[1]);
+	if (oops != NULL)
+		return oops;
+	if (ntohl(addrsp[0].s_addr) > ntohl(addrsp[1].s_addr))
+		return "invalid range, begin > end";
+	return NULL;
+}
+
+
+
+#ifdef ATOASR_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	struct in_addr a[2];
+	char buf[100];
+	const char *oops;
+	size_t n;
+	char type;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
+								argv[0]);
+		exit(2);
+	}
+
+	if (strcmp(argv[1], "-r") == 0) {
+		regress();
+		fprintf(stderr, "regress() returned?!?\n");
+		exit(1);
+	}
+
+	oops = atoasr(argv[1], 0, &type, a);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	switch (type) {
+	case 'a':
+		n = addrtoa(a[0], 0, buf, sizeof(buf));
+		break;
+	case 's':
+		n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
+		break;
+	case 'r':
+		n = rangetoa(a, 0, buf, sizeof(buf));
+		break;
+	default:
+		fprintf(stderr, "%s: unknown type '%c'\n", argv[0], type);
+		exit(1);
+		break;
+	}
+	if (n > sizeof(buf)) {
+		fprintf(stderr, "%s: reverse conversion of ", argv[0]);
+		fprintf(stderr, "%s ", inet_ntoa(a[0]));
+		fprintf(stderr, "%s", inet_ntoa(a[1]));
+		fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+						(long)n, (long)sizeof(buf));
+		exit(1);
+	}
+	printf("%s\n", buf);
+
+	exit(0);
+}
+
+struct rtab {
+	char *input;
+	char *output;			/* NULL means error expected */
+} rtab[] = {
+	"1.2.3.0",			"1.2.3.0",
+	"1.2.3.0/255.255.255.0",	"1.2.3.0/24",
+	"1.2.3.0...1.2.3.5",		"1.2.3.0...1.2.3.5",
+	"1.2.3.4.5",			NULL,
+	"1.2.3.4/",			NULL,
+	"1.2.3.4...",			NULL,
+	"1.2.3.4....",			NULL,
+	"localhost./32",		"127.0.0.1/32",
+	"localhost....127.0.0.3",	"127.0.0.1...127.0.0.3",
+	"127.0.0.0...localhost.",	"127.0.0.0...127.0.0.1",
+	"127.0.0.3...localhost.",	NULL,
+	NULL,				NULL
+};
+
+void
+regress()
+{
+	struct rtab *r;
+	int status = 0;
+	struct in_addr a[2];
+	struct in_addr m;
+	char in[100];
+	char buf[100];
+	const char *oops;
+	size_t n;
+	char type;
+
+	for (r = rtab; r->input != NULL; r++) {
+		strcpy(in, r->input);
+		oops = atoasr(in, 0, &type, a);
+		if (oops != NULL && r->output == NULL)
+			{}		/* okay, error expected */
+		else if (oops != NULL) {
+			printf("`%s' atoasr failed: %s\n", r->input, oops);
+			status = 1;
+		} else if (r->output == NULL) {
+			printf("`%s' atoasr succeeded unexpectedly '%c'\n",
+							r->input, type);
+			status = 1;
+		} else {
+			switch (type) {
+			case 'a':
+				n = addrtoa(a[0], 0, buf, sizeof(buf));
+				break;
+			case 's':
+				n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
+				break;
+			case 'r':
+				n = rangetoa(a, 0, buf, sizeof(buf));
+				break;
+			default:
+				fprintf(stderr, "`%s' unknown type '%c'\n",
+							r->input, type);
+				n = 0;
+				status = 1;
+				break;
+			}
+			if (n > sizeof(buf)) {
+				printf("`%s' '%c' reverse failed:  need %ld\n",
+						r->input, type, (long)n);
+				status = 1;
+			} else if (n > 0 && strcmp(r->output, buf) != 0) {
+				printf("`%s' '%c' gave `%s', expected `%s'\n",
+					r->input, type, buf, r->output);
+				status = 1;
+			}
+		}
+	}
+	exit(status);
+}
+
+#endif /* ATOASR_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/atosa.c linux-patched/net/ipsec/libfreeswan/atosa.c
--- linux/net/ipsec/libfreeswan/atosa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/atosa.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,199 @@
+/*
+ * convert from ASCII form of SA ID to binary
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct satype {
+	char *prefix;
+	size_t prelen;		/* strlen(prefix) */
+	int proto;
+} satypes[] = {
+	{ "ah",		2,	SA_AH	},
+	{ "esp",	3,	SA_ESP	},
+	{ "tun",	3,	SA_IPIP },
+	{ "comp",	4,	SA_COMP },
+	{ NULL,		0,	0,	}
+};
+
+/*
+ - atosa - convert ASCII "ah507@10.0.0.1" to SA identifier
+ */
+const char *			/* NULL for success, else string literal */
+atosa(src, srclen, sa)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+struct sa_id *sa;
+{
+	const char *at;
+	const char *addr;
+	const char *spi = NULL;
+	struct satype *sat;
+	unsigned long ul;
+	const char *oops;
+#	define	MINLEN	5	/* ah0@0 is as short as it can get */
+	static char ptname[] = PASSTHROUGHNAME;
+#	define	PTNLEN	(sizeof(ptname)-1)	/* -1 for NUL */
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+	if (srclen < MINLEN)
+		return "string too short to be SA specifier";
+	if (srclen == PTNLEN && memcmp(src, ptname, PTNLEN) == 0) {
+		src = PASSTHROUGHIS;
+		srclen = strlen(src);
+	}
+
+	at = memchr(src, '@', srclen);
+	if (at == NULL)
+		return "no @ in SA specifier";
+
+	for (sat = satypes; sat->prefix != NULL; sat++)
+		if (sat->prelen < srclen &&
+				strncmp(src, sat->prefix, sat->prelen) == 0) {
+			sa->proto = sat->proto;
+			spi = src + sat->prelen;
+			break;			/* NOTE BREAK OUT */
+		}
+	if (sat->prefix == NULL)
+		return "SA specifier lacks valid protocol prefix";
+
+	if (spi >= at)
+		return "no SPI in SA specifier";
+	oops = atoul(spi, at - spi, 13, &ul);
+	if (oops != NULL)
+		return oops;
+	sa->spi = htonl(ul);
+
+	addr = at + 1;
+	oops = atoaddr(addr, srclen - (addr - src), &sa->dst);
+	if (oops != NULL)
+		return oops;
+
+	return NULL;
+}
+
+
+
+#ifdef ATOSA_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	struct sa_id sa;
+	char buf[100];
+	const char *oops;
+	size_t n;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
+		exit(2);
+	}
+
+	if (strcmp(argv[1], "-r") == 0) {
+		regress();
+		fprintf(stderr, "regress() returned?!?\n");
+		exit(1);
+	}
+
+	oops = atosa(argv[1], 0, &sa);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	n = satoa(sa, 0, buf, sizeof(buf));
+	if (n > sizeof(buf)) {
+		fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
+		fprintf(stderr, "%lu@", sa.spi);
+		fprintf(stderr, "%s", inet_ntoa(sa.dst));
+		fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+						(long)n, (long)sizeof(buf));
+		exit(1);
+	}
+	printf("%s\n", buf);
+
+	exit(0);
+}
+
+struct rtab {
+	char *input;
+	char *output;			/* NULL means error expected */
+} rtab[] = {
+	"esp257@1.2.3.0",		"esp257@1.2.3.0",
+	"ah0x20@1.2.3.4",		"ah32@1.2.3.4",
+	"tun011@111.2.3.99",		"tun11@111.2.3.99",
+	"",				NULL,
+	"_",				NULL,
+	"ah2.2",			NULL,
+	"goo2@1.2.3.4",			NULL,
+	"esp9@1.2.3.4",			"esp9@1.2.3.4",
+	"espp9@1.2.3.4",		NULL,
+	"es9@1.2.3.4",			NULL,
+	"ah@1.2.3.4",			NULL,
+	"esp7x7@1.2.3.4",		NULL,
+	"esp77@1.0x2.3.4",		NULL,
+	PASSTHROUGHNAME,		PASSTHROUGHNAME,
+	NULL,				NULL
+};
+
+void
+regress()
+{
+	struct rtab *r;
+	int status = 0;
+	struct sa_id sa;
+	char in[100];
+	char buf[100];
+	const char *oops;
+	size_t n;
+
+	for (r = rtab; r->input != NULL; r++) {
+		strcpy(in, r->input);
+		oops = atosa(in, 0, &sa);
+		if (oops != NULL && r->output == NULL)
+			{}		/* okay, error expected */
+		else if (oops != NULL) {
+			printf("`%s' atosa failed: %s\n", r->input, oops);
+			status = 1;
+		} else if (r->output == NULL) {
+			printf("`%s' atosa succeeded unexpectedly\n",
+								r->input);
+			status = 1;
+		} else {
+			n = satoa(sa, 'd', buf, sizeof(buf));
+			if (n > sizeof(buf)) {
+				printf("`%s' satoa failed:  need %ld\n",
+							r->input, (long)n);
+				status = 1;
+			} else if (strcmp(r->output, buf) != 0) {
+				printf("`%s' gave `%s', expected `%s'\n",
+						r->input, buf, r->output);
+				status = 1;
+			}
+		}
+	}
+	exit(status);
+}
+
+#endif /* ATOSA_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/atosubnet.c linux-patched/net/ipsec/libfreeswan/atosubnet.c
--- linux/net/ipsec/libfreeswan/atosubnet.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/atosubnet.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,215 @@
+/*
+ * convert from ASCII form of subnet specification to binary
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#ifndef DEFAULTSUBNET
+#define	DEFAULTSUBNET	"%default"
+#endif
+
+/*
+ - atosubnet - convert ASCII "addr/mask" to address and mask
+ * Mask can be integer bit count.
+ */
+const char *			/* NULL for success, else string literal */
+atosubnet(src, srclen, addrp, maskp)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+struct in_addr *addrp;
+struct in_addr *maskp;
+{
+	const char *slash;
+	const char *mask;
+	size_t mlen;
+	const char *oops;
+	unsigned long bc;
+	static char def[] = DEFAULTSUBNET;
+#	define	DEFLEN	(sizeof(def) - 1)	/* -1 for NUL */
+	static char defis[] = "0/0";
+#	define	DEFILEN	(sizeof(defis) - 1)
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+
+	if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
+		src = defis;
+		srclen = DEFILEN;
+	}
+
+	slash = memchr(src, '/', srclen);
+	if (slash == NULL)
+		return "no / in subnet specification";
+	mask = slash + 1;
+	mlen = srclen - (mask - src);
+
+	oops = atoaddr(src, slash-src, addrp);
+	if (oops != NULL)
+		return oops;
+
+	oops = atoul(mask, mlen, 10, &bc);
+	if (oops == NULL) {
+		/* atoul succeeded, it's a bit-count mask */
+		if (bc > ABITS)
+			return "bit-count mask too large";
+#ifdef NOLEADINGZEROS
+		if (mlen > 1 && *mask == '0')
+			return "octal not allowed in mask";
+#endif /* NOLEADINGZEROS */
+		*maskp = bitstomask((int)bc);
+	} else {
+		oops = atoaddr(mask, mlen, maskp);
+		if (oops != NULL)
+			return oops;
+		if (!goodmask(*maskp))
+			return "non-contiguous mask";
+	}
+
+	addrp->s_addr &= maskp->s_addr;
+	return NULL;
+}
+
+
+
+#ifdef ATOSUBNET_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	struct in_addr a;
+	struct in_addr m;
+	char buf[100];
+	const char *oops;
+	size_t n;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]);
+		exit(2);
+	}
+
+	if (strcmp(argv[1], "-r") == 0) {
+		regress();
+		fprintf(stderr, "regress() returned?!?\n");
+		exit(1);
+	}
+
+	oops = atosubnet(argv[1], 0, &a, &m);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	n = subnettoa(a, m, 0, buf, sizeof(buf));
+	if (n > sizeof(buf)) {
+		fprintf(stderr, "%s: reverse conversion of ", argv[0]);
+		fprintf(stderr, "%s/", inet_ntoa(a));
+		fprintf(stderr, "%s", inet_ntoa(m));
+		fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+						(long)n, (long)sizeof(buf));
+		exit(1);
+	}
+	printf("%s\n", buf);
+
+	exit(0);
+}
+
+struct rtab {
+	char *input;
+	char *output;			/* NULL means error expected */
+} rtab[] = {
+	"1.2.3.0/255.255.255.0",	"1.2.3.0/24",
+	"1.2.3.0/24",			"1.2.3.0/24",
+	"1.2.3.1/255.255.255.240",	"1.2.3.0/28",
+	"1.2.3.1/32",			"1.2.3.1/32",
+	"1.2.3.1/0",			"0.0.0.0/0",
+/*	"1.2.3.1/255.255.127.0",	"1.2.3.0/255.255.127.0",	*/
+	"1.2.3.1/255.255.127.0",	NULL,
+	"128.009.000.032/32",		"128.9.0.32/32",
+	"128.0x9.0.32/32",		NULL,
+	"0x80090020/32",		"128.9.0.32/32",
+	"0x800x0020/32",		NULL,
+	"128.9.0.32/0xffFF0000",	"128.9.0.0/16",
+	"128.9.0.32/0xff0000FF",	NULL,
+	"128.9.0.32/0x0000ffFF",	NULL,
+	"128.9.0.32/0x00ffFF0000",	NULL,
+	"128.9.0.32/0xffFF",		NULL,
+	"128.9.0.32.27/32",		NULL,
+	"128.9.0k32/32",		NULL,
+	"328.9.0.32/32",		NULL,
+	"128.9..32/32",			NULL,
+	"10/8",				"10.0.0.0/8",
+	"10.0/8",			"10.0.0.0/8",
+	"10.0.0/8",			"10.0.0.0/8",
+	"10.0.1/24",			"10.0.1.0/24",
+	"_",				NULL,
+	"_/_",				NULL,
+	"1.2.3.1",			NULL,
+	"1.2.3.1/_",			NULL,
+	"1.2.3.1/24._",			NULL,
+	"1.2.3.1/99",			NULL,
+	"localhost./32",		"127.0.0.1/32",
+	"%default",			"0.0.0.0/0",
+	NULL,				NULL
+};
+
+void
+regress()
+{
+	struct rtab *r;
+	int status = 0;
+	struct in_addr a;
+	struct in_addr m;
+	char in[100];
+	char buf[100];
+	const char *oops;
+	size_t n;
+
+	for (r = rtab; r->input != NULL; r++) {
+		strcpy(in, r->input);
+		oops = atosubnet(in, 0, &a, &m);
+		if (oops != NULL && r->output == NULL)
+			{}		/* okay, error expected */
+		else if (oops != NULL) {
+			printf("`%s' atosubnet failed: %s\n", r->input, oops);
+			status = 1;
+		} else if (r->output == NULL) {
+			printf("`%s' atosubnet succeeded unexpectedly\n",
+								r->input);
+			status = 1;
+		} else {
+			n = subnettoa(a, m, 0, buf, sizeof(buf));
+			if (n > sizeof(buf)) {
+				printf("`%s' subnettoa failed:  need %ld\n",
+							r->input, (long)n);
+				status = 1;
+			} else if (strcmp(r->output, buf) != 0) {
+				printf("`%s' gave `%s', expected `%s'\n",
+						r->input, buf, r->output);
+				status = 1;
+			}
+		}
+	}
+	exit(status);
+}
+
+#endif /* ATOSUBNET_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/atoul.c linux-patched/net/ipsec/libfreeswan/atoul.c
--- linux/net/ipsec/libfreeswan/atoul.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/atoul.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,90 @@
+/*
+ * convert from ASCII form of unsigned long to binary
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - atoul - convert ASCII substring to unsigned long number
+ */
+const char *			/* NULL for success, else string literal */
+atoul(src, srclen, base, resultp)
+const char *src;
+size_t srclen;			/* 0 means strlen(src) */
+int base;			/* 0 means figure it out */
+unsigned long *resultp;
+{
+	const char *stop;
+	static char hex[] = "0123456789abcdef";
+	static char uchex[] = "0123456789ABCDEF";
+	int d;
+	char c;
+	char *p;
+	unsigned long r;
+	unsigned long rlimit;
+	int dlimit;
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+
+	if (base == 0 || base == 13) {
+		if (srclen > 2 && *src == '0' && CIEQ(*(src+1), 'x'))
+			return atoul(src+2, srclen-2, 16, resultp);
+		if (srclen > 1 && *src == '0' && base != 13)
+			return atoul(src+1, srclen-1, 8, resultp);
+		return atoul(src, srclen, 10, resultp);
+	}
+	if (base != 8 && base != 10 && base != 16)
+		return "unsupported number base";
+
+	r = 0;
+	stop = src + srclen;
+	if (base == 16) {
+		while (src < stop) {
+			c = *src++;
+			p = strchr(hex, c);
+			if (p != NULL)
+				d = p - hex;
+			else {
+				p = strchr(uchex, c);
+				if (p == NULL)
+					return "non-hex-digit in hex number";
+				d = p - uchex;
+			}
+			r = (r << 4) | d;
+		}
+		/* defer length check to catch invalid digits first */
+		if (srclen > sizeof(unsigned long) * 2)
+			return "hex number too long";
+	} else {
+		rlimit = ULONG_MAX / base;
+		dlimit = (int)(ULONG_MAX - rlimit*base);
+		while (src < stop) {
+			c = *src++;
+			d = c - '0';
+			if (d < 0 || d >= base)
+				return "non-digit in number";
+			if (r > rlimit || (r == rlimit && d > dlimit))
+				return "unsigned-long overflow";
+			r = r*base + d;
+		}
+	}
+
+	*resultp = r;
+	return NULL;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/copyright.c linux-patched/net/ipsec/libfreeswan/copyright.c
--- linux/net/ipsec/libfreeswan/copyright.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/copyright.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,44 @@
+/*
+ * return IPsec copyright notice
+ * Copyright (C) 2001, 2002  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static const char *co[] = {
+ "Copyright (C) 1999, 2000, 2001, 2002  Henry Spencer, Richard Guy Briggs,",
+ "    D. Hugh Redelmeier, Sandy Harris, Claudia Schmeing,",
+ "    Michael Richardson, Angelos D. Keromytis, John Ioannidis.",
+ "",
+ "This program is free software; you can redistribute it and/or modify it",
+ "under the terms of the GNU General Public License as published by the",
+ "Free Software Foundation; either version 2 of the License, or (at your",
+ "option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.",
+ "",
+ "This program is distributed in the hope that it will be useful, but",
+ "WITHOUT ANY WARRANTY; without even the implied warranty of",
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General",
+ "Public License (file COPYING in the distribution) for more details.",
+ NULL
+};
+
+/*
+ - ipsec_copyright_notice - return copyright notice, as a vector of strings
+ */
+const char **
+ipsec_copyright_notice()
+{
+	return co;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/datatot.c linux-patched/net/ipsec/libfreeswan/datatot.c
--- linux/net/ipsec/libfreeswan/datatot.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/datatot.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,225 @@
+/*
+ * convert from binary data (e.g. key) to text form
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static void convert(const char *src, size_t nreal, int format, char *out);
+
+/*
+ - datatot - convert data bytes to text
+ */
+size_t				/* true length (with NUL) for success */
+datatot(src, srclen, format, dst, dstlen)
+const char *src;
+size_t srclen;
+int format;			/* character indicating what format */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	size_t inblocksize;	/* process this many bytes at a time */
+	size_t outblocksize;	/* producing this many */
+	size_t breakevery;	/* add a _ every this many (0 means don't) */
+	size_t sincebreak;	/* output bytes since last _ */
+	char inblock[10];	/* enough for any format */
+	char outblock[10];	/* enough for any format */
+	char fake[1];		/* fake output area for dstlen == 0 */
+	size_t needed;		/* return value */
+	char *stop;		/* where the terminating NUL will go */
+	size_t ntodo;		/* remaining input */
+	size_t nreal;
+	char *out;
+	char *prefix;
+
+	breakevery = 0;
+	switch (format) {
+	case 0:
+	case 'h':
+		format = 'x';
+		breakevery = 8;
+		/* FALLTHROUGH */
+	case 'x':
+		inblocksize = 1;
+		outblocksize = 2;
+		prefix = "0x";
+		break;
+	case 16:
+		inblocksize = 1;
+		outblocksize = 2;
+		prefix = "";
+		format = 'x';
+		break;
+	case 's':
+		inblocksize = 3;
+		outblocksize = 4;
+		prefix = "0s";
+		break;
+	case 64:		/* beware, equals ' ' */
+		inblocksize = 3;
+		outblocksize = 4;
+		prefix = "";
+		format = 's';
+		break;
+	default:
+		return 0;
+		break;
+	}
+	assert(inblocksize < sizeof(inblock));
+	assert(outblocksize < sizeof(outblock));
+	assert(breakevery % outblocksize == 0);
+
+	if (srclen == 0)
+		return 0;
+	ntodo = srclen;
+
+	if (dstlen == 0) {	/* dispose of awkward special case */
+		dst = fake;
+		dstlen = 1;
+	}
+	stop = dst + dstlen - 1;
+
+	nreal = strlen(prefix);
+	needed = nreal;			/* for starters */
+	if (dstlen <= nreal) {		/* prefix won't fit */
+		strncpy(dst, prefix, dstlen - 1);
+		dst += dstlen - 1;
+	} else {
+		strcpy(dst, prefix);
+		dst += nreal;
+	}
+	assert(dst <= stop);
+	sincebreak = 0;
+
+	while (ntodo > 0) {
+		if (ntodo < inblocksize) {	/* incomplete input */
+			memset(inblock, 0, sizeof(inblock));
+			memcpy(inblock, src, ntodo);
+			src = inblock;
+			nreal = ntodo;
+			ntodo = inblocksize;
+		} else
+			nreal = inblocksize;
+		out = (outblocksize > stop - dst) ? outblock : dst;
+
+		convert(src, nreal, format, out);
+		needed += outblocksize;
+		sincebreak += outblocksize;
+		if (dst < stop) {
+			if (out != dst) {
+				assert(outblocksize > stop - dst);
+				memcpy(dst, out, stop - dst);
+				dst = stop;
+			} else
+				dst += outblocksize;
+		}
+
+		src += inblocksize;
+		ntodo -= inblocksize;
+		if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) {
+			if (dst < stop)
+				*dst++ = '_';
+			needed++;
+			sincebreak = 0;
+		}
+	}
+
+	assert(dst <= stop);
+	*dst++ = '\0';
+	needed++;
+
+	return needed;
+}
+
+/*
+ - convert - convert one input block to one output block
+ */
+static void
+convert(src, nreal, format, out)
+const char *src;
+size_t nreal;			/* how much of the input block is real */
+int format;
+char *out;
+{
+	static char hex[] = "0123456789abcdef";
+	static char base64[] =	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+				"abcdefghijklmnopqrstuvwxyz"
+				"0123456789+/";
+	unsigned char c;
+	unsigned char c1, c2, c3;
+
+	assert(nreal > 0);
+	switch (format) {
+	case 'x':
+		assert(nreal == 1);
+		c = (unsigned char)*src;
+		*out++ = hex[c >> 4];
+		*out++ = hex[c & 0xf];
+		break;
+	case 's':
+		c1 = (unsigned char)*src++;
+		c2 = (unsigned char)*src++;
+		c3 = (unsigned char)*src++;
+		*out++ = base64[c1 >> 2];	/* top 6 bits of c1 */
+		c = (c1 & 0x3) << 4;		/* bottom 2 of c1... */
+		c |= c2 >> 4;			/* ...top 4 of c2 */
+		*out++ = base64[c];
+		if (nreal == 1)
+			*out++ = '=';
+		else {
+			c = (c2 & 0xf) << 2;	/* bottom 4 of c2... */
+			c |= c3 >> 6;		/* ...top 2 of c3 */
+			*out++ = base64[c];
+		}
+		if (nreal <= 2)
+			*out++ = '=';
+		else
+			*out++ = base64[c3 & 0x3f];	/* bottom 6 of c3 */
+		break;
+	default:
+		assert(nreal == 0);	/* unknown format */
+		break;
+	}
+}
+
+/*
+ - datatoa - convert data to ASCII
+ * backward-compatibility synonym for datatot
+ */
+size_t				/* true length (with NUL) for success */
+datatoa(src, srclen, format, dst, dstlen)
+const char *src;
+size_t srclen;
+int format;			/* character indicating what format */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	return datatot(src, srclen, format, dst, dstlen);
+}
+
+/*
+ - bytestoa - convert data bytes to ASCII
+ * backward-compatibility synonym for datatot
+ */
+size_t				/* true length (with NUL) for success */
+bytestoa(src, srclen, format, dst, dstlen)
+const char *src;
+size_t srclen;
+int format;			/* character indicating what format */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	return datatot(src, srclen, format, dst, dstlen);
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/freeswan.h linux-patched/net/ipsec/libfreeswan/freeswan.h
--- linux/net/ipsec/libfreeswan/freeswan.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/freeswan.h	Thu Sep  5 04:53:52 2002
@@ -0,0 +1,426 @@
+#ifndef _FREESWAN_H
+/*
+ * header file for FreeS/WAN library functions
+ * Copyright (C) 1998, 1999, 2000  Henry Spencer.
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#define	_FREESWAN_H	/* seen it, no need to see it again */
+
+
+
+/*
+ * We've just got to have some datatypes defined...  And annoyingly, just
+ * where we get them depends on whether we're in userland or not.
+ */
+#ifdef __KERNEL__
+
+#  include <linux/types.h>
+#  include <linux/in.h>
+
+#else /* __KERNEL__ */
+
+#  include <stdio.h>
+#  include <netinet/in.h>
+
+#  define uint8_t u_int8_t
+#  define uint16_t u_int16_t 
+#  define uint32_t u_int32_t 
+#  define uint64_t u_int64_t 
+
+#  define DEBUG_NO_STATIC static
+
+#endif /* __KERNEL__ */
+
+/*
+ * Grab the kernel version to see if we have NET_21, and therefore 
+ * IPv6. Some of this is repeated from ipsec_kversions.h. Of course, 
+ * we aren't really testing if the kernel has IPv6, but rather if the
+ * the include files do.
+ */
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define NET_21
+#endif
+
+#ifndef IPPROTO_COMP
+#  define IPPROTO_COMP 108
+#endif /* !IPPROTO_COMP */
+
+#ifndef IPPROTO_INT
+#  define IPPROTO_INT 61
+#endif /* !IPPROTO_INT */
+
+#ifdef CONFIG_IPSEC_DEBUG
+#  define DEBUG_NO_STATIC
+#else /* CONFIG_IPSEC_DEBUG */
+#  define DEBUG_NO_STATIC static
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL /* KERNEL ifdef */
+#ifndef NAT_TRAVERSAL
+#define NAT_TRAVERSAL
+#endif
+#endif
+#ifdef NAT_TRAVERSAL
+#define ESPINUDP_WITH_NON_IKE   1  /* draft-ietf-ipsec-nat-t-ike-00/01 */
+#define ESPINUDP_WITH_NON_ESP   2  /* draft-ietf-ipsec-nat-t-ike-02    */
+#endif
+
+/*
+ * Basic data types for the address-handling functions.
+ * ip_address and ip_subnet are supposed to be opaque types; do not
+ * use their definitions directly, they are subject to change!
+ */
+
+/* first, some quick fakes in case we're on an old system with no IPv6 */
+#ifndef s6_addr16
+struct in6_addr {
+	union 
+	{
+		__u8		u6_addr8[16];
+		__u16		u6_addr16[8];
+		__u32		u6_addr32[4];
+	} in6_u;
+#define s6_addr			in6_u.u6_addr8
+#define s6_addr16		in6_u.u6_addr16
+#define s6_addr32		in6_u.u6_addr32
+};
+struct sockaddr_in6 {
+	unsigned short int	sin6_family;    /* AF_INET6 */
+	__u16			sin6_port;      /* Transport layer port # */
+	__u32			sin6_flowinfo;  /* IPv6 flow information */
+	struct in6_addr		sin6_addr;      /* IPv6 address */
+	__u32			sin6_scope_id;  /* scope id (new in RFC2553) */
+};
+#endif	/* !s6_addr16 */
+
+/* then the main types */
+typedef struct {
+	union {
+		struct sockaddr_in v4;
+		struct sockaddr_in6 v6;
+	} u;
+} ip_address;
+typedef struct {
+	ip_address addr;
+	int maskbits;
+} ip_subnet;
+
+/* and the SA ID stuff */
+#ifdef __KERNEL__
+typedef __u32 ipsec_spi_t;
+#else
+typedef u_int32_t ipsec_spi_t;
+#endif
+typedef struct {		/* to identify an SA, we need: */
+        ip_address dst;		/* A. destination host */
+        ipsec_spi_t spi;	/* B. 32-bit SPI, assigned by dest. host */
+#		define	SPI_PASS	256	/* magic values... */
+#		define	SPI_DROP	257	/* ...for use... */
+#		define	SPI_REJECT	258	/* ...with SA_INT */
+#		define	SPI_HOLD	259
+#		define	SPI_TRAP	260
+#		define  SPI_TRAPSUBNET  261
+	int proto;		/* C. protocol */
+#		define	SA_ESP	50	/* IPPROTO_ESP */
+#		define	SA_AH	51	/* IPPROTO_AH */
+#		define	SA_IPIP	4	/* IPPROTO_IPIP */
+#		define	SA_COMP	108	/* IPPROTO_COMP */
+#		define	SA_INT	61	/* IANA reserved for internal use */
+} ip_said;
+struct sa_id {			/* old v4-only version */
+        struct in_addr dst;
+        ipsec_spi_t spi;
+	int proto;
+};
+
+/* misc */
+typedef const char *err_t;	/* error message, or NULL for success */
+struct prng {			/* pseudo-random-number-generator guts */
+	unsigned char sbox[256];
+	int i, j;
+	unsigned long count;
+};
+
+
+
+/*
+ * new IPv6-compatible functions
+ */
+
+/* text conversions */
+err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst);
+size_t ultot(unsigned long src, int format, char *buf, size_t buflen);
+#define	ULTOT_BUF	(22+1)	/* holds 64 bits in octal */
+err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst);
+err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst);
+size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen);
+/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */
+#define	ADDRTOT_BUF	(32*2 + 3 + 1 + 3 + 1 + 1)
+err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst);
+size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen);
+#define	SUBNETTOT_BUF	(ADDRTOT_BUF + 1 + 3)
+err_t ttosa(const char *src, size_t srclen, ip_said *dst);
+size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen);
+#define	SATOT_BUF	(5 + ULTOA_BUF + 1 + ADDRTOT_BUF)
+err_t ttodata(const char *src, size_t srclen, int base, char *buf,
+						size_t buflen, size_t *needed);
+err_t ttodatav(const char *src, size_t srclen, int base, char *buf,
+		size_t buflen, size_t *needed, char *errp, size_t errlen);
+#define	TTODATAV_BUF	40	/* ttodatav's largest non-literal message */
+size_t datatot(const char *src, size_t srclen, int format, char *buf,
+								size_t buflen);
+size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst,
+								size_t dstlen);
+size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m,
+					size_t mlen, char *dst, size_t dstlen);
+#define	KEYID_BUF	10	/* up to 9 text digits plus NUL */
+err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port);
+
+/* initializations */
+void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst);
+err_t loopbackaddr(int af, ip_address *dst);
+err_t unspecaddr(int af, ip_address *dst);
+err_t anyaddr(int af, ip_address *dst);
+err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst);
+err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst);
+err_t addrtosubnet(const ip_address *addr, ip_subnet *dst);
+
+/* misc. conversions and related */
+err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst);
+int addrtypeof(const ip_address *src);
+int subnettypeof(const ip_subnet *src);
+size_t addrlenof(const ip_address *src);
+size_t addrbytesptr(const ip_address *src, const unsigned char **dst);
+size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen);
+int masktocount(const ip_address *src);
+void networkof(const ip_subnet *src, ip_address *dst);
+void maskof(const ip_subnet *src, ip_address *dst);
+
+/* tests */
+int sameaddr(const ip_address *a, const ip_address *b);
+int addrcmp(const ip_address *a, const ip_address *b);
+int samesubnet(const ip_subnet *a, const ip_subnet *b);
+int addrinsubnet(const ip_address *a, const ip_subnet *s);
+int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);
+int subnetishost(const ip_subnet *s);
+int samesaid(const ip_said *a, const ip_said *b);
+int sameaddrtype(const ip_address *a, const ip_address *b);
+int samesubnettype(const ip_subnet *a, const ip_subnet *b);
+int isanyaddr(const ip_address *src);
+int isunspecaddr(const ip_address *src);
+int isloopbackaddr(const ip_address *src);
+
+/* low-level grot */
+int portof(const ip_address *src);
+void setportof(int port, ip_address *dst);
+struct sockaddr *sockaddrof(ip_address *src);
+size_t sockaddrlenof(const ip_address *src);
+
+/* PRNG */
+void prng_init(struct prng *prng, const unsigned char *key, size_t keylen);
+void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen);
+unsigned long prng_count(struct prng *prng);
+void prng_final(struct prng *prng);
+
+/* odds and ends */
+const char *ipsec_version_code(void);
+const char *ipsec_version_string(void);
+const char **ipsec_copyright_notice(void);
+
+
+
+/*
+ * old functions, to be deleted eventually
+ */
+
+/* unsigned long */
+const char *			/* NULL for success, else string literal */
+atoul(
+	const char *src,
+	size_t srclen,		/* 0 means strlen(src) */
+	int base,		/* 0 means figure it out */
+	unsigned long *resultp
+);
+size_t				/* space needed for full conversion */
+ultoa(
+	unsigned long n,
+	int base,
+	char *dst,
+	size_t dstlen
+);
+#define	ULTOA_BUF	21	/* just large enough for largest result, */
+				/* assuming 64-bit unsigned long! */
+
+/* Internet addresses */
+const char *			/* NULL for success, else string literal */
+atoaddr(
+	const char *src,
+	size_t srclen,		/* 0 means strlen(src) */
+	struct in_addr *addr
+);
+size_t				/* space needed for full conversion */
+addrtoa(
+	struct in_addr addr,
+	int format,		/* character; 0 means default */
+	char *dst,
+	size_t dstlen
+);
+#define	ADDRTOA_BUF	16	/* just large enough for largest result */
+
+/* subnets */
+const char *			/* NULL for success, else string literal */
+atosubnet(
+	const char *src,
+	size_t srclen,		/* 0 means strlen(src) */
+	struct in_addr *addr,
+	struct in_addr *mask
+);
+size_t				/* space needed for full conversion */
+subnettoa(
+	struct in_addr addr,
+	struct in_addr mask,
+	int format,		/* character; 0 means default */
+	char *dst,
+	size_t dstlen
+);
+#define	SUBNETTOA_BUF	32	/* large enough for worst case result */
+
+/* ranges */
+const char *			/* NULL for success, else string literal */
+atoasr(
+	const char *src,
+	size_t srclen,		/* 0 means strlen(src) */
+	char *type,		/* 'a', 's', 'r' */
+	struct in_addr *addrs	/* two-element array */
+);
+size_t				/* space needed for full conversion */
+rangetoa(
+	struct in_addr *addrs,	/* two-element array */
+	int format,		/* character; 0 means default */
+	char *dst,
+	size_t dstlen
+);
+#define	RANGETOA_BUF	34	/* large enough for worst case result */
+
+/* data types for SA conversion functions */
+
+/* SAs */
+const char *			/* NULL for success, else string literal */
+atosa(
+	const char *src,
+	size_t srclen,		/* 0 means strlen(src) */
+	struct sa_id *sa
+);
+size_t				/* space needed for full conversion */
+satoa(
+	struct sa_id sa,
+	int format,		/* character; 0 means default */
+	char *dst,
+	size_t dstlen
+);
+#define	SATOA_BUF	(3+ULTOA_BUF+ADDRTOA_BUF)
+
+/* generic data, e.g. keys */
+const char *			/* NULL for success, else string literal */
+atobytes(
+	const char *src,
+	size_t srclen,		/* 0 means strlen(src) */
+	char *dst,
+	size_t dstlen,
+	size_t *lenp		/* NULL means don't bother telling me */
+);
+size_t				/* 0 failure, else true size */
+bytestoa(
+	const char *src,
+	size_t srclen,
+	int format,		/* character; 0 means default */
+	char *dst,
+	size_t dstlen
+);
+
+/* old versions of generic-data functions; deprecated */
+size_t				/* 0 failure, else true size */
+atodata(
+	const char *src,
+	size_t srclen,		/* 0 means strlen(src) */
+	char *dst,
+	size_t dstlen
+);
+size_t				/* 0 failure, else true size */
+datatoa(
+	const char *src,
+	size_t srclen,
+	int format,		/* character; 0 means default */
+	char *dst,
+	size_t dstlen
+);
+
+/* part extraction and special addresses */
+struct in_addr
+subnetof(
+	struct in_addr addr,
+	struct in_addr mask
+);
+struct in_addr
+hostof(
+	struct in_addr addr,
+	struct in_addr mask
+);
+struct in_addr
+broadcastof(
+	struct in_addr addr,
+	struct in_addr mask
+);
+
+/* mask handling */
+int
+goodmask(
+	struct in_addr mask
+);
+int
+masktobits(
+	struct in_addr mask
+);
+struct in_addr
+bitstomask(
+	int n
+);
+
+
+
+/*
+ * general utilities
+ */
+
+#ifndef __KERNEL__
+/* option pickup from files (userland only because of use of FILE) */
+const char *optionsfrom(const char *filename, int *argcp, char ***argvp,
+						int optind, FILE *errorreport);
+#endif
+
+/*
+ * Debugging levels for pfkey_parse.c
+ */
+#define PF_KEY_DEBUG_PARSE_PROBLEM 1
+#define PF_KEY_DEBUG_PARSE_STRUCT  3
+#define PF_KEY_DEBUG_PARSE_FLOW    4
+
+
+#endif /* _FREESWAN_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/goodmask.c linux-patched/net/ipsec/libfreeswan/goodmask.c
--- linux/net/ipsec/libfreeswan/goodmask.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/goodmask.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,97 @@
+/*
+ * minor utilities for subnet-mask manipulation
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - goodmask - is this a good (^1*0*$) subnet mask?
+ * You are not expected to understand this.  See Henry S. Warren Jr, 
+ * "Functions realizable with word-parallel logical and two's-complement
+ * addition instructions", CACM 20.6 (June 1977), p.439.
+ */
+int				/* predicate */
+goodmask(mask)
+struct in_addr mask;
+{
+	unsigned long x = ntohl(mask.s_addr);
+	/* clear rightmost contiguous string of 1-bits */
+#	define	CRCS1B(x)	(((x|(x-1))+1)&x)
+#	define	TOPBIT		(1UL << 31)
+
+	/* either zero, or has one string of 1-bits which is left-justified */
+	if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT)))
+		return 1;
+	return 0;
+}
+
+/*
+ - masktobits - how many bits in this mask?
+ * The algorithm is essentially a binary search, but highly optimized
+ * for this particular task.
+ */
+int				/* -1 means !goodmask() */
+masktobits(mask)
+struct in_addr mask;
+{
+	unsigned long m = ntohl(mask.s_addr);
+	int masklen;
+
+	if (!goodmask(mask))
+		return -1;
+
+	if (m&0x00000001UL)
+		return 32;
+	masklen = 0;
+	if (m&(0x0000ffffUL<<1)) {	/* <<1 for 1-origin numbering */
+		masklen |= 0x10;
+		m <<= 16;
+	}
+	if (m&(0x00ff0000UL<<1)) {
+		masklen |= 0x08;
+		m <<= 8;
+	}
+	if (m&(0x0f000000UL<<1)) {
+		masklen |= 0x04;
+		m <<= 4;
+	}
+	if (m&(0x30000000UL<<1)) {
+		masklen |= 0x02;
+		m <<= 2;
+	}
+	if (m&(0x40000000UL<<1))
+		masklen |= 0x01;
+
+	return masklen;
+}
+
+/*
+ - bitstomask - return a mask with this many high bits on
+ */
+struct in_addr
+bitstomask(n)
+int n;
+{
+	struct in_addr result;
+
+	if (n > 0 && n <= ABITS)
+		result.s_addr = htonl(~((1UL << (ABITS - n)) - 1));
+	else if (n == 0)
+		result.s_addr = 0;
+	else
+		result.s_addr = 0;	/* best error report we can do */
+	return result;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/initaddr.c linux-patched/net/ipsec/libfreeswan/initaddr.c
--- linux/net/ipsec/libfreeswan/initaddr.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/initaddr.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,51 @@
+/*
+ * initialize address structure
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - initaddr - initialize ip_address from bytes
+ */
+err_t				/* NULL for success, else string literal */
+initaddr(src, srclen, af, dst)
+const unsigned char *src;
+size_t srclen;
+int af;				/* address family */
+ip_address *dst;
+{
+	switch (af) {
+	case AF_INET:
+		if (srclen != 4)
+			return "IPv4 address must be exactly 4 bytes";
+		dst->u.v4.sin_family = af;
+		dst->u.v4.sin_port = 0;		/* unused */
+		memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen);
+		break;
+	case AF_INET6:
+		if (srclen != 16)
+			return "IPv6 address must be exactly 16 bytes";
+		dst->u.v6.sin6_family = af;
+		dst->u.v6.sin6_flowinfo = 0;		/* unused */
+		dst->u.v6.sin6_port = 0;		/* unused */
+		memcpy((char *)&dst->u.v6.sin6_addr, src, srclen);
+		break;
+	default:
+		return "unknown address family in initaddr";
+		break;
+	}
+	return NULL;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/initsaid.c linux-patched/net/ipsec/libfreeswan/initsaid.c
--- linux/net/ipsec/libfreeswan/initsaid.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/initsaid.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,33 @@
+/*
+ * initialize SA ID structure
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - initsaid - initialize SA ID from bits
+ */
+void
+initsaid(addr, spi, proto, dst)
+const ip_address *addr;
+ipsec_spi_t spi;
+int proto;
+ip_said *dst;
+{
+	dst->dst = *addr;
+	dst->spi = spi;
+	dst->proto = proto;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/initsubnet.c linux-patched/net/ipsec/libfreeswan/initsubnet.c
--- linux/net/ipsec/libfreeswan/initsubnet.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/initsubnet.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,95 @@
+/*
+ * initialize subnet structure
+ * Copyright (C) 2000, 2002  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - initsubnet - initialize ip_subnet from address and count
+ *
+ * The only hard part is checking for host-part bits turned on.
+ */
+err_t				/* NULL for success, else string literal */
+initsubnet(addr, count, clash, dst)
+const ip_address *addr;
+int count;
+int clash;			/* '0' zero host-part bits, 'x' die on them */
+ip_subnet *dst;
+{
+	unsigned char *p;
+	int n;
+	int c;
+	unsigned m;
+	int die;
+
+	dst->addr = *addr;
+	n = addrbytesptr(&dst->addr, (const unsigned char **)&p);
+	if (n == 0)
+		return "unknown address family";
+
+	switch (clash) {
+	case '0':
+		die = 0;
+		break;
+	case 'x':
+		die = 1;
+		break;
+	default:
+		return "unknown clash-control value in initsubnet";
+		break;
+	}
+
+	c = count / 8;
+	if (c > n)
+		return "impossible mask count";
+	p += c;
+	n -= c;
+
+	m = 0xff;
+	c = count % 8;
+	if (n > 0 && c != 0)	/* partial byte */
+		m >>= c;
+	for (; n > 0; n--) {
+		if ((*p & m) != 0) {
+			if (die)
+				return "improper subnet, host-part bits on";
+			*p &= ~m;
+		}
+		m = 0xff;
+		p++;
+	}
+
+	dst->maskbits = count;
+	return NULL;
+}
+
+/*
+ - addrtosubnet - initialize ip_subnet from a single address
+ */
+err_t				/* NULL for success, else string literal */
+addrtosubnet(addr, dst)
+const ip_address *addr;
+ip_subnet *dst;
+{
+	int n;
+
+	dst->addr = *addr;
+	n = addrbytesptr(&dst->addr, (const unsigned char **)NULL);
+	if (n == 0)
+		return "unknown address family";
+	dst->maskbits = n*8;
+	return NULL;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/internal.h linux-patched/net/ipsec/libfreeswan/internal.h
--- linux/net/ipsec/libfreeswan/internal.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/internal.h	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,81 @@
+/*
+ * internal definitions for use within the library; do not export!
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#ifndef ABITS
+#define	ABITS	32	/* bits in an IPv4 address */
+#endif
+
+/* case-independent ASCII character equality comparison */
+#define	CIEQ(c1, c2)	( ((c1)&~040) == ((c2)&~040) )
+
+/* syntax for passthrough SA */
+#ifndef PASSTHROUGHNAME
+#define	PASSTHROUGHNAME	"%passthrough"
+#define	PASSTHROUGH4NAME	"%passthrough4"
+#define	PASSTHROUGH6NAME	"%passthrough6"
+#define	PASSTHROUGHIS	"tun0@0.0.0.0"
+#define	PASSTHROUGH4IS	"tun0@0.0.0.0"
+#define	PASSTHROUGH6IS	"tun0@::"
+#define	PASSTHROUGHTYPE	"tun"
+#define	PASSTHROUGHSPI	0
+#define	PASSTHROUGHDST	0
+#endif
+
+/*
+ * Headers, greatly complicated by stupid and unnecessary inconsistencies
+ * between the user environment and the kernel environment.  These are done
+ * here so that this mess need exist in only one place.
+ *
+ * It may seem like a -I or two could avoid most of this, but on closer
+ * inspection it is not quite that easy.
+ */
+
+/* things that need to come from one place or the other, depending */
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#define	assert(foo)	/* nothing */
+#else
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#endif
+
+/* things that exist only in userland */
+#ifndef __KERNEL__
+
+/* You'd think this would be okay in the kernel too -- it's just a */
+/* bunch of constants -- but no, in RH5.1 it screws up other things. */
+/* (Credit:  Mike Warfield tracked this problem down.  Thanks Mike!) */
+/* Fortunately, we don't need it in the kernel subset of the library. */
+#include <limits.h>
+
+/* header files for things that should never be called in kernel */
+#include <netdb.h>
+
+/* memory allocation, currently user-only, macro-ized just in case */
+#include <stdlib.h>
+#define	MALLOC(n)	malloc(n)
+#define	FREE(p)		free(p)
+
+#endif /* __KERNEL__ */
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/keyblobtoid.c linux-patched/net/ipsec/libfreeswan/keyblobtoid.c
--- linux/net/ipsec/libfreeswan/keyblobtoid.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/keyblobtoid.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,148 @@
+/*
+ * generate printable key IDs
+ * Copyright (C) 2002  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - keyblobtoid - generate a printable key ID from an RFC 2537/3110 key blob
+ * Current algorithm is just to use first nine base64 digits.
+ */
+size_t
+keyblobtoid(src, srclen, dst, dstlen)
+const unsigned char *src;
+size_t srclen;
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	char buf[KEYID_BUF];
+	size_t ret;
+#	define	NDIG	9
+
+	if (srclen < (NDIG*6 + 7)/8) {
+		strcpy(buf, "?len= ?");
+		buf[5] = '0' + srclen;
+		ret = 0;
+	} else {
+		(void) datatot(src, srclen, 64, buf, NDIG+1);
+		ret = NDIG+1;
+	}
+
+	if (dstlen > 0) {
+		if (strlen(buf)+1 > dstlen)
+			*(buf + dstlen - 1) = '\0';
+		strcpy(dst, buf);
+	}
+	return ret;
+}
+
+/*
+ - splitkeytoid - generate a printable key ID from exponent/modulus pair
+ * Just constructs the beginnings of a key blob and calls keyblobtoid().
+ */
+size_t
+splitkeytoid(e, elen, m, mlen, dst, dstlen)
+const unsigned char *e;
+size_t elen;
+const unsigned char *m;
+size_t mlen;
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	unsigned char buf[KEYID_BUF];	/* ample room */
+	unsigned char *bufend = buf + sizeof(buf);
+	unsigned char *p;
+	size_t n;
+
+	p = buf;
+	if (elen <= 255)
+		*p++ = elen;
+	else if ((elen &~ 0xffff) == 0) {
+		*p++ = 0;
+		*p++ = (elen>>8) & 0xff;
+		*p++ = elen & 0xff;
+	} else
+		return 0;	/* unrepresentable exponent length */
+
+	n = bufend - p;
+	if (elen < n)
+		n = elen;
+	memcpy(p, e, n);
+	p += n;
+
+	n = bufend - p;
+	if (n > 0) {
+		if (mlen < n)
+			n = mlen;
+		memcpy(p, m, n);
+		p += n;
+	}
+
+	return keyblobtoid(buf, p - buf, dst, dstlen);
+}
+
+
+
+#ifdef KEYID_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	typedef unsigned char uc;
+	uc hexblob[] = "\x01\x03\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52";
+	uc hexe[] = "\x03";
+	uc hexm[] = "\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52\xef\x85";
+	char b64nine[] = "AQOF8tZ2m";
+	char b64six[] = "AQOF8t";
+	char buf[100];
+	size_t n;
+	char *b = b64nine;
+	size_t bl = strlen(b) + 1;
+	int st = 0;
+
+	n = keyblobtoid(hexblob, strlen(hexblob), buf, sizeof(buf));
+	if (n != bl) {
+		fprintf(stderr, "%s: keyblobtoid returned %d not %d\n",
+							argv[0], n, bl);
+		st = 1;
+	}
+	if (strcmp(buf, b) != 0) {
+		fprintf(stderr, "%s: keyblobtoid generated `%s' not `%s'\n",
+							argv[0], buf, b);
+		st = 1;
+	}
+	n = splitkeytoid(hexe, strlen(hexe), hexm, strlen(hexm), buf,
+								sizeof(buf));
+	if (n != bl) {
+		fprintf(stderr, "%s: splitkeytoid returned %d not %d\n",
+							argv[0], n, bl);
+		st = 1;
+	}
+	if (strcmp(buf, b) != 0) {
+		fprintf(stderr, "%s: splitkeytoid generated `%s' not `%s'\n",
+							argv[0], buf, b);
+		st = 1;
+	}
+	exit(st);
+}
+
+#endif /* KEYID_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/optionsfrom.c linux-patched/net/ipsec/libfreeswan/optionsfrom.c
--- linux/net/ipsec/libfreeswan/optionsfrom.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/optionsfrom.c	Thu Sep  5 04:13:19 2002
@@ -0,0 +1,301 @@
+/*
+ * pick up more options from a file, in the middle of an option scan
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#include <stdio.h>
+
+#define	MAX	100		/* loop-detection limit */
+
+/* internal work area */
+struct work {
+#	define	LOTS	1024
+	char buf[LOTS];
+	char *line;
+	char *pending;
+};
+
+static const char *dowork(const char *, int *, char ***, int);
+static const char *getanarg(FILE *, struct work *, char **);
+static char *getline(FILE *, char *, size_t);
+
+/*
+ - optionsfrom - add some options, taken from a file, to argc/argv
+ * If errsto is non-NULL, does not return in event of error.
+ */
+const char *			/* NULL for success, else string literal */
+optionsfrom(filename, argcp, argvp, optind, errsto)
+const char *filename;
+int *argcp;			/* pointer to argc */
+char ***argvp;			/* pointer to argv */
+int optind;			/* current optind, number of next argument */
+FILE *errsto;			/* where to report errors (NULL means return) */
+{
+	const char *e;
+	static int nuses = 0;
+
+	if (errsto != NULL) {
+		nuses++;
+		if (nuses >= MAX) {
+			fprintf(errsto,
+				"%s: optionsfrom called %d times, looping?\n",
+				(*argvp)[0], nuses);
+			exit(2);
+		}
+	} else
+		nuses = 0;
+
+	e = dowork(filename, argcp, argvp, optind);
+	if (e != NULL && errsto != NULL) {
+		fprintf(errsto, "%s: optionsfrom failed: %s\n", (*argvp)[0], e);
+		exit(2);
+	}
+	return e;
+}
+
+/*
+ - dowork - do all the real work of optionsfrom
+ * Does not alter the existing arguments, but does relocate and alter
+ * the argv pointer vector.
+ */
+static const char *		/* NULL for success, else string literal */
+dowork(filename, argcp, argvp, optind)
+const char *filename;
+int *argcp;			/* pointer to argc */
+char ***argvp;			/* pointer to argv */
+int optind;			/* current optind, number of next argument */
+{
+	char **newargv;
+	char **tmp;
+	int newargc;
+	int next;		/* place for next argument */
+	int room;		/* how many more new arguments we can hold */
+#	define	SOME	10	/* first guess at how many we'll need */
+	FILE *f;
+	int i;
+	const char *p;
+	struct work wa;		/* for getanarg() */
+
+	f = fopen(filename, "r");
+	if (f == NULL)
+		return "unable to open file";
+
+	newargc = *argcp + SOME;
+	newargv = malloc((newargc+1) * sizeof(char *));
+	if (newargv == NULL)
+		return "unable to allocate memory";
+	memcpy(newargv, *argvp, optind * sizeof(char *));
+	room = SOME;
+	next = optind;
+
+	newargv[next] = NULL;
+	wa.pending = NULL;
+	while ((p = getanarg(f, &wa, &newargv[next])) == NULL) {
+		if (room == 0) {
+			newargc += SOME;
+			tmp = realloc(newargv, (newargc+1) * sizeof(char *));
+			if (tmp == NULL) {
+				p = "out of space for new argv";
+				break;		/* NOTE BREAK OUT */
+			}
+			newargv = tmp;
+			room += SOME;
+		}
+		next++;
+		room--;
+	}
+	if (p != NULL && !feof(f)) {	/* error of some kind */
+		for (i = optind+1; i <= next; i++)
+			if (newargv[i] != NULL)
+				free(newargv[i]);
+		free(newargv);
+		fclose(f);
+		return p;
+	}
+
+	fclose(f);
+	memcpy(newargv + next, *argvp + optind,
+					(*argcp+1-optind) * sizeof(char *));
+	*argcp += next - optind;
+	*argvp = newargv;
+	return NULL;
+}
+
+/*
+ - getanarg - get a malloced argument from the file
+ */
+static const char *		/* NULL for success, else string literal */
+getanarg(f, w, linep)
+FILE *f;
+struct work *w;
+char **linep;			/* where to store pointer if successful */
+{
+	size_t len;
+	char *p;
+	char *endp;
+
+	while (w->pending == NULL) {	/* no pending line */
+		if ((w->line = getline(f, w->buf, sizeof(w->buf))) == NULL)
+			return "error in line read";	/* caller checks EOF */
+		if (w->line[0] != '#' &&
+				*(w->line + strspn(w->line, " \t")) != '\0')
+			w->pending = w->line;
+	}
+
+	if (w->pending == w->line && w->line[0] != '-') {
+		/* fresh plain line */
+		w->pending = NULL;
+		p = w->line;
+		endp = p + strlen(p);
+		if (*p == '"' && endp > p+1 && *(endp-1) == '"') {
+			p++;
+			endp--;
+			*endp = '\0';
+		}
+		if (w->line == w->buf) {
+			*linep = malloc(endp - p + 1);
+			if (*linep == NULL)
+				return "out of memory for new line";
+			strcpy(*linep, p);
+		} else			/* getline already malloced it */
+			*linep = p;
+		return NULL;
+	}
+
+	/* chip off a piece of a pending line */
+	p = w->pending;
+	p += strspn(p, " \t");
+	endp = p + strcspn(p, " \t");
+	len = endp - p;
+	if (*endp != '\0') {
+		*endp++ = '\0';
+		endp += strspn(endp, " \t");
+	}
+	/* endp now points to next real character, or to line-end NUL */
+	*linep = malloc(len + 1);
+	if (*linep == NULL) {
+		if (w->line != w->buf)
+			free(w->line);
+		return "out of memory for new argument";
+	}
+	strcpy(*linep, p);
+	if (*endp == '\0') {
+		w->pending = NULL;
+		if (w->line != w->buf)
+			free(w->line);
+	} else
+		w->pending = endp;
+	return NULL;
+}
+
+/*
+ - getline - read a line from the file, trim newline off
+ */
+static char *			/* pointer to line, NULL for eof/error */
+getline(f, buf, bufsize)
+FILE *f;
+char *buf;			/* buffer to use, if convenient */
+size_t bufsize;			/* size of buf */
+{
+	size_t len;
+
+	if (fgets(buf, bufsize, f) == NULL)
+		return NULL;
+	len = strlen(buf);
+
+	if (len < bufsize-1 || buf[bufsize-1] == '\n') {
+		/* it fit */
+		buf[len-1] = '\0';
+		return buf;
+	}
+
+	/* oh crud, buffer overflow */
+	/* for now, to hell with it */
+	return NULL;
+}
+
+
+
+#ifdef TEST
+
+#include <getopt.h>
+
+char usage[] = "Usage: tester [--foo] [--bar] [--optionsfrom file] arg ...";
+struct option opts[] = {
+	"foo",		0,	NULL,	'f',
+	"bar",		0,	NULL,	'b',
+	"builtin",	0,	NULL,	'B',
+	"optionsfrom",	1,	NULL,	'+',
+	"help",		0,	NULL,	'h',
+	"version",	0,	NULL,	'v',
+	0,		0,	NULL,	0,
+};
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	int opt;
+	extern char *optarg;
+	extern int optind;
+	int errflg = 0;
+	const char *p;
+	int i;
+	FILE *errs = NULL;
+
+	while ((opt = getopt_long(argc, argv, "", opts, NULL)) != EOF)
+		switch (opt) {
+		case 'f':
+		case 'b':
+			break;
+		case 'B':
+			errs = stderr;
+			break;
+		case '+':	/* optionsfrom */
+			p = optionsfrom(optarg, &argc, &argv, optind, errs);
+			if (p != NULL) {
+				fprintf(stderr, "%s: optionsfrom error: %s\n",
+								argv[0], p);
+				exit(1);
+			}
+			break;
+		case 'h':	/* help */
+			printf("%s\n", usage);
+			exit(0);
+			break;
+		case 'v':	/* version */
+			printf("1\n");
+			exit(0);
+			break;
+		case '?':
+		default:
+			errflg = 1;
+			break;
+		}
+	if (errflg) {
+		fprintf(stderr, "%s\n", usage);
+		exit(2);
+	}
+
+	for (i = 1; i < argc; i++)
+		printf("%d: `%s'\n", i, argv[i]);
+	exit(0);
+}
+
+
+#endif /* TEST */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/pfkey.h linux-patched/net/ipsec/libfreeswan/pfkey.h
--- linux/net/ipsec/libfreeswan/pfkey.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/pfkey.h	Thu Dec 12 03:32:07 2002
@@ -0,0 +1,412 @@
+/*
+ * FreeS/WAN specific PF_KEY headers
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#ifndef __NET_IPSEC_PF_KEY_H
+#define __NET_IPSEC_PF_KEY_H
+#ifdef __KERNEL__
+extern void pfkey_proto_init(struct net_proto *pro);
+extern struct proto_ops pfkey_proto_ops;
+typedef struct sock pfkey_sock;
+extern int debug_pfkey;
+
+extern /* void */ int pfkey_init(void);
+extern /* void */ int pfkey_cleanup(void);
+
+extern struct sock *pfkey_sock_list;
+struct socket_list
+{
+	struct socket *socketp;
+	struct socket_list *next;
+};
+extern int pfkey_list_insert_socket(struct socket*, struct socket_list**);
+extern int pfkey_list_remove_socket(struct socket*, struct socket_list**);
+extern struct socket_list *pfkey_open_sockets;
+extern struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1];
+
+/* 
+ *	There is a field-by-field copy in klips/net/ipsec/ipsec_alg.h
+ *	please keep in sync until we migrate all support stuff
+ *	to ipsec_alg objects
+ */
+struct supported
+{
+	uint16_t supported_alg_exttype;
+	uint8_t supported_alg_id;
+	uint8_t supported_alg_ivlen;
+	uint16_t supported_alg_minbits;
+	uint16_t supported_alg_maxbits;
+};
+extern struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1];
+struct supported_list
+{
+	struct supported *supportedp;
+	struct supported_list *next;
+};
+extern int pfkey_list_insert_supported(struct supported*, struct supported_list**);
+extern int pfkey_list_remove_supported(struct supported*, struct supported_list**);
+
+/*
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+ */
+struct sockaddr_key
+{
+	uint16_t	key_family;	/* PF_KEY */
+	uint16_t	key_pad;	/* not used */
+	uint32_t	key_pid;	/* process ID */
+};
+/*
+#endif */ /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+ */
+
+struct pfkey_extracted_data
+{
+	struct ipsec_sa* tdb;
+	struct ipsec_sa* tdb2;
+	struct eroute *eroute;
+};
+
+extern int pfkey_register_reply(int satype, struct sadb_msg *);
+extern int pfkey_upmsg(struct socket *, struct sadb_msg *);
+extern int pfkey_expire(struct ipsec_sa *, int);
+extern int pfkey_acquire(struct ipsec_sa *);
+#endif /* __KERNEL__ */
+
+extern uint8_t satype2proto(uint8_t satype);
+extern uint8_t proto2satype(uint8_t proto);
+extern char* satype2name(uint8_t satype);
+extern char* proto2name(uint8_t proto);
+
+struct key_opt
+{
+	uint32_t	key_pid;	/* process ID */
+	struct sock	*sk;
+};
+
+#define key_pid(sk) ((struct key_opt*)&((sk)->protinfo))->key_pid
+
+#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t))
+#define BITS_PER_OCTET 8
+#define OCTETBITS 8
+#define PFKEYBITS 64
+#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */
+#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */
+
+#define PFKEYv2_MAX_MSGSIZE 4096
+
+/*
+ * PF_KEYv2 permitted and required extensions in and out bitmaps
+ */
+struct pf_key_ext_parsers_def {
+	int  (*parser)(struct sadb_ext*);
+	char  *parser_name;
+};
+
+
+extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/];
+#define EXT_BITS_IN 0
+#define EXT_BITS_OUT 1
+#define EXT_BITS_PERM 0
+#define EXT_BITS_REQ 1
+
+extern void pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
+extern void pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
+extern void pfkey_msg_free(struct sadb_msg **pfkey_msg);
+
+extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg,
+			   struct pf_key_ext_parsers_def *ext_parsers[],
+			   struct sadb_ext **extensions,
+			   int dir);
+
+/*
+ * PF_KEYv2 build function prototypes
+ */
+
+int
+pfkey_msg_hdr_build(struct sadb_ext**	pfkey_ext,
+		    uint8_t		msg_type,
+		    uint8_t		satype,
+		    uint8_t		msg_errno,
+		    uint32_t		seq,
+		    uint32_t		pid);
+
+int
+pfkey_sa_build(struct sadb_ext **	pfkey_ext,
+	       uint16_t			exttype,
+	       uint32_t			spi, /* in network order */
+	       uint8_t			replay_window,
+	       uint8_t			sa_state,
+	       uint8_t			auth,
+	       uint8_t			encrypt,
+	       uint32_t			flags);
+
+int
+pfkey_lifetime_build(struct sadb_ext **	pfkey_ext,
+		     uint16_t		exttype,
+		     uint32_t		allocations,
+		     uint64_t		bytes,
+		     uint64_t		addtime,
+		     uint64_t		usetime,
+		     uint32_t		packets);
+
+int
+pfkey_address_build(struct sadb_ext**	pfkey_ext,
+		    uint16_t		exttype,
+		    uint8_t		proto,
+		    uint8_t		prefixlen,
+		    struct sockaddr*	address);
+
+int
+pfkey_key_build(struct sadb_ext**	pfkey_ext,
+		uint16_t		exttype,
+		uint16_t		key_bits,
+		char*			key);
+
+int
+pfkey_ident_build(struct sadb_ext**	pfkey_ext,
+		  uint16_t		exttype,
+		  uint16_t		ident_type,
+		  uint64_t		ident_id,
+		  uint8_t               ident_len,
+		  char*			ident_string);
+
+int
+pfkey_sens_build(struct sadb_ext**	pfkey_ext,
+		 uint32_t		dpd,
+		 uint8_t		sens_level,
+		 uint8_t		sens_len,
+		 uint64_t*		sens_bitmap,
+		 uint8_t		integ_level,
+		 uint8_t		integ_len,
+		 uint64_t*		integ_bitmap);
+
+int
+pfkey_prop_build(struct sadb_ext**	pfkey_ext,
+		 uint8_t		replay,
+		 unsigned int		comb_num,
+		 struct sadb_comb*	comb);
+
+int
+pfkey_supported_build(struct sadb_ext**	pfkey_ext,
+		      uint16_t		exttype,
+		      unsigned int	alg_num,
+		      struct sadb_alg*	alg);
+
+int
+pfkey_spirange_build(struct sadb_ext**	pfkey_ext,
+		     uint16_t		exttype,
+		     uint32_t		min,
+		     uint32_t		max);
+
+int
+pfkey_x_kmprivate_build(struct sadb_ext**	pfkey_ext);
+
+int
+pfkey_x_satype_build(struct sadb_ext**	pfkey_ext,
+		     uint8_t		satype);
+
+int pfkey_x_protocol_build(struct sadb_ext **, uint8_t);
+
+
+int
+pfkey_x_debug_build(struct sadb_ext**	pfkey_ext,
+		    uint32_t            tunnel,
+		    uint32_t		netlink,
+		    uint32_t		xform,
+		    uint32_t		eroute,
+		    uint32_t		spi,
+		    uint32_t		radij,
+		    uint32_t		esp,
+		    uint32_t		ah,
+		    uint32_t		rcv,
+		    uint32_t            pfkey,
+		    uint32_t            ipcomp,
+		    uint32_t            verbose);
+
+#ifdef NAT_TRAVERSAL
+#ifdef __KERNEL__
+extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16);
+#endif /* __KERNEL__ */
+int
+pfkey_x_nat_t_type_build(struct sadb_ext**  pfkey_ext,
+            uint8_t         type);
+int
+pfkey_x_nat_t_port_build(struct sadb_ext**  pfkey_ext,
+            uint16_t         exttype,
+            uint16_t         port);
+#endif
+
+int
+pfkey_msg_build(struct sadb_msg**	pfkey_msg,
+		struct sadb_ext*	extensions[],
+		int			dir);
+
+/* in pfkey_v2_debug.c - routines to decode numbers -> strings */
+const char *
+pfkey_v2_sadb_ext_string(int extnum);
+
+const char *
+pfkey_v2_sadb_type_string(int sadb_type);
+
+
+#endif /* __NET_IPSEC_PF_KEY_H */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.4  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.3  2002/09/05 03:53:52  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.2  2002/09/05 03:22:11  ken
+ * Applied freeswan-alg-0.8.0-BASE-common.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:19  ken
+ * 1.98b
+ *
+ * Revision 1.36  2002/01/20 20:34:49  mcr
+ * 	added pfkey_v2_sadb_type_string to decode sadb_type to string.
+ *
+ * Revision 1.35  2001/11/27 05:27:47  mcr
+ * 	pfkey parses are now maintained by a structure
+ * 	that includes their name for debug purposes.
+ *
+ * Revision 1.34  2001/11/26 09:23:53  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.33  2001/11/06 19:47:47  rgb
+ * Added packet parameter to lifetime and comb structures.
+ *
+ * Revision 1.32  2001/09/08 21:13:34  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.31  2001/06/14 19:35:16  rgb
+ * Update copyright date.
+ *
+ * Revision 1.30  2001/02/27 07:04:52  rgb
+ * Added satype2name prototype.
+ *
+ * Revision 1.29  2001/02/26 19:59:33  rgb
+ * Ditch unused sadb_satype2proto[], replaced by satype2proto().
+ *
+ * Revision 1.28  2000/10/10 20:10:19  rgb
+ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
+ *
+ * Revision 1.27  2000/09/21 04:20:45  rgb
+ * Fixed array size off-by-one error.  (Thanks Svenning!)
+ *
+ * Revision 1.26  2000/09/12 03:26:05  rgb
+ * Added pfkey_acquire prototype.
+ *
+ * Revision 1.25  2000/09/08 19:21:28  rgb
+ * Fix pfkey_prop_build() parameter to be only single indirection.
+ *
+ * Revision 1.24  2000/09/01 18:46:42  rgb
+ * Added a supported algorithms array lists, one per satype and registered
+ * existing algorithms.
+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to
+ * list.
+ *
+ * Revision 1.23  2000/08/27 01:55:26  rgb
+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code.
+ *
+ * Revision 1.22  2000/08/20 21:39:23  rgb
+ * Added kernel prototypes for kernel funcitions pfkey_upmsg() and
+ * pfkey_expire().
+ *
+ * Revision 1.21  2000/08/15 17:29:23  rgb
+ * Fixes from SZI to untested pfkey_prop_build().
+ *
+ * Revision 1.20  2000/05/10 20:14:19  rgb
+ * Fleshed out sensitivity, proposal and supported extensions.
+ *
+ * Revision 1.19  2000/03/16 14:07:23  rgb
+ * Renamed ALIGN macro to avoid fighting with others in kernel.
+ *
+ * Revision 1.18  2000/01/22 23:24:06  rgb
+ * Added prototypes for proto2satype(), satype2proto() and proto2name().
+ *
+ * Revision 1.17  2000/01/21 06:26:59  rgb
+ * Converted from double tdb arguments to one structure (extr)
+ * containing pointers to all temporary information structures.
+ * Added klipsdebug switching capability.
+ * Dropped unused argument to pfkey_x_satype_build().
+ *
+ * Revision 1.16  1999/12/29 21:17:41  rgb
+ * Changed pfkey_msg_build() I/F to include a struct sadb_msg**
+ * parameter for cleaner manipulation of extensions[] and to guard
+ * against potential memory leaks.
+ * Changed the I/F to pfkey_msg_free() for the same reason.
+ *
+ * Revision 1.15  1999/12/09 23:12:54  rgb
+ * Added macro for BITS_PER_OCTET.
+ * Added argument to pfkey_sa_build() to do eroutes.
+ *
+ * Revision 1.14  1999/12/08 20:33:25  rgb
+ * Changed sa_family_t to uint16_t for 2.0.xx compatibility.
+ *
+ * Revision 1.13  1999/12/07 19:53:40  rgb
+ * Removed unused first argument from extension parsers.
+ * Changed __u* types to uint* to avoid use of asm/types.h and
+ * sys/types.h in userspace code.
+ * Added function prototypes for pfkey message and extensions
+ * initialisation and cleanup.
+ *
+ * Revision 1.12  1999/12/01 22:19:38  rgb
+ * Change pfkey_sa_build to accept an SPI in network byte order.
+ *
+ * Revision 1.11  1999/11/27 11:55:26  rgb
+ * Added extern sadb_satype2proto to enable moving protocol lookup table
+ * to lib/pfkey_v2_parse.c.
+ * Delete unused, moved typedefs.
+ * Add argument to pfkey_msg_parse() for direction.
+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
+ *
+ * Revision 1.10  1999/11/23 22:29:21  rgb
+ * This file has been moved in the distribution from klips/net/ipsec to
+ * lib.
+ * Add macros for dealing with alignment and rounding up more opaquely.
+ * The uint<n>_t type defines have been moved to freeswan.h to avoid
+ * chicken-and-egg problems.
+ * Add macros for dealing with alignment and rounding up more opaque.
+ * Added prototypes for using extention header bitmaps.
+ * Added prototypes of all the build functions.
+ *
+ * Revision 1.9  1999/11/20 21:59:48  rgb
+ * Moved socketlist type declarations and prototypes for shared use.
+ * Slightly modified scope of sockaddr_key declaration.
+ *
+ * Revision 1.8  1999/11/17 14:34:25  rgb
+ * Protect sa_family_t from being used in userspace with GLIBC<2.
+ *
+ * Revision 1.7  1999/10/27 19:40:35  rgb
+ * Add a maximum PFKEY packet size macro.
+ *
+ * Revision 1.6  1999/10/26 16:58:58  rgb
+ * Created a sockaddr_key and key_opt socket extension structures.
+ *
+ * Revision 1.5  1999/06/10 05:24:41  rgb
+ * Renamed variables to reduce confusion.
+ *
+ * Revision 1.4  1999/04/29 15:21:11  rgb
+ * Add pfkey support to debugging.
+ * Add return values to init and cleanup functions.
+ *
+ * Revision 1.3  1999/04/15 17:58:07  rgb
+ * Add RCSID labels.
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/pfkey_v2_build.c linux-patched/net/ipsec/libfreeswan/pfkey_v2_build.c
--- linux/net/ipsec/libfreeswan/pfkey_v2_build.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/pfkey_v2_build.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,1502 @@
+/*
+ * RFC2367 PF_KEYv2 Key management API message parser
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ *		Template from klips/net/ipsec/ipsec/ipsec_parser.c.
+ */
+
+char pfkey_v2_build_c_version[] = "$Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+/*
+ * Some ugly stuff to allow consistent debugging code for use in the
+ * kernel and in user space
+*/
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h>  /* for printk */
+
+# include "../ipsec_kversion.h" /* for malloc switch */
+# ifdef MALLOC_SLAB
+#  include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+#  include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h>  /* error codes */
+# include <linux/types.h>  /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h>   /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+# include <linux/ip.h>          /* struct iphdr */ 
+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#  include <linux/ipv6.h>        /* struct ipv6hdr */
+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
+# define MALLOC(size) kmalloc(size, GFP_ATOMIC)
+# define FREE(obj) kfree(obj)
+# include <freeswan.h>
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+# include <malloc.h>
+# include <string.h> /* memset */
+
+# include <freeswan.h>
+# include "../pluto/constants.h" 
+# include "../pluto/defs.h"  /* for PRINTF_LIKE */
+# include "../pluto/log.h"  /* for debugging and DBG_log */
+
+extern unsigned int debugging;  /* bits selecting what to report */
+unsigned int pfkey_lib_debug = 0;
+
+/* #define PLUTO */
+
+# ifdef PLUTO
+#  define DEBUGGING(args...)  { DBG_log("pfkey_lib_debug:" args);  }
+# else
+#  define DEBUGGING(args...)  if(pfkey_lib_debug) { printf("pfkey_lib_debug:" args); } else { ; }
+# endif
+# define MALLOC(size) malloc(size)
+# define FREE(obj) free(obj)
+#endif /* __KERNEL__ */
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#ifdef __KERNEL__
+# include "../radij.h"  /* rd_nodes */
+# include "../ipsec_encap.h"  /* sockaddr_encap */
+# include "../ipsec_netlink.h"  /* KLIPS_PRINT */
+# define DEBUGGING(args...) \
+         KLIPS_PRINT(debug_pfkey, "klips_debug:" args)
+/*         ((debug_pfkey) ? printk(KERN_INFO "klips_debug:" format , ## args) : 0) */
+#endif /* __KERNEL__ */
+
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+void
+pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
+{
+	int i;
+	
+	for (i = 0; i != SADB_EXT_MAX + 1; i++) {
+		extensions[i] = NULL;
+	}
+}
+
+void
+pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
+{
+	int i;
+	
+	if(!extensions) {
+		return;
+	}
+
+	if(extensions[0]) {
+		memset(extensions[0], 0, sizeof(struct sadb_msg));
+		FREE(extensions[0]);
+		extensions[0] = NULL;
+	}
+	
+	for (i = 1; i != SADB_EXT_MAX + 1; i++) {
+		if(extensions[i]) {
+			memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
+			FREE(extensions[i]);
+			extensions[i] = NULL;
+		}
+	}
+}
+
+void
+pfkey_msg_free(struct sadb_msg **pfkey_msg)
+{
+	if(*pfkey_msg) {
+		memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
+		FREE(*pfkey_msg);
+		*pfkey_msg = NULL;
+	}
+}
+
+/* Default extension builders taken from the KLIPS code */
+
+int
+pfkey_msg_hdr_build(struct sadb_ext**	pfkey_ext,
+		    uint8_t		msg_type,
+		    uint8_t		satype,
+		    uint8_t		msg_errno,
+		    uint32_t		seq,
+		    uint32_t		pid)
+{
+	int error = 0;
+	struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext;
+
+	DEBUGGING(
+		"pfkey_msg_hdr_build:\n");
+	DEBUGGING(
+		"pfkey_msg_hdr_build: "
+		"on_entry &pfkey_ext=%p pfkey_ext=%p *pfkey_ext=%p.\n",
+		&pfkey_ext,
+		pfkey_ext,
+		*pfkey_ext);
+	/* sanity checks... */
+	if(pfkey_msg) {
+		DEBUGGING(
+			"pfkey_msg_hdr_build: "
+			"why is pfkey_msg already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if(!msg_type) {
+		DEBUGGING(
+			"pfkey_msg_hdr_build: "
+			"msg type not set, must be non-zero..\n");
+		SENDERR(EINVAL);
+	}
+
+	if(msg_type > SADB_MAX) {
+		DEBUGGING(
+			"pfkey_msg_hdr_build: "
+			"msg type too large:%d.\n",
+			msg_type);
+		SENDERR(EINVAL);
+	}
+
+	if(satype > SADB_SATYPE_MAX) {
+		DEBUGGING(
+			"pfkey_msg_hdr_build: "
+			"satype %d > max %d\n", 
+			satype, SADB_SATYPE_MAX);
+		SENDERR(EINVAL);
+	}
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_msg = (struct sadb_msg*)
+	     MALLOC(sizeof(struct sadb_msg)))) {
+		DEBUGGING(
+			"pfkey_msg_hdr_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_msg, 0, sizeof(struct sadb_msg));
+
+	pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
+
+	pfkey_msg->sadb_msg_type = msg_type;
+	pfkey_msg->sadb_msg_satype = satype;
+
+	pfkey_msg->sadb_msg_version = PF_KEY_V2;
+	pfkey_msg->sadb_msg_errno = msg_errno;
+	pfkey_msg->sadb_msg_reserved = 0;
+	pfkey_msg->sadb_msg_seq = seq;
+	pfkey_msg->sadb_msg_pid = pid;
+	DEBUGGING(
+		"pfkey_msg_hdr_build: "
+		"on_exit &pfkey_ext=%p pfkey_ext=%p *pfkey_ext=%p.\n",
+		&pfkey_ext,
+		pfkey_ext,
+		*pfkey_ext);
+errlab:
+	return error;
+}	
+
+int
+pfkey_sa_build(struct sadb_ext **	pfkey_ext,
+	       uint16_t			exttype,
+	       uint32_t			spi, /* in network order */
+	       uint8_t			replay_window,
+	       uint8_t			sa_state,
+	       uint8_t			auth,
+	       uint8_t			encrypt,
+	       uint32_t			flags)
+{
+	int error = 0;
+	struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext;
+
+	DEBUGGING(
+		    "pfkey_sa_build: "
+		    "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n",
+		    ntohl(spi), /* in network order */
+		    replay_window,
+		    sa_state,
+		    auth,
+		    encrypt,
+		    flags);
+	/* sanity checks... */
+	if(pfkey_sa) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"why is pfkey_sa already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if(exttype != SADB_EXT_SA &&
+	   exttype != SADB_X_EXT_SA2) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"invalid exttype=%d.\n",
+			exttype);
+		SENDERR(EINVAL);
+	}
+
+	if(replay_window > 64) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"replay window size: %d -- must be 0 <= size <= 64\n",
+			replay_window);
+		SENDERR(EINVAL);
+	}
+
+	if(auth > SADB_AALG_MAX) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"auth=%d > SADB_AALG_MAX=%d.\n",
+			auth,
+			SADB_AALG_MAX);
+		SENDERR(EINVAL);
+	}
+
+	if(encrypt > SADB_EALG_MAX) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"encrypt=%d > SADB_EALG_MAX=%d.\n",
+			encrypt,
+			SADB_EALG_MAX);
+		SENDERR(EINVAL);
+	}
+
+	if(sa_state > SADB_SASTATE_MAX) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"sa_state=%d exceeds MAX=%d.\n",
+			sa_state,
+			SADB_SASTATE_MAX);
+		SENDERR(EINVAL);
+	}
+
+	if(sa_state == SADB_SASTATE_DEAD) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"sa_state=%d is DEAD=%d is not allowed.\n",
+			sa_state,
+			SADB_SASTATE_DEAD);
+		SENDERR(EINVAL);
+	}
+	
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_sa = (struct sadb_sa*)
+	     MALLOC(sizeof(struct sadb_sa)))) {
+		DEBUGGING(
+			"pfkey_sa_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_sa, 0, sizeof(struct sadb_sa));
+	
+	pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN;
+	pfkey_sa->sadb_sa_exttype = exttype;
+	pfkey_sa->sadb_sa_spi = spi;
+	pfkey_sa->sadb_sa_replay = replay_window;
+	pfkey_sa->sadb_sa_state = sa_state;
+	pfkey_sa->sadb_sa_auth = auth;
+	pfkey_sa->sadb_sa_encrypt = encrypt;
+	pfkey_sa->sadb_sa_flags = flags;
+
+errlab:
+	return error;
+}	
+
+int
+pfkey_lifetime_build(struct sadb_ext **	pfkey_ext,
+		     uint16_t		exttype,
+		     uint32_t		allocations,
+		     uint64_t		bytes,
+		     uint64_t		addtime,
+		     uint64_t		usetime,
+		     uint32_t		packets)
+{
+	int error = 0;
+	struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext;
+
+	DEBUGGING(
+		"pfkey_lifetime_build:\n");
+	/* sanity checks... */
+	if(pfkey_lifetime) {
+		DEBUGGING(
+			"pfkey_lifetime_build: "
+			"why is pfkey_lifetime already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if(exttype != SADB_EXT_LIFETIME_CURRENT &&
+	   exttype != SADB_EXT_LIFETIME_HARD &&
+	   exttype != SADB_EXT_LIFETIME_SOFT) {
+		DEBUGGING(
+			"pfkey_lifetime_build: "
+			"invalid exttype=%d.\n",
+			exttype);
+		SENDERR(EINVAL);
+	}
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_lifetime = (struct sadb_lifetime*)
+	     MALLOC(sizeof(struct sadb_lifetime)))) {
+		DEBUGGING(
+			"pfkey_lifetime_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime));
+
+	pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN;
+	pfkey_lifetime->sadb_lifetime_exttype = exttype;
+	pfkey_lifetime->sadb_lifetime_allocations = allocations;
+	pfkey_lifetime->sadb_lifetime_bytes = bytes;
+	pfkey_lifetime->sadb_lifetime_addtime = addtime;
+	pfkey_lifetime->sadb_lifetime_usetime = usetime;
+	pfkey_lifetime->sadb_x_lifetime_packets = packets;
+
+errlab:
+	return error;
+}
+
+int
+pfkey_address_build(struct sadb_ext**	pfkey_ext,
+		    uint16_t		exttype,
+		    uint8_t		proto,
+		    uint8_t		prefixlen,
+		    struct sockaddr*	address)
+{
+	int error = 0;
+	int saddr_len = 0;
+	char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/];
+	struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext;
+	
+	DEBUGGING(
+		"pfkey_address_build: "
+		"exttype=%d proto=%d prefixlen=%d\n",
+		exttype,
+		proto,
+		prefixlen);
+	/* sanity checks... */
+	if(pfkey_address) {
+		DEBUGGING(
+			"pfkey_address_build: "
+			"why is pfkey_address already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if (!address)  {
+			DEBUGGING("pfkey_address_build: "
+				  "address is NULL\n");
+			SENDERR(EINVAL);
+	}
+	
+	switch(exttype) {	
+	case SADB_EXT_ADDRESS_SRC:
+	case SADB_EXT_ADDRESS_DST:
+	case SADB_EXT_ADDRESS_PROXY:
+	case SADB_X_EXT_ADDRESS_DST2:
+	case SADB_X_EXT_ADDRESS_SRC_FLOW:
+	case SADB_X_EXT_ADDRESS_DST_FLOW:
+	case SADB_X_EXT_ADDRESS_SRC_MASK:
+	case SADB_X_EXT_ADDRESS_DST_MASK:
+#ifdef NAT_TRAVERSAL
+	case SADB_X_EXT_NAT_T_OA:
+#endif
+		break;
+	default:
+		DEBUGGING( 
+			"pfkey_address_build: "
+			"unrecognised ext_type=%d.\n", 
+			exttype); 
+		SENDERR(EINVAL); 
+	}
+
+	switch(address->sa_family) {
+	case AF_INET:
+		DEBUGGING(
+			"pfkey_address_build: "
+			"found address family AF_INET.\n");
+		saddr_len = sizeof(struct sockaddr_in);
+		sprintf(ipaddr_txt, "%d.%d.%d.%d:%d"
+			, (((struct sockaddr_in*)address)->sin_addr.s_addr >>  0) & 0xFF
+			, (((struct sockaddr_in*)address)->sin_addr.s_addr >>  8) & 0xFF
+			, (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF
+			, (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF
+			, ntohs(((struct sockaddr_in*)address)->sin_port));
+		break;
+	case AF_INET6:
+		DEBUGGING(
+			"pfkey_address_build: "
+			"found address family AF_INET6.\n");
+		saddr_len = sizeof(struct sockaddr_in6);
+		sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x"
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[1])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[2])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[3])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[4])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[5])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[6])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[7])
+			, ntohs(((struct sockaddr_in6*)address)->sin6_port));
+		break;
+	default:
+		DEBUGGING(
+			"pfkey_address_build: "
+			"address->sa_family=%d not supported.\n",
+			address->sa_family);
+		SENDERR(EPFNOSUPPORT);
+	}
+
+	DEBUGGING(
+		"pfkey_address_build: "
+		"found address=%s.\n",
+		ipaddr_txt);
+	if(prefixlen != 0) {
+		DEBUGGING(
+			"pfkey_address_build: "
+			"address prefixes not supported yet.\n");
+		SENDERR(EAFNOSUPPORT); /* not supported yet */
+	}
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_address = (struct sadb_address*)
+	     MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN) ))) {
+		DEBUGGING(
+			"pfkey_lifetime_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_address,
+	       0,
+	       ALIGN_N(sizeof(struct sadb_address) + saddr_len,
+		     IPSEC_PFKEYv2_ALIGN));
+	       
+	pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len,
+						IPSEC_PFKEYv2_ALIGN);
+	
+	pfkey_address->sadb_address_exttype = exttype;
+	pfkey_address->sadb_address_proto = proto;
+	pfkey_address->sadb_address_prefixlen = prefixlen;
+	pfkey_address->sadb_address_reserved = 0;
+
+	memcpy((char*)pfkey_address + sizeof(struct sadb_address),
+	       address,
+	       saddr_len);
+
+#if 0
+	for(i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) {
+		pfkey_address_s_ska.sin_zero[i] = 0;
+	}
+#endif
+	DEBUGGING(
+		"pfkey_address_build: "
+		"successful.\n");
+
+ errlab:
+	return error;
+}
+
+int
+pfkey_key_build(struct sadb_ext**	pfkey_ext,
+		uint16_t		exttype,
+		uint16_t		key_bits,
+		char*			key)
+{
+	int error = 0;
+	struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext;
+
+	DEBUGGING(
+		"pfkey_key_build:\n");
+	/* sanity checks... */
+	if(pfkey_key) {
+		DEBUGGING(
+			"pfkey_key_build: "
+			"why is pfkey_key already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if(!key_bits) {
+		DEBUGGING(
+			"pfkey_key_build: "
+			"key_bits is zero, it must be non-zero.\n");
+		SENDERR(EINVAL);
+	}
+
+	if( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) {
+		DEBUGGING(
+			"pfkey_key_build: "
+			"unsupported extension type=%d.\n",
+			exttype);
+		SENDERR(EINVAL);
+	}
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_key = (struct sadb_key*)
+	     MALLOC(sizeof(struct sadb_key) +
+				    DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN))) {
+		DEBUGGING(
+			"pfkey_key_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_key,
+	       0,
+	       sizeof(struct sadb_key) +
+	       DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN);
+	
+	pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN +	key_bits,
+					64);
+	pfkey_key->sadb_key_exttype = exttype;
+	pfkey_key->sadb_key_bits = key_bits;
+	pfkey_key->sadb_key_reserved = 0;
+	memcpy((char*)pfkey_key + sizeof(struct sadb_key),
+	       key,
+	       DIVUP(key_bits, 8));
+
+errlab:
+	return error;
+}
+
+int
+pfkey_ident_build(struct sadb_ext**	pfkey_ext,
+		  uint16_t		exttype,
+		  uint16_t		ident_type,
+		  uint64_t		ident_id,
+		  uint8_t               ident_len,
+		  char*			ident_string)
+{
+	int error = 0;
+	struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext;
+	int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+
+	DEBUGGING(
+		"pfkey_ident_build:\n");
+	/* sanity checks... */
+	if(pfkey_ident) {
+		DEBUGGING(
+			"pfkey_ident_build: "
+			"why is pfkey_ident already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if( ! ((exttype == SADB_EXT_IDENTITY_SRC) ||
+	       (exttype == SADB_EXT_IDENTITY_DST))) {
+		DEBUGGING(
+			"pfkey_ident_build: "
+			"unsupported extension type=%d.\n",
+			exttype);
+		SENDERR(EINVAL);
+	}
+
+	if((ident_type == SADB_IDENTTYPE_RESERVED)) {
+		DEBUGGING(
+			"pfkey_ident_build: "
+			"ident_type must be non-zero.\n");
+		SENDERR(EINVAL);
+	}
+
+	if(ident_type > SADB_IDENTTYPE_MAX) {
+		DEBUGGING(
+			"pfkey_ident_build: "
+			"identtype=%d out of range.\n",
+			ident_type);
+		SENDERR(EINVAL);
+	}
+
+	if(((ident_type == SADB_IDENTTYPE_PREFIX) ||
+	    (ident_type == SADB_IDENTTYPE_FQDN)) &&
+	   !ident_string) {
+		DEBUGGING(
+			"pfkey_ident_build: "
+			"string required to allocate size of extension.\n");
+		SENDERR(EINVAL);
+	}
+	
+#if 0
+	if((ident_type == SADB_IDENTTYPE_USERFQDN) ) {
+	}
+#endif
+	    
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_ident = (struct sadb_ident*)
+	     MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN))) {
+		DEBUGGING(
+			"pfkey_ident_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN);
+	
+	pfkey_ident->sadb_ident_len = ident_len;
+	pfkey_ident->sadb_ident_exttype = exttype;
+	pfkey_ident->sadb_ident_type = ident_type;
+	pfkey_ident->sadb_ident_reserved = 0;
+	pfkey_ident->sadb_ident_id = ident_id;
+	memcpy((char*)pfkey_ident + sizeof(struct sadb_ident),
+	       ident_string,
+	       data_len);
+
+errlab:
+	return error;
+}
+
+int
+pfkey_sens_build(struct sadb_ext**	pfkey_ext,
+		 uint32_t		dpd,
+		 uint8_t		sens_level,
+		 uint8_t		sens_len,
+		 uint64_t*		sens_bitmap,
+		 uint8_t		integ_level,
+		 uint8_t		integ_len,
+		 uint64_t*		integ_bitmap)
+{
+	int error = 0;
+	struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext;
+	int i;
+	uint64_t* bitmap;
+
+	DEBUGGING(
+		"pfkey_sens_build:\n");
+	/* sanity checks... */
+	if(pfkey_sens) {
+		DEBUGGING(
+			"pfkey_sens_build: "
+			"why is pfkey_sens already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	DEBUGGING(
+		"pfkey_sens_build: "
+		"Sorry, I can't build exttype=%d yet.\n",
+		(*pfkey_ext)->sadb_ext_type);
+	SENDERR(EINVAL); /* don't process these yet */
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_sens = (struct sadb_sens*)
+	     MALLOC(sizeof(struct sadb_sens) +
+		    (sens_len + integ_len) * sizeof(uint64_t)))) {
+		DEBUGGING(
+			"pfkey_sens_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_sens,
+	       0,
+	       sizeof(struct sadb_sens) +
+	       (sens_len + integ_len) * sizeof(uint64_t));
+	
+	pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) +
+		    (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN;
+	pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY;
+	pfkey_sens->sadb_sens_dpd = dpd;
+	pfkey_sens->sadb_sens_sens_level = sens_level;
+	pfkey_sens->sadb_sens_sens_len = sens_len;
+	pfkey_sens->sadb_sens_integ_level = integ_level;
+	pfkey_sens->sadb_sens_integ_len = integ_len;
+	pfkey_sens->sadb_sens_reserved = 0;
+
+	bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens));
+	for(i = 0; i < sens_len; i++) {
+		*bitmap = sens_bitmap[i];
+		bitmap++;
+	}
+	for(i = 0; i < integ_len; i++) {
+		*bitmap = integ_bitmap[i];
+		bitmap++;
+	}
+
+errlab:
+	return error;
+}
+
+int
+pfkey_prop_build(struct sadb_ext**	pfkey_ext,
+		 uint8_t		replay,
+		 unsigned int		comb_num,
+		 struct sadb_comb*	comb)
+{
+	int error = 0;
+	int i;
+	struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext;
+	struct sadb_comb *combp;
+
+	DEBUGGING(
+		"pfkey_prop_build:\n");
+	/* sanity checks... */
+	if(pfkey_prop) {
+		DEBUGGING(
+			"pfkey_prop_build: "
+			"why is pfkey_prop already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_prop = (struct sadb_prop*)
+	     MALLOC(sizeof(struct sadb_prop) +
+		    comb_num * sizeof(struct sadb_comb)))) {
+		DEBUGGING(
+			"pfkey_prop_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_prop,
+	       0,
+	       sizeof(struct sadb_prop) +
+		    comb_num * sizeof(struct sadb_comb));
+	
+	pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
+		    comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN;
+
+	pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
+	pfkey_prop->sadb_prop_replay = replay;
+
+	for(i=0; i<3; i++) {
+		pfkey_prop->sadb_prop_reserved[i] = 0;
+	}
+
+	combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop));
+	for(i = 0; i < comb_num; i++) {
+		memcpy (combp, &(comb[i]), sizeof(struct sadb_comb));
+		combp++;
+	}
+
+#if 0
+  uint8_t sadb_comb_auth;
+  uint8_t sadb_comb_encrypt;
+  uint16_t sadb_comb_flags;
+  uint16_t sadb_comb_auth_minbits;
+  uint16_t sadb_comb_auth_maxbits;
+  uint16_t sadb_comb_encrypt_minbits;
+  uint16_t sadb_comb_encrypt_maxbits;
+  uint32_t sadb_comb_reserved;
+  uint32_t sadb_comb_soft_allocations;
+  uint32_t sadb_comb_hard_allocations;
+  uint64_t sadb_comb_soft_bytes;
+  uint64_t sadb_comb_hard_bytes;
+  uint64_t sadb_comb_soft_addtime;
+  uint64_t sadb_comb_hard_addtime;
+  uint64_t sadb_comb_soft_usetime;
+  uint64_t sadb_comb_hard_usetime;
+  uint32_t sadb_comb_soft_packets;
+  uint32_t sadb_comb_hard_packets;
+#endif
+errlab:
+	return error;
+}
+
+int
+pfkey_supported_build(struct sadb_ext**	pfkey_ext,
+		      uint16_t		exttype,
+		      unsigned int	alg_num,
+		      struct sadb_alg*	alg)
+{
+	int error = 0;
+	unsigned int i;
+	struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext;
+	struct sadb_alg *pfkey_alg;
+
+	/* sanity checks... */
+	if(pfkey_supported) {
+		DEBUGGING(
+			"pfkey_supported_build: "
+			"why is pfkey_supported already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+
+	if( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) {
+		DEBUGGING(
+			"pfkey_supported_build: "
+			"unsupported extension type=%d.\n",
+			exttype);
+		SENDERR(EINVAL);
+	}
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_supported = (struct sadb_supported*)
+	     MALLOC(sizeof(struct sadb_supported) +
+					       alg_num *
+					       sizeof(struct sadb_alg)))) {
+		DEBUGGING(
+			"pfkey_supported_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_supported,
+	       0,
+	       sizeof(struct sadb_supported) +
+					       alg_num *
+					       sizeof(struct sadb_alg));
+	
+	pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) +
+					       alg_num *
+					       sizeof(struct sadb_alg)) /
+						IPSEC_PFKEYv2_ALIGN;
+	pfkey_supported->sadb_supported_exttype = exttype;
+	pfkey_supported->sadb_supported_reserved = 0;
+
+	pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported));
+	for(i = 0; i < alg_num; i++) {
+		memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg));
+		pfkey_alg->sadb_alg_reserved = 0;
+		pfkey_alg++;
+	}
+	
+#if 0
+	DEBUGGING(
+		"pfkey_supported_build: "
+		"Sorry, I can't build exttype=%d yet.\n",
+		(*pfkey_ext)->sadb_ext_type);
+	SENDERR(EINVAL); /* don't process these yet */
+
+  uint8_t sadb_alg_id;
+  uint8_t sadb_alg_ivlen;
+  uint16_t sadb_alg_minbits;
+  uint16_t sadb_alg_maxbits;
+  uint16_t sadb_alg_reserved;
+#endif
+errlab:
+	return error;
+}
+
+int
+pfkey_spirange_build(struct sadb_ext**	pfkey_ext,
+		     uint16_t		exttype,
+		     uint32_t		min, /* in network order */
+		     uint32_t		max) /* in network order */
+{
+	int error = 0;
+	struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext;
+	
+	/* sanity checks... */
+	if(pfkey_spirange) {
+		DEBUGGING(
+			"pfkey_spirange_build: "
+			"why is pfkey_spirange already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+	
+        if(ntohl(max) < ntohl(min)) {
+		DEBUGGING(
+			"pfkey_spirange_build: "
+			"minspi=%08x must be < maxspi=%08x.\n",
+			ntohl(min),
+			ntohl(max));
+                SENDERR(EINVAL);
+        }
+	
+	if(ntohl(min) <= 255) {
+		DEBUGGING(
+			"pfkey_spirange_build: "
+			"minspi=%08x must be > 255.\n",
+			ntohl(min));
+		SENDERR(EEXIST);
+	}
+	
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_spirange = (struct sadb_spirange*)
+	     MALLOC(sizeof(struct sadb_spirange)))) {
+		DEBUGGING(
+			"pfkey_spirange_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_spirange,
+	       0,
+	       sizeof(struct sadb_spirange));
+	
+        pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN;
+
+	pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+	pfkey_spirange->sadb_spirange_min = min;
+	pfkey_spirange->sadb_spirange_max = max;
+	pfkey_spirange->sadb_spirange_reserved = 0;
+ errlab:
+	return error;
+}
+
+int
+pfkey_x_kmprivate_build(struct sadb_ext**	pfkey_ext)
+{
+	int error = 0;
+	struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext;
+
+	/* sanity checks... */
+	if(pfkey_x_kmprivate) {
+		DEBUGGING(
+			"pfkey_x_kmprivate_build: "
+			"why is pfkey_x_kmprivate already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+	
+	pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
+
+	DEBUGGING(
+		"pfkey_x_kmprivate_build: "
+		"Sorry, I can't build exttype=%d yet.\n",
+		(*pfkey_ext)->sadb_ext_type);
+	SENDERR(EINVAL); /* don't process these yet */
+
+	if(!(*pfkey_ext = (struct sadb_ext*)
+	     pfkey_x_kmprivate = (struct sadb_x_kmprivate*)
+	     MALLOC(sizeof(struct sadb_x_kmprivate)))) {
+		DEBUGGING(
+			"pfkey_x_kmprivate_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_x_kmprivate,
+	       0,
+	       sizeof(struct sadb_x_kmprivate));
+	
+        pfkey_x_kmprivate->sadb_x_kmprivate_len =
+		sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN;
+
+        pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE;
+        pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
+errlab:
+	return error;
+}
+
+int
+pfkey_x_satype_build(struct sadb_ext**	pfkey_ext,
+		     uint8_t		satype)
+{
+	int error = 0;
+	int i;
+	struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext;
+
+	DEBUGGING(
+		"pfkey_x_satype_build:\n");
+	/* sanity checks... */
+	if(pfkey_x_satype) {
+		DEBUGGING(
+			"pfkey_x_satype_build: "
+			"why is pfkey_x_satype already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+	
+	if(!satype) {
+		DEBUGGING(
+			"pfkey_x_satype_build: "
+			"SA type not set, must be non-zero.\n");
+		SENDERR(EINVAL);
+	}
+
+	if(satype > SADB_SATYPE_MAX) {
+		DEBUGGING(
+			"pfkey_x_satype_build: "
+			"satype %d > max %d\n", 
+			satype, SADB_SATYPE_MAX);
+		SENDERR(EINVAL);
+	}
+
+	if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_satype = (struct sadb_x_satype*)
+	     MALLOC(sizeof(struct sadb_x_satype)))) {
+		DEBUGGING(
+			"pfkey_x_satype_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	memset(pfkey_x_satype,
+	       0,
+	       sizeof(struct sadb_x_satype));
+	
+        pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN;
+
+	pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2;
+	pfkey_x_satype->sadb_x_satype_satype = satype;
+	for(i=0; i<3; i++) {
+		pfkey_x_satype->sadb_x_satype_reserved[i] = 0;
+	}
+
+errlab:
+	return error;
+}
+
+int
+pfkey_x_debug_build(struct sadb_ext**	pfkey_ext,
+		    uint32_t            tunnel,
+		    uint32_t		netlink,
+		    uint32_t		xform,
+		    uint32_t		eroute,
+		    uint32_t		spi,
+		    uint32_t		radij,
+		    uint32_t		esp,
+		    uint32_t		ah,
+		    uint32_t		rcv,
+		    uint32_t            pfkey,
+		    uint32_t            ipcomp,
+		    uint32_t            verbose)
+{
+	int error = 0;
+	int i;
+	struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext;
+
+	DEBUGGING(
+		"pfkey_x_debug_build:\n");
+	/* sanity checks... */
+	if(pfkey_x_debug) {
+		DEBUGGING(
+			"pfkey_x_debug_build: "
+			"why is pfkey_x_debug already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+	
+	DEBUGGING(
+		"pfkey_x_debug_build: "
+		"tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n",
+		tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose);
+
+	if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_debug = (struct sadb_x_debug*)
+	     MALLOC(sizeof(struct sadb_x_debug)))) {
+		DEBUGGING(
+			"pfkey_x_debug_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+#if 0
+	memset(pfkey_x_debug,
+	       0,
+	       sizeof(struct sadb_x_debug));
+#endif
+	
+        pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN;
+	pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG;
+
+	pfkey_x_debug->sadb_x_debug_tunnel = tunnel;
+	pfkey_x_debug->sadb_x_debug_netlink = netlink;
+	pfkey_x_debug->sadb_x_debug_xform = xform;
+	pfkey_x_debug->sadb_x_debug_eroute = eroute;
+	pfkey_x_debug->sadb_x_debug_spi = spi;
+	pfkey_x_debug->sadb_x_debug_radij = radij;
+	pfkey_x_debug->sadb_x_debug_esp = esp;
+	pfkey_x_debug->sadb_x_debug_ah = ah;
+	pfkey_x_debug->sadb_x_debug_rcv = rcv;
+	pfkey_x_debug->sadb_x_debug_pfkey = pfkey;
+	pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp;
+	pfkey_x_debug->sadb_x_debug_verbose = verbose;
+
+	for(i=0; i<4; i++) {
+		pfkey_x_debug->sadb_x_debug_reserved[i] = 0;
+	}
+
+errlab:
+	return error;
+}
+
+#ifdef NAT_TRAVERSAL
+int
+pfkey_x_nat_t_type_build(struct sadb_ext**	pfkey_ext,
+		    uint8_t         type)
+{
+	int error = 0;
+	int i;
+	struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext;
+
+	DEBUGGING(
+		"pfkey_x_nat_t_type_build:\n");
+	/* sanity checks... */
+	if(pfkey_x_nat_t_type) {
+		DEBUGGING(
+			"pfkey_x_nat_t_type_build: "
+			"why is pfkey_x_nat_t_type already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+	
+	DEBUGGING(
+		"pfkey_x_nat_t_type_build: "
+		"type=%d\n", type);
+
+	if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*)
+	     MALLOC(sizeof(struct sadb_x_nat_t_type)))) {
+		DEBUGGING(
+			"pfkey_x_nat_t_type_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	
+	pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN;
+	pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+	pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type;
+	for(i=0; i<3; i++) {
+		pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0;
+	}
+
+errlab:
+	return error;
+}
+int
+pfkey_x_nat_t_port_build(struct sadb_ext**	pfkey_ext,
+		    uint16_t         exttype,
+		    uint16_t         port)
+{
+	int error = 0;
+	struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext;
+
+	DEBUGGING(
+		"pfkey_x_nat_t_port_build:\n");
+	/* sanity checks... */
+	if(pfkey_x_nat_t_port) {
+		DEBUGGING(
+			"pfkey_x_nat_t_port_build: "
+			"why is pfkey_x_nat_t_port already pointing to something?\n");
+		SENDERR(EINVAL);
+	}
+	
+	switch(exttype) {	
+	case SADB_X_EXT_NAT_T_SPORT:
+	case SADB_X_EXT_NAT_T_DPORT:
+		break;
+	default:
+		DEBUGGING( 
+			"pfkey_nat_t_port_build: "
+			"unrecognised ext_type=%d.\n", 
+			exttype); 
+		SENDERR(EINVAL); 
+	}
+
+	DEBUGGING(
+		"pfkey_x_nat_t_port_build: "
+		"ext=%d, port=%d\n", exttype, port);
+
+	if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*)
+	     MALLOC(sizeof(struct sadb_x_nat_t_port)))) {
+		DEBUGGING(
+			"pfkey_x_nat_t_port_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	
+	pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN;
+	pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype;
+	pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port;
+	pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0;
+
+errlab:
+	return error;
+}
+
+int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext,
+			   uint8_t protocol)
+{
+	int error = 0;
+	struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext;
+	DEBUGGING("pfkey_x_protocol_build: protocol=%u\n", protocol);
+	/* sanity checks... */
+	if (p != 0) {
+		DEBUGGING("pfkey_x_protocol_build: bogus protocol pointer\n");
+		SENDERR(EINVAL);
+	}
+	if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) {
+		DEBUGGING("pfkey_build: memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+	*pfkey_ext = (struct sadb_ext *)p;
+	p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t);
+	p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
+	p->sadb_protocol_proto = protocol;
+	p->sadb_protocol_flags = 0;
+	p->sadb_protocol_reserved2 = 0;
+ errlab:
+	return error;
+}
+#endif /* NAT_TRAVERSAL */
+
+#if I_DONT_THINK_THIS_WILL_BE_USEFUL
+int (*ext_default_builders[SADB_EXT_MAX +1])(struct sadb_msg*, struct sadb_ext*)
+ =
+{
+	NULL, /* pfkey_msg_build, */
+	pfkey_sa_build,
+	pfkey_lifetime_build,
+	pfkey_lifetime_build,
+	pfkey_lifetime_build,
+	pfkey_address_build,
+	pfkey_address_build,
+	pfkey_address_build,
+	pfkey_key_build,
+	pfkey_key_build,
+	pfkey_ident_build,
+	pfkey_ident_build,
+	pfkey_sens_build,
+	pfkey_prop_build,
+	pfkey_supported_build,
+	pfkey_supported_build,
+	pfkey_spirange_build,
+	pfkey_x_kmprivate_build,
+	pfkey_x_satype_build,
+	pfkey_sa_build,
+	pfkey_address_build,
+	pfkey_address_build,
+	pfkey_address_build,
+	pfkey_address_build,
+	pfkey_address_build,
+	pfkey_x_ext_debug_build
+};
+#endif
+
+int
+pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir)
+{
+	int error = 0;
+	int ext;
+	int total_size;
+	struct sadb_ext *pfkey_ext;
+	int extensions_seen = 0;
+	struct sadb_ext *extensions_check[SADB_EXT_MAX + 1];
+	
+	if(!extensions[0]) {
+		DEBUGGING(
+			"pfkey_msg_build: "
+			"extensions[0] must be specified (struct sadb_msg).\n");
+		SENDERR(EINVAL);
+	}
+
+	total_size = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
+	for(ext = 1; ext <= SADB_EXT_MAX; ext++) {
+		if(extensions[ext]) {
+			total_size += (extensions[ext])->sadb_ext_len;
+		}
+        }                
+
+	if(!(*pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN))) {
+		DEBUGGING(
+			"pfkey_msg_build: "
+			"memory allocation failed\n");
+		SENDERR(ENOMEM);
+	}
+
+	DEBUGGING(
+		"pfkey_msg_build: "
+		"pfkey_msg=%p allocated %d bytes, &(extensions[0])=%p\n",
+		*pfkey_msg,
+		total_size * IPSEC_PFKEYv2_ALIGN,
+		&(extensions[0]));
+	memcpy(*pfkey_msg,
+	       extensions[0],
+	       sizeof(struct sadb_msg));
+	(*pfkey_msg)->sadb_msg_len = total_size;
+	(*pfkey_msg)->sadb_msg_reserved = 0;
+	extensions_seen =  1 ;
+
+	pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg));
+
+	for(ext = 1; ext <= SADB_EXT_MAX; ext++) {
+		/* copy from extension[ext] to buffer */
+		if(extensions[ext]) {    
+			/* Is this type of extension permitted for this type of message? */
+			if(!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] &
+			     1<<ext)) {
+				DEBUGGING(
+					"pfkey_msg_build: "
+					"ext type %d not permitted, exts_perm=%08x, 1<<type=%08x\n", 
+					ext, 
+					extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
+					1<<ext);
+				SENDERR(EINVAL);
+			}
+			DEBUGGING(
+				"pfkey_msg_build: "
+				"copying %d bytes from extensions[%d]=%p to=%p\n",
+				(extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN,
+				ext,
+				(extensions[ext]),
+				pfkey_ext);
+			memcpy(pfkey_ext,
+			       extensions[ext],
+			       (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
+			((char*)pfkey_ext) += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN;
+			/* Mark that we have seen this extension and remember the header location */
+			extensions_seen |= ( 1 << ext );
+		}
+	}
+
+	/* check required extensions */
+	DEBUGGING(
+		"pfkey_msg_build: "
+		"extensions permitted=%08x, seen=%08x, required=%08x.\n",
+		extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
+		extensions_seen,
+		extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]);
+	
+	if((extensions_seen &
+	    extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) !=
+	   extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) {
+		DEBUGGING(
+			"pfkey_msg_build: "
+			"required extensions missing:%08x.\n",
+			extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] -
+			(extensions_seen &
+			 extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) );
+		SENDERR(EINVAL);
+	}
+	
+	if((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) {
+		DEBUGGING(
+			"pfkey_msg_build: "
+			"Trouble parsing newly built pfkey message, error=%d.\n",
+			error);
+		SENDERR(-error);
+	}
+
+errlab:
+
+	return error;
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.4  2003/02/07 13:14:25  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.3.2.1  2003/02/07 01:47:12  jjo
+ * . some #ifdef's tweaking to allow compilation without NAT_TRAVERSAL
+ *
+ * Revision 1.3  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.2  2002/09/05 03:53:53  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:20  ken
+ * 1.98b
+ *
+ * Revision 1.31  2002/01/29 22:25:35  rgb
+ * Re-add ipsec_kversion.h to keep MALLOC happy.
+ *
+ * Revision 1.30  2002/01/29 01:59:09  mcr
+ * 	removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * 	updating of IPv6 structures to match latest in6.h version.
+ * 	removed dead code from freeswan.h that also duplicated kversions.h
+ * 	code.
+ *
+ * Revision 1.29  2001/12/19 21:06:09  rgb
+ * Added port numbers to pfkey_address_build() debugging.
+ *
+ * Revision 1.28  2001/11/06 19:47:47  rgb
+ * Added packet parameter to lifetime and comb structures.
+ *
+ * Revision 1.27  2001/10/18 04:45:24  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.26  2001/09/08 21:13:34  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.25  2001/06/14 19:35:16  rgb
+ * Update copyright date.
+ *
+ * Revision 1.24  2001/03/20 03:49:45  rgb
+ * Ditch superfluous debug_pfkey declaration.
+ * Move misplaced freeswan.h inclusion for kernel case.
+ *
+ * Revision 1.23  2001/03/16 07:41:50  rgb
+ * Put freeswan.h include before pluto includes.
+ *
+ * Revision 1.22  2001/02/27 22:24:56  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.21  2000/11/17 18:10:30  rgb
+ * Fixed bugs mostly relating to spirange, to treat all spi variables as
+ * network byte order since this is the way PF_KEYv2 stored spis.
+ *
+ * Revision 1.20  2000/10/12 00:02:39  rgb
+ * Removed 'format, ##' nonsense from debug macros for RH7.0.
+ *
+ * Revision 1.19  2000/10/10 20:10:20  rgb
+ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
+ *
+ * Revision 1.18  2000/09/12 18:59:54  rgb
+ * Added Gerhard's IPv6 support to pfkey parts of libfreeswan.
+ *
+ * Revision 1.17  2000/09/12 03:27:00  rgb
+ * Moved DEBUGGING definition to compile kernel with debug off.
+ *
+ * Revision 1.16  2000/09/08 19:22:12  rgb
+ * Fixed pfkey_prop_build() parameter to be only single indirection.
+ * Fixed struct alg copy.
+ *
+ * Revision 1.15  2000/08/20 21:40:01  rgb
+ * Added an address parameter sanity check to pfkey_address_build().
+ *
+ * Revision 1.14  2000/08/15 17:29:23  rgb
+ * Fixes from SZI to untested pfkey_prop_build().
+ *
+ * Revision 1.13  2000/06/02 22:54:14  rgb
+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
+ *
+ * Revision 1.12  2000/05/10 19:24:01  rgb
+ * Fleshed out sensitivity, proposal and supported extensions.
+ *
+ * Revision 1.11  2000/03/16 14:07:23  rgb
+ * Renamed ALIGN macro to avoid fighting with others in kernel.
+ *
+ * Revision 1.10  2000/01/24 21:14:35  rgb
+ * Added disabled pluto pfkey lib debug flag.
+ *
+ * Revision 1.9  2000/01/21 06:27:32  rgb
+ * Added address cases for eroute flows.
+ * Removed unused code.
+ * Dropped unused argument to pfkey_x_satype_build().
+ * Indented compiler directives for readability.
+ * Added klipsdebug switching capability.
+ * Fixed SADB_EXT_MAX bug not permitting last extension access.
+ *
+ * Revision 1.8  1999/12/29 21:17:41  rgb
+ * Changed pfkey_msg_build() I/F to include a struct sadb_msg**
+ * parameter for cleaner manipulation of extensions[] and to guard
+ * against potential memory leaks.
+ * Changed the I/F to pfkey_msg_free() for the same reason.
+ *
+ * Revision 1.7  1999/12/09 23:12:20  rgb
+ * Removed unused cruft.
+ * Added argument to pfkey_sa_build() to do eroutes.
+ * Fixed exttype check in as yet unused pfkey_lifetime_build().
+ *
+ * Revision 1.6  1999/12/07 19:54:29  rgb
+ * Removed static pluto debug flag.
+ * Added functions for pfkey message and extensions initialisation
+ * and cleanup.
+ *
+ * Revision 1.5  1999/12/01 22:20:06  rgb
+ * Changed pfkey_sa_build to accept an SPI in network byte order.
+ * Added <string.h> to quiet userspace compiler.
+ * Moved pfkey_lib_debug variable into the library.
+ * Removed SATYPE check from pfkey_msg_hdr_build so FLUSH will work.
+ * Added extension assembly debugging.
+ * Isolated assignment with brackets to be sure of scope.
+ *
+ * Revision 1.4  1999/11/27 11:57:35  rgb
+ * Added ipv6 headers.
+ * Remove over-zealous algorithm sanity checkers from pfkey_sa_build.
+ * Debugging error messages added.
+ * Fixed missing auth and encrypt assignment bug.
+ * Add argument to pfkey_msg_parse() for direction.
+ * Move parse-after-build check inside pfkey_msg_build().
+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
+ * Add CVS log entry to bottom of file.
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/pfkey_v2_debug.c linux-patched/net/ipsec/libfreeswan/pfkey_v2_debug.c
--- linux/net/ipsec/libfreeswan/pfkey_v2_debug.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/pfkey_v2_debug.c	Thu Sep  5 04:53:53 2002
@@ -0,0 +1,167 @@
+/*
+ * @(#) pfkey version 2 debugging messages
+ *
+ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
+ *                 and Michael Richardson  <mcr@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ *
+ */
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h>  /* for printk */
+
+# include "../ipsec_kversion.h" /* for malloc switch */
+# ifdef MALLOC_SLAB
+#  include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+#  include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h>  /* error codes */
+# include <linux/types.h>  /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h>   /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+extern int debug_pfkey;
+
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+
+#endif /* __KERNEL__ */
+
+#include "freeswan.h"
+#include "pfkeyv2.h"
+#include "pfkey.h"
+
+/* 
+ * This file provides ASCII translations of PF_KEY magic numbers.
+ *
+ */
+
+static char *pfkey_sadb_ext_strings[]={
+  "reserved",                     /* SADB_EXT_RESERVED             0 */
+  "security-association",         /* SADB_EXT_SA                   1 */
+  "lifetime-current",             /* SADB_EXT_LIFETIME_CURRENT     2 */
+  "lifetime-hard",                /* SADB_EXT_LIFETIME_HARD        3 */
+  "lifetime-soft",                /* SADB_EXT_LIFETIME_SOFT        4 */
+  "source-address",               /* SADB_EXT_ADDRESS_SRC          5 */
+  "destination-address",          /* SADB_EXT_ADDRESS_DST          6 */
+  "proxy-address",                /* SADB_EXT_ADDRESS_PROXY        7 */
+  "authentication-key",           /* SADB_EXT_KEY_AUTH             8 */
+  "cipher-key",                   /* SADB_EXT_KEY_ENCRYPT          9 */
+  "source-identity",              /* SADB_EXT_IDENTITY_SRC         10 */
+  "destination-identity",         /* SADB_EXT_IDENTITY_DST         11 */
+  "sensitivity-label",            /* SADB_EXT_SENSITIVITY          12 */
+  "proposal",                     /* SADB_EXT_PROPOSAL             13 */
+  "supported-auth",               /* SADB_EXT_SUPPORTED_AUTH       14 */
+  "supported-cipher",             /* SADB_EXT_SUPPORTED_ENCRYPT    15 */
+  "spi-range",                    /* SADB_EXT_SPIRANGE             16 */
+  "X-kmpprivate",                 /* SADB_X_EXT_KMPRIVATE          17 */
+  "X-satype2",                    /* SADB_X_EXT_SATYPE2            18 */
+  "X-security-association",       /* SADB_X_EXT_SA2                19 */
+  "X-destination-address2",       /* SADB_X_EXT_ADDRESS_DST2       20 */
+  "X-source-flow-address",        /* SADB_X_EXT_ADDRESS_SRC_FLOW   21 */
+  "X-dest-flow-address",          /* SADB_X_EXT_ADDRESS_DST_FLOW   22 */
+  "X-source-mask",                /* SADB_X_EXT_ADDRESS_SRC_MASK   23 */
+  "X-dest-mask",                  /* SADB_X_EXT_ADDRESS_DST_MASK   24 */
+  "X-set-debug",                  /* SADB_X_EXT_DEBUG              25 */
+#ifdef NAT_TRAVERSAL
+  "X-NAT-T-type",                 /* SADB_X_EXT_NAT_T_TYPE         26 */
+  "X-NAT-T-sport",                /* SADB_X_EXT_NAT_T_SPORT        27 */
+  "X-NAT-T-dport",                /* SADB_X_EXT_NAT_T_DPORT        28 */
+  "X-NAT-T-OA",                   /* SADB_X_EXT_NAT_T_OA           29 */
+#endif
+};
+
+const char *
+pfkey_v2_sadb_ext_string(int ext)
+{
+  if(ext < SADB_EXT_MAX) {
+    return pfkey_sadb_ext_strings[ext];
+  } else {
+    return "unknown-ext";
+  }
+}
+
+
+static char *pfkey_sadb_type_strings[]={
+	"reserved",                     /* SADB_RESERVED      */
+	"getspi",                       /* SADB_GETSPI        */
+	"update",                       /* SADB_UPDATE        */
+	"add",                          /* SADB_ADD           */
+	"delete",                       /* SADB_DELETE        */
+	"get",                          /* SADB_GET           */
+	"acquire",                      /* SADB_ACQUIRE       */
+	"register",                     /* SADB_REGISTER      */
+	"expire",                       /* SADB_EXPIRE        */
+	"flush",                        /* SADB_FLUSH         */
+	"dump",                         /* SADB_DUMP          */
+	"x-promisc",                    /* SADB_X_PROMISC     */
+	"x-pchange",                    /* SADB_X_PCHANGE     */
+	"x-groupsa",                    /* SADB_X_GRPSA       */
+	"x-addflow(eroute)",            /* SADB_X_ADDFLOW     */
+	"x-delflow(eroute)",            /* SADB_X_DELFLOW     */
+	"x-debug",                      /* SADB_X_DEBUG       */
+};
+
+const char *
+pfkey_v2_sadb_type_string(int sadb_type)
+{
+  if(sadb_type < SADB_MAX) {
+    return pfkey_sadb_type_strings[sadb_type];
+  } else {
+    return "unknown-sadb-type";
+  }
+}
+
+
+
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.2  2002/09/05 03:53:53  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:20  ken
+ * 1.98b
+ *
+ * Revision 1.4  2002/01/29 22:25:36  rgb
+ * Re-add ipsec_kversion.h to keep MALLOC happy.
+ *
+ * Revision 1.3  2002/01/29 01:59:09  mcr
+ * 	removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * 	updating of IPv6 structures to match latest in6.h version.
+ * 	removed dead code from freeswan.h that also duplicated kversions.h
+ * 	code.
+ *
+ * Revision 1.2  2002/01/20 20:34:50  mcr
+ * 	added pfkey_v2_sadb_type_string to decode sadb_type to string.
+ *
+ * Revision 1.1  2001/11/27 05:30:06  mcr
+ * 	initial set of debug strings for pfkey debugging.
+ * 	this will eventually only be included for debug builds.
+ *
+ * Revision 1.1  2001/09/21 04:12:03  mcr
+ * 	first compilable version.
+ *
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/pfkey_v2_ext_bits.c linux-patched/net/ipsec/libfreeswan/pfkey_v2_ext_bits.c
--- linux/net/ipsec/libfreeswan/pfkey_v2_ext_bits.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/pfkey_v2_ext_bits.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,814 @@
+/*
+ * RFC2367 PF_KEYv2 Key management API message parser
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ *		Template from klips/net/ipsec/ipsec/ipsec_parse.c.
+ */
+
+char pfkey_v2_ext_bits_c_version[] = "$Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+/*
+ * Some ugly stuff to allow consistent debugging code for use in the
+ * kernel and in user space
+*/
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h>  /* for printk */
+
+# include "../ipsec_kversion.h" /* for malloc switch */
+# ifdef MALLOC_SLAB
+#  include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+#  include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h>  /* error codes */
+# include <linux/types.h>  /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h>   /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+# include <linux/ip.h>          /* struct iphdr */ 
+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#  include <linux/ipv6.h>
+# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+#endif
+
+#include <freeswan.h>
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = {
+
+/* INBOUND EXTENSIONS */
+{
+
+/* PERMITTED IN */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_SPIRANGE
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+#ifdef NAT_TRAVERSAL
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+#endif
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+#ifdef NAT_TRAVERSAL
+| 1<<SADB_X_EXT_NAT_T_TYPE
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+| 1<<SADB_X_EXT_NAT_T_OA
+#endif
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_EXPIRE */
+0
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+#ifdef NAT_TRAVERSAL
+| 1<<SADB_X_EXT_PROTOCOL
+#endif /* NAT_TRAVERSAL */
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+#ifdef NAT_TRAVERSAL
+| 1<<SADB_X_EXT_PROTOCOL
+#endif /* NAT_TRAVERSAL */
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+#ifdef NAT_TRAVERSAL
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+#endif
+},
+
+/* REQUIRED IN */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_SPIRANGE
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+/*| 1<<SADB_EXT_KEY_AUTH*/
+/*| 1<<SADB_EXT_KEY_ENCRYPT*/
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+/*| 1<<SADB_EXT_KEY_AUTH*/
+/*| 1<<SADB_EXT_KEY_ENCRYPT*/
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_EXPIRE */
+0
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+/*| 1<<SADB_X_EXT_SATYPE2*/
+/*| 1<<SADB_X_EXT_SA2*/
+/*| 1<<SADB_X_EXT_ADDRESS_DST2*/
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+/*| 1<<SADB_EXT_SA*/
+#if 0 /* SADB_X_CLREROUTE doesn't need all these... */
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+#endif
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+#ifdef NAT_TRAVERSAL
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+#endif
+}
+
+},
+
+/* OUTBOUND EXTENSIONS */
+{
+
+/* PERMITTED OUT */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+#ifdef NAT_TRAVERSAL
+| 1<<SADB_X_EXT_NAT_T_TYPE
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+| 1<<SADB_X_EXT_NAT_T_OA
+#endif
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+,
+/* SADB_EXPIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+#ifdef NAT_TRAVERSAL
+| 1<<SADB_X_EXT_PROTOCOL
+#endif /* NAT_TRAVERSAL */
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+#ifdef NAT_TRAVERSAL
+| 1<<SADB_X_EXT_PROTOCOL
+#endif /* NAT_TRAVERSAL */
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+#ifdef NAT_TRAVERSAL
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+#endif
+},
+
+/* REQUIRED OUT */
+{
+/* SADB_RESERVED */
+0
+,
+/* SADB_GETSPI */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_UPDATE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_ADD */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_DELETE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_GET */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+/* | 1<<SADB_EXT_KEY_AUTH */
+/* | 1<<SADB_EXT_KEY_ENCRYPT */
+,
+/* SADB_ACQUIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_PROPOSAL
+,
+/* SADB_REGISTER */
+1<<SADB_EXT_RESERVED
+/* | 1<<SADB_EXT_SUPPORTED_AUTH
+   | 1<<SADB_EXT_SUPPORTED_ENCRYPT */
+,
+/* SADB_EXPIRE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+/* | 1<<SADB_EXT_LIFETIME_HARD
+   | 1<<SADB_EXT_LIFETIME_SOFT */
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_FLUSH */
+1<<SADB_EXT_RESERVED
+,
+/* SADB_DUMP */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+,
+/* SADB_X_PROMISC */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_PCHANGE */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_LIFETIME_CURRENT
+| 1<<SADB_EXT_LIFETIME_HARD
+| 1<<SADB_EXT_LIFETIME_SOFT
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_EXT_ADDRESS_PROXY
+| 1<<SADB_EXT_KEY_AUTH
+| 1<<SADB_EXT_KEY_ENCRYPT
+| 1<<SADB_EXT_IDENTITY_SRC
+| 1<<SADB_EXT_IDENTITY_DST
+| 1<<SADB_EXT_SENSITIVITY
+| 1<<SADB_EXT_PROPOSAL
+| 1<<SADB_EXT_SUPPORTED_AUTH
+| 1<<SADB_EXT_SUPPORTED_ENCRYPT
+| 1<<SADB_EXT_SPIRANGE
+| 1<<SADB_X_EXT_KMPRIVATE
+| 1<<SADB_X_EXT_SATYPE2
+| 1<<SADB_X_EXT_SA2
+| 1<<SADB_X_EXT_ADDRESS_DST2
+,
+/* SADB_X_GRPSA */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+,
+/* SADB_X_ADDFLOW */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+,
+/* SADB_X_DELFLOW */
+1<<SADB_EXT_RESERVED
+/*| 1<<SADB_EXT_SA*/
+| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
+| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
+| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
+| 1<<SADB_X_EXT_ADDRESS_DST_MASK
+,
+/* SADB_X_DEBUG */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_X_EXT_DEBUG
+#ifdef NAT_TRAVERSAL
+,
+/* SADB_X_NAT_T_NEW_MAPPING */
+1<<SADB_EXT_RESERVED
+| 1<<SADB_EXT_SA
+| 1<<SADB_EXT_ADDRESS_SRC
+| 1<<SADB_EXT_ADDRESS_DST
+| 1<<SADB_X_EXT_NAT_T_SPORT
+| 1<<SADB_X_EXT_NAT_T_DPORT
+#endif
+}
+}
+};
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.5  2003/02/07 13:14:26  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.4.2.1  2003/02/07 01:47:12  jjo
+ * . some #ifdef's tweaking to allow compilation without NAT_TRAVERSAL
+ *
+ * Revision 1.4  2003/01/02 21:58:15  ken
+ * NAT-T 0.4 -> 0.5 - This looks weird...
+ *
+ * Revision 1.3  2002/12/12 03:32:08  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.2  2002/09/05 03:53:53  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:20  ken
+ * 1.98b
+ *
+ * Revision 1.13  2002/01/29 22:25:36  rgb
+ * Re-add ipsec_kversion.h to keep MALLOC happy.
+ *
+ * Revision 1.12  2002/01/29 01:59:10  mcr
+ * 	removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * 	updating of IPv6 structures to match latest in6.h version.
+ * 	removed dead code from freeswan.h that also duplicated kversions.h
+ * 	code.
+ *
+ * Revision 1.11  2001/10/18 04:45:24  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.10  2001/09/08 21:13:35  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.9  2001/06/14 19:35:16  rgb
+ * Update copyright date.
+ *
+ * Revision 1.8  2001/03/26 23:07:36  rgb
+ * Remove requirement for auth and enc key from UPDATE.
+ *
+ * Revision 1.7  2000/09/12 22:35:37  rgb
+ * Restructured to remove unused extensions from CLEARFLOW messages.
+ *
+ * Revision 1.6  2000/09/09 06:39:01  rgb
+ * Added comments for clarity.
+ *
+ * Revision 1.5  2000/06/02 22:54:14  rgb
+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
+ *
+ * Revision 1.4  2000/01/21 06:27:56  rgb
+ * Added address cases for eroute flows.
+ * Added comments for each message type.
+ * Added klipsdebug switching capability.
+ * Fixed GRPSA bitfields.
+ *
+ * Revision 1.3  1999/12/01 22:20:27  rgb
+ * Remove requirement for a proxy address in an incoming getspi message.
+ *
+ * Revision 1.2  1999/11/27 11:57:06  rgb
+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
+ * Add CVS log entry to bottom of file.
+ * Cleaned out unused bits.
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/pfkey_v2_parse.c linux-patched/net/ipsec/libfreeswan/pfkey_v2_parse.c
--- linux/net/ipsec/libfreeswan/pfkey_v2_parse.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/pfkey_v2_parse.c	Fri Feb  7 13:14:26 2003
@@ -0,0 +1,1706 @@
+/*
+ * RFC2367 PF_KEYv2 Key management API message parser
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ *		Template from klips/net/ipsec/ipsec/ipsec_parser.c.
+ */
+
+char pfkey_v2_parse_c_version[] = "$Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+/*
+ * Some ugly stuff to allow consistent debugging code for use in the
+ * kernel and in user space
+*/
+
+#ifdef __KERNEL__
+
+# include <linux/kernel.h>  /* for printk */
+
+# include "../ipsec_kversion.h" /* for malloc switch */
+# ifdef MALLOC_SLAB
+#  include <linux/slab.h> /* kmalloc() */
+# else /* MALLOC_SLAB */
+#  include <linux/malloc.h> /* kmalloc() */
+# endif /* MALLOC_SLAB */
+# include <linux/errno.h>  /* error codes */
+# include <linux/types.h>  /* size_t */
+# include <linux/interrupt.h> /* mark_bh */
+
+# include <linux/netdevice.h>   /* struct device, and other headers */
+# include <linux/etherdevice.h> /* eth_type_trans */
+# include <linux/ip.h>          /* struct iphdr */ 
+# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#  include <linux/ipv6.h>        /* struct ipv6hdr */
+# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+extern int debug_pfkey;
+
+# include <freeswan.h>
+
+#include "../ipsec_encap.h"
+
+#else /* __KERNEL__ */
+
+# include <sys/types.h>
+# include <linux/types.h>
+# include <linux/errno.h>
+
+# include <freeswan.h>
+# include "../pluto/constants.h" 
+# include "../pluto/defs.h"  /* for PRINTF_LIKE */
+# include "../pluto/log.h"  /* for debugging and DBG_log */
+
+extern unsigned int pfkey_lib_debug;  /* bits selecting what to report */
+
+/* #define PLUTO */
+
+# ifdef PLUTO
+#  define DEBUGGING(level, args...)  { DBG_log("pfkey_lib_debug:" args);  }
+# else
+#  define DEBUGGING(level, args...)  if(pfkey_lib_debug >= level) { printf("pfkey_lib_debug:" args); } else { ; }
+# endif
+
+#endif /* __KERNEL__ */
+
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#ifdef __KERNEL__
+#if 0
+# include "../radij.h"  /* rd_nodes */
+# include "../ipsec_encap.h"  /* sockaddr_encap */
+#endif
+# include "../ipsec_netlink.h"  /* KLIPS_PRINT */
+# define DEBUGGING(level, args...) \
+         KLIPS_PRINT((debug_pfkey >= level), "klips_debug:" args)
+#endif /* __KERNEL__ */
+
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+struct satype_tbl {
+	uint8_t proto;
+	uint8_t satype;
+	char* name;
+} static satype_tbl[] = {
+#ifdef __KERNEL__
+	{ IPPROTO_ESP,	SADB_SATYPE_ESP,	"ESP"  },
+	{ IPPROTO_AH,	SADB_SATYPE_AH,		"AH"   },
+	{ IPPROTO_IPIP,	SADB_X_SATYPE_IPIP,	"IPIP" },
+#ifdef CONFIG_IPSEC_IPCOMP
+	{ IPPROTO_COMP,	SADB_X_SATYPE_COMP,	"COMP" },
+#endif /* CONFIG_IPSEC_IPCOMP */
+	{ IPPROTO_INT,	SADB_X_SATYPE_INT,	"INT" },
+#else /* __KERNEL__ */
+	{ SA_ESP,	SADB_SATYPE_ESP,	"ESP"  },
+	{ SA_AH,	SADB_SATYPE_AH,		"AH"   },
+	{ SA_IPIP,	SADB_X_SATYPE_IPIP,	"IPIP" },
+	{ SA_COMP,	SADB_X_SATYPE_COMP,	"COMP" },
+	{ SA_INT,	SADB_X_SATYPE_INT,	"INT" },
+#endif /* __KERNEL__ */
+	{ 0,		0,			"UNKNOWN" }
+};
+
+uint8_t satype2proto(uint8_t satype) {
+	int i =0;
+
+	while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
+		i++;
+	}
+	return satype_tbl[i].proto;
+}
+
+uint8_t proto2satype(uint8_t proto) {
+	int i = 0;
+
+	while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
+		i++;
+	}
+	return satype_tbl[i].satype;
+}
+
+char* satype2name(uint8_t satype) {
+	int i = 0;
+
+	while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
+		i++;
+	}
+	return satype_tbl[i].name;
+}
+
+char* proto2name(uint8_t proto) {
+	int i = 0;
+
+	while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
+		i++;
+	}
+	return satype_tbl[i].name;
+}
+
+/* Default extension parsers taken from the KLIPS code */
+
+DEBUG_NO_STATIC int
+pfkey_sa_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;
+	
+	DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+		  "pfkey_sa_parse: entry\n");
+	/* sanity checks... */
+	if(!pfkey_sa) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			  "pfkey_sa_parse: "
+			  "NULL pointer passed in.\n");
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sa_parse: "
+			"length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n",
+			pfkey_sa->sadb_sa_len,
+			sizeof(struct sadb_sa));
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sa_parse: "
+			"pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n",
+			pfkey_sa->sadb_sa_encrypt,
+			SADB_EALG_MAX);
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sa_parse: "
+			"pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n",
+			pfkey_sa->sadb_sa_auth,
+			SADB_AALG_MAX);
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sa_parse: "
+			"state=%d exceeds MAX=%d.\n",
+			pfkey_sa->sadb_sa_state,
+			SADB_SASTATE_MAX);
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sa_parse: "
+			"state=%d is DEAD=%d.\n",
+			pfkey_sa->sadb_sa_state,
+			SADB_SASTATE_DEAD);
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_sa->sadb_sa_replay > 64) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sa_parse: "
+			"replay window size: %d -- must be 0 <= size <= 64\n",
+			pfkey_sa->sadb_sa_replay);
+		SENDERR(EINVAL);
+	}
+	
+	if(! ((pfkey_sa->sadb_sa_exttype ==  SADB_EXT_SA) ||
+	      (pfkey_sa->sadb_sa_exttype ==  SADB_X_EXT_SA2)))
+	{
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sa_parse: "
+			"unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n",
+			pfkey_sa->sadb_sa_exttype,
+			SADB_EXT_SA,
+			SADB_X_EXT_SA2);
+		SENDERR(EINVAL);
+	}
+	DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+		"pfkey_sa_parse: "
+		"successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d.\n",
+		  pfkey_sa->sadb_sa_len,
+		  pfkey_sa->sadb_sa_exttype, pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype),
+		(long unsigned int)ntohl(pfkey_sa->sadb_sa_spi),
+		pfkey_sa->sadb_sa_replay,
+		pfkey_sa->sadb_sa_state,
+		pfkey_sa->sadb_sa_auth,
+		pfkey_sa->sadb_sa_encrypt,
+		pfkey_sa->sadb_sa_flags);
+
+ errlab:
+	return error;
+}	
+
+DEBUG_NO_STATIC int
+pfkey_lifetime_parse(struct sadb_ext  *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext;
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+		  "pfkey_lifetime_parse:enter\n");
+	/* sanity checks... */
+	if(!pfkey_lifetime) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_lifetime_parse: "
+			"NULL pointer passed in.\n");
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_lifetime->sadb_lifetime_len !=
+	   sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_lifetime_parse: "
+			"length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n",
+			pfkey_lifetime->sadb_lifetime_len,
+			sizeof(struct sadb_lifetime));
+		SENDERR(EINVAL);
+	}
+
+	if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) &&
+	   (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) &&
+	   (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_lifetime_parse: "
+			"unexpected ext_type=%d.\n", 
+			pfkey_lifetime->sadb_lifetime_exttype); 
+		SENDERR(EINVAL);
+	}
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_address_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	int saddr_len = 0;
+	struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext;
+	struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address));
+	char ipaddr_txt[ADDRTOT_BUF];
+	
+	DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+		"pfkey_address_parse:enter\n");
+	/* sanity checks... */
+	if(!pfkey_address) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_address_parse: "
+			"NULL pointer passed in.\n");
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_address->sadb_address_len <
+	   (sizeof(struct sadb_address) + sizeof(struct sockaddr))/
+	   IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_address_parse: "
+			"size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
+			pfkey_address->sadb_address_len,
+			sizeof(struct sadb_address),
+			sizeof(struct sockaddr));
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_address->sadb_address_reserved) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_address_parse: "
+			"res=%d, must be zero.\n",
+			pfkey_address->sadb_address_reserved);
+		SENDERR(EINVAL);
+	}
+	
+	switch(pfkey_address->sadb_address_exttype) {	
+	case SADB_EXT_ADDRESS_SRC:
+	case SADB_EXT_ADDRESS_DST:
+	case SADB_EXT_ADDRESS_PROXY:
+	case SADB_X_EXT_ADDRESS_DST2:
+	case SADB_X_EXT_ADDRESS_SRC_FLOW:
+	case SADB_X_EXT_ADDRESS_DST_FLOW:
+	case SADB_X_EXT_ADDRESS_SRC_MASK:
+	case SADB_X_EXT_ADDRESS_DST_MASK:
+#ifdef NAT_TRAVERSAL
+	case SADB_X_EXT_NAT_T_OA:
+#endif
+		break;
+	default:
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, 
+			"pfkey_address_parse: "
+			"unexpected ext_type=%d.\n", 
+			pfkey_address->sadb_address_exttype); 
+		SENDERR(EINVAL); 
+	}
+	
+	switch(s->sa_family) {
+	case AF_INET:
+		DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+			"pfkey_address_parse: "
+			"found address family=%d, AF_INET.\n",
+			s->sa_family);
+		saddr_len = sizeof(struct sockaddr_in);
+		sprintf(ipaddr_txt, "%d.%d.%d.%d"
+			, (((struct sockaddr_in*)s)->sin_addr.s_addr >>  0) & 0xFF
+			, (((struct sockaddr_in*)s)->sin_addr.s_addr >>  8) & 0xFF
+			, (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF
+			, (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF);
+		DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+			"pfkey_address_parse: "
+			"found address=%s.\n",
+			ipaddr_txt);
+		break;
+	case AF_INET6:
+		DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+			"pfkey_address_parse: "
+			"found address family=%d, AF_INET6.\n",
+			s->sa_family);
+		saddr_len = sizeof(struct sockaddr_in6);
+		sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x"
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0])
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1])
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2])
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3])
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4])
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5])
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6])
+			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7]));
+		DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+			"pfkey_address_parse: "
+			"found address=%s.\n",
+			ipaddr_txt);
+		break;
+	default:
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_address_parse: "
+			"s->sa_family=%d not supported.\n",
+			s->sa_family);
+		SENDERR(EPFNOSUPPORT);
+	}
+	
+	if(pfkey_address->sadb_address_len !=
+	   DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_address_parse: "
+			"size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
+			pfkey_address->sadb_address_len,
+			sizeof(struct sadb_address),
+			saddr_len);
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_address->sadb_address_prefixlen != 0) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_address_parse: "
+			"address prefixes not supported yet.\n");
+		SENDERR(EAFNOSUPPORT); /* not supported yet */
+	}
+	
+	/* XXX check if port!=0 */
+	
+	DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+		"pfkey_address_parse: successful.\n");
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_key_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext;
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+		"pfkey_key_parse:enter\n");
+	/* sanity checks... */
+
+	if(!pfkey_key) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_key_parse: "
+			"NULL pointer passed in.\n");
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_key_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
+			pfkey_key->sadb_key_len,
+			sizeof(struct sadb_key));
+		SENDERR(EINVAL);
+	}
+
+	if(!pfkey_key->sadb_key_bits) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_key_parse: "
+			"key length set to zero, must be non-zero.\n");
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_key->sadb_key_len !=
+	   DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits,
+		 PFKEYBITS)) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_key_parse: "
+			"key length=%d does not agree with extension length=%d.\n",
+			pfkey_key->sadb_key_bits,
+			pfkey_key->sadb_key_len);
+		SENDERR(EINVAL);
+	}
+	
+	if(pfkey_key->sadb_key_reserved) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_key_parse: "
+			"res=%d, must be zero.\n",
+			pfkey_key->sadb_key_reserved);
+		SENDERR(EINVAL);
+	}
+
+	if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ||
+	       (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_key_parse: "
+			"expecting extension type AUTH or ENCRYPT, got %d.\n",
+			pfkey_key->sadb_key_exttype);
+		SENDERR(EINVAL);
+	}
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+		"pfkey_key_parse: "
+		"success, found len=%d exttype=%d bits=%d reserved=%d.\n",
+		pfkey_key->sadb_key_len,
+		pfkey_key->sadb_key_exttype,
+		pfkey_key->sadb_key_bits,
+		pfkey_key->sadb_key_reserved);
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_ident_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext;
+
+	/* sanity checks... */
+	if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_ident_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
+			pfkey_ident->sadb_ident_len,
+			sizeof(struct sadb_ident));
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_ident_parse: "
+			"ident_type=%d out of range, must be less than %d.\n",
+			pfkey_ident->sadb_ident_type,
+			SADB_IDENTTYPE_MAX);
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_ident->sadb_ident_reserved) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_ident_parse: "
+			"res=%d, must be zero.\n",
+			pfkey_ident->sadb_ident_reserved);
+		SENDERR(EINVAL);
+	}
+
+	/* string terminator/padding must be zero */
+	if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
+		if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_ident_parse: "
+				"string padding must be zero, last is 0x%02x.\n",
+				*((char*)pfkey_ident +
+				  pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1));
+			SENDERR(EINVAL);
+		}
+	}
+	
+	if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ||
+	       (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_key_parse: "
+			"expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n",
+			pfkey_ident->sadb_ident_exttype);
+		SENDERR(EINVAL);
+	}
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_sens_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext;
+
+	/* sanity checks... */
+	if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_sens_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
+			pfkey_sens->sadb_sens_len,
+			sizeof(struct sadb_sens));
+		SENDERR(EINVAL);
+	}
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+		"pfkey_sens_parse: "
+		"Sorry, I can't parse exttype=%d yet.\n",
+		pfkey_ext->sadb_ext_type);
+#if 0
+	SENDERR(EINVAL); /* don't process these yet */
+#endif
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_prop_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	int i, num_comb;
+	struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext;
+	struct sadb_comb *pfkey_comb = (struct sadb_comb *)((char*)pfkey_ext + sizeof(struct sadb_prop));
+
+	/* sanity checks... */
+	if((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) || 
+	   (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_prop_parse: "
+			"size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n",
+			pfkey_prop->sadb_prop_len,
+			sizeof(struct sadb_prop),
+			sizeof(struct sadb_comb));
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_prop->sadb_prop_replay > 64) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_prop_parse: "
+			"replay window size: %d -- must be 0 <= size <= 64\n",
+			pfkey_prop->sadb_prop_replay);
+		SENDERR(EINVAL);
+	}
+	
+	for(i=0; i<3; i++) {
+		if(pfkey_prop->sadb_prop_reserved[i]) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"res[%d]=%d, must be zero.\n",
+				i, pfkey_prop->sadb_prop_reserved[i]);
+			SENDERR(EINVAL);
+		}
+	}
+
+	num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb);
+
+	for(i = 0; i < num_comb; i++) {
+		if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n",
+				i,
+				pfkey_comb->sadb_comb_auth,
+				SADB_AALG_MAX);
+			SENDERR(EINVAL);
+		}
+
+		if(pfkey_comb->sadb_comb_auth) {
+			if(!pfkey_comb->sadb_comb_auth_minbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n",
+					i);
+				SENDERR(EINVAL);
+			}
+			if(!pfkey_comb->sadb_comb_auth_maxbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n",
+					i);
+				SENDERR(EINVAL);
+			}
+			if(pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n",
+					i,
+					pfkey_comb->sadb_comb_auth_minbits,
+					pfkey_comb->sadb_comb_auth_maxbits);
+				SENDERR(EINVAL);
+			}
+		} else {
+			if(pfkey_comb->sadb_comb_auth_minbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n",
+					i,
+					pfkey_comb->sadb_comb_auth_minbits);
+				SENDERR(EINVAL);
+			}
+			if(pfkey_comb->sadb_comb_auth_maxbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n",
+					i,
+					pfkey_comb->sadb_comb_auth_maxbits);
+				SENDERR(EINVAL);
+			}
+		}
+
+		if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_comb_parse: "
+				"pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n",
+				i,
+				pfkey_comb->sadb_comb_encrypt,
+				SADB_EALG_MAX);
+			SENDERR(EINVAL);
+		}
+
+		if(pfkey_comb->sadb_comb_encrypt) {
+			if(!pfkey_comb->sadb_comb_encrypt_minbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n",
+					i);
+				SENDERR(EINVAL);
+			}
+			if(!pfkey_comb->sadb_comb_encrypt_maxbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n",
+					i);
+				SENDERR(EINVAL);
+			}
+			if(pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n",
+					i,
+					pfkey_comb->sadb_comb_encrypt_minbits,
+					pfkey_comb->sadb_comb_encrypt_maxbits);
+				SENDERR(EINVAL);
+			}
+		} else {
+			if(pfkey_comb->sadb_comb_encrypt_minbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n",
+					i,
+					pfkey_comb->sadb_comb_encrypt_minbits);
+				SENDERR(EINVAL);
+			}
+			if(pfkey_comb->sadb_comb_encrypt_maxbits) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n",
+					i,
+					pfkey_comb->sadb_comb_encrypt_maxbits);
+				SENDERR(EINVAL);
+			}
+		}
+
+		/* XXX do sanity check on flags */
+
+		if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n",
+				i,
+				pfkey_comb->sadb_comb_soft_allocations,
+				pfkey_comb->sadb_comb_hard_allocations);
+			SENDERR(EINVAL);
+		}
+
+		if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n",
+				i,
+				pfkey_comb->sadb_comb_soft_bytes,
+				pfkey_comb->sadb_comb_hard_bytes);
+			SENDERR(EINVAL);
+		}
+
+		if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n",
+				i,
+				pfkey_comb->sadb_comb_soft_addtime,
+				pfkey_comb->sadb_comb_hard_addtime);
+			SENDERR(EINVAL);
+		}
+
+		if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n",
+				i,
+				pfkey_comb->sadb_comb_soft_usetime,
+				pfkey_comb->sadb_comb_hard_usetime);
+			SENDERR(EINVAL);
+		}
+
+		if(pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n",
+				i,
+				pfkey_comb->sadb_x_comb_soft_packets,
+				pfkey_comb->sadb_x_comb_hard_packets);
+			SENDERR(EINVAL);
+		}
+
+		if(pfkey_comb->sadb_comb_reserved) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_prop_parse: "
+				"comb[%d].res=%d, must be zero.\n",
+				i,
+				pfkey_comb->sadb_comb_reserved);
+			SENDERR(EINVAL);
+		}
+		pfkey_comb++;
+	}
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_supported_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	unsigned int i, num_alg;
+	struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext;
+	struct sadb_alg *pfkey_alg = (struct sadb_alg*)((char*)pfkey_ext + sizeof(struct sadb_supported));
+
+	/* sanity checks... */
+	if((pfkey_supported->sadb_supported_len <
+	   sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) ||
+	   (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) -
+	     sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) {
+
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_supported_parse: "
+			"size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n",
+			pfkey_supported->sadb_supported_len,
+			sizeof(struct sadb_supported),
+			sizeof(struct sadb_alg));
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_supported->sadb_supported_reserved) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_supported_parse: "
+			"res=%d, must be zero.\n",
+			pfkey_supported->sadb_supported_reserved);
+		SENDERR(EINVAL);
+	}
+
+	num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg);
+
+	for(i = 0; i < num_alg; i++) {
+		/* process algo description */
+		if(pfkey_alg->sadb_alg_reserved) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_supported_parse: "
+				"alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n",
+				i,
+				pfkey_alg->sadb_alg_id,
+				pfkey_alg->sadb_alg_ivlen,
+				pfkey_alg->sadb_alg_minbits,
+				pfkey_alg->sadb_alg_maxbits,
+				pfkey_alg->sadb_alg_reserved);
+			SENDERR(EINVAL);
+		}
+
+		/* XXX can alg_id auth/enc be determined from info given?
+		   Yes, but OpenBSD's method does not iteroperate with rfc2367.
+		   rgb, 2000-04-06 */
+
+		switch(pfkey_supported->sadb_supported_exttype) {
+		case SADB_EXT_SUPPORTED_AUTH:
+			if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_supported_parse: "
+					"alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n",
+					i,
+					pfkey_alg->sadb_alg_id,
+					SADB_AALG_MAX);
+				SENDERR(EINVAL);
+			}
+			break;
+		case SADB_EXT_SUPPORTED_ENCRYPT:
+			if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_supported_parse: "
+					"alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
+					i,
+					pfkey_alg->sadb_alg_id,
+					SADB_EALG_MAX);
+				SENDERR(EINVAL);
+			}
+			break;
+		default:
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_supported_parse: "
+				"alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
+				i,
+				pfkey_alg->sadb_alg_id,
+				SADB_EALG_MAX);
+			SENDERR(EINVAL);
+		}
+		pfkey_alg++;
+	}
+	
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_spirange_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext;
+	
+	/* sanity checks... */
+        if(pfkey_spirange->sadb_spirange_len !=
+	   sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_spirange_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
+			pfkey_spirange->sadb_spirange_len,
+			sizeof(struct sadb_spirange));
+                SENDERR(EINVAL);
+        }
+	
+        if(pfkey_spirange->sadb_spirange_reserved) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_spirange_parse: "
+			"reserved=%d must be set to zero.\n",
+			pfkey_spirange->sadb_spirange_reserved);
+                SENDERR(EINVAL);
+        }
+	
+        if(ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_spirange_parse: "
+			"minspi=%08x must be < maxspi=%08x.\n",
+			ntohl(pfkey_spirange->sadb_spirange_min),
+			ntohl(pfkey_spirange->sadb_spirange_max));
+                SENDERR(EINVAL);
+        }
+	
+	if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_spirange_parse: "
+			"minspi=%08x must be > 255.\n",
+			ntohl(pfkey_spirange->sadb_spirange_min));
+		SENDERR(EEXIST);
+	}
+	
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext;
+
+	/* sanity checks... */
+	if(pfkey_x_kmprivate->sadb_x_kmprivate_len <
+	   sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_x_kmprivate_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
+			pfkey_x_kmprivate->sadb_x_kmprivate_len,
+			sizeof(struct sadb_x_kmprivate));
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_x_kmprivate_parse: "
+			"reserved=%d must be set to zero.\n",
+			pfkey_x_kmprivate->sadb_x_kmprivate_reserved);
+		SENDERR(EINVAL);
+	}
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+		"pfkey_x_kmprivate_parse: "
+		"Sorry, I can't parse exttype=%d yet.\n",
+		pfkey_ext->sadb_ext_type);
+	SENDERR(EINVAL); /* don't process these yet */
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_satype_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	int i;
+	struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+		"pfkey_x_satype_parse: enter\n");
+	/* sanity checks... */
+	if(pfkey_x_satype->sadb_x_satype_len !=
+	   sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_x_satype_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
+			pfkey_x_satype->sadb_x_satype_len,
+			sizeof(struct sadb_x_satype));
+		SENDERR(EINVAL);
+	}
+	
+	if(!pfkey_x_satype->sadb_x_satype_satype) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_x_satype_parse: "
+			"satype is zero, must be non-zero.\n");
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_x_satype->sadb_x_satype_satype > SADB_SATYPE_MAX) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_x_satype_parse: "
+			"satype %d > max %d, invalid.\n", 
+			pfkey_x_satype->sadb_x_satype_satype, SADB_SATYPE_MAX);
+		SENDERR(EINVAL);
+	}
+
+	if(!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_x_satype_parse: "
+			"proto lookup from satype=%d failed.\n",
+			pfkey_x_satype->sadb_x_satype_satype);
+		SENDERR(EINVAL);
+	}
+
+	for(i = 0; i < 3; i++) {
+		if(pfkey_x_satype->sadb_x_satype_reserved[i]) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_x_satype_parse: "
+				"reserved[%d]=%d must be set to zero.\n",
+				i, pfkey_x_satype->sadb_x_satype_reserved[i]);
+			SENDERR(EINVAL);
+		}
+	}
+	
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	int i;
+	struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext;
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
+		"pfkey_x_debug_parse: enter\n");
+	/* sanity checks... */
+	if(pfkey_x_debug->sadb_x_debug_len !=
+	   sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_x_debug_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
+			pfkey_x_debug->sadb_x_debug_len,
+			sizeof(struct sadb_x_debug));
+		SENDERR(EINVAL);
+	}
+	
+	for(i = 0; i < 4; i++) {
+		if(pfkey_x_debug->sadb_x_debug_reserved[i]) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_x_debug_parse: "
+				"reserved[%d]=%d must be set to zero.\n",
+				i, pfkey_x_debug->sadb_x_debug_reserved[i]);
+			SENDERR(EINVAL);
+		}
+	}
+	
+errlab:
+	return error;
+}
+
+#ifdef NAT_TRAVERSAL
+DEBUG_NO_STATIC int
+pfkey_x_ext_nat_t_type_parse(struct sadb_ext *pfkey_ext)
+{
+	return 0;
+}
+DEBUG_NO_STATIC int
+pfkey_x_ext_nat_t_port_parse(struct sadb_ext *pfkey_ext)
+{
+	return 0;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext)
+{
+	int error = 0;
+	struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext;
+	
+	DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n");
+	/* sanity checks... */
+	
+	if (p->sadb_protocol_len != sizeof(*p)/IPSEC_PFKEYv2_ALIGN) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			  "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			  p->sadb_protocol_len, sizeof(*p));
+		SENDERR(EINVAL);
+	}
+
+	if (p->sadb_protocol_reserved2 != 0) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			  "pfkey_protocol_parse: res=%d, must be zero.\n",
+			  p->sadb_protocol_reserved2);
+		SENDERR(EINVAL);
+	}
+
+ errlab:
+	return error;
+}
+#endif /* NAT_TRAVERSAL */
+
+#define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME##_def={NAME, #NAME};
+
+DEFINEPARSER(pfkey_sa_parse);
+DEFINEPARSER(pfkey_lifetime_parse);
+DEFINEPARSER(pfkey_address_parse);
+DEFINEPARSER(pfkey_key_parse);
+DEFINEPARSER(pfkey_ident_parse);
+DEFINEPARSER(pfkey_sens_parse);
+DEFINEPARSER(pfkey_prop_parse);
+DEFINEPARSER(pfkey_supported_parse);
+DEFINEPARSER(pfkey_spirange_parse);
+DEFINEPARSER(pfkey_x_kmprivate_parse);
+DEFINEPARSER(pfkey_x_satype_parse);
+DEFINEPARSER(pfkey_x_ext_debug_parse);
+#ifdef NAT_TRAVERSAL
+DEFINEPARSER(pfkey_x_ext_protocol_parse);
+DEFINEPARSER(pfkey_x_ext_nat_t_type_parse);
+DEFINEPARSER(pfkey_x_ext_nat_t_port_parse);
+#endif
+
+struct pf_key_ext_parsers_def *ext_default_parsers[]=
+{
+	NULL,                 /* pfkey_msg_parse, */
+	&pfkey_sa_parse_def,
+	&pfkey_lifetime_parse_def,
+	&pfkey_lifetime_parse_def,
+	&pfkey_lifetime_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_key_parse_def,
+	&pfkey_key_parse_def,
+	&pfkey_ident_parse_def,
+	&pfkey_ident_parse_def,
+	&pfkey_sens_parse_def,
+	&pfkey_prop_parse_def,
+	&pfkey_supported_parse_def,
+	&pfkey_supported_parse_def,
+	&pfkey_spirange_parse_def,
+	&pfkey_x_kmprivate_parse_def,
+	&pfkey_x_satype_parse_def,
+	&pfkey_sa_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_address_parse_def,
+	&pfkey_x_ext_debug_parse_def
+#ifdef NAT_TRAVERSAL
+	,
+	&pfkey_x_ext_nat_t_type_parse_def,
+	&pfkey_x_ext_nat_t_port_parse_def,
+	&pfkey_x_ext_nat_t_port_parse_def,
+	&pfkey_address_parse_def,
+        &pfkey_x_ext_protocol_parse_def
+#endif
+};
+
+int
+pfkey_msg_parse(struct sadb_msg *pfkey_msg,
+		struct pf_key_ext_parsers_def *ext_parsers[],
+		struct sadb_ext *extensions[],
+		int dir)
+{
+	int error = 0;
+	int remain;
+	struct sadb_ext *pfkey_ext;
+	int extensions_seen = 0;
+	
+	DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+		  "pfkey_msg_parse: "
+		  "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", 
+		  pfkey_msg->sadb_msg_version,
+		  pfkey_msg->sadb_msg_type,
+		  pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type),
+		  pfkey_msg->sadb_msg_errno,
+		  pfkey_msg->sadb_msg_satype,
+		  satype2name(pfkey_msg->sadb_msg_satype),
+		  pfkey_msg->sadb_msg_len,
+		  pfkey_msg->sadb_msg_reserved,
+		  pfkey_msg->sadb_msg_seq,
+		  pfkey_msg->sadb_msg_pid);
+	
+	if(ext_parsers == NULL) ext_parsers = ext_default_parsers;
+	
+	pfkey_extensions_init(extensions);
+	
+	remain = pfkey_msg->sadb_msg_len;
+	remain -= sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
+	
+	pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg +
+				       sizeof(struct sadb_msg));
+	
+	extensions[0] = (struct sadb_ext *) pfkey_msg;
+	
+	
+	if(pfkey_msg->sadb_msg_version != PF_KEY_V2) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_msg_parse: "
+			"not PF_KEY_V2 msg, found %d, should be %d.\n",
+			pfkey_msg->sadb_msg_version,
+			PF_KEY_V2);
+		SENDERR(EINVAL);
+	}
+
+	if(!pfkey_msg->sadb_msg_type) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_msg_parse: "
+			"msg type not set, must be non-zero..\n");
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_msg->sadb_msg_type > SADB_MAX) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_msg_parse: "
+			"msg type=%d > max=%d.\n",
+			pfkey_msg->sadb_msg_type,
+			SADB_MAX);
+		SENDERR(EINVAL);
+	}
+
+	switch(pfkey_msg->sadb_msg_type) {
+	case SADB_GETSPI:
+	case SADB_UPDATE:
+	case SADB_ADD:
+	case SADB_DELETE:
+	case SADB_GET:
+	case SADB_X_GRPSA:
+	case SADB_X_ADDFLOW:
+		if(!satype2proto(pfkey_msg->sadb_msg_satype)) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				  "pfkey_msg_parse: "
+				  "satype %d conversion to proto failed for msg_type %d (%s).\n",
+				  pfkey_msg->sadb_msg_satype,
+				  pfkey_msg->sadb_msg_type,
+				  pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
+			SENDERR(EINVAL);
+		} else {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				  "pfkey_msg_parse: "
+				  "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n",
+				  pfkey_msg->sadb_msg_satype,
+				  satype2name(pfkey_msg->sadb_msg_satype),
+				  satype2proto(pfkey_msg->sadb_msg_satype),
+				  pfkey_msg->sadb_msg_type,
+				  pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
+		}
+	case SADB_ACQUIRE:
+	case SADB_REGISTER:
+	case SADB_EXPIRE:
+		if(!pfkey_msg->sadb_msg_satype) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				  "pfkey_msg_parse: "
+				  "satype is zero, must be non-zero for msg_type %d(%s).\n",
+				  pfkey_msg->sadb_msg_type,
+				  pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
+			SENDERR(EINVAL);
+		}
+	default:
+	}
+	
+	/* errno must not be set in downward messages */
+	/* this is not entirely true... a response to an ACQUIRE could return an error */
+	if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			    "pfkey_msg_parse: "
+			    "errno set to %d.\n",
+			    pfkey_msg->sadb_msg_errno);
+		SENDERR(EINVAL);
+	}
+
+	DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+		  "pfkey_msg_parse: "
+		  "remain=%d, ext_type=%d(%s), ext_len=%d.\n", 
+		  remain,
+		  pfkey_ext->sadb_ext_type,
+		  pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
+		  pfkey_ext->sadb_ext_len);
+	
+	DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+		"pfkey_msg_parse: "
+		"extensions permitted=%08x, required=%08x.\n",
+		extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
+		extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
+	
+	extensions_seen = 1;
+	
+	while( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) {
+		/* Is there enough message left to support another extension header? */
+		if(remain < pfkey_ext->sadb_ext_len) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"remain %d less than ext len %d.\n", 
+				remain, pfkey_ext->sadb_ext_len);
+			SENDERR(EINVAL);
+		}
+		
+		DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+			"pfkey_msg_parse: "
+			"parsing ext type=%d remain=%d.\n",
+			pfkey_ext->sadb_ext_type,
+			remain);
+		
+		/* Is the extension header type valid? */
+		if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"ext type %d invalid, SADB_EXT_MAX=%d.\n", 
+				pfkey_ext->sadb_ext_type, SADB_EXT_MAX);
+			SENDERR(EINVAL);
+		}
+		
+		/* Have we already seen this type of extension? */
+		if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0)
+		{
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"ext type %d already seen.\n", 
+				pfkey_ext->sadb_ext_type);
+			SENDERR(EINVAL);
+		}
+
+		/* Do I even know about this type of extension? */
+		if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"ext type %d unknown, ignoring.\n", 
+				pfkey_ext->sadb_ext_type);
+			goto next_ext;
+		}
+
+		/* Is this type of extension permitted for this type of message? */
+		if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] &
+		     1<<pfkey_ext->sadb_ext_type)) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"ext type %d not permitted, exts_perm_in=%08x, 1<<type=%08x\n", 
+				pfkey_ext->sadb_ext_type, 
+				extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
+				1<<pfkey_ext->sadb_ext_type);
+			SENDERR(EINVAL);
+		}
+
+		DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+			"pfkey_msg_parse: "
+			"About to parse extension %d %p with parser %s.\n",
+			pfkey_ext->sadb_ext_type,
+			pfkey_ext,
+			ext_parsers[pfkey_ext->sadb_ext_type]->parser_name);
+		/* Parse the extension */
+		if((error =
+		    (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)(pfkey_ext))) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"extension parsing for type %d failed with error %d.\n",
+				pfkey_ext->sadb_ext_type, error); 
+			SENDERR(-error);
+		}
+		DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+			"pfkey_msg_parse: "
+			"Extension %d parsed.\n",
+			pfkey_ext->sadb_ext_type);
+		
+		/* Mark that we have seen this extension and remember the header location */
+		extensions_seen |= ( 1 << pfkey_ext->sadb_ext_type );
+		extensions[pfkey_ext->sadb_ext_type] = pfkey_ext;
+
+	next_ext:		
+		/* Calculate how much message remains */
+		remain -= pfkey_ext->sadb_ext_len;
+
+		if(!remain) {
+			break;
+		}
+		/* Find the next extension header */
+		pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext +
+			pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
+	}
+
+	if(remain) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_msg_parse: "
+			"unexpected remainder of %d.\n", 
+			remain);
+		/* why is there still something remaining? */
+		SENDERR(EINVAL);
+	}
+
+	/* check required extensions */
+	DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
+		"pfkey_msg_parse: "
+		"extensions permitted=%08x, seen=%08x, required=%08x.\n",
+		extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
+		extensions_seen,
+		extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
+
+	/* don't check further if it is an error return message since it
+	   may not have a body */
+	if(pfkey_msg->sadb_msg_errno) {
+		SENDERR(-error);
+	}
+
+	if((extensions_seen &
+	    extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) !=
+	   extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_msg_parse: "
+			"required extensions missing:%08x.\n",
+			extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type] -
+			(extensions_seen &
+			 extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]));
+		SENDERR(EINVAL);
+	}
+	
+	if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == SADB_X_DELFLOW)
+	   && ((extensions_seen	& SADB_X_EXT_ADDRESS_DELFLOW)
+	       != SADB_X_EXT_ADDRESS_DELFLOW)
+	   && (((extensions_seen & (1<<SADB_EXT_SA)) != (1<<SADB_EXT_SA))
+	   || ((((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_flags
+		& SADB_X_SAFLAGS_CLEARFLOW)
+	       != SADB_X_SAFLAGS_CLEARFLOW))) {
+		DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+			"pfkey_msg_parse: "
+			"required SADB_X_DELFLOW extensions missing: either %08x must be present or %08x must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n",
+			SADB_X_EXT_ADDRESS_DELFLOW
+			- (extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW),
+			(1<<SADB_EXT_SA) - (extensions_seen & (1<<SADB_EXT_SA)));
+		SENDERR(EINVAL);
+	}
+	
+	switch(pfkey_msg->sadb_msg_type) {
+	case SADB_ADD:
+	case SADB_UPDATE:
+		/* check maturity */
+		if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state !=
+		   SADB_SASTATE_MATURE) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"state=%d for add or update should be MATURE=%d.\n",
+				((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
+				SADB_SASTATE_MATURE);
+			SENDERR(EINVAL);
+		}
+		
+		/* check AH and ESP */
+		switch(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype) {
+		case SADB_SATYPE_AH:
+			if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
+			     ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth !=
+			     SADB_AALG_NONE)) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_msg_parse: "
+					"auth alg is zero, must be non-zero for AH SAs.\n");
+				SENDERR(EINVAL);
+			}
+			if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt !=
+			   SADB_EALG_NONE) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_msg_parse: "
+					"AH handed encalg=%d, must be zero.\n",
+					((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt);
+				SENDERR(EINVAL);
+			}
+			break;
+		case SADB_SATYPE_ESP:
+			if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
+			     ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
+			     SADB_EALG_NONE)) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_msg_parse: "
+					"encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n",
+					((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
+					((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
+				SENDERR(EINVAL);
+			}
+			if((((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt ==
+			    SADB_EALG_NULL) &&
+			   (((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth ==
+			    SADB_AALG_NONE) ) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_msg_parse: "
+					"ESP handed encNULL+authNONE, illegal combination.\n");
+				SENDERR(EINVAL);
+			}
+			break;
+		case SADB_X_SATYPE_COMP:
+			if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
+			     ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
+			     SADB_EALG_NONE)) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_msg_parse: "
+					"encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n",
+					((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
+					((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
+				SENDERR(EINVAL);
+			}
+			if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth !=
+			   SADB_AALG_NONE) {
+				DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+					"pfkey_msg_parse: "
+					"COMP handed auth=%d, must be zero.\n",
+					((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth);
+				SENDERR(EINVAL);
+			}
+			break;
+		default:
+		}
+		if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) {
+			DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
+				"pfkey_msg_parse: "
+				"spi=%08x must be > 255.\n",
+				ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi));
+			SENDERR(EINVAL);
+		}
+	default:	
+	}
+errlab:
+
+	return error;
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.5  2003/02/07 13:14:26  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.4.2.1  2003/02/07 01:47:12  jjo
+ * . some #ifdef's tweaking to allow compilation without NAT_TRAVERSAL
+ *
+ * Revision 1.4  2002/12/26 02:30:48  ken
+ * Fix order of SADB definations
+ *
+ * Revision 1.3  2002/12/12 03:32:08  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.2  2002/09/05 03:53:53  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:20  ken
+ * 1.98b
+ *
+ * Revision 1.42  2002/01/29 22:25:36  rgb
+ * Re-add ipsec_kversion.h to keep MALLOC happy.
+ *
+ * Revision 1.41  2002/01/29 01:59:10  mcr
+ * 	removal of kversions.h - sources that needed it now use ipsec_param.h.
+ * 	updating of IPv6 structures to match latest in6.h version.
+ * 	removed dead code from freeswan.h that also duplicated kversions.h
+ * 	code.
+ *
+ * Revision 1.40  2002/01/20 20:34:50  mcr
+ * 	added pfkey_v2_sadb_type_string to decode sadb_type to string.
+ *
+ * Revision 1.39  2001/11/27 05:29:22  mcr
+ * 	pfkey parses are now maintained by a structure
+ * 	that includes their name for debug purposes.
+ * 	DEBUGGING() macro changed so that it takes a debug
+ * 	level so that pf_key() can use this to decode the
+ * 	structures without innundanting humans.
+ * 	Also uses pfkey_v2_sadb_ext_string() in messages.
+ *
+ * Revision 1.38  2001/11/06 19:47:47  rgb
+ * Added packet parameter to lifetime and comb structures.
+ *
+ * Revision 1.37  2001/10/18 04:45:24  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.36  2001/06/14 19:35:16  rgb
+ * Update copyright date.
+ *
+ * Revision 1.35  2001/05/03 19:44:51  rgb
+ * Standardise on SENDERR() macro.
+ *
+ * Revision 1.34  2001/03/16 07:41:51  rgb
+ * Put freeswan.h include before pluto includes.
+ *
+ * Revision 1.33  2001/02/27 07:13:51  rgb
+ * Added satype2name() function.
+ * Added text to default satype_tbl entry.
+ * Added satype2name() conversions for most satype debug output.
+ *
+ * Revision 1.32  2001/02/26 20:01:09  rgb
+ * Added internal IP protocol 61 for magic SAs.
+ * Ditch unused sadb_satype2proto[], replaced by satype2proto().
+ * Re-formatted debug output (split lines, consistent spacing).
+ * Removed acquire, register and expire requirements for a known satype.
+ * Changed message type checking to a switch structure.
+ * Verify expected NULL auth for IPCOMP.
+ * Enforced spi > 0x100 requirement, now that pass uses a magic SA for
+ * appropriate message types.
+ *
+ * Revision 1.31  2000/12/01 07:09:00  rgb
+ * Added ipcomp sanity check to require encalgo is set.
+ *
+ * Revision 1.30  2000/11/17 18:10:30  rgb
+ * Fixed bugs mostly relating to spirange, to treat all spi variables as
+ * network byte order since this is the way PF_KEYv2 stored spis.
+ *
+ * Revision 1.29  2000/10/12 00:02:39  rgb
+ * Removed 'format, ##' nonsense from debug macros for RH7.0.
+ *
+ * Revision 1.28  2000/09/20 16:23:04  rgb
+ * Remove over-paranoid extension check in the presence of sadb_msg_errno.
+ *
+ * Revision 1.27  2000/09/20 04:04:21  rgb
+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in
+ * oopsen.
+ *
+ * Revision 1.26  2000/09/15 11:37:02  rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.25  2000/09/12 22:35:37  rgb
+ * Restructured to remove unused extensions from CLEARFLOW messages.
+ *
+ * Revision 1.24  2000/09/12 18:59:54  rgb
+ * Added Gerhard's IPv6 support to pfkey parts of libfreeswan.
+ *
+ * Revision 1.23  2000/09/12 03:27:00  rgb
+ * Moved DEBUGGING definition to compile kernel with debug off.
+ *
+ * Revision 1.22  2000/09/09 06:39:27  rgb
+ * Restrict pfkey errno check to downward messages only.
+ *
+ * Revision 1.21  2000/09/08 19:22:34  rgb
+ * Enabled pfkey_sens_parse().
+ * Added check for errno on downward acquire messages only.
+ *
+ * Revision 1.20  2000/09/01 18:48:23  rgb
+ * Fixed reserved check bug and added debug output in
+ * pfkey_supported_parse().
+ * Fixed debug output label bug in pfkey_ident_parse().
+ *
+ * Revision 1.19  2000/08/27 01:55:26  rgb
+ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code.
+ *
+ * Revision 1.18  2000/08/24 17:00:36  rgb
+ * Ignore unknown extensions instead of failing.
+ *
+ * Revision 1.17  2000/06/02 22:54:14  rgb
+ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
+ *
+ * Revision 1.16  2000/05/10 19:25:11  rgb
+ * Fleshed out proposal and supported extensions.
+ *
+ * Revision 1.15  2000/01/24 21:15:31  rgb
+ * Added disabled pluto pfkey lib debug flag.
+ * Added algo debugging reporting.
+ *
+ * Revision 1.14  2000/01/22 23:24:29  rgb
+ * Added new functions proto2satype() and satype2proto() and lookup
+ * table satype_tbl.  Also added proto2name() since it was easy.
+ *
+ * Revision 1.13  2000/01/21 09:43:59  rgb
+ * Cast ntohl(spi) as (unsigned long int) to shut up compiler.
+ *
+ * Revision 1.12  2000/01/21 06:28:19  rgb
+ * Added address cases for eroute flows.
+ * Indented compiler directives for readability.
+ * Added klipsdebug switching capability.
+ *
+ * Revision 1.11  1999/12/29 21:14:59  rgb
+ * Fixed debug text cut and paste typo.
+ *
+ * Revision 1.10  1999/12/10 17:45:24  rgb
+ * Added address debugging.
+ *
+ * Revision 1.9  1999/12/09 23:11:42  rgb
+ * Ditched <string.h> include since we no longer use memset().
+ * Use new pfkey_extensions_init() instead of memset().
+ * Added check for SATYPE in pfkey_msg_build().
+ * Tidy up comments and debugging comments.
+ *
+ * Revision 1.8  1999/12/07 19:55:26  rgb
+ * Removed unused first argument from extension parsers.
+ * Removed static pluto debug flag.
+ * Moved message type and state checking to pfkey_msg_parse().
+ * Changed print[fk] type from lx to x to quiet compiler.
+ * Removed redundant remain check.
+ * Changed __u* types to uint* to avoid use of asm/types.h and
+ * sys/types.h in userspace code.
+ *
+ * Revision 1.7  1999/12/01 22:20:51  rgb
+ * Moved pfkey_lib_debug variable into the library.
+ * Added pfkey version check into header parsing.
+ * Added check for SATYPE only for those extensions that require a
+ * non-zero value.
+ *
+ * Revision 1.6  1999/11/27 11:58:05  rgb
+ * Added ipv6 headers.
+ * Moved sadb_satype2proto protocol lookup table from
+ * klips/net/ipsec/pfkey_v2_parser.c.
+ * Enable lifetime_current checking.
+ * Debugging error messages added.
+ * Add argument to pfkey_msg_parse() for direction.
+ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
+ * Add CVS log entry to bottom of file.
+ * Moved auth and enc alg check to pfkey_msg_parse().
+ * Enable accidentally disabled spirange parsing.
+ * Moved protocol/algorithm checks from klips/net/ipsec/pfkey_v2_parser.c
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/pfkeyv2.h linux-patched/net/ipsec/libfreeswan/pfkeyv2.h
--- linux/net/ipsec/libfreeswan/pfkeyv2.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/pfkeyv2.h	Thu Dec 12 03:32:08 2002
@@ -0,0 +1,408 @@
+/*
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+RFC 2367               PF_KEY Key Management API               July 1998
+
+
+Appendix D: Sample Header File
+
+This file defines structures and symbols for the PF_KEY Version 2
+key management interface. It was written at the U.S. Naval Research
+Laboratory. This file is in the public domain. The authors ask that
+you leave this credit intact on any copies of this file.
+*/
+#ifndef __PFKEY_V2_H
+#define __PFKEY_V2_H 1
+
+#define PF_KEY_V2 2
+#define PFKEYV2_REVISION        199806L
+
+#define SADB_RESERVED    0
+#define SADB_GETSPI      1
+#define SADB_UPDATE      2
+#define SADB_ADD         3
+#define SADB_DELETE      4
+#define SADB_GET         5
+#define SADB_ACQUIRE     6
+#define SADB_REGISTER    7
+#define SADB_EXPIRE      8
+#define SADB_FLUSH       9
+#define SADB_DUMP       10
+#define SADB_X_PROMISC  11
+#define SADB_X_PCHANGE  12
+#define SADB_X_GRPSA    13
+#define SADB_X_ADDFLOW	14
+#define SADB_X_DELFLOW	15
+#define SADB_X_DEBUG	16
+#ifdef NAT_TRAVERSAL
+#define SADB_X_NAT_T_NEW_MAPPING  17
+#define SADB_MAX                  17
+#else
+#define SADB_MAX        16
+#endif
+
+struct sadb_msg {
+  uint8_t sadb_msg_version;
+  uint8_t sadb_msg_type;
+  uint8_t sadb_msg_errno;
+  uint8_t sadb_msg_satype;
+  uint16_t sadb_msg_len;
+  uint16_t sadb_msg_reserved;
+  uint32_t sadb_msg_seq;
+  uint32_t sadb_msg_pid;
+};
+
+struct sadb_ext {
+  uint16_t sadb_ext_len;
+  uint16_t sadb_ext_type;
+};
+
+struct sadb_sa {
+  uint16_t sadb_sa_len;
+  uint16_t sadb_sa_exttype;
+  uint32_t sadb_sa_spi;
+  uint8_t sadb_sa_replay;
+  uint8_t sadb_sa_state;
+  uint8_t sadb_sa_auth;
+  uint8_t sadb_sa_encrypt;
+  uint32_t sadb_sa_flags;
+};
+
+struct sadb_lifetime {
+  uint16_t sadb_lifetime_len;
+  uint16_t sadb_lifetime_exttype;
+  uint32_t sadb_lifetime_allocations;
+  uint64_t sadb_lifetime_bytes;
+  uint64_t sadb_lifetime_addtime;
+  uint64_t sadb_lifetime_usetime;
+  uint32_t sadb_x_lifetime_packets;
+  uint32_t sadb_x_lifetime_reserved;
+};
+
+struct sadb_address {
+  uint16_t sadb_address_len;
+  uint16_t sadb_address_exttype;
+  uint8_t sadb_address_proto;
+  uint8_t sadb_address_prefixlen;
+  uint16_t sadb_address_reserved;
+};
+
+struct sadb_key {
+  uint16_t sadb_key_len;
+  uint16_t sadb_key_exttype;
+  uint16_t sadb_key_bits;
+  uint16_t sadb_key_reserved;
+};
+
+struct sadb_ident {
+  uint16_t sadb_ident_len;
+  uint16_t sadb_ident_exttype;
+  uint16_t sadb_ident_type;
+  uint16_t sadb_ident_reserved;
+  uint64_t sadb_ident_id;
+};
+
+struct sadb_sens {
+  uint16_t sadb_sens_len;
+  uint16_t sadb_sens_exttype;
+  uint32_t sadb_sens_dpd;
+  uint8_t sadb_sens_sens_level;
+  uint8_t sadb_sens_sens_len;
+  uint8_t sadb_sens_integ_level;
+  uint8_t sadb_sens_integ_len;
+  uint32_t sadb_sens_reserved;
+};
+
+struct sadb_prop {
+  uint16_t sadb_prop_len;
+  uint16_t sadb_prop_exttype;
+  uint8_t sadb_prop_replay;
+  uint8_t sadb_prop_reserved[3];
+};
+
+struct sadb_comb {
+  uint8_t sadb_comb_auth;
+  uint8_t sadb_comb_encrypt;
+  uint16_t sadb_comb_flags;
+  uint16_t sadb_comb_auth_minbits;
+  uint16_t sadb_comb_auth_maxbits;
+  uint16_t sadb_comb_encrypt_minbits;
+  uint16_t sadb_comb_encrypt_maxbits;
+  uint32_t sadb_comb_reserved;
+  uint32_t sadb_comb_soft_allocations;
+  uint32_t sadb_comb_hard_allocations;
+  uint64_t sadb_comb_soft_bytes;
+  uint64_t sadb_comb_hard_bytes;
+  uint64_t sadb_comb_soft_addtime;
+  uint64_t sadb_comb_hard_addtime;
+  uint64_t sadb_comb_soft_usetime;
+  uint64_t sadb_comb_hard_usetime;
+  uint32_t sadb_x_comb_soft_packets;
+  uint32_t sadb_x_comb_hard_packets;
+};
+
+struct sadb_supported {
+  uint16_t sadb_supported_len;
+  uint16_t sadb_supported_exttype;
+  uint32_t sadb_supported_reserved;
+};
+
+struct sadb_alg {
+  uint8_t sadb_alg_id;
+  uint8_t sadb_alg_ivlen;
+  uint16_t sadb_alg_minbits;
+  uint16_t sadb_alg_maxbits;
+  uint16_t sadb_alg_reserved;
+};
+
+struct sadb_spirange {
+  uint16_t sadb_spirange_len;
+  uint16_t sadb_spirange_exttype;
+  uint32_t sadb_spirange_min;
+  uint32_t sadb_spirange_max;
+  uint32_t sadb_spirange_reserved;
+};
+
+struct sadb_x_kmprivate {
+  uint16_t sadb_x_kmprivate_len;
+  uint16_t sadb_x_kmprivate_exttype;
+  uint32_t sadb_x_kmprivate_reserved;
+};
+
+struct sadb_x_satype {
+  uint16_t sadb_x_satype_len;
+  uint16_t sadb_x_satype_exttype;
+  uint8_t sadb_x_satype_satype;
+  uint8_t sadb_x_satype_reserved[3];
+};
+  
+struct sadb_x_debug {
+  uint16_t sadb_x_debug_len;
+  uint16_t sadb_x_debug_exttype;
+  uint32_t sadb_x_debug_tunnel;
+  uint32_t sadb_x_debug_netlink;
+  uint32_t sadb_x_debug_xform;
+  uint32_t sadb_x_debug_eroute;
+  uint32_t sadb_x_debug_spi;
+  uint32_t sadb_x_debug_radij;
+  uint32_t sadb_x_debug_esp;
+  uint32_t sadb_x_debug_ah;
+  uint32_t sadb_x_debug_rcv;
+  uint32_t sadb_x_debug_pfkey;
+  uint32_t sadb_x_debug_ipcomp;
+  uint32_t sadb_x_debug_verbose;
+  uint8_t sadb_x_debug_reserved[4];
+};
+
+#ifdef NAT_TRAVERSAL
+struct sadb_x_nat_t_type {
+  uint16_t sadb_x_nat_t_type_len;
+  uint16_t sadb_x_nat_t_type_exttype;
+  uint8_t sadb_x_nat_t_type_type;
+  uint8_t sadb_x_nat_t_type_reserved[3];
+};
+struct sadb_x_nat_t_port {
+  uint16_t sadb_x_nat_t_port_len;
+  uint16_t sadb_x_nat_t_port_exttype;
+  uint16_t sadb_x_nat_t_port_port;
+  uint16_t sadb_x_nat_t_port_reserved;
+};
+#endif
+  
+/*
+ * A protocol structure for passing through the transport level
+ * protocol.  It contains more fields than are actually used/needed
+ * but it is this way to be compatible with the structure used in
+ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
+ */
+struct sadb_protocol {
+  uint16_t sadb_protocol_len;
+  uint16_t sadb_protocol_exttype;
+  uint8_t  sadb_protocol_proto;
+  uint8_t  sadb_protocol_direction;
+  uint8_t  sadb_protocol_flags;
+  uint8_t  sadb_protocol_reserved2;
+};
+
+#define SADB_EXT_RESERVED             0
+#define SADB_EXT_SA                   1
+#define SADB_EXT_LIFETIME_CURRENT     2
+#define SADB_EXT_LIFETIME_HARD        3
+#define SADB_EXT_LIFETIME_SOFT        4
+#define SADB_EXT_ADDRESS_SRC          5
+#define SADB_EXT_ADDRESS_DST          6
+#define SADB_EXT_ADDRESS_PROXY        7
+#define SADB_EXT_KEY_AUTH             8
+#define SADB_EXT_KEY_ENCRYPT          9
+#define SADB_EXT_IDENTITY_SRC         10
+#define SADB_EXT_IDENTITY_DST         11
+#define SADB_EXT_SENSITIVITY          12
+#define SADB_EXT_PROPOSAL             13
+#define SADB_EXT_SUPPORTED_AUTH       14
+#define SADB_EXT_SUPPORTED_ENCRYPT    15
+#define SADB_EXT_SPIRANGE             16
+#define SADB_X_EXT_KMPRIVATE          17
+#define SADB_X_EXT_SATYPE2            18
+#define SADB_X_EXT_SA2                19
+#define SADB_X_EXT_ADDRESS_DST2       20
+#define SADB_X_EXT_ADDRESS_SRC_FLOW   21
+#define SADB_X_EXT_ADDRESS_DST_FLOW   22
+#define SADB_X_EXT_ADDRESS_SRC_MASK   23
+#define SADB_X_EXT_ADDRESS_DST_MASK   24
+#define SADB_X_EXT_DEBUG              25
+#ifdef NAT_TRAVERSAL
+#define SADB_X_EXT_NAT_T_TYPE         26
+#define SADB_X_EXT_NAT_T_SPORT        27
+#define SADB_X_EXT_NAT_T_DPORT        28
+#define SADB_X_EXT_NAT_T_OA           29
+#define SADB_X_EXT_PROTOCOL           30
+#define SADB_EXT_MAX                  30
+#else
+#define SADB_X_EXT_PROTOCOL           26
+#define SADB_EXT_MAX                  26
+
+#endif
+
+/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
+#define SADB_X_EXT_ADDRESS_DELFLOW \
+	( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
+	| (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
+	| (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
+	| (1<<SADB_X_EXT_ADDRESS_DST_MASK))
+
+#define SADB_SATYPE_UNSPEC    0
+#define SADB_SATYPE_AH        2
+#define SADB_SATYPE_ESP       3
+#define SADB_SATYPE_RSVP      5
+#define SADB_SATYPE_OSPFV2    6
+#define SADB_SATYPE_RIPV2     7
+#define SADB_SATYPE_MIP       8
+#define SADB_X_SATYPE_IPIP    9
+#define SADB_X_SATYPE_COMP    10
+#define SADB_X_SATYPE_INT     11
+#define SADB_SATYPE_MAX       11
+
+#define SADB_SASTATE_LARVAL   0
+#define SADB_SASTATE_MATURE   1
+#define SADB_SASTATE_DYING    2
+#define SADB_SASTATE_DEAD     3
+#define SADB_SASTATE_MAX      3
+
+#define SADB_SAFLAGS_PFS		1
+#define SADB_X_SAFLAGS_REPLACEFLOW	2
+#define SADB_X_SAFLAGS_CLEARFLOW	4
+#define SADB_X_SAFLAGS_INFLOW		8
+
+#define SADB_AALG_NONE        0
+#define SADB_AALG_MD5HMAC     2
+#define SADB_AALG_SHA1HMAC    3
+#define	SADB_AALG_SHA256_HMAC    5
+#define	SADB_AALG_SHA384_HMAC    6
+#define	SADB_AALG_SHA512_HMAC    7
+#define	SADB_AALG_RIPEMD160HMAC      8
+#define	SADB_AALG_MAX         15
+
+#define SADB_EALG_NONE        0
+#define SADB_EALG_DESCBC      2
+#define SADB_EALG_3DESCBC     3
+#define SADB_EALG_BFCBC	      7
+#define SADB_EALG_NULL        11
+#define SADB_EALG_AESCBC      12
+#define SADB_EALG_MAX         255
+
+#define SADB_X_CALG_NONE          0
+#define SADB_X_CALG_OUI           1
+#define SADB_X_CALG_DEFLATE       2
+#define SADB_X_CALG_LZS           3
+#define SADB_X_CALG_V42BIS        4
+#define SADB_X_CALG_MAX           4
+
+#define SADB_X_TALG_NONE          0
+#define SADB_X_TALG_IPv4_in_IPv4  1
+#define SADB_X_TALG_IPv6_in_IPv4  2
+#define SADB_X_TALG_IPv4_in_IPv6  3
+#define SADB_X_TALG_IPv6_in_IPv6  4
+#define SADB_X_TALG_MAX           4
+
+
+#define SADB_IDENTTYPE_RESERVED   0
+#define SADB_IDENTTYPE_PREFIX     1
+#define SADB_IDENTTYPE_FQDN       2
+#define SADB_IDENTTYPE_USERFQDN   3
+#define SADB_X_IDENTTYPE_CONNECTION 4
+#define SADB_IDENTTYPE_MAX        4
+
+#define SADB_KEY_FLAGS_MAX     0
+#endif /* __PFKEY_V2_H */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.4  2002/12/12 03:32:08  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.3  2002/09/05 03:53:53  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.2  2002/09/05 03:22:11  ken
+ * Applied freeswan-alg-0.8.0-BASE-common.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:20  ken
+ * 1.98b
+ *
+ * Revision 1.18  2001/11/06 19:47:47  rgb
+ * Added packet parameter to lifetime and comb structures.
+ *
+ * Revision 1.17  2001/09/08 21:13:35  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ *
+ * Revision 1.16  2001/07/06 19:49:46  rgb
+ * Added SADB_X_SAFLAGS_INFLOW for supporting incoming policy checks.
+ *
+ * Revision 1.15  2001/02/26 20:00:43  rgb
+ * Added internal IP protocol 61 for magic SAs.
+ *
+ * Revision 1.14  2001/02/08 18:51:05  rgb
+ * Include RFC document title and appendix subsection title.
+ *
+ * Revision 1.13  2000/10/10 20:10:20  rgb
+ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
+ *
+ * Revision 1.12  2000/09/15 06:41:50  rgb
+ * Added V42BIS constant.
+ *
+ * Revision 1.11  2000/09/12 22:35:37  rgb
+ * Restructured to remove unused extensions from CLEARFLOW messages.
+ *
+ * Revision 1.10  2000/09/12 18:50:09  rgb
+ * Added IPIP tunnel types as algo support.
+ *
+ * Revision 1.9  2000/08/21 16:47:19  rgb
+ * Added SADB_X_CALG_* macros for IPCOMP.
+ *
+ * Revision 1.8  2000/08/09 20:43:34  rgb
+ * Fixed bitmask value for SADB_X_SAFLAGS_CLEAREROUTE.
+ *
+ * Revision 1.7  2000/01/21 06:28:37  rgb
+ * Added flow add/delete message type macros.
+ * Added flow address extension type macros.
+ * Tidied up spacing.
+ * Added klipsdebug switching capability.
+ *
+ * Revision 1.6  1999/11/27 11:56:08  rgb
+ * Add SADB_X_SATYPE_COMP for compression, eventually.
+ *
+ * Revision 1.5  1999/11/23 22:23:16  rgb
+ * This file has been moved in the distribution from klips/net/ipsec to
+ * lib.
+ *
+ * Revision 1.4  1999/04/29 15:23:29  rgb
+ * Add GRPSA support.
+ * Add support for a second SATYPE, SA and DST_ADDRESS.
+ * Add IPPROTO_IPIP support.
+ *
+ * Revision 1.3  1999/04/15 17:58:08  rgb
+ * Add RCSID labels.
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/portof.c linux-patched/net/ipsec/libfreeswan/portof.c
--- linux/net/ipsec/libfreeswan/portof.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/portof.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,96 @@
+/*
+ * low-level ip_address ugliness
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - portof - get the port field of an ip_address
+ */
+int				/* network order */
+portof(src)
+const ip_address *src;
+{
+	switch (src->u.v4.sin_family) {
+	case AF_INET:
+		return src->u.v4.sin_port;
+		break;
+	case AF_INET6:
+		return src->u.v6.sin6_port;
+		break;
+	default:
+		return -1;	/* "can't happen" */
+		break;
+	}
+}
+
+/*
+ - setportof - set the port field of an ip_address
+ */
+void
+setportof(port, dst)
+int port;			/* network order */
+ip_address *dst;
+{
+	switch (dst->u.v4.sin_family) {
+	case AF_INET:
+		dst->u.v4.sin_port = port;
+		break;
+	case AF_INET6:
+		dst->u.v6.sin6_port = port;
+		break;
+	}
+}
+
+/*
+ - sockaddrof - get a pointer to the sockaddr hiding inside an ip_address
+ */
+struct sockaddr *
+sockaddrof(src)
+ip_address *src;
+{
+	switch (src->u.v4.sin_family) {
+	case AF_INET:
+		return (struct sockaddr *)&src->u.v4;
+		break;
+	case AF_INET6:
+		return (struct sockaddr *)&src->u.v6;
+		break;
+	default:
+		return NULL;	/* "can't happen" */
+		break;
+	}
+}
+
+/*
+ - sockaddrlenof - get length of the sockaddr hiding inside an ip_address
+ */
+size_t				/* 0 for error */
+sockaddrlenof(src)
+const ip_address *src;
+{
+	switch (src->u.v4.sin_family) {
+	case AF_INET:
+		return sizeof(src->u.v4);
+		break;
+	case AF_INET6:
+		return sizeof(src->u.v6);
+		break;
+	default:
+		return 0;
+		break;
+	}
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/prng.c linux-patched/net/ipsec/libfreeswan/prng.c
--- linux/net/ipsec/libfreeswan/prng.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/prng.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,202 @@
+/*
+ * crypto-class pseudorandom number generator
+ * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397
+ * Copyright (C) 2002  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - prng_init - initialize PRNG from a key
+ */
+void
+prng_init(prng, key, keylen)
+struct prng *prng;
+const unsigned char *key;
+size_t keylen;
+{
+	unsigned char k[256];
+	int i, j;
+	unsigned const char *p;
+	unsigned const char *keyend = key + keylen;
+	unsigned char t;
+
+	for (i = 0; i <= 255; i++)
+		prng->sbox[i] = i;
+	p = key;
+	for (i = 0; i <= 255; i++) {
+		k[i] = *p++;
+		if (p >= keyend)
+			p = key;
+	}
+	j = 0;
+	for (i = 0; i <= 255; i++) {
+		j = (j + prng->sbox[i] + k[i]) & 0xff;
+		t = prng->sbox[i];
+		prng->sbox[i] = prng->sbox[j];
+		prng->sbox[j] = t;
+		k[i] = 0;	/* clear out key memory */
+	}
+	prng->i = 0;
+	prng->j = 0;
+	prng->count = 0;
+}
+
+/*
+ - prng_bytes - get some pseudorandom bytes from PRNG
+ */
+void
+prng_bytes(prng, dst, dstlen)
+struct prng *prng;
+unsigned char *dst;
+size_t dstlen;
+{
+	int i, j, t;
+	unsigned char *p = dst;
+	size_t remain = dstlen;
+#	define	MAX	4000000000ul
+
+	while (remain > 0) {
+		i = (prng->i + 1) & 0xff;
+		prng->i = i;
+		j = (prng->j + prng->sbox[i]) & 0xff;
+		prng->j = j;
+		t = prng->sbox[i];
+		prng->sbox[i] = prng->sbox[j];
+		prng->sbox[j] = t;
+		t = (t + prng->sbox[i]) & 0xff;
+		*p++ = prng->sbox[t];
+		remain--;
+	}
+	if (prng->count < MAX - dstlen)
+		prng->count += dstlen;
+	else
+		prng->count = MAX;
+}
+
+/*
+ - prnt_count - how many bytes have been extracted from PRNG so far?
+ */
+unsigned long
+prng_count(prng)
+struct prng *prng;
+{
+	return prng->count;
+}
+
+/*
+ - prng_final - clear out PRNG to ensure nothing left in memory
+ */
+void
+prng_final(prng)
+struct prng *prng;
+{
+	int i;
+
+	for (i = 0; i <= 255; i++)
+		prng->sbox[i] = 0;
+	prng->i = 0;
+	prng->j = 0;
+	prng->count = 0;	/* just for good measure */
+}
+
+
+
+#ifdef PRNG_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	struct prng pr;
+	unsigned char buf[100];
+	unsigned char *p;
+	size_t n;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]);
+		exit(2);
+	}
+
+	if (strcmp(argv[1], "-r") == 0) {
+		regress();
+		fprintf(stderr, "regress() returned?!?\n");
+		exit(1);
+	}
+
+	prng_init(&pr, argv[1], strlen(argv[1]));
+	prng_bytes(&pr, buf, 32);
+	printf("0x");
+	for (p = buf, n = 32; n > 0; p++, n--)
+		printf("%02x", *p);
+	printf("\n%lu bytes\n", prng_count(&pr));
+	prng_final(&pr);
+	exit(0);
+}
+
+void
+regress()
+{
+	struct prng pr;
+	unsigned char buf[100];
+	unsigned char *p;
+	size_t n;
+	/* somewhat non-random sample key */
+	unsigned char key[] = "here we go gathering nuts in May";
+	/* first thirty bytes of output from that key */
+	unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c"
+				"\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71"
+				"\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28";
+	int nzero, none;
+	int show = 0;
+
+	prng_init(&pr, key, strlen(key));
+	prng_bytes(&pr, buf, sizeof(buf));
+	for (p = buf, n = sizeof(buf); n > 0; p++, n--) {
+		if (*p == 0)
+			nzero++;
+		if (*p == 255)
+			none++;
+	}
+	if (nzero > 3 || none > 3) {
+		fprintf(stderr, "suspiciously non-random output!\n");
+		show = 1;
+	}
+	if (memcmp(buf, good, strlen(good)) != 0) {
+		fprintf(stderr, "incorrect output!\n");
+		show = 1;
+	}
+	if (show) {
+		fprintf(stderr, "0x");
+		for (p = buf, n = sizeof(buf); n > 0; p++, n--)
+			fprintf(stderr, "%02x", *p);
+		fprintf(stderr, "\n");
+		exit(1);
+	}
+	if (prng_count(&pr) != sizeof(buf)) {
+		fprintf(stderr, "got %u bytes, but count is %lu\n",
+					sizeof(buf), prng_count(&pr));
+		exit(1);
+	}
+	prng_final(&pr);
+	exit(0);
+}
+
+#endif /* PRNG_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/rangetoa.c linux-patched/net/ipsec/libfreeswan/rangetoa.c
--- linux/net/ipsec/libfreeswan/rangetoa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/rangetoa.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,61 @@
+/*
+ * convert binary form of address range to ASCII
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - rangetoa - convert address range to ASCII
+ */
+size_t				/* space needed for full conversion */
+rangetoa(addrs, format, dst, dstlen)
+struct in_addr addrs[2];
+int format;			/* character */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	size_t len;
+	size_t rest;
+	int n;
+	char *p;
+
+	switch (format) {
+	case 0:
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	len = addrtoa(addrs[0], 0, dst, dstlen);
+	if (len < dstlen)
+		for (p = dst + len - 1, n = 3; len < dstlen && n > 0;
+								p++, len++, n--)
+			*p = '.';
+	else
+		p = NULL;
+	if (len < dstlen)
+		rest = dstlen - len;
+	else {
+		if (dstlen > 0)
+			*(dst + dstlen - 1) = '\0';
+		rest = 0;
+	}
+
+	len += addrtoa(addrs[1], 0, p, rest);
+
+	return len;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/rangetosubnet.c linux-patched/net/ipsec/libfreeswan/rangetosubnet.c
--- linux/net/ipsec/libfreeswan/rangetosubnet.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/rangetosubnet.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,228 @@
+/*
+ * express an address range as a subnet (if possible)
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - rangetosubnet - turn an address range into a subnet, if possible
+ *
+ * A range which is a valid subnet will have a network part which is the
+ * same in the from value and the to value, followed by a host part which
+ * is all 0 in the from value and all 1 in the to value.
+ */
+err_t
+rangetosubnet(from, to, dst)
+const ip_address *from;
+const ip_address *to;
+ip_subnet *dst;
+{
+	unsigned const char *fp;
+	unsigned const char *tp;
+	unsigned fb;
+	unsigned tb;
+	unsigned const char *f;
+	unsigned const char *t;
+	size_t n;
+	size_t n2;
+	int i;
+	int nnet;
+	unsigned m;
+
+	if (addrtypeof(from) != addrtypeof(to))
+		return "mismatched address types";
+	n = addrbytesptr(from, &fp);
+	if (n == 0)
+		return "unknown address type";
+	n2 = addrbytesptr(to, &tp);
+	if (n != n2)
+		return "internal size mismatch in rangetosubnet";
+
+	f = fp;
+	t = tp;
+	nnet = 0;
+	for (i = n; i > 0 && *f == *t; i--, f++, t++)
+		nnet += 8;
+	if (i > 0 && !(*f == 0x00 && *t == 0xff)) {	/* mid-byte bdry. */
+		fb = *f++;
+		tb = *t++;
+		i--;
+		m = 0x80;
+		while ((fb&m) == (tb&m)) {
+			fb &= ~m;
+			tb |= m;
+			m >>= 1;
+			nnet++;
+		}
+		if (fb != 0x00 || tb != 0xff)
+			return "not a valid subnet";
+	}
+	for (; i > 0 && *f == 0x00 && *t == 0xff; i--, f++, t++)
+		continue;
+
+	if (i != 0)
+		return "invalid subnet";
+
+	return initsubnet(from, nnet, 'x', dst);
+}
+
+
+
+#ifdef RANGETOSUBNET_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	ip_address start;
+	ip_address stop;
+	ip_subnet sub;
+	char buf[100];
+	const char *oops;
+	size_t n;
+	int af;
+	int i;
+
+	if (argc == 2 && strcmp(argv[1], "-r") == 0) {
+		regress();
+		fprintf(stderr, "regress() returned?!?\n");
+		exit(1);
+	}
+
+	if (argc < 3) {
+		fprintf(stderr, "Usage: %s [-6] start stop\n", argv[0]);
+		fprintf(stderr, "   or: %s -r\n", argv[0]);
+		exit(2);
+	}
+
+	af = AF_INET;
+	i = 1;
+	if (strcmp(argv[i], "-6") == 0) {
+		af = AF_INET6;
+		i++;
+	}
+
+	oops = ttoaddr(argv[i], 0, af, &start);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: start conversion failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	oops = ttoaddr(argv[i+1], 0, af, &stop);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: stop conversion failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	oops = rangetosubnet(&start, &stop, &sub);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: rangetosubnet failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	n = subnettot(&sub, 0, buf, sizeof(buf));
+	if (n > sizeof(buf)) {
+		fprintf(stderr, "%s: reverse conversion", argv[0]);
+		fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+						(long)n, (long)sizeof(buf));
+		exit(1);
+	}
+	printf("%s\n", buf);
+
+	exit(0);
+}
+
+struct rtab {
+	int family;
+	char *start;
+	char *stop;
+	char *output;			/* NULL means error expected */
+} rtab[] = {
+	4, "1.2.3.0",		"1.2.3.255",		"1.2.3.0/24",
+	4, "1.2.3.0",		"1.2.3.7",		"1.2.3.0/29",
+	4, "1.2.3.240",		"1.2.3.255",		"1.2.3.240/28",
+	4, "0.0.0.0",		"255.255.255.255",	"0.0.0.0/0",
+	4, "1.2.3.4",		"1.2.3.4",		"1.2.3.4/32",
+	4, "1.2.3.0",		"1.2.3.254",		NULL,
+	4, "1.2.3.0",		"1.2.3.126",		NULL,
+	4, "1.2.3.0",		"1.2.3.125",		NULL,
+	4, "1.2.0.0",		"1.2.255.255",		"1.2.0.0/16",
+	4, "1.2.0.0",		"1.2.0.255",		"1.2.0.0/24",
+	4, "1.2.255.0",		"1.2.255.255",		"1.2.255.0/24",
+	4, "1.2.255.0",		"1.2.254.255",		NULL,
+	4, "1.2.255.1",		"1.2.255.255",		NULL,
+	4, "1.2.0.1",		"1.2.255.255",		NULL,
+	6, "1:2:3:4:5:6:7:0",	"1:2:3:4:5:6:7:ffff",	"1:2:3:4:5:6:7:0/112",
+	6, "1:2:3:4:5:6:7:0",	"1:2:3:4:5:6:7:fff",	"1:2:3:4:5:6:7:0/116",
+	6, "1:2:3:4:5:6:7:f0",	"1:2:3:4:5:6:7:ff",	"1:2:3:4:5:6:7:f0/124",
+	4, NULL,		NULL,			NULL,
+};
+
+void
+regress()
+{
+	struct rtab *r;
+	int status = 0;
+	ip_address start;
+	ip_address stop;
+	ip_subnet sub;
+	char buf[100];
+	const char *oops;
+	size_t n;
+	int af;
+
+	for (r = rtab; r->start != NULL; r++) {
+		af = (r->family == 4) ? AF_INET : AF_INET6;
+		oops = ttoaddr(r->start, 0, af, &start);
+		if (oops != NULL) {
+			printf("surprise failure converting `%s'\n", r->start);
+			exit(1);
+		}
+		oops = ttoaddr(r->stop, 0, af, &stop);
+		if (oops != NULL) {
+			printf("surprise failure converting `%s'\n", r->stop);
+			exit(1);
+		}
+		oops = rangetosubnet(&start, &stop, &sub);
+		if (oops != NULL && r->output == NULL)
+			{}		/* okay, error expected */
+		else if (oops != NULL) {
+			printf("`%s'-`%s' rangetosubnet failed: %s\n",
+						r->start, r->stop, oops);
+			status = 1;
+		} else if (r->output == NULL) {
+			printf("`%s'-`%s' rangetosubnet succeeded unexpectedly\n",
+							r->start, r->stop);
+			status = 1;
+		} else {
+			n = subnettot(&sub, 0, buf, sizeof(buf));
+			if (n > sizeof(buf)) {
+				printf("`%s'-`%s' subnettot failed:  need %ld\n",
+						r->start, r->stop, (long)n);
+				status = 1;
+			} else if (strcmp(r->output, buf) != 0) {
+				printf("`%s'-`%s' gave `%s', expected `%s'\n",
+					r->start, r->stop, buf, r->output);
+				status = 1;
+			}
+		}
+	}
+	exit(status);
+}
+
+#endif /* RANGETOSUBNET_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/sameaddr.c linux-patched/net/ipsec/libfreeswan/sameaddr.c
--- linux/net/ipsec/libfreeswan/sameaddr.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/sameaddr.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,190 @@
+/*
+ * comparisons
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static int samenbits(const ip_address *a, const ip_address *b, int n);
+
+/*
+ - addrcmp - compare two addresses
+ * Caution, the order of the tests is subtle:  doing type test before
+ * size test can yield cases where a<b, b<c, but a>c.
+ */
+int				/* like memcmp */
+addrcmp(a, b)
+const ip_address *a;
+const ip_address *b;
+{
+	int at = addrtypeof(a);
+	int bt = addrtypeof(b);
+	const unsigned char *ap;
+	const unsigned char *bp;
+	size_t as = addrbytesptr(a, &ap);
+	size_t bs = addrbytesptr(b, &bp);
+	size_t n = (as < bs) ? as : bs;		/* min(as, bs) */
+	int c = memcmp(ap, bp, n);
+
+	if (c != 0)		/* bytes differ */
+		return (c < 0) ? -1 : 1;
+	if (as != bs)		/* comparison incomplete:  lexical order */
+		return (as < bs) ? -1 : 1;
+	if (at != bt)		/* bytes same but not same type:  break tie */
+		return (at < bt) ? -1 : 1;
+	return 0;
+}
+
+/*
+ - sameaddr - are two addresses the same?
+ */
+int
+sameaddr(a, b)
+const ip_address *a;
+const ip_address *b;
+{
+	return (addrcmp(a, b) == 0) ? 1 : 0;
+}
+
+/*
+ - samesubnet - are two subnets the same?
+ */
+int
+samesubnet(a, b)
+const ip_subnet *a;
+const ip_subnet *b;
+{
+	if (!sameaddr(&a->addr, &b->addr))	/* also does type check */
+		return 0;
+	if (a->maskbits != b->maskbits)
+		return 0;
+	return 1;
+}
+
+/*
+ - subnetishost - is a subnet in fact a single host?
+ */
+int
+subnetishost(a)
+const ip_subnet *a;
+{
+	return (a->maskbits == addrlenof(&a->addr)*8) ? 1 : 0;
+}
+
+/*
+ - samesaid - are two SA IDs the same?
+ */
+int
+samesaid(a, b)
+const ip_said *a;
+const ip_said *b;
+{
+	if (a->spi != b->spi)	/* test first, most likely to be different */
+		return 0;
+	if (!sameaddr(&a->dst, &b->dst))
+		return 0;
+	if (a->proto != b->proto)
+		return 0;
+	return 1;
+}
+
+/*
+ - sameaddrtype - do two addresses have the same type?
+ */
+int
+sameaddrtype(a, b)
+const ip_address *a;
+const ip_address *b;
+{
+	return (addrtypeof(a) == addrtypeof(b)) ? 1 : 0;
+}
+
+/*
+ - samesubnettype - do two subnets have the same type?
+ */
+int
+samesubnettype(a, b)
+const ip_subnet *a;
+const ip_subnet *b;
+{
+	return (subnettypeof(a) == subnettypeof(b)) ? 1 : 0;
+}
+
+/*
+ - addrinsubnet - is this address in this subnet?
+ */
+int
+addrinsubnet(a, s)
+const ip_address *a;
+const ip_subnet *s;
+{
+	if (addrtypeof(a) != subnettypeof(s))
+		return 0;
+	if (!samenbits(a, &s->addr, s->maskbits))
+		return 0;
+	return 1;
+}
+
+/*
+ - subnetinsubnet - is one subnet within another?
+ */
+int
+subnetinsubnet(a, b)
+const ip_subnet *a;
+const ip_subnet *b;
+{
+	if (subnettypeof(a) != subnettypeof(b))
+		return 0;
+	if (a->maskbits < b->maskbits)	/* a is bigger than b */
+		return 0;
+	if (!samenbits(&a->addr, &b->addr, b->maskbits))
+		return 0;
+	return 1;
+}
+
+/*
+ - samenbits - do two addresses have the same first n bits?
+ */
+static int
+samenbits(a, b, nbits)
+const ip_address *a;
+const ip_address *b;
+int nbits;
+{
+	const unsigned char *ap;
+	const unsigned char *bp;
+	size_t n;
+	int m;
+
+	if (addrtypeof(a) != addrtypeof(b))
+		return 0;	/* arbitrary */
+	n = addrbytesptr(a, &ap);
+	if (n == 0)
+		return 0;	/* arbitrary */
+	(void) addrbytesptr(b, &bp);
+	if (nbits > n*8)
+		return 0;	/* "can't happen" */
+
+	for (; nbits >= 8 && *ap == *bp; nbits -= 8, ap++, bp++)
+		continue;
+	if (nbits >= 8)
+		return 0;
+	if (nbits > 0) {	/* partial byte */
+		m = ~(0xff >> nbits);
+		if ((*ap & m) != (*bp & m))
+			return 0;
+	}
+	return 1;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/satoa.c linux-patched/net/ipsec/libfreeswan/satoa.c
--- linux/net/ipsec/libfreeswan/satoa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/satoa.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,102 @@
+/*
+ * convert from binary form of SA ID to ASCII
+ * Copyright (C) 1998, 1999, 2001  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct typename {
+	char type;
+	char *name;
+} typenames[] = {
+	{ SA_AH,	"ah" },
+	{ SA_ESP,	"esp" },
+	{ SA_IPIP,	"tun" },
+	{ SA_COMP,	"comp" },
+	{ SA_INT,	"int" },
+	{ 0,		NULL }
+};
+
+/*
+ - satoa - convert SA to ASCII "ah507@1.2.3.4"
+ */
+size_t				/* space needed for full conversion */
+satoa(sa, format, dst, dstlen)
+struct sa_id sa;
+int format;			/* character */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	size_t len = 0;		/* 0 means not handled yet */
+	int base;
+	struct typename *tn;
+	char buf[30+ADDRTOA_BUF];
+
+	switch (format) {
+	case 0:
+		base = 16;	/* temporarily at least */
+		break;
+	case 'd':
+		base = 10;
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	for (tn = typenames; tn->name != NULL; tn++)
+		if (sa.proto == tn->type)
+			break;
+	if (tn->name == NULL)
+		return 0;
+
+	if (strcmp(tn->name, PASSTHROUGHTYPE) == 0 &&
+					sa.spi == PASSTHROUGHSPI &&
+					sa.dst.s_addr == PASSTHROUGHDST) {
+		strcpy(buf, PASSTHROUGHNAME);
+		len = strlen(buf);
+	} else if (sa.proto == SA_INT && sa.dst.s_addr == 0) {
+		char *p;
+
+		switch (ntohl(sa.spi)) {
+		case SPI_PASS:	p = "%pass";	break;
+		case SPI_DROP:	p = "%drop";	break;
+		case SPI_REJECT:	p = "%reject";	break;
+		case SPI_HOLD:	p = "%hold";	break;
+		case SPI_TRAP:	p = "%trap";	break;
+		case SPI_TRAPSUBNET:	p = "%trapsubnet";	break;
+		default:	p = NULL;	break;
+		}
+		if (p != NULL) {
+			strcpy(buf, p);
+			len = strlen(buf);
+		}
+	}
+
+	if (len == 0) {
+		strcpy(buf, tn->name);
+		len = strlen(buf);
+		len += ultoa(ntohl(sa.spi), base, buf+len, sizeof(buf)-len);
+		*(buf+len-1) = '@';
+		len += addrtoa(sa.dst, 0, buf+len, sizeof(buf)-len);
+	}
+
+	if (dst != NULL) {
+		if (len > dstlen)
+			*(buf+dstlen-1) = '\0';
+		strcpy(dst, buf);
+	}
+	return len;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/satot.c linux-patched/net/ipsec/libfreeswan/satot.c
--- linux/net/ipsec/libfreeswan/satot.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/satot.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,132 @@
+/*
+ * convert from binary form of SA ID to text
+ * Copyright (C) 2000, 2001  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct typename {
+	char type;
+	char *name;
+} typenames[] = {
+	{ SA_AH,	"ah" },
+	{ SA_ESP,	"esp" },
+	{ SA_IPIP,	"tun" },
+	{ SA_COMP,	"comp" },
+	{ SA_INT,	"int" },
+	{ 0,		NULL }
+};
+
+/*
+ - satot - convert SA to text "ah507@1.2.3.4"
+ */
+size_t				/* space needed for full conversion */
+satot(sa, format, dst, dstlen)
+const ip_said *sa;
+int format;			/* character */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	size_t len = 0;		/* 0 means "not recognized yet" */
+	int base;
+	int showversion;	/* use delimiter to show IP version? */
+	struct typename *tn;
+	char *p;
+	char *pre;
+	char buf[10+1+ULTOT_BUF+ADDRTOT_BUF];
+	char unk[10];
+
+	switch (format) {
+	case 0:
+		base = 16;
+		showversion = 1;
+		break;
+	case 'f':
+		base = 17;
+		showversion = 1;
+		break;
+	case 'x':
+		base = 'x';
+		showversion = 0;
+		break;
+	case 'd':
+		base = 10;
+		showversion = 0;
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	pre = NULL;
+	for (tn = typenames; tn->name != NULL; tn++)
+		if (sa->proto == tn->type) {
+			pre = tn->name;
+			break;			/* NOTE BREAK OUT */
+		}
+	if (pre == NULL) {		/* unknown protocol */
+		strcpy(unk, "unk");
+		(void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk),
+						sizeof(unk)-strlen(unk));
+		pre = unk;
+	}
+
+	if (strcmp(pre, PASSTHROUGHTYPE) == 0 &&
+					sa->spi == PASSTHROUGHSPI &&
+					isunspecaddr(&sa->dst)) {
+		strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ?
+							PASSTHROUGH4NAME :
+							PASSTHROUGH6NAME);
+		len = strlen(buf);
+	}
+	
+	if (sa->proto == SA_INT && addrtypeof(&sa->dst) == AF_INET &&
+						isunspecaddr(&sa->dst)) {
+		switch (ntohl(sa->spi)) {
+		case SPI_PASS:	p = "%pass";	break;
+		case SPI_DROP:	p = "%drop";	break;
+		case SPI_REJECT:	p = "%reject";	break;
+		case SPI_HOLD:	p = "%hold";	break;
+		case SPI_TRAP:	p = "%trap";	break;
+		case SPI_TRAPSUBNET:	p = "%trapsubnet";	break;
+		default:	p = NULL;	break;
+		}
+		if (p != NULL) {
+			strcpy(buf, p);
+			len = strlen(buf);
+		}
+	}
+
+	if (len == 0) {			/* general case needed */
+		strcpy(buf, pre);
+		len = strlen(buf);
+		if (showversion) {
+			*(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' :
+									':';
+			len++;
+			*(buf+len) = '\0';
+		}
+		len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len);
+		*(buf+len-1) = '@';
+		len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len);
+	}
+
+	if (dst != NULL) {
+		if (len > dstlen)
+			*(buf+dstlen-1) = '\0';
+		strcpy(dst, buf);
+	}
+	return len;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/subnetof.c linux-patched/net/ipsec/libfreeswan/subnetof.c
--- linux/net/ipsec/libfreeswan/subnetof.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/subnetof.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,60 @@
+/*
+ * minor network-address manipulation utilities
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnetof - given address and mask, return subnet part
+ */
+struct in_addr
+subnetof(addr, mask)
+struct in_addr addr;
+struct in_addr mask;
+{
+	struct in_addr result;
+
+	result.s_addr = addr.s_addr & mask.s_addr;
+	return result;
+}
+
+/*
+ - hostof - given address and mask, return host part
+ */
+struct in_addr
+hostof(addr, mask)
+struct in_addr addr;
+struct in_addr mask;
+{
+	struct in_addr result;
+
+	result.s_addr = addr.s_addr & ~mask.s_addr;
+	return result;
+}
+
+/*
+ - broadcastof - given (network) address and mask, return broadcast address
+ */
+struct in_addr
+broadcastof(addr, mask)
+struct in_addr addr;
+struct in_addr mask;
+{
+	struct in_addr result;
+
+	result.s_addr = addr.s_addr | ~mask.s_addr;
+	return result;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/subnettoa.c linux-patched/net/ipsec/libfreeswan/subnettoa.c
--- linux/net/ipsec/libfreeswan/subnettoa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/subnettoa.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,62 @@
+/*
+ * convert binary form of subnet description to ASCII
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnettoa - convert address and mask to ASCII "addr/mask"
+ * Output expresses the mask as a bit count if possible, else dotted decimal.
+ */
+size_t				/* space needed for full conversion */
+subnettoa(addr, mask, format, dst, dstlen)
+struct in_addr addr;
+struct in_addr mask;
+int format;			/* character */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	size_t len;
+	size_t rest;
+	int n;
+	char *p;
+
+	switch (format) {
+	case 0:
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	len = addrtoa(addr, 0, dst, dstlen);
+	if (len < dstlen) {
+		dst[len - 1] = '/';
+		p = dst + len;
+		rest = dstlen - len;
+	} else {
+		p = NULL;
+		rest = 0;
+	}
+
+	n = masktobits(mask);
+	if (n >= 0)
+		len += ultoa((unsigned long)n, 10, p, rest);
+	else
+		len += addrtoa(mask, 0, p, rest);
+
+	return len;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/subnettot.c linux-patched/net/ipsec/libfreeswan/subnettot.c
--- linux/net/ipsec/libfreeswan/subnettot.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/subnettot.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,56 @@
+/*
+ * convert binary form of subnet description to text
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnettot - convert subnet to text "addr/bitcount"
+ */
+size_t				/* space needed for full conversion */
+subnettot(sub, format, dst, dstlen)
+const ip_subnet *sub;
+int format;			/* character */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	size_t len;
+	size_t rest;
+	char *p;
+
+	switch (format) {
+	case 0:
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	len = addrtot(&sub->addr, format, dst, dstlen);
+	if (len < dstlen) {
+		dst[len - 1] = '/';
+		p = dst + len;
+		rest = dstlen - len;
+	} else {
+		p = NULL;
+		rest = 0;
+	}
+
+
+	len += ultoa((unsigned long)sub->maskbits, 10, p, rest);
+
+	return len;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/subnettypeof.c linux-patched/net/ipsec/libfreeswan/subnettypeof.c
--- linux/net/ipsec/libfreeswan/subnettypeof.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/subnettypeof.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,109 @@
+/*
+ * extract parts of an ip_subnet, and related
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - subnettypeof - get the address type of an ip_subnet
+ */
+int
+subnettypeof(src)
+const ip_subnet *src;
+{
+	return src->addr.u.v4.sin_family;
+}
+
+/*
+ - networkof - get the network address of a subnet
+ */
+void
+networkof(src, dst)
+const ip_subnet *src;
+ip_address *dst;
+{
+	*dst = src->addr;
+}
+
+/*
+ - maskof - get the mask of a subnet, as an address
+ */
+void
+maskof(src, dst)
+const ip_subnet *src;
+ip_address *dst;
+{
+	int b;
+	unsigned char buf[16];
+	size_t n = addrlenof(&src->addr);
+	unsigned char *p;
+
+	if (src->maskbits > n*8 || n > sizeof(buf))
+		return;		/* "can't happen" */
+
+	p = buf;
+	for (b = src->maskbits; b >= 8; b -= 8)
+		*p++ = 0xff;
+	if (b != 0)
+		*p++ = (0xff << (8 - b)) & 0xff;
+	while (p - buf < n)
+		*p++ = 0;
+
+	(void) initaddr(buf, n, addrtypeof(&src->addr), dst);
+}
+
+/*
+ - masktocount - convert a mask, expressed as an address, to a bit count
+ */
+int				/* -1 if not valid mask */
+masktocount(src)
+const ip_address *src;
+{
+	int b;
+	unsigned const char *bp;
+	size_t n;
+	unsigned const char *p;
+	unsigned const char *stop;
+
+	n = addrbytesptr(src, &bp);
+	if (n == 0)
+		return -1;
+
+	p = bp;
+	stop = bp + n;
+
+	n = 0;
+	while (p < stop && *p == 0xff) {
+		p++;
+		n += 8;
+	}
+	if (p < stop && *p != 0) {	/* boundary in mid-byte */
+		b = *p++;
+		while (b&0x80) {
+			b <<= 1;
+			n++;
+		}
+		if ((b&0xff) != 0)
+			return -1;	/* bits not contiguous */
+	}
+	while (p < stop && *p == 0)
+		p++;
+
+	if (p != stop)
+		return -1;
+
+	return n;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ttoaddr.c linux-patched/net/ipsec/libfreeswan/ttoaddr.c
--- linux/net/ipsec/libfreeswan/ttoaddr.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ttoaddr.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,405 @@
+/*
+ * conversion from text forms of addresses to internal ones
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ * Legal ASCII characters in a domain name.  Underscore technically is not,
+ * but is a common misunderstanding.  Non-ASCII characters are simply
+ * exempted from checking at the moment, to allow for UTF-8 encoded stuff;
+ * the purpose of this check is merely to catch blatant errors.
+ */
+static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
+				"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
+#define	ISASCII(c)	(((c) & 0x80) == 0)
+
+static err_t tryname(const char *, size_t, int, int, ip_address *);
+static err_t tryhex(const char *, size_t, int, ip_address *);
+static err_t trydotted(const char *, size_t, ip_address *);
+static err_t getbyte(const char **, const char *, int *);
+static err_t colon(const char *, size_t, ip_address *);
+static err_t getpiece(const char **, const char *, unsigned *);
+
+/*
+ - ttoaddr - convert text name or dotted-decimal address to binary address
+ */
+err_t				/* NULL for success, else string literal */
+ttoaddr(src, srclen, af, dst)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+int af;				/* address family */
+ip_address *dst;
+{
+	err_t oops;
+#	define	HEXLEN	10	/* strlen("0x11223344") */
+	int nultermd;
+
+	if (srclen == 0) {
+		srclen = strlen(src);
+		if (srclen == 0)
+			return "empty string";
+		nultermd = 1;
+	} else
+		nultermd = 0;	/* at least, not *known* to be terminated */
+
+	switch (af) {
+	case AF_INET:
+	case AF_INET6:
+		break;
+	default:
+		return "invalid address family";
+	}
+
+	if (af == AF_INET && srclen == HEXLEN && *src == '0') {
+		if (*(src+1) == 'x' || *(src+1) == 'X')
+			return tryhex(src+2, srclen-2, 'x', dst);
+		if (*(src+1) == 'h' || *(src+1) == 'H')
+			return tryhex(src+2, srclen-2, 'h', dst);
+	}
+
+	if (memchr(src, ':', srclen) != NULL) {
+		if (af != AF_INET6)
+			return "non-ipv6 address may not contain `:'";
+		return colon(src, srclen, dst);
+	}
+
+	if (af == AF_INET) {
+		oops = trydotted(src, srclen, dst);
+		if (oops == NULL)
+			return NULL;		/* it worked */
+		if (*oops != '?')
+			return oops;		/* probably meant as d-d */
+	}
+
+	return tryname(src, srclen, nultermd, af, dst);
+}
+
+/*
+ - tnatoaddr - convert text numeric address (only) to binary address
+ */
+err_t				/* NULL for success, else string literal */
+tnatoaddr(src, srclen, af, dst)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+int af;				/* address family */
+ip_address *dst;
+{
+	err_t oops;
+
+	if (srclen == 0) {
+		srclen = strlen(src);
+		if (srclen == 0)
+			return "empty string";
+	}
+
+	switch (af) {
+	case AF_INET6:
+		return colon(src, srclen, dst);
+		break;
+	case AF_INET:
+		oops = trydotted(src, srclen, dst);
+		if (oops == NULL)
+			return NULL;		/* it worked */
+		if (*oops != '?')
+			return oops;		/* probably meant as d-d */
+		return "does not appear to be numeric address";
+		break;
+	default:
+		return "unknown address family in tnatoaddr";
+		break;
+	}
+}
+
+/*
+ - tryname - try it as a name
+ * Slightly complicated by lack of reliable NUL termination in source.
+ */
+static err_t
+tryname(src, srclen, nultermd, af, dst)
+const char *src;
+size_t srclen;
+int nultermd;			/* is it known to be NUL-terminated? */
+int af;
+ip_address *dst;
+{
+	struct hostent *h;
+	struct netent *ne = NULL;
+	char namebuf[100];	/* enough for most DNS names */
+	const char *cp;
+	char *p = namebuf;
+	size_t n;
+
+	for (cp = src, n = srclen; n > 0; cp++, n--)
+		if (ISASCII(*cp) && strchr(namechars, *cp) == NULL)
+			return "illegal (non-DNS-name) character in name";
+
+	if (nultermd)
+		cp = src;
+	else {
+		if (srclen+1 > sizeof(namebuf)) {
+			p = (char *) MALLOC(srclen+1);
+			if (p == NULL)
+				return "unable to get temporary space for name";
+		}
+		p[0] = '\0';	/* strncpy semantics are wrong */
+		strncat(p, src, srclen);
+		cp = (const char *)p;
+	}
+
+	h = gethostbyname2(cp, af);
+	if (h == NULL && af == AF_INET)
+		ne = getnetbyname(cp);
+	if (p != namebuf)
+		FREE(p);
+	if (h == NULL && ne == NULL)
+		return "does not look numeric and name lookup failed";
+
+	if (h != NULL) {
+		if (h->h_addrtype != af)
+			return "address-type mismatch from gethostbyname2!!!";
+		return initaddr((unsigned char *)h->h_addr, h->h_length, af, dst);
+	} else {
+		if (ne->n_addrtype != af)
+			return "address-type mismatch from getnetbyname!!!";
+		ne->n_net = htonl(ne->n_net);
+		return initaddr((unsigned char *)&ne->n_net, sizeof(ne->n_net),
+								af, dst);
+	}
+}
+
+/*
+ - tryhex - try conversion as an eight-digit hex number (AF_INET only)
+ */
+static err_t
+tryhex(src, srclen, flavor, dst)
+const char *src;
+size_t srclen;			/* should be 8 */
+int flavor;			/* 'x' for network order, 'h' for host order */
+ip_address *dst;
+{
+	err_t oops;
+	unsigned long ul;
+	union {
+		uint32_t addr;
+		unsigned char buf[4];
+	} u;
+
+	if (srclen != 8)
+		return "internal error, tryhex called with bad length";
+
+	oops = ttoul(src, srclen, 16, &ul);
+	if (oops != NULL)
+		return oops;
+
+	u.addr = (flavor == 'h') ? ul : htonl(ul);
+	return initaddr(u.buf, sizeof(u.buf), AF_INET, dst);
+}
+
+/*
+ - trydotted - try conversion as dotted decimal (AF_INET only)
+ *
+ * If the first char of a complaint is '?', that means "didn't look like
+ * dotted decimal at all".
+ */
+static err_t
+trydotted(src, srclen, dst)
+const char *src;
+size_t srclen;
+ip_address *dst;
+{
+	const char *stop = src + srclen;	/* just past end */
+	int byte;
+	err_t oops;
+#	define	NBYTES	4
+	unsigned char buf[NBYTES];
+	int i;
+
+	memset(buf, 0, sizeof(buf));
+	for (i = 0; i < NBYTES && src < stop; i++) {
+		oops = getbyte(&src, stop, &byte);
+		if (oops != NULL) {
+			if (*oops != '?')
+				return oops;	/* bad number */
+			if (i > 1)
+				return oops+1;	/* failed number */
+			return oops;		/* with leading '?' */
+		}
+		buf[i] = byte;
+		if (i < 3 && src < stop && *src++ != '.') {
+			if (i == 0)
+				return "?syntax error in dotted-decimal address";
+			else
+				return "syntax error in dotted-decimal address";
+		}
+	}
+	if (src != stop)
+		return "extra garbage on end of dotted-decimal address";
+
+	return initaddr(buf, sizeof(buf), AF_INET, dst);
+}
+
+/*
+ - getbyte - try to scan a byte in dotted decimal
+ * A subtlety here is that all this arithmetic on ASCII digits really is
+ * highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
+ * It's easier to just do it ourselves than set up for a call to ttoul().
+ *
+ * If the first char of a complaint is '?', that means "didn't look like a
+ * number at all".
+ */
+err_t
+getbyte(srcp, stop, retp)
+const char **srcp;		/* *srcp is updated */
+const char *stop;		/* first untouchable char */
+int *retp;			/* return-value pointer */
+{
+	char c;
+	const char *p;
+	int no;
+
+	if (*srcp >= stop)
+		return "?empty number in dotted-decimal address";
+
+	no = 0;
+	p = *srcp;
+	while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
+		no = no*10 + (c - '0');
+		p++;
+	}
+	if (p == *srcp)
+		return "?non-numeric component in dotted-decimal address";
+	*srcp = p;
+	if (no > 255)
+		return "byte overflow in dotted-decimal address";
+	*retp = no;
+	return NULL;
+}
+
+/*
+ - colon - convert IPv6 "numeric" address
+ */
+static err_t
+colon(src, srclen, dst)
+const char *src;
+size_t srclen;			/* known to be >0 */
+ip_address *dst;
+{
+	const char *stop = src + srclen;	/* just past end */
+	unsigned piece;
+	int gapat;		/* where was empty piece seen */
+	err_t oops;
+#	define	NPIECES	8
+	unsigned char buf[NPIECES*2];	/* short may have wrong byte order */
+	int i;
+	int j;
+#	define	IT	"IPv6 numeric address"
+	int naftergap;
+
+	/* leading or trailing :: becomes single empty field */
+	if (*src == ':') {		/* legal only if leading :: */
+		if (srclen == 1 || *(src+1) != ':')
+			return "illegal leading `:' in " IT;
+		if (srclen == 2) {
+			unspecaddr(AF_INET6, dst);
+			return NULL;
+		}
+		src++;		/* past first but not second */
+		srclen--;
+	}
+	if (*(stop-1) == ':') {		/* legal only if trailing :: */
+		if (srclen == 1 || *(stop-2) != ':')
+			return "illegal trailing `:' in " IT;
+		srclen--;		/* leave one */
+	}
+
+	gapat = -1;
+	for (i = 0; i < NPIECES && src < stop; i++) {
+		oops = getpiece(&src, stop, &piece);
+		if (oops != NULL && *oops == ':') {	/* empty field */
+			if (gapat >= 0)
+				return "more than one :: in " IT;
+			gapat = i;
+		} else if (oops != NULL)
+			return oops;
+		buf[2*i] = piece >> 8;
+		buf[2*i + 1] = piece & 0xff;
+		if (i < NPIECES-1) {	/* there should be more input */
+			if (src == stop && gapat < 0)
+				return IT " ends prematurely";
+			if (src != stop && *src++ != ':')
+				return "syntax error in " IT;
+		}
+	}
+	if (src != stop)
+		return "extra garbage on end of " IT;
+
+	if (gapat < 0 && i < NPIECES)	/* should have been caught earlier */
+		return "incomplete " IT " (internal error)";
+	if (gapat >= 0 && i == NPIECES)
+		return "non-abbreviating empty field in " IT;
+	if (gapat >= 0) {
+		naftergap = i - (gapat + 1);
+		for (i--, j = NPIECES-1; naftergap > 0; i--, j--, naftergap--) {
+			buf[2*j] = buf[2*i];
+			buf[2*j + 1] = buf[2*i + 1];
+		}
+		for (; j >= gapat; j--)
+			buf[2*j] = buf[2*j + 1] = 0;
+	}
+
+	return initaddr(buf, sizeof(buf), AF_INET6, dst);
+}
+
+/*
+ - getpiece - try to scan one 16-bit piece of an IPv6 address
+ */
+err_t				/* ":" means "empty field seen" */
+getpiece(srcp, stop, retp)
+const char **srcp;		/* *srcp is updated */
+const char *stop;		/* first untouchable char */
+unsigned *retp;			/* return-value pointer */
+{
+	const char *p;
+#	define	NDIG	4
+	int d;
+	unsigned long ret;
+	err_t oops;
+
+	if (*srcp >= stop || **srcp == ':') {	/* empty field */
+		*retp = 0;
+		return ":";
+	}
+
+	p = *srcp;
+	d = 0;
+	while (p < stop && d < NDIG && isxdigit(*p)) {
+		p++;
+		d++;
+	}
+	if (d == 0)
+		return "non-hex field in IPv6 numeric address";
+	if (p < stop && d == NDIG && isxdigit(*p))
+		return "field in IPv6 numeric address longer than 4 hex digits";
+
+	oops = ttoul(*srcp, d, 16, &ret);
+	if (oops != NULL)	/* shouldn't happen, really... */
+		return oops;
+
+	*srcp = p;
+	*retp = ret;
+	return NULL;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ttodata.c linux-patched/net/ipsec/libfreeswan/ttodata.c
--- linux/net/ipsec/libfreeswan/ttodata.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ttodata.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,644 @@
+/*
+ * convert from text form of arbitrary data (e.g., keys) to binary
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/* converters and misc */
+static int unhex(const char *, char *, size_t);
+static int unb64(const char *, char *, size_t);
+static int untext(const char *, char *, size_t);
+static const char *badch(const char *, int, char *, size_t);
+
+/* internal error codes for converters */
+#define	SHORT	(-2)		/* internal buffer too short */
+#define	BADPAD	(-3)		/* bad base64 padding */
+#define	BADCH0	(-4)		/* invalid character 0 */
+#define	BADCH1	(-5)		/* invalid character 1 */
+#define	BADCH2	(-6)		/* invalid character 2 */
+#define	BADCH3	(-7)		/* invalid character 3 */
+#define	BADOFF(code) (BADCH0-(code))
+
+/*
+ - ttodatav - convert text to data, with verbose error reports
+ * If some of this looks slightly odd, it's because it has changed
+ * repeatedly (from the original atodata()) without a major rewrite.
+ */
+const char *			/* NULL on success, else literal or errp */
+ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen)
+const char *src;
+size_t srclen;			/* 0 means apply strlen() */
+int base;			/* 0 means figure it out */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+size_t *lenp;			/* where to record length (NULL is nowhere) */
+char *errp;			/* error buffer */
+size_t errlen;
+{
+	size_t ingroup;		/* number of input bytes converted at once */
+	char buf[4];		/* output from conversion */
+	int nbytes;		/* size of output */
+	int (*decode)(const char *, char *, size_t);
+	char *stop;
+	int ndone;
+	int i;
+	int underscoreok;
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (dstlen == 0)
+		dst = buf;	/* point it somewhere valid */
+	stop = dst + dstlen;
+
+	if (base == 0) {
+		if (srclen < 2)
+			return "input too short to be valid";
+		if (*src++ != '0')
+			return "input does not begin with format prefix";
+		switch (*src++) {
+		case 'x':
+		case 'X':
+			base = 16;
+			break;
+		case 's':
+		case 'S':
+			base = 64;
+			break;
+		case 't':
+		case 'T':
+			base = 256;
+			break;
+		default:
+			return "unknown format prefix";
+			break;
+		}
+		srclen -= 2;
+	}
+	switch (base) {
+	case 16:
+		ingroup = 2;
+		decode = unhex;
+		underscoreok = 1;
+		break;
+	case 64:
+		ingroup = 4;
+		decode = unb64;
+		underscoreok = 0;
+		break;
+	case 256:
+		ingroup = 1;
+		decode = untext;
+		underscoreok = 0;
+		break;
+	default:
+		return "unknown base";
+		break;
+	}
+
+	/* proceed */
+	ndone = 0;
+	while (srclen >= ingroup) {
+		nbytes = (*decode)(src, buf, sizeof(buf));
+		switch (nbytes) {
+		case BADCH0:
+		case BADCH1:
+		case BADCH2:
+		case BADCH3:
+			return badch(src, nbytes, errp, errlen);
+			break;
+		case SHORT:
+			return "internal buffer too short (\"can't happen\")";
+			break;
+		case BADPAD:
+			return "bad (non-zero) padding at end of base64 input";
+			break;
+		}
+		if (nbytes <= 0)
+			return "unknown internal error";
+		for (i = 0; i < nbytes; i++) {
+			if (dst < stop)
+				*dst++ = buf[i];
+			ndone++;
+		}
+		src += ingroup;
+		srclen -= ingroup;
+		if (underscoreok && srclen > 1 && *src == '_') {
+			/* srclen > 1 means not last character */
+			src++;
+			srclen--;
+		}
+	}
+	if (srclen != 0)
+		return "input ends in mid-byte, perhaps truncated";
+	if (ndone == 0)
+		return "no data bytes specified by input";
+	if (lenp != NULL)
+		*lenp = ndone;
+	return NULL;
+}
+
+/*
+ - ttodata - convert text to data
+ */
+const char *			/* NULL on success, else literal */
+ttodata(src, srclen, base, dst, dstlen, lenp)
+const char *src;
+size_t srclen;			/* 0 means apply strlen() */
+int base;			/* 0 means figure it out */
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+size_t *lenp;			/* where to record length (NULL is nowhere) */
+{
+	return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
+								(size_t)0);
+}
+
+/*
+ - atodata - convert ASCII to data
+ * backward-compatibility interface
+ */
+size_t				/* 0 for failure, true length for success */
+atodata(src, srclen, dst, dstlen)
+const char *src;
+size_t srclen;
+char *dst;
+size_t dstlen;
+{
+	size_t len;
+	const char *err;
+
+	err = ttodata(src, srclen, 0, dst, dstlen, &len);
+	if (err != NULL)
+		return 0;
+	return len;
+}
+
+/*
+ - atobytes - convert ASCII to data bytes
+ * another backward-compatibility interface
+ */
+const char *
+atobytes(src, srclen, dst, dstlen, lenp)
+const char *src;
+size_t srclen;
+char *dst;
+size_t dstlen;
+size_t *lenp;
+{
+	return ttodata(src, srclen, 0, dst, dstlen, lenp);
+}
+
+/*
+ - unhex - convert two ASCII hex digits to byte
+ */
+static int		/* number of result bytes, or error code */
+unhex(src, dst, dstlen)
+const char *src;	/* known to be full length */
+char *dst;
+size_t dstlen;		/* not large enough is a failure */
+{
+	char *p;
+	unsigned byte;
+	static char hex[] = "0123456789abcdef";
+
+	if (dstlen < 1)
+		return SHORT;
+
+	p = strchr(hex, *src);
+	if (p == NULL)
+		p = strchr(hex, tolower(*src));
+	if (p == NULL)
+		return BADCH0;
+	byte = (p - hex) << 4;
+	src++;
+
+	p = strchr(hex, *src);
+	if (p == NULL)
+		p = strchr(hex, tolower(*src));
+	if (p == NULL)
+		return BADCH1;
+	byte |= (p - hex);
+
+	*dst = byte;
+	return 1;
+}
+
+/*
+ - unb64 - convert four ASCII base64 digits to three bytes
+ * Note that a base64 digit group is padded out with '=' if it represents
+ * less than three bytes:  one byte is dd==, two is ddd=, three is dddd.
+ */
+static int		/* number of result bytes, or error code */
+unb64(src, dst, dstlen)
+const char *src;	/* known to be full length */
+char *dst;
+size_t dstlen;
+{
+	char *p;
+	unsigned byte1;
+	unsigned byte2;
+	static char base64[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+	if (dstlen < 3)
+		return SHORT;
+
+	p = strchr(base64, *src++);
+	if (p == NULL)
+		return BADCH0;
+	byte1 = (p - base64) << 2;	/* first six bits */
+
+	p = strchr(base64, *src++);
+	if (p == NULL)
+		return BADCH1;
+	byte2 = p - base64;		/* next six:  two plus four */
+	*dst++ = byte1 | (byte2 >> 4);
+	byte1 = (byte2 & 0xf) << 4;
+
+	p = strchr(base64, *src++);
+	if (p == NULL) {
+		if (*(src-1) == '=' && *src == '=') {
+			if (byte1 != 0)		/* bad padding */
+				return BADPAD;
+			return 1;
+		}
+		return BADCH2;
+	}
+	byte2 = p - base64;		/* next six:  four plus two */
+	*dst++ = byte1 | (byte2 >> 2);
+	byte1 = (byte2 & 0x3) << 6;
+
+	p = strchr(base64, *src++);
+	if (p == NULL) {
+		if (*(src-1) == '=') {
+			if (byte1 != 0)		/* bad padding */
+				return BADPAD;
+			return 2;
+		}
+		return BADCH3;
+	}
+	byte2 = p - base64;		/* last six */
+	*dst++ = byte1 | byte2;
+	return 3;
+}
+
+/*
+ - untext - convert one ASCII character to byte
+ */
+static int		/* number of result bytes, or error code */
+untext(src, dst, dstlen)
+const char *src;	/* known to be full length */
+char *dst;
+size_t dstlen;		/* not large enough is a failure */
+{
+	if (dstlen < 1)
+		return SHORT;
+
+	*dst = *src;
+	return 1;
+}
+
+/*
+ - badch - produce a nice complaint about an unknown character
+ *
+ * If the compiler complains that the array bigenough[] has a negative
+ * size, that means the TTODATAV_BUF constant has been set too small.
+ */
+static const char *		/* literal or errp */
+badch(src, errcode, errp, errlen)
+const char *src;
+int errcode;
+char *errp;			/* might be NULL */
+size_t errlen;
+{
+	static const char pre[] = "unknown character (`";
+	static const char suf[] = "') in input";
+	char buf[5];
+#	define	REQD	(sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
+	struct sizecheck {
+		char bigenough[TTODATAV_BUF - REQD];	/* see above */
+	};
+	char ch;
+
+	if (errp == NULL || errlen < REQD)
+		return "unknown character in input";
+	strcpy(errp, pre);
+	ch = *(src + BADOFF(errcode));
+	if (isprint(ch)) {
+		buf[0] = ch;
+		buf[1] = '\0';
+	} else {
+		buf[0] = '\\';
+		buf[1] = ((ch & 0700) >> 6) + '0';
+		buf[2] = ((ch & 0070) >> 3) + '0';
+		buf[3] = ((ch & 0007) >> 0) + '0';
+		buf[4] = '\0';
+	}
+	strcat(errp, buf);
+	strcat(errp, suf);
+	return (const char *)errp;
+}
+
+
+
+#ifdef TTODATA_MAIN
+
+#include <stdio.h>
+
+void regress();
+void hexout();
+
+/*
+ - main - convert first argument to hex, or run regression
+ */
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	char buf[1024];
+	char buf2[1024];
+	char err[512];
+	size_t n;
+	size_t i;
+	char *p = buf;
+	char *p2 = buf2;
+	char *pgm = argv[0];
+	const char *oops;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
+		exit(2);
+	}
+
+	if (strcmp(argv[1], "-r") == 0) {
+		regress(pgm);	/* should not return */
+		fprintf(stderr, "%s: regress() returned?!?\n", pgm);
+		exit(1);
+	}
+
+	oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n, err, sizeof(err));
+	if (oops != NULL) {
+		fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
+								oops, argv[1]);
+		exit(1);
+	}
+
+	if (n > sizeof(buf)) {
+		p = (char *)malloc((size_t)n);
+		if (p == NULL) {
+			fprintf(stderr,
+				"%s: unable to malloc %d bytes for result\n",
+				pgm, n);
+			exit(1);
+		}
+		oops = ttodata(argv[1], 0, 0, p, n, &n);
+		if (oops != NULL) {
+			fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
+								pgm, oops);
+			exit(1);
+		}
+	}
+
+	hexout(p, n, stdout);
+	printf("\n");
+
+	i = datatot(buf, n, 'h', buf2, sizeof(buf2));
+	if (i == 0) {
+		fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
+								argv[1]);
+		exit(1);
+	}
+
+	if (i > sizeof(buf2)) {
+		p2 = (char *)malloc((size_t)i);
+		if (p == NULL) {
+			fprintf(stderr,
+				"%s: unable to malloc %d bytes for result\n",
+				pgm, i);
+			exit(1);
+		}
+		i = datatot(buf, n, 'h', p2, i);
+		if (i == 0) {
+			fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
+			exit(1);
+		}
+	}
+
+	printf("%s\n", p2);
+
+	exit(0);
+}
+
+/*
+ - hexout - output an arbitrary-length string in hex
+ */
+void
+hexout(s, len, f)
+const char *s;
+size_t len;
+FILE *f;
+{
+	size_t i;
+
+	fprintf(f, "0x");
+	for (i = 0; i < len; i++)
+		fprintf(f, "%02x", (unsigned char)s[i]);
+}
+
+struct artab {
+	int base;
+	char *ascii;		/* NULL for end */
+	char *data;		/* NULL for error expected */
+} atodatatab[] = {
+	0, "",			NULL,
+	0, "0",			NULL,
+	0, "0x",		NULL,
+	0, "0xa",		NULL,
+	0, "0xab",		"\xab",
+	0, "0xabc",		NULL,
+	0, "0xabcd",		"\xab\xcd",
+	0, "0x0123456789",	"\x01\x23\x45\x67\x89",
+	0, "0x01x",		NULL,
+	0, "0xabcdef",		"\xab\xcd\xef",
+	0, "0xABCDEF",		"\xab\xcd\xef",
+	0, "0XaBc0eEd81f",	"\xab\xc0\xee\xd8\x1f",
+	0, "0XaBc0_eEd8",	"\xab\xc0\xee\xd8",
+	0, "0XaBc0_",		NULL,
+	0, "0X_aBc0",		NULL,
+	0, "0Xa_Bc0",		NULL,
+	16, "aBc0_eEd8",	"\xab\xc0\xee\xd8",
+	0, "0s",		NULL,
+	0, "0sA",		NULL,
+	0, "0sBA",		NULL,
+	0, "0sCBA",		NULL,
+	0, "0sDCBA",		"\x0c\x20\x40",
+	0, "0SDCBA",		"\x0c\x20\x40",
+	0, "0sDA==",		"\x0c",
+	0, "0sDC==",		NULL,
+	0, "0sDCA=",		"\x0c\x20",
+	0, "0sDCB=",		NULL,
+	0, "0sDCAZ",		"\x0c\x20\x19",
+	0, "0sDCAa",		"\x0c\x20\x1a",
+	0, "0sDCAz",		"\x0c\x20\x33",
+	0, "0sDCA0",		"\x0c\x20\x34",
+	0, "0sDCA9",		"\x0c\x20\x3d",
+	0, "0sDCA+",		"\x0c\x20\x3e",
+	0, "0sDCA/",		"\x0c\x20\x3f",
+	0, "0sAbraCadabra+",	"\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe",
+	64, "AbraCadabra+",	"\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe",
+	0, "0t",		NULL,
+	0, "0tabc_xyz",		"abc_xyz",
+	256, "abc_xyz",		"abc_xyz",
+	0, NULL,		NULL,
+};
+
+struct drtab {
+	char *data;	/* input; NULL for end */
+	char format;
+	int buflen;	/* -1 means big buffer */
+	int outlen;	/* -1 means strlen(ascii)+1 */
+	char *ascii;	/* NULL for error expected */
+} datatoatab[] = {
+	"",			'x',	-1,	-1,	NULL,
+	"",			'X',	-1,	-1,	NULL,
+	"",			'n',	-1,	-1,	NULL,
+	"0",			'x',	-1,	-1,	"0x30",
+	"0",			'x',	0,	5,	"---",
+	"0",			'x',	1,	5,	"",
+	"0",			'x',	2,	5,	"0",
+	"0",			'x',	3,	5,	"0x",
+	"0",			'x',	4,	5,	"0x3",
+	"0",			'x',	5,	5,	"0x30",
+	"0",			'x',	6,	5,	"0x30",
+	"\xab\xcd",		'x',	-1,	-1,	"0xabcd",
+	"\x01\x23\x45\x67\x89",	'x',	-1,	-1,	"0x0123456789",
+	"\xab\xcd\xef",		'x',	-1,	-1,	"0xabcdef",
+	"\xab\xc0\xee\xd8\x1f",	'x',	-1,	-1,	"0xabc0eed81f",
+	"\x01\x02",		'h',	-1,	-1,	"0x0102",
+	"\x01\x02\x03\x04\x05\x06",	'h',	-1, -1,	"0x01020304_0506",
+	"\xab\xc0\xee\xd8\x1f",	16,	-1,	-1,	"abc0eed81f",
+	"\x0c\x20\x40",		's',	-1,	-1,	"0sDCBA",
+	"\x0c\x20\x40",		's',	0,	7,	"---",
+	"\x0c\x20\x40",		's',	1,	7,	"",
+	"\x0c\x20\x40",		's',	2,	7,	"0",
+	"\x0c\x20\x40",		's',	3,	7,	"0s",
+	"\x0c\x20\x40",		's',	4,	7,	"0sD",
+	"\x0c\x20\x40",		's',	5,	7,	"0sDC",
+	"\x0c\x20\x40",		's',	6,	7,	"0sDCB",
+	"\x0c\x20\x40",		's',	7,	7,	"0sDCBA",
+	"\x0c\x20\x40",		's',	8,	7,	"0sDCBA",
+	"\x0c",			's',	-1,	-1,	"0sDA==",
+	"\x0c\x20",		's',	-1,	-1,	"0sDCA=",
+	"\x0c\x20\x19",		's',	-1,	-1,	"0sDCAZ",
+	"\x0c\x20\x1a",		's',	-1,	-1,	"0sDCAa",
+	"\x0c\x20\x33",		's',	-1,	-1,	"0sDCAz",
+	"\x0c\x20\x34",		's',	-1,	-1,	"0sDCA0",
+	"\x0c\x20\x3d",		's',	-1,	-1,	"0sDCA9",	
+	"\x0c\x20\x3e",		's',	-1,	-1,	"0sDCA+",
+	"\x0c\x20\x3f",		's',	-1,	-1,	"0sDCA/",	
+	"\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+",
+	"\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+",
+	NULL,			'x',	-1,	-1,	NULL,
+};
+
+/*
+ - regress - regression-test ttodata() and datatot()
+ */
+void			/* should not return at all, in fact */
+regress(pgm)
+char *pgm;
+{
+	struct artab *r;
+	struct drtab *dr;
+	char buf[100];
+	size_t n;
+	int status = 0;
+	size_t should;
+	const char *oops;
+
+	for (r = atodatatab; r->ascii != NULL; r++) {
+		oops = ttodata(r->ascii, 0, r->base, buf, sizeof(buf), &n);
+		if (oops != NULL && r->data == NULL)
+			{}			/* error expected */
+		else if (oops != NULL) {
+			printf("`%s' gave error `%s', expecting %d `", r->ascii,
+							oops, strlen(r->data));
+			hexout(r->data, strlen(r->data), stdout);
+			printf("'\n");
+			status = 1;
+		} else if (r->data == NULL) {
+			printf("`%s' gave %d `", r->ascii, n);
+			hexout(buf, n, stdout);
+			printf("', expecting error\n");
+			status = 1;
+		} else if (n != strlen(r->data)) {
+			printf("length wrong in `%s': got %d `", r->ascii, n);
+			hexout(buf, n, stdout);
+			printf("', expecting %d `", strlen(r->data));
+			hexout(r->data, strlen(r->data), stdout);
+			printf("'\n");
+			status = 1;
+		} else if (memcmp(buf, r->data, n) != 0) {
+			printf("`%s' gave %d `", r->ascii, n);
+			hexout(buf, n, stdout);
+			printf("', expecting %d `", strlen(r->data));
+			hexout(r->data, strlen(r->data), stdout);
+			printf("'\n");
+			status = 1;
+		}
+		fflush(stdout);
+	}
+	for (dr = datatoatab; dr->data != NULL; dr++) {
+		strcpy(buf, "---");
+		n = datatot(dr->data, strlen(dr->data), dr->format, buf,
+				(dr->buflen == -1) ? sizeof(buf) : dr->buflen);
+		should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
+		if (dr->outlen != -1)
+			should = dr->outlen;
+		if (n == 0 && dr->ascii == NULL)
+			{}			/* error expected */
+		else if (n == 0) {
+			printf("`");
+			hexout(dr->data, strlen(dr->data), stdout);
+			printf("' %c gave error, expecting %d `%s'\n",
+				dr->format, should, dr->ascii);
+			status = 1;
+		} else if (dr->ascii == NULL) {
+			printf("`");
+			hexout(dr->data, strlen(dr->data), stdout);
+			printf("' %c gave %d `%.*s', expecting error\n",
+				dr->format, n, n, buf);
+			status = 1;
+		} else if (n != should) {
+			printf("length wrong in `");
+			hexout(dr->data, strlen(dr->data), stdout);
+			printf("': got %d `%s'", n, buf);
+			printf(", expecting %d `%s'\n", should, dr->ascii);
+			status = 1;
+		} else if (strcmp(buf, dr->ascii) != 0) {
+			printf("`");
+			hexout(dr->data, strlen(dr->data), stdout);
+			printf("' gave %d `%s'", n, buf);
+			printf(", expecting %d `%s'\n", should, dr->ascii);
+			status = 1;
+		}
+		fflush(stdout);
+	}
+	exit(status);
+}
+
+#endif /* TTODATA_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ttoprotoport.c linux-patched/net/ipsec/libfreeswan/ttoprotoport.c
--- linux/net/ipsec/libfreeswan/ttoprotoport.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ttoprotoport.c	Thu Sep  5 04:24:03 2002
@@ -0,0 +1,93 @@
+/*
+ * conversion from protocol/port string to protocol and port
+ * Copyright (C) 2002 Mario Strasser <mast@gmx.net>,
+ *                    Zuercher Hochschule Winterthur,
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ * ttoprotoport - converts from protocol/port string to protocol and port
+ */
+err_t
+ttoprotoport(src, src_len, proto, port)
+char *src;		/* input string */
+size_t src_len;		/* length of input string, use strlen() if 0 */
+u_int8_t *proto;	/* extracted protocol number */
+u_int16_t *port;	/* extracted port number if it exists */
+{
+    char *end, *service_name;
+    char proto_name[16];
+    int proto_len;
+    long int l;
+    struct protoent *protocol;
+    struct servent *service;
+
+    /* get the length of the string */
+    if (!src_len) src_len = strlen(src);
+
+    /* locate delimiter '/' between protocol and port */
+    end = strchr(src, '/');
+    if (end != NULL) {
+      proto_len = end - src;
+      service_name = end + 1;
+    } else {
+      proto_len = src_len;
+      service_name = src + src_len;
+    }
+
+   /* copy protocol name*/
+    memset(proto_name, '\0', sizeof(proto_name));
+    memcpy(proto_name, src, proto_len);
+
+    /* extract protocol by trying to resolve it by name */
+    protocol = getprotobyname(proto_name);
+    if (protocol != NULL) {
+	*proto = protocol->p_proto;
+    }
+    else  /* failed, now try it by number */
+    {
+	l = strtol(proto_name, &end, 0);
+
+	if (*proto_name && *end)
+	    return "<protocol> is neither a number nor a valid name";
+
+	if (l < 0 || l > 0xff)
+            return "<protocol> must be between 0 and 255";
+
+	*proto = (u_int8_t)l;
+    }
+
+    /* extract port by trying to resolve it by name */
+    service = getservbyname(service_name, NULL);
+    if (service != NULL) {
+        *port = ntohs(service->s_port);
+    }
+    else /* failed, now try it by number */
+    {
+	l = strtol(service_name, &end, 0);
+
+	if (*service_name && *end)
+	    return "<port> is neither a number nor a valid name";
+
+	if (l < 0 || l > 0xffff)
+	    return "<port> must be between 0 and 65535";
+
+	*port = (u_int16_t)l;
+    }
+    return NULL;
+}
+
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ttosa.c linux-patched/net/ipsec/libfreeswan/ttosa.c
--- linux/net/ipsec/libfreeswan/ttosa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ttosa.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,282 @@
+/*
+ * convert from text form of SA ID to binary
+ * Copyright (C) 2000, 2001  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+static struct satype {
+	char *prefix;
+	size_t prelen;		/* strlen(prefix) */
+	int proto;
+} satypes[] = {
+	{ "ah",		2,	SA_AH	},
+	{ "esp",	3,	SA_ESP	},
+	{ "tun",	3,	SA_IPIP },
+	{ "comp",	4,	SA_COMP	},
+	{ "int",	3,	SA_INT	},
+	{ NULL,		0,	0,	}
+};
+
+static struct magic {
+	char *name;
+	char *really;
+} magic[] = {
+	{ PASSTHROUGHNAME,	PASSTHROUGH4IS		},
+	{ PASSTHROUGH4NAME,	PASSTHROUGH4IS		},
+	{ PASSTHROUGH6NAME,	PASSTHROUGH6IS		},
+	{ "%pass",		"int256@0.0.0.0"	},
+	{ "%drop",		"int257@0.0.0.0"	},
+	{ "%reject",		"int258@0.0.0.0"	},
+	{ "%hold",		"int259@0.0.0.0"	},
+	{ "%trap",		"int260@0.0.0.0"	},
+	{ "%trapsubnet",	"int261@0.0.0.0"	},
+	{ NULL,			NULL			}
+};
+
+/*
+ - ttosa - convert text "ah507@10.0.0.1" to SA identifier
+ */
+err_t				/* NULL for success, else string literal */
+ttosa(src, srclen, sa)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+ip_said *sa;
+{
+	const char *at;
+	const char *addr;
+	size_t alen;
+	const char *spi = NULL;
+	struct satype *sat;
+	unsigned long ul;
+	const char *oops;
+	struct magic *mp;
+	size_t nlen;
+#	define	MINLEN	5	/* ah0@0 is as short as it can get */
+	int af;
+	int base;
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+	if (srclen < MINLEN)
+		return "string too short to be SA identifier";
+	if (*src == '%') {
+		for (mp = magic; mp->name != NULL; mp++) {
+			nlen = strlen(mp->name);
+			if (srclen == nlen && memcmp(src, mp->name, nlen) == 0)
+				break;
+		}
+		if (mp->name == NULL)
+			return "unknown % keyword";
+		src = mp->really;
+		srclen = strlen(src);
+	}
+
+	at = memchr(src, '@', srclen);
+	if (at == NULL)
+		return "no @ in SA specifier";
+
+	for (sat = satypes; sat->prefix != NULL; sat++)
+		if (sat->prelen < srclen &&
+				strncmp(src, sat->prefix, sat->prelen) == 0) {
+			sa->proto = sat->proto;
+			spi = src + sat->prelen;
+			break;			/* NOTE BREAK OUT */
+		}
+	if (sat->prefix == NULL)
+		return "SA specifier lacks valid protocol prefix";
+
+	if (spi >= at)
+		return "no SPI in SA specifier";
+	switch (*spi) {
+	case '.':
+		af = AF_INET;
+		spi++;
+		base = 16;
+		break;
+	case ':':
+		af = AF_INET6;
+		spi++;
+		base = 16;
+		break;
+	default:
+		af = AF_UNSPEC;		/* not known yet */
+		base = 0;
+		break;
+	}
+	if (spi >= at)
+		return "no SPI found in SA specifier";
+	oops = ttoul(spi, at - spi, base, &ul);
+	if (oops != NULL)
+		return oops;
+	sa->spi = htonl(ul);
+
+	addr = at + 1;
+	alen = srclen - (addr - src);
+	if (af == AF_UNSPEC)
+		af = (memchr(addr, ':', alen) != NULL) ? AF_INET6 : AF_INET;
+	oops = ttoaddr(addr, alen, af, &sa->dst);
+	if (oops != NULL)
+		return oops;
+
+	return NULL;
+}
+
+
+
+#ifdef TTOSA_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	ip_said sa;
+	char buf[100];
+	char buf2[100];
+	const char *oops;
+	size_t n;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
+		exit(2);
+	}
+
+	if (strcmp(argv[1], "-r") == 0) {
+		regress();
+		fprintf(stderr, "regress() returned?!?\n");
+		exit(1);
+	}
+
+	oops = ttosa(argv[1], 0, &sa);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	n = satot(&sa, 0, buf, sizeof(buf));
+	if (n > sizeof(buf)) {
+		fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
+		fprintf(stderr, "%lx@", sa.spi);
+		(void) addrtot(&sa.dst, 0, buf2, sizeof(buf2));
+		fprintf(stderr, "%s", buf2);
+		fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+						(long)n, (long)sizeof(buf));
+		exit(1);
+	}
+	printf("%s\n", buf);
+
+	exit(0);
+}
+
+struct rtab {
+	int format;
+#		define	FUDGE	0x1000
+	char *input;
+	char *output;			/* NULL means error expected */
+} rtab[] = {
+	0, "esp257@1.2.3.0",		"esp.101@1.2.3.0",
+	0, "ah0x20@1.2.3.4",		"ah.20@1.2.3.4",
+	0, "tun20@1.2.3.4",		"tun.14@1.2.3.4",
+	0, "comp20@1.2.3.4",		"comp.14@1.2.3.4",
+	0, "esp257@::1",		"esp:101@::1",
+	0, "esp257@0bc:12de::1",	"esp:101@bc:12de::1",
+	0, "esp78@1049:1::8007:2040",	"esp:4e@1049:1::8007:2040",
+	0, "esp0x78@1049:1::8007:2040",	"esp:78@1049:1::8007:2040",
+	0, "ah78@1049:1::8007:2040",	"ah:4e@1049:1::8007:2040",
+	0, "ah0x78@1049:1::8007:2040",	"ah:78@1049:1::8007:2040",
+	0, "tun78@1049:1::8007:2040",	"tun:4e@1049:1::8007:2040",
+	0, "tun0x78@1049:1::8007:2040",	"tun:78@1049:1::8007:2040",
+	0, "duk99@3ffe:370:400:ff::9001:3001",	NULL,
+	0, "esp78x@1049:1::8007:2040",	NULL,
+	0, "esp0x78@1049:1:0xfff::8007:2040",	NULL,
+	0, "es78@1049:1::8007:2040",	NULL,
+	0, "",				NULL,
+	0, "_",				NULL,
+	0, "ah2.2",			NULL,
+	0, "goo2@1.2.3.4",		NULL,
+	0, "esp9@1.2.3.4",		"esp.9@1.2.3.4",
+	'f', "esp0xa9@1.2.3.4",		"esp.000000a9@1.2.3.4",
+	0, "espp9@1.2.3.4",		NULL,
+	0, "es9@1.2.3.4",		NULL,
+	0, "ah@1.2.3.4",		NULL,
+	0, "esp7x7@1.2.3.4",		NULL,
+	0, "esp77@1.0x2.3.4",		NULL,
+	0, PASSTHROUGHNAME,		PASSTHROUGH4NAME,
+	0, PASSTHROUGH6NAME,		PASSTHROUGH6NAME,
+	0, "%pass",			"%pass",
+	0, "int256@0.0.0.0",		"%pass",
+	0, "%drop",			"%drop",
+	0, "int257@0.0.0.0",		"%drop",
+	0, "%reject",			"%reject",
+	0, "int258@0.0.0.0",		"%reject",
+	0, "%hold",			"%hold",
+	0, "int259@0.0.0.0",		"%hold",
+	0, "%trap",			"%trap",
+	0, "int260@0.0.0.0",		"%trap",
+	0, "%trapsubnet",		"%trapsubnet",
+	0, "int261@0.0.0.0",		"%trapsubnet",
+	0, "int262@0.0.0.0",		"int.106@0.0.0.0",
+	FUDGE, "esp9@1.2.3.4",		"unk77.9@1.2.3.4",
+	0, NULL,			NULL
+};
+
+void
+regress()
+{
+	struct rtab *r;
+	int status = 0;
+	ip_said sa;
+	char in[100];
+	char buf[100];
+	const char *oops;
+	size_t n;
+
+	for (r = rtab; r->input != NULL; r++) {
+		strcpy(in, r->input);
+		oops = ttosa(in, 0, &sa);
+		if (oops != NULL && r->output == NULL)
+			{}		/* okay, error expected */
+		else if (oops != NULL) {
+			printf("`%s' ttosa failed: %s\n", r->input, oops);
+			status = 1;
+		} else if (r->output == NULL) {
+			printf("`%s' ttosa succeeded unexpectedly\n",
+								r->input);
+			status = 1;
+		} else {
+			if (r->format&FUDGE)
+				sa.proto = 77;
+			n = satot(&sa, (char)r->format, buf, sizeof(buf));
+			if (n > sizeof(buf)) {
+				printf("`%s' satot failed:  need %ld\n",
+							r->input, (long)n);
+				status = 1;
+			} else if (strcmp(r->output, buf) != 0) {
+				printf("`%s' gave `%s', expected `%s'\n",
+						r->input, buf, r->output);
+				status = 1;
+			}
+		}
+	}
+	exit(status);
+}
+
+#endif /* TTOSA_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ttosubnet.c linux-patched/net/ipsec/libfreeswan/ttosubnet.c
--- linux/net/ipsec/libfreeswan/ttosubnet.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ttosubnet.c	Sun Jan 19 22:32:30 2003
@@ -0,0 +1,294 @@
+/*
+ * convert from text form of subnet specification to binary
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#ifndef DEFAULTSUBNET
+#define	DEFAULTSUBNET	"%default"
+#endif
+
+/*
+ - ttosubnet - convert text "addr/mask" to address and mask
+ * Mask can be integer bit count.
+ */
+err_t
+ttosubnet(src, srclen, af, dst)
+const char *src;
+size_t srclen;			/* 0 means "apply strlen" */
+int af;				/* AF_INET or AF_INET6 */
+ip_subnet *dst;
+{
+	const char *slash;
+	const char *colon;
+	const char *mask;
+	size_t mlen;
+	const char *oops;
+	unsigned long bc;
+	static char def[] = DEFAULTSUBNET;
+#	define	DEFLEN	(sizeof(def) - 1)	/* -1 for NUL */
+	static char defis4[] = "0/0";
+#	define	DEFIS4LEN	(sizeof(defis4) - 1)
+	static char defis6[] = "::/0";
+#	define	DEFIS6LEN	(sizeof(defis6) - 1)
+	ip_address addrtmp;
+	ip_address masktmp;
+	int nbits;
+	int i;
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+
+	switch (af) {
+	case AF_INET:
+		nbits = 32;
+		break;
+	case AF_INET6:
+		nbits = 128;
+		break;
+	default:
+		return "unknown address family in ttosubnet";
+		break;
+	}
+
+	if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
+		src = (af == AF_INET) ? defis4 : defis6;
+		srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN;
+	}
+
+	slash = memchr(src, '/', srclen);
+	if (slash == NULL)
+		return "no / in subnet specification";
+	mask = slash + 1;
+	mlen = srclen - (mask - src);
+
+	oops = ttoaddr(src, slash-src, af, &addrtmp);
+	if (oops != NULL)
+		return oops;
+
+	/* extract port */
+	colon = memchr(mask, ':', mlen);
+	if (colon == 0)
+	{
+		setportof(0, &addrtmp);
+	}
+	else
+	{
+		long port;
+
+		oops =  ttoul(colon+1, mlen-(colon-mask+1), 10, &port);
+		if (oops != NULL)
+			return oops;
+		setportof(htons(port), &addrtmp);
+		mlen = colon - mask;
+	}
+
+	/*extract mask */
+	oops = ttoul(mask, mlen, 10, &bc);
+	if (oops == NULL) {
+		/* ttoul succeeded, it's a bit-count mask */
+		if (bc > nbits)
+			return "subnet mask bit count too large";
+		i = bc;
+	} else {
+		oops = ttoaddr(mask, mlen, af, &masktmp);
+		if (oops != NULL)
+			return oops;
+		i = masktocount(&masktmp);
+		if (i < 0)
+			return "non-contiguous or otherwise erroneous mask";
+	}
+
+	return initsubnet(&addrtmp, i, '0', dst);
+}
+
+
+
+#ifdef TTOSUBNET_MAIN
+
+#include <stdio.h>
+
+void regress();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	ip_address a;
+	ip_subnet s;
+	char buf[100];
+	char buf2[100];
+	const char *oops;
+	size_t n;
+	int af;
+	char *p;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s [-6] addr/mask\n", argv[0]);
+		fprintf(stderr, "   or: %s -r\n", argv[0]);
+		exit(2);
+	}
+
+	if (strcmp(argv[1], "-r") == 0) {
+		regress();
+		fprintf(stderr, "regress() returned?!?\n");
+		exit(1);
+	}
+
+	af = AF_INET;
+	p = argv[1];
+	if (strcmp(argv[1], "-6") == 0) {
+		af = AF_INET6;
+		p = argv[2];
+	} else if (strchr(argv[1], ':') != NULL)
+		af = AF_INET6;
+
+	oops = ttosubnet(p, 0, af, &s);
+	if (oops != NULL) {
+		fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
+		exit(1);
+	}
+	n = subnettot(&s, 0, buf, sizeof(buf));
+	if (n > sizeof(buf)) {
+		fprintf(stderr, "%s: reverse conversion of ", argv[0]);
+		(void) addrtot(&s.addr, 0, buf2, sizeof(buf2));
+		fprintf(stderr, "%s/", buf2);
+		fprintf(stderr, "%d", s.maskbits);
+		fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
+						(long)n, (long)sizeof(buf));
+		exit(1);
+	}
+	printf("%s\n", buf);
+
+	exit(0);
+}
+
+struct rtab {
+	int family;
+	char *input;
+	char *output;			/* NULL means error expected */
+} rtab[] = {
+	4, "1.2.3.0/255.255.255.0",	"1.2.3.0/24",
+	4, "1.2.3.0/24",		"1.2.3.0/24",
+	4, "1.2.3.1/255.255.255.240",	"1.2.3.0/28",
+	4, "1.2.3.1/32",		"1.2.3.1/32",
+	4, "1.2.3.1/0",			"0.0.0.0/0",
+/*	4, "1.2.3.1/255.255.127.0",	"1.2.3.0/255.255.127.0",	*/
+	4, "1.2.3.1/255.255.127.0",	NULL,
+	4, "128.009.000.032/32",	"128.9.0.32/32",
+	4, "128.0x9.0.32/32",		NULL,
+	4, "0x80090020/32",		"128.9.0.32/32",
+	4, "0x800x0020/32",		NULL,
+	4, "128.9.0.32/0xffFF0000",	"128.9.0.0/16",
+	4, "128.9.0.32/0xff0000FF",	NULL,
+	4, "128.9.0.32/0x0000ffFF",	NULL,
+	4, "128.9.0.32/0x00ffFF0000",	NULL,
+	4, "128.9.0.32/0xffFF",		NULL,
+	4, "128.9.0.32.27/32",		NULL,
+	4, "128.9.0k32/32",		NULL,
+	4, "328.9.0.32/32",		NULL,
+	4, "128.9..32/32",		NULL,
+	4, "10/8",			"10.0.0.0/8",
+	4, "10.0/8",			"10.0.0.0/8",
+	4, "10.0.0/8",			"10.0.0.0/8",
+	4, "10.0.1/24",			"10.0.1.0/24",
+	4, "_",				NULL,
+	4, "_/_",			NULL,
+	4, "1.2.3.1",			NULL,
+	4, "1.2.3.1/_",			NULL,
+	4, "1.2.3.1/24._",		NULL,
+	4, "1.2.3.1/99",		NULL,
+	4, "localhost./32",		"127.0.0.1/32",
+	4, "%default",			"0.0.0.0/0",
+	6, "3049:1::8007:2040/0",	"::/0",
+	6, "3049:1::8007:2040/128",	"3049:1::8007:2040/128",
+	6, "3049:1::192.168.0.1/128", NULL,	/*"3049:1::c0a8:1/128",*/
+	6, "3049:1::8007::2040/128",	NULL,
+	6, "3049:1::8007:2040/ffff::0",	"3049::/16",
+	6, "3049:1::8007:2040/64",	"3049:1::/64",
+	6, "3049:1::8007:2040/ffff::",	"3049::/16",
+	6, "3049:1::8007:2040/0000:ffff::0",	NULL,
+	6, "3049:1::8007:2040/ff1f::0",	NULL,
+	6, "3049:1::8007:x:2040/128",	NULL,
+	6, "3049:1t::8007:2040/128",	NULL,
+	6, "3049:1::80071:2040/128",	NULL,
+	6, "::/21",			"::/21",
+	6, "::1/128",			"::1/128",
+	6, "1::/21",			"1::/21",
+	6, "1::2/128",			"1::2/128",
+	6, "1:0:0:0:0:0:0:2/128",	"1::2/128",
+	6, "1:0:0:0:3:0:0:2/128",	"1::3:0:0:2/128",
+	6, "1:0:0:3:0:0:0:2/128",	"1::3:0:0:0:2/128",
+	6, "1:0:3:0:0:0:0:2/128",	"1:0:3::2/128",
+	6, "abcd:ef01:2345:6789:0:00a:000:20/128",	"abcd:ef01:2345:6789:0:a:0:20/128",
+	6, "3049:1::8007:2040/ffff:ffff:",	NULL,
+	6, "3049:1::8007:2040/ffff:88::",	NULL,
+	6, "3049:12::9000:3200/ffff:fff0::",	"3049:10::/28",
+	6, "3049:12::9000:3200/28",	"3049:10::/28",
+	6, "3049:12::9000:3200/ff00:::",	NULL,
+	6, "3049:12::9000:3200/ffff:::",	NULL,
+	6, "3049:12::9000:3200/128_",	NULL,
+	6, "3049:12::9000:3200/",	NULL,
+	6, "%default",			"::/0",
+	4, NULL,			NULL
+};
+
+void
+regress()
+{
+	struct rtab *r;
+	int status = 0;
+	ip_address a;
+	ip_subnet s;
+	char in[100];
+	char buf[100];
+	const char *oops;
+	size_t n;
+	int af;
+
+	for (r = rtab; r->input != NULL; r++) {
+		af = (r->family == 4) ? AF_INET : AF_INET6;
+		strcpy(in, r->input);
+		oops = ttosubnet(in, 0, af, &s);
+		if (oops != NULL && r->output == NULL)
+			{}		/* okay, error expected */
+		else if (oops != NULL) {
+			printf("`%s' ttosubnet failed: %s\n", r->input, oops);
+			status = 1;
+		} else if (r->output == NULL) {
+			printf("`%s' ttosubnet succeeded unexpectedly\n",
+								r->input);
+			status = 1;
+		} else {
+			n = subnettot(&s, 0, buf, sizeof(buf));
+			if (n > sizeof(buf)) {
+				printf("`%s' subnettot failed:  need %ld\n",
+							r->input, (long)n);
+				status = 1;
+			} else if (strcmp(r->output, buf) != 0) {
+				printf("`%s' gave `%s', expected `%s'\n",
+						r->input, buf, r->output);
+				status = 1;
+			}
+		}
+	}
+	exit(status);
+}
+
+#endif /* TTOSUBNET_MAIN */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ttoul.c linux-patched/net/ipsec/libfreeswan/ttoul.c
--- linux/net/ipsec/libfreeswan/ttoul.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ttoul.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,91 @@
+/*
+ * convert from text form of unsigned long to binary
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - ttoul - convert text substring to unsigned long number
+ */
+const char *			/* NULL for success, else string literal */
+ttoul(src, srclen, base, resultp)
+const char *src;
+size_t srclen;			/* 0 means strlen(src) */
+int base;			/* 0 means figure it out */
+unsigned long *resultp;
+{
+	const char *stop;
+	static char hex[] = "0123456789abcdef";
+	static char uchex[] = "0123456789ABCDEF";
+	int d;
+	char c;
+	char *p;
+	unsigned long r;
+	unsigned long rlimit;
+	int dlimit;
+
+	if (srclen == 0)
+		srclen = strlen(src);
+	if (srclen == 0)
+		return "empty string";
+
+	if (base == 0) {
+		if (srclen > 2 && *src == '0' &&
+					(*(src+1) == 'x' || *(src+1) == 'X'))
+			return ttoul(src+2, srclen-2, 16, resultp);
+		if (srclen > 1 && *src == '0')
+			return ttoul(src+1, srclen-1, 8, resultp);
+		return ttoul(src, srclen, 10, resultp);
+	}
+	if (base != 8 && base != 10 && base != 16)
+		return "unsupported number base";
+
+	r = 0;
+	stop = src + srclen;
+	if (base == 16) {
+		while (src < stop) {
+			c = *src++;
+			p = strchr(hex, c);
+			if (p != NULL)
+				d = p - hex;
+			else {
+				p = strchr(uchex, c);
+				if (p == NULL)
+					return "non-hex digit in hex number";
+				d = p - uchex;
+			}
+			r = (r << 4) | d;
+		}
+		/* defer length check to catch invalid digits first */
+		if (srclen > sizeof(unsigned long) * 2)
+			return "hex number too long";
+	} else {
+		rlimit = ULONG_MAX / base;
+		dlimit = (int)(ULONG_MAX - rlimit*base);
+		while (src < stop) {
+			c = *src++;
+			d = c - '0';
+			if (d < 0 || d >= base)
+				return "non-digit in number";
+			if (r > rlimit || (r == rlimit && d > dlimit))
+				return "unsigned-long overflow";
+			r = r*base + d;
+		}
+	}
+
+	*resultp = r;
+	return NULL;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ultoa.c linux-patched/net/ipsec/libfreeswan/ultoa.c
--- linux/net/ipsec/libfreeswan/ultoa.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ultoa.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,67 @@
+/*
+ * convert unsigned long to ASCII
+ * Copyright (C) 1998, 1999  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - ultoa - convert unsigned long to decimal ASCII
+ */
+size_t				/* length required for full conversion */
+ultoa(n, base, dst, dstlen)
+unsigned long n;
+int base;
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	char buf[3*sizeof(unsigned long) + 1];
+	char *bufend = buf + sizeof(buf);
+	size_t len;
+	char *p;
+	static char hex[] = "0123456789abcdef";
+
+	p = bufend;
+	*--p = '\0';
+	if (base == 10) {
+		do {
+			*--p = n%10 + '0';
+			n /= 10;
+		} while (n != 0);
+	} else if (base == 16) {
+		do {
+			*--p = hex[n&0xf];
+			n >>= 4;
+		} while (n != 0);
+		*--p = 'x';
+		*--p = '0';
+	} else if (base == 8) {
+		do {
+			*--p = (n&07) + '0';
+			n >>= 3;
+		} while (n != 0);
+		*--p = '0';
+	} else
+		*--p = '?';
+
+	len = bufend - p;
+
+	if (dstlen > 0) {
+		if (len > dstlen)
+			*(p + dstlen - 1) = '\0';
+		strcpy(dst, p);
+	}
+	return len;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/ultot.c linux-patched/net/ipsec/libfreeswan/ultot.c
--- linux/net/ipsec/libfreeswan/ultot.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/ultot.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,83 @@
+/*
+ * convert unsigned long to text
+ * Copyright (C) 2000  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+/*
+ - ultot - convert unsigned long to text
+ */
+size_t				/* length required for full conversion */
+ultot(n, base, dst, dstlen)
+unsigned long n;
+int base;
+char *dst;			/* need not be valid if dstlen is 0 */
+size_t dstlen;
+{
+	char buf[3*sizeof(unsigned long) + 1];
+	char *bufend = buf + sizeof(buf);
+	size_t len;
+	char *p;
+	static char hex[] = "0123456789abcdef";
+#	define	HEX32	(32/4)
+
+	p = bufend;
+	*--p = '\0';
+	switch (base) {
+	case 10:
+	case 'd':
+		do {
+			*--p = n%10 + '0';
+			n /= 10;
+		} while (n != 0);
+		break;
+	case 16:
+	case 17:
+	case 'x':
+		do {
+			*--p = hex[n&0xf];
+			n >>= 4;
+		} while (n != 0);
+		if (base == 17)
+			while (bufend - p < HEX32 + 1)
+				*--p = '0';
+		if (base == 'x') {
+			*--p = 'x';
+			*--p = '0';
+		}
+		break;
+	case 8:
+	case 'o':
+		do {
+			*--p = (n&07) + '0';
+			n >>= 3;
+		} while (n != 0);
+		if (base == 'o')
+			*--p = '0';
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	len = bufend - p;
+	if (dstlen > 0) {
+		if (len > dstlen)
+			*(p + dstlen - 1) = '\0';
+		strcpy(dst, p);
+	}
+	return len;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/libfreeswan/version.in.c linux-patched/net/ipsec/libfreeswan/version.in.c
--- linux/net/ipsec/libfreeswan/version.in.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/libfreeswan/version.in.c	Thu Sep  5 04:13:20 2002
@@ -0,0 +1,40 @@
+/*
+ * return IPsec version information
+ * Copyright (C) 2001  Henry Spencer.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
+ * 
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+#include "internal.h"
+#include "freeswan.h"
+
+#define	V	"xxx"		/* substituted in by Makefile */
+static const char freeswan_number[] = V;
+static const char freeswan_string[] = "Linux FreeS/WAN " V;
+
+/*
+ - ipsec_version_code - return IPsec version number/code, as string
+ */
+const char *
+ipsec_version_code()
+{
+	return freeswan_number;
+}
+
+/*
+ - ipsec_version_string - return full version string
+ */
+const char *
+ipsec_version_string()
+{
+	return freeswan_string;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/pfkey_v2.c linux-patched/net/ipsec/pfkey_v2.c
--- linux/net/ipsec/pfkey_v2.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/pfkey_v2.c	Thu Sep  5 04:27:09 2002
@@ -0,0 +1,2072 @@
+/*
+ * @(#) RFC2367 PF_KEYv2 Key management API domain socket I/F
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ *		Template from /usr/src/linux-2.0.36/net/unix/af_unix.c.
+ *		Hints from /usr/src/linux-2.0.36/net/ipv4/udp.c.
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#include "ipsec_param.h"
+
+#include <linux/major.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/un.h>
+#include <linux/fcntl.h>
+#include <linux/termios.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/net.h> /* struct socket */
+#include <linux/in.h>
+#include <linux/fs.h>
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <asm/segment.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <net/sock.h> /* struct sock */
+/* #include <net/tcp.h> */
+#include <net/af_unix.h>
+#ifdef CONFIG_PROC_FS
+# include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+
+#include <linux/types.h>
+ 
+#include <freeswan.h>
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+#endif /* NET_21 */
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_sa.h"
+#include "ipsec_netlink.h"
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_proto.h"
+
+#ifdef CONFIG_IPSEC_DEBUG
+int debug_pfkey = 0;
+extern int sysctl_ipsec_debug_verbose;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+#ifndef SOCKOPS_WRAPPED
+#define SOCKOPS_WRAPPED(name) name
+#endif /* SOCKOPS_WRAPPED */
+
+struct proto_ops SOCKOPS_WRAPPED(pfkey_ops);
+struct sock *pfkey_sock_list = NULL;
+struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1];
+
+struct socket_list *pfkey_open_sockets = NULL;
+struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1];
+
+int pfkey_msg_interp(struct sock *, struct sadb_msg *, struct sadb_msg **);
+
+int
+pfkey_list_remove_socket(struct socket *socketp, struct socket_list **sockets)
+{
+	struct socket_list *socket_listp,*prev;
+
+	if(!socketp) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_remove_socket: "
+			    "NULL socketp handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	if(!sockets) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_remove_socket: "
+			    "NULL sockets list handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	socket_listp = *sockets;
+	prev = NULL;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_list_remove_socket: "
+		    "removing sock=%p\n",
+		    socketp);
+	
+	while(socket_listp != NULL) {
+		if(socket_listp->socketp == socketp) {
+			if(prev != NULL) {
+				prev->next = socket_listp->next;
+			} else {
+				*sockets = socket_listp->next;
+			}
+			
+			kfree((void*)socket_listp);
+			
+			break;
+		}
+		prev = socket_listp;
+		socket_listp = socket_listp->next;
+	}
+
+	return 0;
+}
+
+int
+pfkey_list_insert_socket(struct socket *socketp, struct socket_list **sockets)
+{
+	struct socket_list *socket_listp;
+
+	if(!socketp) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_insert_socket: "
+			    "NULL socketp handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	if(!sockets) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_insert_socket: "
+			    "NULL sockets list handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_list_insert_socket: "
+		    "socketp=%p\n",socketp);
+	
+	if((socket_listp = (struct socket_list *)kmalloc(sizeof(struct socket_list), GFP_KERNEL)) == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_insert_socket: "
+			    "memory allocation error.\n");
+		return -ENOMEM;
+	}
+	
+	socket_listp->socketp = socketp;
+	socket_listp->next = *sockets;
+	*sockets = socket_listp;
+
+	return 0;
+}
+  
+int
+pfkey_list_remove_supported(struct supported *supported, struct supported_list **supported_list)
+{
+	struct supported_list *supported_listp = *supported_list, *prev = NULL;
+	
+	if(!supported) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_remove_supported: "
+			    "NULL supported handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	if(!supported_list) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_remove_supported: "
+			    "NULL supported_list handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_list_remove_supported: "
+		    "removing supported=%p\n",
+		    supported);
+	
+	while(supported_listp != NULL) {
+		if(supported_listp->supportedp == supported) {
+			if(prev != NULL) {
+				prev->next = supported_listp->next;
+			} else {
+				*supported_list = supported_listp->next;
+			}
+			
+			kfree((void*)supported_listp);
+			
+			break;
+		}
+		prev = supported_listp;
+		supported_listp = supported_listp->next;
+	}
+
+	return 0;
+}
+
+int
+pfkey_list_insert_supported(struct supported *supported, struct supported_list **supported_list)
+{
+	struct supported_list *supported_listp;
+
+	if(!supported) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_insert_supported: "
+			    "NULL supported handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	if(!supported_list) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_insert_supported: "
+			    "NULL supported_list handed in, failed.\n");
+		return -EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_list_insert_supported: "
+		    "incoming, supported=%p, supported_list=%p\n",
+		    supported,
+		    supported_list);
+	
+	supported_listp = (struct supported_list *)kmalloc(sizeof(struct supported_list), GFP_KERNEL);
+	if(supported_listp == NULL)	{
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_list_insert_supported: "
+			    "memory allocation error.\n");
+		return -ENOMEM;
+	}
+	
+	supported_listp->supportedp = supported;
+	supported_listp->next = *supported_list;
+	*supported_list = supported_listp;
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_list_insert_supported: "
+		    "outgoing, supported=%p, supported_list=%p\n",
+		    supported,
+		    supported_list);
+
+	return 0;
+}
+  
+#ifndef NET_21
+DEBUG_NO_STATIC void
+pfkey_state_change(struct sock *sk)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_state_change: .\n");
+	if(!sk->dead) {
+		wake_up_interruptible(sk->sleep);
+	}
+}
+#endif /* !NET_21 */
+
+#ifndef NET_21
+DEBUG_NO_STATIC void
+pfkey_data_ready(struct sock *sk, int len)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_data_ready: "
+		    "sk=%p len=%d\n",
+		    sk,
+		    len);
+	if(!sk->dead) {
+		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket, 1);
+	}
+}
+
+DEBUG_NO_STATIC void
+pfkey_write_space(struct sock *sk)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_write_space: .\n");
+	if(!sk->dead) {
+		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket, 2);
+	}
+}
+#endif /* !NET_21 */
+
+DEBUG_NO_STATIC void
+pfkey_insert_socket(struct sock *sk)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_insert_socket: "
+		    "sk=%p\n",
+		    sk);
+	cli();
+	sk->next=pfkey_sock_list;
+	pfkey_sock_list=sk;
+	sti();
+}
+
+DEBUG_NO_STATIC void
+pfkey_remove_socket(struct sock *sk)
+{
+	struct sock **s;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_remove_socket: .\n");
+	cli();
+	s=&pfkey_sock_list;
+
+	while(*s!=NULL) {
+		if(*s==sk) {
+			*s=sk->next;
+			sk->next=NULL;
+			sti();
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_remove_socket: "
+				    "succeeded.\n");
+			return;
+		}
+		s=&((*s)->next);
+	}
+	sti();
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_remove_socket: "
+		    "not found.\n");
+	return;
+}
+
+DEBUG_NO_STATIC void
+pfkey_destroy_socket(struct sock *sk)
+{
+	struct sk_buff *skb;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_destroy_socket: .\n");
+	pfkey_remove_socket(sk);
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_destroy_socket: "
+		    "pfkey_remove_socket called.\n");
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_destroy_socket: "
+		    "sk(%p)->(&%p)receive_queue.{next=%p,prev=%p}.\n",
+		    sk,
+		    &(sk->receive_queue),
+		    sk->receive_queue.next,
+		    sk->receive_queue.prev);
+	while(sk && ((skb=skb_dequeue(&(sk->receive_queue)))!=NULL)) {
+#ifdef NET_21
+#ifdef CONFIG_IPSEC_DEBUG
+		if(debug_pfkey && sysctl_ipsec_debug_verbose) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_destroy_socket: "
+				    "skb=%p dequeued.\n", skb);
+			printk(KERN_INFO "klips_debug:pfkey_destroy_socket: "
+			       "pfkey_skb contents:");
+			printk(" next:%p", skb->next);
+			printk(" prev:%p", skb->prev);
+			printk(" list:%p", skb->list);
+			printk(" sk:%p", skb->sk);
+			printk(" stamp:%ld.%ld", skb->stamp.tv_sec, skb->stamp.tv_usec);
+			printk(" dev:%p", skb->dev);
+			if(skb->dev) {
+				if(skb->dev->name) {
+					printk(" dev->name:%s", skb->dev->name);
+				} else {
+					printk(" dev->name:NULL?");
+				}
+			} else {
+				printk(" dev:NULL");
+			}
+			printk(" h:%p", skb->h.raw);
+			printk(" nh:%p", skb->nh.raw);
+			printk(" mac:%p", skb->mac.raw);
+			printk(" dst:%p", skb->dst);
+			if(sysctl_ipsec_debug_verbose) {
+				int i;
+				
+				printk(" cb");
+				for(i=0; i<48; i++) {
+					printk(":%2x", skb->cb[i]);
+				}
+			}
+			printk(" len:%d", skb->len);
+			printk(" csum:%d", skb->csum);
+#ifndef NETDEV_23
+			printk(" used:%d", skb->used);
+			printk(" is_clone:%d", skb->is_clone);
+#endif /* NETDEV_23 */
+			printk(" cloned:%d", skb->cloned);
+			printk(" pkt_type:%d", skb->pkt_type);
+			printk(" ip_summed:%d", skb->ip_summed);
+			printk(" priority:%d", skb->priority);
+			printk(" protocol:%d", skb->protocol);
+			printk(" security:%d", skb->security);
+			printk(" truesize:%d", skb->truesize);
+			printk(" head:%p", skb->head);
+			printk(" data:%p", skb->data);
+			printk(" tail:%p", skb->tail);
+			printk(" end:%p", skb->end);
+			if(sysctl_ipsec_debug_verbose) {
+				unsigned int i;
+				printk(" data");
+				for(i=(unsigned int)(skb->head); i<(unsigned int)(skb->end); i++) {
+					printk(":%2x", (unsigned char)(*(char*)(i)));
+				}
+			}
+			printk(" destructor:%p", skb->destructor);
+			printk("\n");
+		}
+#endif /* CONFIG_IPSEC_DEBUG */
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_destroy_socket: "
+			    "skb=%p freed.\n",
+			    skb);
+		kfree_skb(skb);
+
+#else /* NET_21 */
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_destroy_socket: "
+			    "skb=%p dequeued and freed.\n",
+			    skb);
+		kfree_skb(skb, FREE_WRITE);
+
+#endif /* NET_21 */
+	}
+
+	sk->dead = 1;
+	sk_free(sk);
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_destroy_socket: destroyed.\n");
+}
+
+int
+pfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg)
+{
+	int error = 0;
+	struct sk_buff * skb = NULL;
+	struct sock *sk;
+
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_upmsg: "
+			    "NULL socket passed in.\n");
+		return -EINVAL;
+	}
+
+	if(pfkey_msg == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_upmsg: "
+			    "NULL pfkey_msg passed in.\n");
+		return -EINVAL;
+	}
+
+#ifdef NET_21
+	sk = sock->sk;
+#else /* NET_21 */
+	sk = sock->data;
+#endif /* NET_21 */
+
+	if(sk == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_upmsg: "
+			    "NULL sock passed in.\n");
+		return -EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_upmsg: "
+		    "allocating %d bytes...\n",
+		    pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
+	if(!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_upmsg: "
+			    "no buffers left to send up a message.\n");
+		return -ENOBUFS;
+	}
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_upmsg: "
+		    "...allocated at %p.\n",
+		    skb);
+	
+	skb->dev = NULL;
+	
+	if(skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
+		printk(KERN_WARNING "klips_error:pfkey_upmsg: "
+		       "tried to skb_put %ld, %d available.  This should never happen, please report.\n",
+		       (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN,
+		       skb_tailroom(skb));
+#ifdef NET_21
+		kfree_skb(skb);
+#else /* NET_21 */
+		kfree_skb(skb, FREE_WRITE);
+#endif /* NET_21 */
+		return -ENOBUFS;
+	}
+	skb->h.raw = skb_put(skb, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
+	memcpy(skb->h.raw, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
+
+#ifndef NET_21
+	skb->free = 1;
+#endif /* !NET_21 */
+
+	if((error = sock_queue_rcv_skb(sk, skb)) < 0) {
+		skb->sk=NULL;
+#ifdef NET_21
+		kfree_skb(skb);
+#else /* NET_21 */
+		kfree_skb(skb, FREE_WRITE);
+#endif /* NET_21 */
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_upmsg: "
+			    "error=%d calling sock_queue_rcv_skb with skb=%p.\n",
+			    error,
+			    skb);
+		return error;
+	}
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_create(struct socket *sock, int protocol)
+{
+	struct sock *sk;
+
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_create: "
+			    "socket NULL.\n");
+		return -EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_create: "
+		    "sock=%p type:%d state:%d flags:%ld protocol:%d\n",
+		    sock,
+		    sock->type,
+		    (unsigned int)(sock->state),
+		    sock->flags, protocol);
+
+	if(sock->type != SOCK_RAW) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_create: "
+			    "only SOCK_RAW supported.\n");
+		return -ESOCKTNOSUPPORT;
+	}
+
+	if(protocol != PF_KEY_V2) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_create: "
+			    "protocol not PF_KEY_V2.\n");
+		return -EPROTONOSUPPORT;
+	}
+
+	if((current->uid != 0)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_create: "
+			    "must be root to open pfkey sockets.\n");
+		return -EACCES;
+	}
+
+#ifdef NET_21
+	sock->state = SS_UNCONNECTED;
+#endif /* NET_21 */
+	MOD_INC_USE_COUNT;
+#ifdef NET_21
+	if((sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1)) == NULL)
+#else /* NET_21 */
+	if((sk=(struct sock *)sk_alloc(GFP_KERNEL)) == NULL)
+#endif /* NET_21 */
+	{
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_create: "
+			    "Out of memory trying to allocate.\n");
+		MOD_DEC_USE_COUNT;
+		return -ENOMEM;
+	}
+
+#ifndef NET_21
+	memset(sk, 0, sizeof(*sk));
+#endif /* !NET_21 */
+
+#ifdef NET_21
+	sock_init_data(sock, sk);
+
+	sk->destruct = NULL;
+	sk->reuse = 1;
+	sock->ops = &SOCKOPS_WRAPPED(pfkey_ops);
+
+	sk->zapped=0;
+	sk->family = PF_KEY;
+/*	sk->num = protocol; */
+	sk->protocol = protocol;
+	key_pid(sk) = current->pid;
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_create: "
+		    "sock->fasync_list=%p sk->sleep=%p.\n",
+		    sock->fasync_list,
+		    sk->sleep);
+#else /* NET_21 */
+	sk->type=sock->type;
+	init_timer(&sk->timer);
+	skb_queue_head_init(&sk->write_queue);
+	skb_queue_head_init(&sk->receive_queue);
+	skb_queue_head_init(&sk->back_log);
+	sk->rcvbuf=SK_RMEM_MAX;
+	sk->sndbuf=SK_WMEM_MAX;
+	sk->allocation=GFP_KERNEL;
+	sk->state=TCP_CLOSE;
+	sk->priority=SOPRI_NORMAL;
+	sk->state_change=pfkey_state_change;
+	sk->data_ready=pfkey_data_ready;
+	sk->write_space=pfkey_write_space;
+	sk->error_report=pfkey_state_change;
+	sk->mtu=4096;
+	sk->socket=sock;
+	sock->data=(void *)sk;
+	sk->sleep=sock->wait;
+#endif /* NET_21 */
+
+	pfkey_insert_socket(sk);
+	pfkey_list_insert_socket(sock, &pfkey_open_sockets);
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_create: "
+		    "Socket sock=%p sk=%p initialised.\n", sock, sk);
+	return 0;
+}
+
+#ifndef NET_21
+DEBUG_NO_STATIC int
+pfkey_dup(struct socket *newsock, struct socket *oldsock)
+{
+	struct sock *sk;
+
+	if(newsock==NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_dup: "
+			    "No new socket attached.\n");
+		return -EINVAL;
+	}
+		
+	if(oldsock==NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_dup: "
+			    "No old socket attached.\n");
+		return -EINVAL;
+	}
+		
+#ifdef NET_21
+	sk=oldsock->sk;
+#else /* NET_21 */
+	sk=oldsock->data;
+#endif /* NET_21 */
+	
+	/* May not have data attached */
+	if(sk==NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_dup: "
+			    "No sock attached to old socket.\n");
+		return -EINVAL;
+	}
+		
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_dup: .\n");
+
+	return pfkey_create(newsock, sk->protocol);
+}
+#endif /* !NET_21 */
+
+DEBUG_NO_STATIC int
+#ifdef NETDEV_23
+pfkey_release(struct socket *sock)
+#else /* NETDEV_23 */
+pfkey_release(struct socket *sock, struct socket *peersock)
+#endif /* NETDEV_23 */
+{
+	struct sock *sk;
+	int i;
+
+	if(sock==NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_release: "
+			    "No socket attached.\n");
+		return 0; /* -EINVAL; */
+	}
+		
+#ifdef NET_21
+	sk=sock->sk;
+#else /* NET_21 */
+	sk=sock->data;
+#endif /* NET_21 */
+	
+	/* May not have data attached */
+	if(sk==NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_release: "
+			    "No sk attached to sock=%p.\n", sock);
+		return 0; /* -EINVAL; */
+	}
+		
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_release: "
+		    "sock=%p sk=%p\n", sock, sk);
+
+#ifdef NET_21
+	if(!sk->dead)
+#endif /* NET_21 */
+		if(sk->state_change) {
+			sk->state_change(sk);
+		}
+
+#ifdef NET_21
+	sock->sk = NULL;
+#else /* NET_21 */
+	sock->data = NULL;
+#endif /* NET_21 */
+
+	/* Try to flush out this socket. Throw out buffers at least */
+	pfkey_destroy_socket(sk);
+	pfkey_list_remove_socket(sock, &pfkey_open_sockets);
+	for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) {
+		pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i]));
+	}
+
+	MOD_DEC_USE_COUNT;
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_release: "
+		    "succeeded.\n");
+
+	return 0;
+}
+
+#ifndef NET_21
+DEBUG_NO_STATIC int
+pfkey_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_bind: "
+		    "operation not supported.\n");
+	return -EINVAL;
+}
+
+DEBUG_NO_STATIC int
+pfkey_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_connect: "
+		    "operation not supported.\n");
+	return -EINVAL;
+}
+
+DEBUG_NO_STATIC int
+pfkey_socketpair(struct socket *a, struct socket *b)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_socketpair: "
+		    "operation not supported.\n");
+	return -EINVAL;
+}
+
+DEBUG_NO_STATIC int
+pfkey_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_aaccept: "
+		    "operation not supported.\n");
+	return -EINVAL;
+}
+
+DEBUG_NO_STATIC int
+pfkey_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len,
+		int peer)
+{
+	struct sockaddr *ska = (struct sockaddr*)uaddr;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_getname: .\n");
+	ska->sa_family = PF_KEY;
+	*uaddr_len = sizeof(*ska);
+	return 0;
+}
+
+DEBUG_NO_STATIC int
+pfkey_select(struct socket *sock, int sel_type, select_table *wait)
+{
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_select: "
+		    ".sock=%p sk=%p sel_type=%d\n",
+		    sock,
+		    sock->data,
+		    sel_type);
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_select: "
+			    "Null socket passed in.\n");
+		return -EINVAL;
+	}
+	return datagram_select(sock->data, sel_type, wait);
+}
+
+DEBUG_NO_STATIC int
+pfkey_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_ioctl: "
+		    "not supported.\n");
+	return -EINVAL;
+}
+
+DEBUG_NO_STATIC int
+pfkey_listen(struct socket *sock, int backlog)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_listen: "
+		    "not supported.\n");
+	return -EINVAL;
+}
+#endif /* !NET_21 */
+
+DEBUG_NO_STATIC int
+pfkey_shutdown(struct socket *sock, int mode)
+{
+	struct sock *sk;
+
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_shutdown: "
+			    "NULL socket passed in.\n");
+		return -EINVAL;
+	}
+
+#ifdef NET_21
+	sk=sock->sk;
+#else /* NET_21 */
+	sk=sock->data;
+#endif /* NET_21 */
+	
+	if(sk == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_shutdown: "
+			    "No sock attached to socket.\n");
+		return -EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_shutdown: "
+		    "mode=%x.\n", mode);
+	mode++;
+	
+	if(mode&SEND_SHUTDOWN) {
+		sk->shutdown|=SEND_SHUTDOWN;
+		sk->state_change(sk);
+	}
+
+	if(mode&RCV_SHUTDOWN) {
+		sk->shutdown|=RCV_SHUTDOWN;
+		sk->state_change(sk);
+	}
+	return 0;
+}
+
+#ifndef NET_21
+DEBUG_NO_STATIC int
+pfkey_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
+{
+#ifndef NET_21
+	struct sock *sk;
+
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null socket passed in.\n");
+		return -EINVAL;
+	}
+	
+	sk=sock->data;
+	
+	if(sk == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null sock passed in.\n");
+		return -EINVAL;
+	}
+#endif /* !NET_21 */
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_setsockopt: .\n");
+	if(level!=SOL_SOCKET) {
+		return -EOPNOTSUPP;
+	}
+#ifdef NET_21
+	return sock_setsockopt(sock, level, optname, optval, optlen);
+#else /* NET_21 */
+	return sock_setsockopt(sk, level, optname, optval, optlen);
+#endif /* NET_21 */
+}
+
+DEBUG_NO_STATIC int
+pfkey_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen)
+{
+#ifndef NET_21
+	struct sock *sk;
+
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null socket passed in.\n");
+		return -EINVAL;
+	}
+	
+	sk=sock->data;
+	
+	if(sk == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null sock passed in.\n");
+		return -EINVAL;
+	}
+#endif /* !NET_21 */
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_getsockopt: .\n");
+	if(level!=SOL_SOCKET) {
+		return -EOPNOTSUPP;
+	}
+#ifdef NET_21
+	return sock_getsockopt(sock, level, optname, optval, optlen);
+#else /* NET_21 */
+	return sock_getsockopt(sk, level, optname, optval, optlen);
+#endif /* NET_21 */
+}
+
+DEBUG_NO_STATIC int
+pfkey_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_fcntl: "
+		    "not supported.\n");
+	return -EINVAL;
+}
+#endif /* !NET_21 */
+
+/*
+ *	Send PF_KEY data down.
+ */
+		
+DEBUG_NO_STATIC int
+#ifdef NET_21
+pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
+#else /* NET_21 */
+pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
+#endif /* NET_21 */
+{
+	struct sock *sk;
+	int error = 0;
+	struct sadb_msg *pfkey_msg = NULL, *pfkey_reply = NULL;
+	
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "Null socket passed in.\n");
+		SENDERR(EINVAL);
+	}
+	
+#ifdef NET_21
+	sk = sock->sk;
+#else /* NET_21 */
+	sk = sock->data;
+#endif /* NET_21 */
+
+	if(sk == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "Null sock passed in.\n");
+		SENDERR(EINVAL);
+	}
+	
+	if(msg == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "Null msghdr passed in.\n");
+		SENDERR(EINVAL);
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_sendmsg: .\n");
+	if(sk->err) {
+		error = sock_error(sk);
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "sk->err is non-zero, returns %d.\n",
+			    error);
+		SENDERR(-error);
+	}
+
+	if((current->uid != 0)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "must be root to send messages to pfkey sockets.\n");
+		SENDERR(EACCES);
+	}
+
+#ifdef NET_21
+	if(msg->msg_control)
+#else /* NET_21 */
+	if(flags || msg->msg_control)
+#endif /* NET_21 */
+	{
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "can't set flags or set msg_control.\n");
+		SENDERR(EINVAL);
+	}
+		
+	if(sk->shutdown & SEND_SHUTDOWN) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "shutdown.\n");
+		send_sig(SIGPIPE, current, 0);
+		SENDERR(EPIPE);
+	}
+	
+	if(len < sizeof(struct sadb_msg)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "bogus msg len of %d, too small.\n", len);
+		SENDERR(EMSGSIZE);
+	}
+
+	if((pfkey_msg = (struct sadb_msg*)kmalloc(len, GFP_KERNEL)) == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "memory allocation error.\n");
+		SENDERR(ENOBUFS);
+	}
+
+	memcpy_fromiovec((void *)pfkey_msg, msg->msg_iov, len);
+
+	if(pfkey_msg->sadb_msg_version != PF_KEY_V2) {
+		KLIPS_PRINT(1 || debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "not PF_KEY_V2 msg, found %d, should be %d.\n",
+			    pfkey_msg->sadb_msg_version,
+			    PF_KEY_V2);
+		kfree((void*)pfkey_msg);
+		return -EINVAL;
+	}
+
+	if(len != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "bogus msg len of %d, not %d byte aligned.\n",
+			    len, IPSEC_PFKEYv2_ALIGN);
+		SENDERR(EMSGSIZE);
+	}
+
+#if 0
+	/* This check is questionable, since a downward message could be
+	   the result of an ACQUIRE either from kernel (PID==0) or
+	   userspace (some other PID). */
+	/* check PID */
+	if(pfkey_msg->sadb_msg_pid != current->pid) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "pid (%d) does not equal sending process pid (%d).\n",
+			    pfkey_msg->sadb_msg_pid, current->pid);
+		SENDERR(EINVAL);
+	}
+#endif
+
+	if(pfkey_msg->sadb_msg_reserved) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "reserved field must be zero, set to %d.\n",
+			    pfkey_msg->sadb_msg_reserved);
+		SENDERR(EINVAL);
+	}
+	
+	if((pfkey_msg->sadb_msg_type > SADB_MAX) || (!pfkey_msg->sadb_msg_type)){
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "msg type too large or small:%d.\n",
+			    pfkey_msg->sadb_msg_type);
+		SENDERR(EINVAL);
+	}
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_sendmsg: "
+		    "msg sent for parsing.\n");
+	
+	if((error = pfkey_msg_interp(sk, pfkey_msg, &pfkey_reply))) {
+		struct socket_list *pfkey_socketsp;
+
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
+			    "pfkey_msg_parse returns %d.\n",
+			    error);
+
+		if((pfkey_reply = (struct sadb_msg*)kmalloc(sizeof(struct sadb_msg), GFP_KERNEL)) == NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_sendmsg: "
+				    "memory allocation error.\n");
+			SENDERR(ENOBUFS);
+		}
+		memcpy((void*)pfkey_reply, (void*)pfkey_msg, sizeof(struct sadb_msg));
+		pfkey_reply->sadb_msg_errno = -error;
+		pfkey_reply->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
+
+		for(pfkey_socketsp = pfkey_open_sockets;
+		    pfkey_socketsp;
+		    pfkey_socketsp = pfkey_socketsp->next) {
+			int error_upmsg = 0;
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
+				    "sending up error=%d message=%p to socket=%p.\n",
+				    error,
+				    pfkey_reply,
+				    pfkey_socketsp->socketp);
+			if((error_upmsg = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+				KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
+					    "sending up error message to socket=%p failed with error=%d.\n",
+					    pfkey_socketsp->socketp,
+					    error_upmsg);
+				/* pfkey_msg_free(&pfkey_reply); */
+				/* SENDERR(-error); */
+			}
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
+				    "sending up error message to socket=%p succeeded.\n",
+				    pfkey_socketsp->socketp);
+		}
+		
+		pfkey_msg_free(&pfkey_reply);
+		
+		SENDERR(-error);
+	}
+
+ errlab:
+	if (pfkey_msg) {
+		kfree((void*)pfkey_msg);
+	}
+	
+	if(error) {
+		return error;
+	} else {
+		return len;
+	}
+}
+
+/*
+ *	Receive PF_KEY data up.
+ */
+		
+DEBUG_NO_STATIC int
+#ifdef NET_21
+pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
+#else /* NET_21 */
+pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
+#endif /* NET_21 */
+{
+	struct sock *sk;
+#ifdef NET_21
+	int noblock = flags & MSG_DONTWAIT;
+#endif /* NET_21 */
+	struct sk_buff *skb;
+	int error;
+
+	if(sock == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_recvmsg: "
+			    "Null socket passed in.\n");
+		return -EINVAL;
+	}
+
+#ifdef NET_21
+	sk = sock->sk;
+#else /* NET_21 */
+	sk = sock->data;
+#endif /* NET_21 */
+
+	if(sk == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_recvmsg: "
+			    "Null sock passed in for sock=%p.\n", sock);
+		return -EINVAL;
+	}
+
+	if(msg == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_recvmsg: "
+			    "Null msghdr passed in for sock=%p, sk=%p.\n",
+			    sock, sk);
+		return -EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+		    "klips_debug:pfkey_recvmsg: sock=%p sk=%p msg=%p size=%d.\n",
+		    sock, sk, msg, size);
+	if(flags & ~MSG_PEEK) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "flags (%d) other than MSG_PEEK not supported.\n",
+			    flags);
+		return -EOPNOTSUPP;
+	}
+		
+#ifdef NET_21
+	msg->msg_namelen = 0; /* sizeof(*ska); */
+#else /* NET_21 */
+	if(addr_len) {
+		*addr_len = 0; /* sizeof(*ska); */
+	}
+#endif /* NET_21 */
+		
+	if(sk->err) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sendmsg: "
+			    "sk->err=%d.\n", sk->err);
+		return sock_error(sk);
+	}
+
+	if((skb = skb_recv_datagram(sk, flags, noblock, &error) ) == NULL) {
+                return error;
+	}
+
+	if(size > skb->len) {
+		size = skb->len;
+	}
+#ifdef NET_21
+	else if(size <skb->len) {
+		msg->msg_flags |= MSG_TRUNC;
+	}
+#endif /* NET_21 */
+
+	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size);
+        sk->stamp=skb->stamp;
+
+	skb_free_datagram(sk, skb);
+	return size;
+}
+
+#ifdef NET_21
+struct net_proto_family pfkey_family_ops = {
+	PF_KEY,
+	pfkey_create
+};
+
+struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = {
+#ifdef NETDEV_23
+	family:		PF_KEY,
+	release:	pfkey_release,
+	bind:		sock_no_bind,
+	connect:	sock_no_connect,
+	socketpair:	sock_no_socketpair,
+	accept:		sock_no_accept,
+	getname:	sock_no_getname,
+	poll:		datagram_poll,
+	ioctl:		sock_no_ioctl,
+	listen:		sock_no_listen,
+	shutdown:	pfkey_shutdown,
+	setsockopt:	sock_no_setsockopt,
+	getsockopt:	sock_no_getsockopt,
+	sendmsg:	pfkey_sendmsg,
+	recvmsg:	pfkey_recvmsg,
+	mmap:		sock_no_mmap,
+#else /* NETDEV_23 */
+	PF_KEY,
+	sock_no_dup,
+	pfkey_release,
+	sock_no_bind,
+	sock_no_connect,
+	sock_no_socketpair,
+	sock_no_accept,
+	sock_no_getname,
+	datagram_poll,
+	sock_no_ioctl,
+	sock_no_listen,
+	pfkey_shutdown,
+	sock_no_setsockopt,
+	sock_no_getsockopt,
+	sock_no_fcntl,
+	pfkey_sendmsg,
+	pfkey_recvmsg
+#endif /* NETDEV_23 */
+};
+
+#ifdef NETDEV_23
+#include <linux/smp_lock.h>
+SOCKOPS_WRAP(pfkey, PF_KEY);
+#endif /* NETDEV_23 */
+
+#else /* NET_21 */
+struct proto_ops pfkey_proto_ops = {
+	PF_KEY,
+	pfkey_create,
+	pfkey_dup,
+	pfkey_release,
+	pfkey_bind,
+	pfkey_connect,
+	pfkey_socketpair,
+	pfkey_accept,
+	pfkey_getname,
+	pfkey_select,
+	pfkey_ioctl,
+	pfkey_listen,
+	pfkey_shutdown,
+	pfkey_setsockopt,
+	pfkey_getsockopt,
+	pfkey_fcntl,
+	pfkey_sendmsg,
+	pfkey_recvmsg
+};
+#endif /* NET_21 */
+   
+#ifdef CONFIG_PROC_FS
+#ifndef PROC_FS_2325
+DEBUG_NO_STATIC
+#endif /* PROC_FS_2325 */
+int
+pfkey_get_info(char *buffer, char **start, off_t offset, int length
+#ifndef  PROC_NO_DUMMY
+, int dummy
+#endif /* !PROC_NO_DUMMY */
+)
+{
+	off_t pos=0;
+	off_t begin=0;
+	int len=0;
+	struct sock *sk=pfkey_sock_list;
+	
+#ifdef CONFIG_IPSEC_DEBUG
+	if(!sysctl_ipsec_debug_verbose) {
+#endif /* CONFIG_IPSEC_DEBUG */
+	len+= sprintf(buffer,
+		      "    sock   pid   socket     next     prev e n p sndbf    Flags     Type St\n");
+#ifdef CONFIG_IPSEC_DEBUG
+	} else {
+	len+= sprintf(buffer,
+		      "    sock   pid d    sleep   socket     next     prev e r z n p sndbf    stamp    Flags     Type St\n");
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+	
+	while(sk!=NULL) {
+#ifdef CONFIG_IPSEC_DEBUG
+		if(!sysctl_ipsec_debug_verbose) {
+#endif /* CONFIG_IPSEC_DEBUG */
+		len+=sprintf(buffer+len,
+			     "%8p %5d %8p %8p %8p %d %d %d %5d %08lX %8X %2X\n",
+			     sk,
+			     key_pid(sk),
+			     sk->socket,
+			     sk->next,
+			     sk->prev,
+			     sk->err,
+			     sk->num,
+			     sk->protocol,
+			     sk->sndbuf,
+			     sk->socket->flags,
+			     sk->socket->type,
+			     sk->socket->state);
+#ifdef CONFIG_IPSEC_DEBUG
+		} else {
+		len+=sprintf(buffer+len,
+			     "%8p %5d %d %8p %8p %8p %8p %d %d %d %d %d %5d %d.%06d %08lX %8X %2X\n",
+			     sk,
+			     key_pid(sk),
+			     sk->dead,
+			     sk->sleep,
+			     sk->socket,
+			     sk->next,
+			     sk->prev,
+			     sk->err,
+			     sk->reuse,
+			     sk->zapped,
+			     sk->num,
+			     sk->protocol,
+			     sk->sndbuf,
+			     (unsigned int)sk->stamp.tv_sec,
+			     (unsigned int)sk->stamp.tv_usec,
+			     sk->socket->flags,
+			     sk->socket->type,
+			     sk->socket->state);
+		}
+#endif /* CONFIG_IPSEC_DEBUG */
+		
+		pos=begin+len;
+		if(pos<offset)
+		{
+			len=0;
+			begin=pos;
+		}
+		if(pos>offset+length)
+			break;
+		sk=sk->next;
+	}
+	*start=buffer+(offset-begin);
+	len-=(offset-begin);
+	if(len>length)
+		len=length;
+	return len;
+}
+
+#ifndef PROC_FS_2325
+DEBUG_NO_STATIC
+#endif /* PROC_FS_2325 */
+int
+pfkey_supported_get_info(char *buffer, char **start, off_t offset, int length
+#ifndef  PROC_NO_DUMMY
+, int dummy
+#endif /* !PROC_NO_DUMMY */
+)
+{
+	off_t pos=0;
+	off_t begin=0;
+	int len=0;
+	int satype;
+	struct supported_list *pfkey_supported_p;
+	
+	len+= sprintf(buffer,
+		      "satype exttype alg_id ivlen minbits maxbits\n");
+	
+	for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) {
+		pfkey_supported_p = pfkey_supported_list[satype];
+		while(pfkey_supported_p) {
+			len+=sprintf(buffer+len,
+				     "    %2d      %2d     %2d   %3d     %3d     %3d\n",
+				     satype,
+				     pfkey_supported_p->supportedp->supported_alg_exttype,
+				     pfkey_supported_p->supportedp->supported_alg_id,
+				     pfkey_supported_p->supportedp->supported_alg_ivlen,
+				     pfkey_supported_p->supportedp->supported_alg_minbits,
+				     pfkey_supported_p->supportedp->supported_alg_maxbits);
+			
+			pos=begin+len;
+			if(pos<offset) {
+				len=0;
+				begin=pos;
+			}
+			if(pos>offset+length)
+				break;
+			pfkey_supported_p = pfkey_supported_p->next;
+		}
+	}
+	*start=buffer+(offset-begin);
+	len-=(offset-begin);
+	if(len>length)
+		len=length;
+	return len;
+}
+
+#ifndef PROC_FS_2325
+DEBUG_NO_STATIC
+#endif /* PROC_FS_2325 */
+int
+pfkey_registered_get_info(char *buffer, char **start, off_t offset, int length
+#ifndef  PROC_NO_DUMMY
+, int dummy
+#endif /* !PROC_NO_DUMMY */
+)
+{
+	off_t pos=0;
+	off_t begin=0;
+	int len=0;
+	int satype;
+	struct socket_list *pfkey_sockets;
+	
+	len+= sprintf(buffer,
+		      "satype   socket   pid       sk\n");
+	
+	for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) {
+		pfkey_sockets = pfkey_registered_sockets[satype];
+		while(pfkey_sockets) {
+#ifdef NET_21
+			len+=sprintf(buffer+len,
+				     "    %2d %8p %5d %8p\n",
+				     satype,
+				     pfkey_sockets->socketp,
+				     key_pid(pfkey_sockets->socketp->sk),
+				     pfkey_sockets->socketp->sk);
+#else /* NET_21 */
+			len+=sprintf(buffer+len,
+				     "    %2d %8p   N/A %8p\n",
+				     satype,
+				     pfkey_sockets->socketp,
+#if 0
+				     key_pid((pfkey_sockets->socketp)->data),
+#endif
+				     (pfkey_sockets->socketp)->data);
+#endif /* NET_21 */
+			
+			pos=begin+len;
+			if(pos<offset) {
+				len=0;
+				begin=pos;
+			}
+			if(pos>offset+length)
+				break;
+			pfkey_sockets = pfkey_sockets->next;
+		}
+	}
+	*start=buffer+(offset-begin);
+	len-=(offset-begin);
+	if(len>length)
+		len=length;
+	return len;
+}
+
+#ifndef PROC_FS_2325
+struct proc_dir_entry proc_net_pfkey =
+{
+	0,
+	6, "pf_key",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	pfkey_get_info
+};
+struct proc_dir_entry proc_net_pfkey_supported =
+{
+	0,
+	16, "pf_key_supported",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	pfkey_supported_get_info
+};
+struct proc_dir_entry proc_net_pfkey_registered =
+{
+	0,
+	17, "pf_key_registered",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	pfkey_registered_get_info
+};
+#endif /* !PROC_FS_2325 */
+#endif /* CONFIG_PROC_FS */
+
+DEBUG_NO_STATIC int
+supported_add_all(int satype, struct supported supported[], int size)
+{
+	int i;
+	int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:init_pfkey: "
+		    "sizeof(supported_init_<satype=%d>)[%d]/sizeof(struct supported)[%d]=%d.\n",
+		    satype,
+		    size,
+		    sizeof(struct supported),
+		    size/sizeof(struct supported));
+
+	for(i = 0; i < size / sizeof(struct supported); i++) {
+		
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:init_pfkey: "
+			    "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n",
+			    i,
+			    satype,
+			    supported[i].supported_alg_exttype,
+			    supported[i].supported_alg_id,
+			    supported[i].supported_alg_ivlen,
+			    supported[i].supported_alg_minbits,
+			    supported[i].supported_alg_maxbits);
+			    
+		error |= pfkey_list_insert_supported(&(supported[i]),
+					    &(pfkey_supported_list[satype]));
+	}
+	return error;
+}
+
+DEBUG_NO_STATIC int
+supported_remove_all(int satype)
+{
+	int error = 0;
+	struct supported*supportedp;
+
+	while(pfkey_supported_list[satype]) {
+		supportedp = pfkey_supported_list[satype]->supportedp;
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:init_pfkey: "
+			    "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n",
+			    satype,
+			    supportedp->supported_alg_exttype,
+			    supportedp->supported_alg_id,
+			    supportedp->supported_alg_ivlen,
+			    supportedp->supported_alg_minbits,
+			    supportedp->supported_alg_maxbits);
+			    
+		error |= pfkey_list_remove_supported(supportedp,
+					    &(pfkey_supported_list[satype]));
+	}
+	return error;
+}
+
+int
+pfkey_init(void)
+{
+	int error = 0;
+	int i;
+	
+	static struct supported supported_init_ah[] = {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+		{SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128},
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+		{SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160}
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+	};
+	static struct supported supported_init_esp[] = {
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+		{SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128},
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+		{SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160},
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+#ifdef CONFIG_IPSEC_ENC_3DES
+		{SADB_EXT_SUPPORTED_ENCRYPT, SADB_EALG_3DESCBC, 64, 168, 168},
+#endif /* CONFIG_IPSEC_ENC_3DES */
+	};
+	static struct supported supported_init_ipip[] = {
+		{SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		, {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32}
+		, {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128}
+		, {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128}
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+	};
+#ifdef CONFIG_IPSEC_IPCOMP
+	static struct supported supported_init_ipcomp[] = {
+		{SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1}
+	};
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#if 0
+        printk(KERN_INFO
+	       "klips_info:pfkey_init: "
+	       "FreeS/WAN: initialising PF_KEYv2 domain sockets.\n");
+#endif
+
+	for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) {
+		pfkey_registered_sockets[i] = NULL;
+		pfkey_supported_list[i] = NULL;
+	}
+
+	error |= supported_add_all(SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah));
+	error |= supported_add_all(SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp));
+#ifdef CONFIG_IPSEC_IPCOMP
+	error |= supported_add_all(SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp));
+#endif /* CONFIG_IPSEC_IPCOMP */
+	error |= supported_add_all(SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip));
+
+#ifdef NET_21
+        error |= sock_register(&pfkey_family_ops);
+#else /* NET_21 */
+        error |= sock_register(pfkey_proto_ops.family, &pfkey_proto_ops);
+#endif /* NET_21 */
+
+#ifdef CONFIG_PROC_FS
+#  ifndef PROC_FS_2325
+#    ifdef PROC_FS_21
+	error |= proc_register(proc_net, &proc_net_pfkey);
+	error |= proc_register(proc_net, &proc_net_pfkey_supported);
+	error |= proc_register(proc_net, &proc_net_pfkey_registered);
+#    else /* PROC_FS_21 */
+	error |= proc_register_dynamic(&proc_net, &proc_net_pfkey);
+	error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_supported);
+	error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_registered);
+#    endif /* PROC_FS_21 */
+#  else /* !PROC_FS_2325 */
+	proc_net_create ("pf_key", 0, pfkey_get_info);
+	proc_net_create ("pf_key_supported", 0, pfkey_supported_get_info);
+	proc_net_create ("pf_key_registered", 0, pfkey_registered_get_info);
+#  endif /* !PROC_FS_2325 */
+#endif /* CONFIG_PROC_FS */
+
+	return error;
+}
+
+int
+pfkey_cleanup(void)
+{
+	int error = 0;
+	
+        printk(KERN_INFO "klips_info:pfkey_cleanup: "
+	       "shutting down PF_KEY domain sockets.\n");
+#ifdef NET_21
+        error |= sock_unregister(PF_KEY);
+#else /* NET_21 */
+        error |= sock_unregister(pfkey_proto_ops.family);
+#endif /* NET_21 */
+
+	error |= supported_remove_all(SADB_SATYPE_AH);
+	error |= supported_remove_all(SADB_SATYPE_ESP);
+#ifdef CONFIG_IPSEC_IPCOMP
+	error |= supported_remove_all(SADB_X_SATYPE_COMP);
+#endif /* CONFIG_IPSEC_IPCOMP */
+	error |= supported_remove_all(SADB_X_SATYPE_IPIP);
+
+#ifdef CONFIG_PROC_FS
+#  ifndef PROC_FS_2325
+	if (proc_net_unregister(proc_net_pfkey.low_ino) != 0)
+		printk("klips_debug:pfkey_cleanup: "
+		       "cannot unregister /proc/net/pf_key\n");
+	if (proc_net_unregister(proc_net_pfkey_supported.low_ino) != 0)
+		printk("klips_debug:pfkey_cleanup: "
+		       "cannot unregister /proc/net/pf_key_supported\n");
+	if (proc_net_unregister(proc_net_pfkey_registered.low_ino) != 0)
+		printk("klips_debug:pfkey_cleanup: "
+		       "cannot unregister /proc/net/pf_key_registered\n");
+#  else /* !PROC_FS_2325 */
+	proc_net_remove ("pf_key");
+	proc_net_remove ("pf_key_supported");
+	proc_net_remove ("pf_key_registered");
+#  endif /* !PROC_FS_2325 */
+#endif /* CONFIG_PROC_FS */
+
+	/* other module unloading cleanup happens here */
+	return error;
+}
+
+#ifdef MODULE
+#if 0
+int
+init_module(void)
+{
+	pfkey_init();
+	return 0;
+}
+
+void
+cleanup_module(void)
+{
+	pfkey_cleanup();
+}
+#endif /* 0 */
+#else /* MODULE */
+void
+pfkey_proto_init(struct net_proto *pro)
+{
+	pfkey_init();
+}
+#endif /* MODULE */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.2  2002/09/05 03:27:09  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:18  ken
+ * 1.98b
+ *
+ * Revision 1.68  2002/03/08 01:15:17  mcr
+ * 	put some internal structure only debug messages behind
+ * 	&& sysctl_ipsec_debug_verbose.
+ *
+ * Revision 1.67  2002/01/29 17:17:57  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.66  2002/01/29 04:00:54  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.65  2002/01/29 02:13:18  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.64  2001/11/26 09:23:51  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.61.2.1  2001/09/25 02:28:44  mcr
+ * 	cleaned up includes.
+ *
+ * Revision 1.63  2001/11/12 19:38:00  rgb
+ * Continue trying other sockets even if one fails and return only original
+ * error.
+ *
+ * Revision 1.62  2001/10/18 04:45:22  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.61  2001/09/20 15:32:59  rgb
+ * Min/max cleanup.
+ *
+ * Revision 1.60  2001/06/14 19:35:12  rgb
+ * Update copyright date.
+ *
+ * Revision 1.59  2001/06/13 15:35:48  rgb
+ * Fixed #endif comments.
+ *
+ * Revision 1.58  2001/05/04 16:37:24  rgb
+ * Remove erroneous checking of return codes for proc_net_* in 2.4.
+ *
+ * Revision 1.57  2001/05/03 19:43:36  rgb
+ * Initialise error return variable.
+ * Check error return codes in startup and shutdown.
+ * Standardise on SENDERR() macro.
+ *
+ * Revision 1.56  2001/04/21 23:05:07  rgb
+ * Define out skb->used for 2.4 kernels.
+ *
+ * Revision 1.55  2001/02/28 05:03:28  rgb
+ * Clean up and rationalise startup messages.
+ *
+ * Revision 1.54  2001/02/27 22:24:55  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.53  2001/02/27 06:48:18  rgb
+ * Fixed pfkey socket unregister log message to reflect type and function.
+ *
+ * Revision 1.52  2001/02/26 22:34:38  rgb
+ * Fix error return code that was getting overwritten by the error return
+ * code of an upmsg.
+ *
+ * Revision 1.51  2001/01/30 23:42:47  rgb
+ * Allow pfkey msgs from pid other than user context required for ACQUIRE
+ * and subsequent ADD or UDATE.
+ *
+ * Revision 1.50  2001/01/23 20:22:59  rgb
+ * 2.4 fix to remove removed is_clone member.
+ *
+ * Revision 1.49  2000/11/06 04:33:47  rgb
+ * Changed non-exported functions to DEBUG_NO_STATIC.
+ *
+ * Revision 1.48  2000/09/29 19:47:41  rgb
+ * Update copyright.
+ *
+ * Revision 1.47  2000/09/22 04:23:04  rgb
+ * Added more debugging to pfkey_upmsg() call from pfkey_sendmsg() error.
+ *
+ * Revision 1.46  2000/09/21 04:20:44  rgb
+ * Fixed array size off-by-one error.  (Thanks Svenning!)
+ *
+ * Revision 1.45  2000/09/20 04:01:26  rgb
+ * Changed static functions to DEBUG_NO_STATIC for revealing function names
+ * in oopsen.
+ *
+ * Revision 1.44  2000/09/19 00:33:17  rgb
+ * 2.0 fixes.
+ *
+ * Revision 1.43  2000/09/16 01:28:13  rgb
+ * Fixed use of 0 in p format warning.
+ *
+ * Revision 1.42  2000/09/16 01:09:41  rgb
+ * Fixed debug format warning for pointers that was expecting ints.
+ *
+ * Revision 1.41  2000/09/13 15:54:00  rgb
+ * Rewrote pfkey_get_info(), added pfkey_{supported,registered}_get_info().
+ * Moved supported algos add and remove to functions.
+ *
+ * Revision 1.40  2000/09/12 18:49:28  rgb
+ * Added IPIP tunnel and IPCOMP register support.
+ *
+ * Revision 1.39  2000/09/12 03:23:49  rgb
+ * Converted #if0 debugs to sysctl.
+ * Removed debug_pfkey initialisations that prevented no_debug loading or
+ * linking.
+ *
+ * Revision 1.38  2000/09/09 06:38:02  rgb
+ * Return positive errno in pfkey_reply error message.
+ *
+ * Revision 1.37  2000/09/08 19:19:09  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Clean-up of long-unused crud...
+ * Create pfkey error message on on failure.
+ * Give pfkey_list_{insert,remove}_{socket,supported}() some error
+ * checking.
+ *
+ * Revision 1.36  2000/09/01 18:49:38  rgb
+ * Reap experimental NET_21_ bits.
+ * Turned registered sockets list into an array of one list per satype.
+ * Remove references to deprecated sklist_{insert,remove}_socket.
+ * Removed leaking socket debugging code.
+ * Removed duplicate pfkey_insert_socket in pfkey_create.
+ * Removed all references to pfkey msg->msg_name, since it is not used for
+ * pfkey.
+ * Added a supported algorithms array lists, one per satype and registered
+ * existing algorithms.
+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to
+ * list.
+ * Only send pfkey_expire() messages to sockets registered for that satype.
+ *
+ * Revision 1.35  2000/08/24 17:03:00  rgb
+ * Corrected message size error return code for PF_KEYv2.
+ * Removed downward error prohibition.
+ *
+ * Revision 1.34  2000/08/21 16:32:26  rgb
+ * Re-formatted for cosmetic consistency and readability.
+ *
+ * Revision 1.33  2000/08/20 21:38:24  rgb
+ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil)
+ * Extended the upward message initiation of pfkey_sendmsg(). (Momchil)
+ *
+ * Revision 1.32  2000/07/28 14:58:31  rgb
+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
+ *
+ * Revision 1.31  2000/05/16 03:04:00  rgb
+ * Updates for 2.3.99pre8 from MB.
+ *
+ * Revision 1.30  2000/05/10 19:22:21  rgb
+ * Use sklist private functions for 2.3.xx compatibility.
+ *
+ * Revision 1.29  2000/03/22 16:17:03  rgb
+ * Fixed SOCKOPS_WRAPPED macro for SMP (MB).
+ *
+ * Revision 1.28  2000/02/21 19:30:45  rgb
+ * Removed references to pkt_bridged for 2.3.47 compatibility.
+ *
+ * Revision 1.27  2000/02/14 21:07:00  rgb
+ * Fixed /proc/net/pf-key legend spacing.
+ *
+ * Revision 1.26  2000/01/22 03:46:59  rgb
+ * Fixed pfkey error return mechanism so that we are able to free the
+ * local copy of the pfkey_msg, plugging a memory leak and silencing
+ * the bad object free complaints.
+ *
+ * Revision 1.25  2000/01/21 06:19:44  rgb
+ * Moved pfkey_list_remove_socket() calls to before MOD_USE_DEC_COUNT.
+ * Added debugging to pfkey_upmsg.
+ *
+ * Revision 1.24  2000/01/10 16:38:23  rgb
+ * MB fixups for 2.3.x.
+ *
+ * Revision 1.23  1999/12/09 23:22:16  rgb
+ * Added more instrumentation for debugging 2.0 socket
+ * selection/reading.
+ * Removed erroneous 2.0 wait==NULL check bug in select.
+ *
+ * Revision 1.22  1999/12/08 20:32:16  rgb
+ * Tidied up 2.0.xx support, after major pfkey work, eliminating
+ * msg->msg_name twiddling in the process, since it is not defined
+ * for PF_KEYv2.
+ *
+ * Revision 1.21  1999/12/01 22:17:19  rgb
+ * Set skb->dev to zero on new skb in case it is a reused skb.
+ * Added check for skb_put overflow and freeing to avoid upmsg on error.
+ * Added check for wrong pfkey version and freeing to avoid upmsg on
+ * error.
+ * Shut off content dumping in pfkey_destroy.
+ * Added debugging message for size of buffer allocated for upmsg.
+ *
+ * Revision 1.20  1999/11/27 12:11:00  rgb
+ * Minor clean-up, enabling quiet operation of pfkey if desired.
+ *
+ * Revision 1.19  1999/11/25 19:04:21  rgb
+ * Update proc_fs code for pfkey to use dynamic registration.
+ *
+ * Revision 1.18  1999/11/25 09:07:17  rgb
+ * Implemented SENDERR macro for propagating error codes.
+ * Fixed error return code bug.
+ *
+ * Revision 1.17  1999/11/23 23:07:20  rgb
+ * Change name of pfkey_msg_parser to pfkey_msg_interp since it no longer
+ * parses. (PJO)
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ *
+ * Revision 1.16  1999/11/20 22:00:22  rgb
+ * Moved socketlist type declarations and prototypes for shared use.
+ * Renamed reformatted and generically extended for use by other socket
+ * lists pfkey_{del,add}_open_socket to pfkey_list_{remove,insert}_socket.
+ *
+ * Revision 1.15  1999/11/18 04:15:09  rgb
+ * Make pfkey_data_ready temporarily available for 2.2.x testing.
+ * Clean up pfkey_destroy_socket() debugging statements.
+ * Add Peter Onion's code to send messages up to all listening sockets.
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ * Replaced all kernel version macros to shorter, readable form.
+ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
+ *
+ * Revision 1.14  1999/11/17 16:01:00  rgb
+ * Make pfkey_data_ready temporarily available for 2.2.x testing.
+ * Clean up pfkey_destroy_socket() debugging statements.
+ * Add Peter Onion's code to send messages up to all listening sockets.
+ * Changed #include "../../../lib/freeswan.h" to #include <freeswan.h>
+ * which works due to -Ilibfreeswan in the klips/net/ipsec/Makefile.
+ *
+ * Revision 1.13  1999/10/27 19:59:51  rgb
+ * Removed af_unix comments that are no longer relevant.
+ * Added debug prink statements.
+ * Added to the /proc output in pfkey_get_info.
+ * Made most functions non-static to enable oops tracing.
+ * Re-enable skb dequeueing and freeing.
+ * Fix skb_alloc() and skb_put() size bug in pfkey_upmsg().
+ *
+ * Revision 1.12  1999/10/26 17:05:42  rgb
+ * Complete re-ordering based on proto_ops structure order.
+ * Separated out proto_ops structures for 2.0.x and 2.2.x for clarity.
+ * Simplification to use built-in socket ops where possible for 2.2.x.
+ * Add shorter macros for compiler directives to visually clean-up.
+ * Add lots of sk skb dequeueing debugging statements.
+ * Added to the /proc output in pfkey_get_info.
+ *
+ * Revision 1.11  1999/09/30 02:55:10  rgb
+ * Bogus skb detection.
+ * Fix incorrect /proc/net/ipsec-eroute printk message.
+ *
+ * Revision 1.10  1999/09/21 15:22:13  rgb
+ * Temporary fix while I figure out the right way to destroy sockets.
+ *
+ * Revision 1.9  1999/07/08 19:19:44  rgb
+ * Fix pointer format warning.
+ * Fix missing member error under 2.0.xx kernels.
+ *
+ * Revision 1.8  1999/06/13 07:24:04  rgb
+ * Add more debugging.
+ *
+ * Revision 1.7  1999/06/10 05:24:17  rgb
+ * Clarified compiler directives.
+ * Renamed variables to reduce confusion.
+ * Used sklist_*_socket() kernel functions to simplify 2.2.x socket support.
+ * Added lots of sanity checking.
+ *
+ * Revision 1.6  1999/06/03 18:59:50  rgb
+ * More updates to 2.2.x socket support.  Almost works, oops at end of call.
+ *
+ * Revision 1.5  1999/05/25 22:44:05  rgb
+ * Start fixing 2.2 sockets.
+ *
+ * Revision 1.4  1999/04/29 15:21:34  rgb
+ * Move log to the end of the file.
+ * Eliminate min/max redefinition in #include <net/tcp.h>.
+ * Correct path for pfkey #includes
+ * Standardise an error return method.
+ * Add debugging instrumentation.
+ * Move message type checking to pfkey_msg_parse().
+ * Add check for errno incorrectly set.
+ * Add check for valid PID.
+ * Add check for reserved illegally set.
+ * Add check for message out of bounds.
+ *
+ * Revision 1.3  1999/04/15 17:58:07  rgb
+ * Add RCSID labels.
+ *
+ * Revision 1.2  1999/04/15 15:37:26  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.1.2.2  1999/04/13 20:37:12  rgb
+ * Header Title correction.
+ *
+ * Revision 1.1.2.1  1999/03/26 20:58:55  rgb
+ * Add pfkeyv2 support to KLIPS.
+ *
+ *
+ * RFC 2367
+ * PF_KEY_v2 Key Management API
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/pfkey_v2_parser.c linux-patched/net/ipsec/pfkey_v2_parser.c
--- linux/net/ipsec/pfkey_v2_parser.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/pfkey_v2_parser.c	Fri Feb  7 13:14:25 2003
@@ -0,0 +1,4627 @@
+/*
+ * @(#) RFC2367 PF_KEYv2 Key management API message parser
+ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ *		Template from klips/net/ipsec/ipsec/ipsec_netlink.c.
+ */
+
+char pfkey_v2_parser_c_version[] = "$Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+#define IPSEC_KLIPS1_COMPAT
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#include <freeswan.h>
+#include <des.h>
+#ifdef SPINLOCK
+# ifdef SPINLOCK_23
+#  include <linux/spinlock.h> /* *lock* */
+# else /* SPINLOCK_23 */
+#  include <asm/spinlock.h> /* *lock* */
+# endif /* SPINLOCK_23 */
+#endif /* SPINLOCK */
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+# define ip_chk_addr inet_addr_type
+# define IS_MYADDR RTN_LOCAL
+#endif
+#include <asm/checksum.h>
+#include <net/ip.h>
+#ifdef NETLINK_SOCK
+# include <linux/netlink.h>
+#else
+# include <net/netlink.h>
+#endif
+
+#include <linux/random.h>	/* get_random_bytes() */
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_sa.h"
+
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+#include "ipsec_xform.h"
+#include "ipsec_ah.h"
+#include "ipsec_esp.h"
+#include "ipsec_tunnel.h"	/* ..., ipsec_tunnel_start_xmit() */
+#include "ipsec_rcv.h"
+#include "ipcomp.h"
+
+#include <pfkeyv2.h>
+#include <pfkey.h>
+
+#include "ipsec_proto.h"
+
+#include "ipsec_alg.h"
+
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
+
+struct sklist_t {
+	struct socket *sk;
+	struct sklist_t* next;
+} pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev;
+
+__u32 pfkey_msg_seq = 0;
+
+DEBUG_NO_STATIC int
+pfkey_alloc_ipsec_sa(struct ipsec_sa** tdb)
+{
+	int error = 0;
+	if(*tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_alloc_ipsec_sa: "
+			    "tdb struct already allocated\n");
+		SENDERR(EEXIST);
+	}
+
+	if((*tdb = kmalloc(sizeof(**tdb), GFP_ATOMIC) ) == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_alloc_ipsec_sa: "
+			    "memory allocation error\n");
+		SENDERR(ENOMEM);
+	}
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_alloc_ipsec_sa: "
+		    "allocated tdb struct=%p.\n", tdb);
+
+	memset((caddr_t)*tdb, 0, sizeof(**tdb));
+ errlab:
+	return(error);
+}
+
+DEBUG_NO_STATIC int
+pfkey_alloc_eroute(struct eroute** eroute)
+{
+	int error = 0;
+	if(*eroute) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_alloc_eroute: "
+			    "eroute struct already allocated\n");
+		SENDERR(EEXIST);
+	}
+
+	if((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_alloc_eroute: "
+			    "memory allocation error\n");
+		SENDERR(ENOMEM);
+	}
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_alloc_eroute: "
+		    "allocated eroute struct=%p.\n", eroute);
+	memset((caddr_t)*eroute, 0, sizeof(**eroute));
+	(*eroute)->er_eaddr.sen_len =
+		(*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap);
+	(*eroute)->er_eaddr.sen_family =
+		(*eroute)->er_emask.sen_family = AF_ENCAP;
+	(*eroute)->er_eaddr.sen_type = SENT_IP4;
+	(*eroute)->er_emask.sen_type = 255;
+	(*eroute)->er_pid = 0;
+	(*eroute)->er_count = 0;
+	(*eroute)->er_lasttime = jiffies/HZ;
+
+ errlab:
+	return(error);
+}
+
+DEBUG_NO_STATIC int
+pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;
+	int error = 0;
+	struct ipsec_sa* tdbp;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_sa_process: .\n");
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sa_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	switch(pfkey_ext->sadb_ext_type) {
+	case SADB_EXT_SA:
+		tdbp = extr->tdb;
+		break;
+	case SADB_X_EXT_SA2:
+		if(pfkey_alloc_ipsec_sa(&(extr->tdb2)) == ENOMEM) {
+			SENDERR(ENOMEM);
+		}
+		tdbp = extr->tdb2;
+		break;
+	default:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sa_process: "
+			    "invalid exttype=%d.\n",
+			    pfkey_ext->sadb_ext_type);
+		SENDERR(EINVAL);
+	}
+
+	tdbp->tdb_said.spi = pfkey_sa->sadb_sa_spi;
+	tdbp->tdb_replaywin = pfkey_sa->sadb_sa_replay;
+	tdbp->tdb_state = pfkey_sa->sadb_sa_state;
+	tdbp->tdb_flags = pfkey_sa->sadb_sa_flags;
+	tdbp->tdb_replaywin_lastseq = tdbp->tdb_replaywin_bitmap = 0;
+	
+	switch(tdbp->tdb_said.proto) {
+	case IPPROTO_AH:
+		tdbp->tdb_authalg = pfkey_sa->sadb_sa_auth;
+		tdbp->tdb_encalg = SADB_EALG_NONE;
+		break;
+	case IPPROTO_ESP:
+		tdbp->tdb_authalg = pfkey_sa->sadb_sa_auth;
+		tdbp->tdb_encalg = pfkey_sa->sadb_sa_encrypt;
+#ifdef CONFIG_IPSEC_ALG
+		ipsec_alg_sa_init(tdbp);
+#endif /* CONFIG_IPSEC_ALG */
+		break;
+	case IPPROTO_IPIP:
+		tdbp->tdb_authalg = AH_NONE;
+		tdbp->tdb_encalg = ESP_NONE;
+		break;
+#ifdef CONFIG_IPSEC_IPCOMP
+	case IPPROTO_COMP:
+		tdbp->tdb_authalg = AH_NONE;
+		tdbp->tdb_encalg = pfkey_sa->sadb_sa_encrypt;
+		break;
+#endif /* CONFIG_IPSEC_IPCOMP */
+	case IPPROTO_INT:
+		tdbp->tdb_authalg = AH_NONE;
+		tdbp->tdb_encalg = ESP_NONE;
+		break;
+	case 0:
+		break;
+	default:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_sa_process: "
+			    "unknown proto=%d.\n",
+			    tdbp->tdb_said.proto);
+		SENDERR(EINVAL);
+	}
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_lifetime_process: .\n");
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_lifetime_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	switch(pfkey_lifetime->sadb_lifetime_exttype) {
+	case SADB_EXT_LIFETIME_CURRENT:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_lifetime_process: "
+			    "lifetime_current not supported yet.\n");
+  		SENDERR(EINVAL);
+  		break;
+	case SADB_EXT_LIFETIME_HARD:
+		ipsec_lifetime_update_hard(&extr->tdb->ips_life.ipl_allocations,
+					  pfkey_lifetime->sadb_lifetime_allocations);
+
+		ipsec_lifetime_update_hard(&extr->tdb->ips_life.ipl_bytes,
+					  pfkey_lifetime->sadb_lifetime_bytes);
+
+		ipsec_lifetime_update_hard(&extr->tdb->ips_life.ipl_addtime,
+					  pfkey_lifetime->sadb_lifetime_addtime);
+
+		ipsec_lifetime_update_hard(&extr->tdb->ips_life.ipl_usetime,
+					  pfkey_lifetime->sadb_lifetime_usetime);
+
+		break;
+
+	case SADB_EXT_LIFETIME_SOFT:
+		ipsec_lifetime_update_soft(&extr->tdb->ips_life.ipl_allocations,
+					   pfkey_lifetime->sadb_lifetime_allocations);
+
+		ipsec_lifetime_update_soft(&extr->tdb->ips_life.ipl_bytes,
+					   pfkey_lifetime->sadb_lifetime_bytes);
+
+		ipsec_lifetime_update_soft(&extr->tdb->ips_life.ipl_addtime,
+					   pfkey_lifetime->sadb_lifetime_addtime);
+
+		ipsec_lifetime_update_soft(&extr->tdb->ips_life.ipl_usetime,
+					   pfkey_lifetime->sadb_lifetime_usetime);
+
+		break;
+	default:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_lifetime_process: "
+			    "invalid exttype=%d.\n",
+			    pfkey_ext->sadb_ext_type);
+		SENDERR(EINVAL);
+	}
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	int saddr_len = 0;
+	char ipaddr_txt[ADDRTOA_BUF];
+	unsigned char **sap;
+	unsigned short * portp = 0;
+	struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext;
+	struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address));
+	struct ipsec_sa* tdbp;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_address_process:\n");
+	
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	switch(s->sa_family) {
+	case AF_INET:
+		saddr_len = sizeof(struct sockaddr_in);
+		addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt));
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found address family=%d, AF_INET, %s.\n",
+			    s->sa_family,
+			    ipaddr_txt);
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		saddr_len = sizeof(struct sockaddr_in6);
+		break;
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+	default:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "s->sa_family=%d not supported.\n",
+			    s->sa_family);
+		SENDERR(EPFNOSUPPORT);
+	}
+	
+	switch(pfkey_address->sadb_address_exttype) {
+	case SADB_EXT_ADDRESS_SRC:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found src address.\n");
+		sap = (unsigned char **)&(extr->tdb->tdb_addr_s);
+		extr->tdb->tdb_addr_s_size = saddr_len;
+		break;
+	case SADB_EXT_ADDRESS_DST:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found dst address.\n");
+		sap = (unsigned char **)&(extr->tdb->tdb_addr_d);
+		extr->tdb->tdb_addr_d_size = saddr_len;
+		break;
+	case SADB_EXT_ADDRESS_PROXY:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found proxy address.\n");
+		sap = (unsigned char **)&(extr->tdb->tdb_addr_p);
+		extr->tdb->tdb_addr_p_size = saddr_len;
+		break;
+	case SADB_X_EXT_ADDRESS_DST2:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found 2nd dst address.\n");
+		if(pfkey_alloc_ipsec_sa(&(extr->tdb2)) == ENOMEM) {
+			SENDERR(ENOMEM);
+		}
+		sap = (unsigned char **)&(extr->tdb2->tdb_addr_d);
+		extr->tdb2->tdb_addr_d_size = saddr_len;
+		break;
+	case SADB_X_EXT_ADDRESS_SRC_FLOW:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found src flow address.\n");
+		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
+			SENDERR(ENOMEM);
+		}
+		sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_src);
+		portp = &(extr->eroute->er_eaddr.sen_sport);
+		break;
+	case SADB_X_EXT_ADDRESS_DST_FLOW:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found dst flow address.\n");
+		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
+			SENDERR(ENOMEM);
+		}
+		sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_dst);
+		portp = &(extr->eroute->er_eaddr.sen_dport);
+		break;
+	case SADB_X_EXT_ADDRESS_SRC_MASK:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found src mask address.\n");
+		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
+			SENDERR(ENOMEM);
+		}
+		sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_src);
+		portp = &(extr->eroute->er_emask.sen_sport);
+		break;
+	case SADB_X_EXT_ADDRESS_DST_MASK:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found dst mask address.\n");
+		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
+			SENDERR(ENOMEM);
+		}
+		sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_dst);
+		portp = &(extr->eroute->er_emask.sen_dport);
+		break;
+#ifdef NAT_TRAVERSAL
+	case SADB_X_EXT_NAT_T_OA:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "found NAT-OA address.\n");
+		sap = (unsigned char **)&(extr->tdb->ips_natt_oa);
+		extr->tdb->ips_natt_oa_size = saddr_len;
+		break;
+#endif
+	default:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_address_process: "
+			    "unrecognised ext_type=%d.\n",
+			    pfkey_address->sadb_address_exttype);
+		SENDERR(EINVAL);
+	}
+	
+	switch(pfkey_address->sadb_address_exttype) {
+	case SADB_EXT_ADDRESS_SRC:
+	case SADB_EXT_ADDRESS_DST:
+	case SADB_EXT_ADDRESS_PROXY:
+	case SADB_X_EXT_ADDRESS_DST2:
+#ifdef NAT_TRAVERSAL
+	case SADB_X_EXT_NAT_T_OA:
+#endif
+		if(!(*sap = kmalloc(saddr_len, GFP_KERNEL))) {
+			SENDERR(ENOMEM);
+		}
+		memcpy(*sap, s, saddr_len);
+		break;
+	default:
+		if(s->sa_family	!= AF_INET) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_address_process: "
+				    "s->sa_family=%d not supported.\n",
+				    s->sa_family);
+			SENDERR(EPFNOSUPPORT);
+		}
+		(unsigned int)(*sap) = ((struct sockaddr_in*)s)->sin_addr.s_addr;
+		if (portp != 0)
+			*portp = ((struct sockaddr_in*)s)->sin_port;
+#ifdef CONFIG_IPSEC_DEBUG
+		if(extr->eroute) {
+			char buf1[64], buf2[64];
+			if (debug_pfkey) {
+				subnettoa(extr->eroute->er_eaddr.sen_ip_src,
+					  extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
+				subnettoa(extr->eroute->er_eaddr.sen_ip_dst,
+					  extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_address_parse: "
+					    "extr->eroute set to %s:%d->%s:%d\n",
+					    buf1,
+					    ntohs(extr->eroute->er_eaddr.sen_sport),
+					    buf2,
+					    ntohs(extr->eroute->er_eaddr.sen_dport));
+			}
+		}
+#endif /* CONFIG_IPSEC_DEBUG */
+	}
+
+	tdbp = extr->tdb;
+	switch(pfkey_address->sadb_address_exttype) {
+	case SADB_X_EXT_ADDRESS_DST2:
+		tdbp = extr->tdb2;
+	case SADB_EXT_ADDRESS_DST:
+		if(s->sa_family == AF_INET) {
+			tdbp->tdb_said.dst.s_addr = ((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr.s_addr;
+			addrtoa(((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr,
+				0,
+				ipaddr_txt,
+				sizeof(ipaddr_txt));
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_address_process: "
+				    "tdb_said.dst set to %s.\n",
+				    ipaddr_txt);
+		} else {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_address_process: "
+				    "uh, tdb_said.dst doesn't do address family=%d yet, said will be invalid.\n",
+				    s->sa_family);
+		}
+	default:
+	}
+	
+	/* XXX check if port!=0 */
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_address_process: successful.\n");
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+        int error = 0;
+        struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_key_process: .\n");
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_key_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+        switch(pfkey_key->sadb_key_exttype) {
+        case SADB_EXT_KEY_AUTH:
+		if(!(extr->tdb->tdb_key_a = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_key_process: "
+				    "memory allocation error.\n");
+			SENDERR(ENOMEM);
+		}
+                extr->tdb->tdb_key_bits_a = pfkey_key->sadb_key_bits;
+                extr->tdb->tdb_key_a_size = DIVUP(pfkey_key->sadb_key_bits, 8);
+		memcpy(extr->tdb->tdb_key_a,
+		       (char*)pfkey_key + sizeof(struct sadb_key),
+		       extr->tdb->tdb_key_a_size);
+		break;
+	case SADB_EXT_KEY_ENCRYPT: /* Key(s) */
+		if(!(extr->tdb->tdb_key_e = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_key_process: "
+				    "memory allocation error.\n");
+			SENDERR(ENOMEM);
+		}
+		extr->tdb->tdb_key_bits_e = pfkey_key->sadb_key_bits;
+		extr->tdb->tdb_key_e_size = DIVUP(pfkey_key->sadb_key_bits, 8);
+		memcpy(extr->tdb->tdb_key_e,
+		       (char*)pfkey_key + sizeof(struct sadb_key),
+		       extr->tdb->tdb_key_e_size);
+		break;
+	default:
+		SENDERR(EINVAL);
+ 	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_key_process: "
+		    "success.\n");
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+        int error = 0;
+        struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext;
+	int data_len;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_ident_process: .\n");
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_ident_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	switch(pfkey_ident->sadb_ident_exttype) {
+	case SADB_EXT_IDENTITY_SRC:
+		data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+		
+		extr->tdb->tdb_ident_s.type = pfkey_ident->sadb_ident_type;
+		extr->tdb->tdb_ident_s.id = pfkey_ident->sadb_ident_id;
+		extr->tdb->tdb_ident_s.len = pfkey_ident->sadb_ident_len;
+		if(data_len) {
+			if(!(extr->tdb->tdb_ident_s.data
+			     = kmalloc(data_len, GFP_KERNEL))) {
+                                SENDERR(ENOMEM);
+                        }
+			memcpy(extr->tdb->tdb_ident_s.data,
+                               (char*)pfkey_ident + sizeof(struct sadb_ident),
+			       data_len);
+                } else {
+			extr->tdb->tdb_ident_s.data = NULL;
+                }
+                break;
+	case SADB_EXT_IDENTITY_DST: /* Identity(ies) */
+		data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
+		
+		extr->tdb->tdb_ident_d.type = pfkey_ident->sadb_ident_type;
+		extr->tdb->tdb_ident_d.id = pfkey_ident->sadb_ident_id;
+		extr->tdb->tdb_ident_d.len = pfkey_ident->sadb_ident_len;
+		if(data_len) {
+			if(!(extr->tdb->tdb_ident_d.data
+			     = kmalloc(data_len, GFP_KERNEL))) {
+                                SENDERR(ENOMEM);
+                        }
+			memcpy(extr->tdb->tdb_ident_d.data,
+                               (char*)pfkey_ident + sizeof(struct sadb_ident),
+			       data_len);
+                } else {
+			extr->tdb->tdb_ident_d.data = NULL;
+                }
+                break;
+	default:
+		SENDERR(EINVAL);
+ 	}
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+        int error = 0;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_sens_process: "
+		    "Sorry, I can't process exttype=%d yet.\n",
+		    pfkey_ext->sadb_ext_type);
+        SENDERR(EINVAL); /* don't process these yet */
+ errlab:
+        return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+        int error = 0;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_prop_process: "
+		    "Sorry, I can't process exttype=%d yet.\n",
+		    pfkey_ext->sadb_ext_type);
+	SENDERR(EINVAL); /* don't process these yet */
+	
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+        int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_supported_process: "
+		    "Sorry, I can't process exttype=%d yet.\n",
+		    pfkey_ext->sadb_ext_type);
+	SENDERR(EINVAL); /* don't process these yet */
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+        int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_spirange_process: .\n");
+/* errlab: */
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_kmprivate_process: "
+		    "Sorry, I can't process exttype=%d yet.\n",
+		    pfkey_ext->sadb_ext_type);
+	SENDERR(EINVAL); /* don't process these yet */
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_satype_process: .\n");
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_satype_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	if(pfkey_alloc_ipsec_sa(&(extr->tdb2)) == ENOMEM) {
+		SENDERR(ENOMEM);
+	}
+	if(!(extr->tdb2->tdb_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_satype_process: "
+			    "proto lookup from satype=%d failed.\n",
+			    pfkey_x_satype->sadb_x_satype_satype);
+		SENDERR(EINVAL);
+	}
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_satype_process: "
+		    "protocol==%d decoded from satype==%d(%s).\n",
+		    extr->tdb2->tdb_said.proto,
+		    pfkey_x_satype->sadb_x_satype_satype,
+		    satype2name(pfkey_x_satype->sadb_x_satype_satype));
+
+errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext;
+
+	if(!pfkey_x_debug) {
+		printk("klips_debug:pfkey_x_debug_process: "
+		       "null pointer passed in\n");
+		SENDERR(EINVAL);
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_debug_process: .\n");
+
+#ifdef CONFIG_IPSEC_DEBUG
+		if(pfkey_x_debug->sadb_x_debug_netlink >>
+		   (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 - 1)) {
+			pfkey_x_debug->sadb_x_debug_netlink &=
+				~(1 << (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 -1));
+			debug_tunnel  |= pfkey_x_debug->sadb_x_debug_tunnel;
+			debug_netlink |= pfkey_x_debug->sadb_x_debug_netlink;
+			debug_xform   |= pfkey_x_debug->sadb_x_debug_xform;
+			debug_eroute  |= pfkey_x_debug->sadb_x_debug_eroute;
+			debug_spi     |= pfkey_x_debug->sadb_x_debug_spi;
+			debug_radij   |= pfkey_x_debug->sadb_x_debug_radij;
+			debug_esp     |= pfkey_x_debug->sadb_x_debug_esp;
+			debug_ah      |= pfkey_x_debug->sadb_x_debug_ah;
+			debug_rcv     |= pfkey_x_debug->sadb_x_debug_rcv;
+			debug_pfkey   |= pfkey_x_debug->sadb_x_debug_pfkey;
+#ifdef CONFIG_IPSEC_IPCOMP
+			sysctl_ipsec_debug_ipcomp  |= pfkey_x_debug->sadb_x_debug_ipcomp;
+#endif /* CONFIG_IPSEC_IPCOMP */
+			sysctl_ipsec_debug_verbose |= pfkey_x_debug->sadb_x_debug_verbose;
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_debug_process: "
+				    "set\n");
+		} else {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_debug_process: "
+				    "unset\n");
+			debug_tunnel  &= pfkey_x_debug->sadb_x_debug_tunnel;
+			debug_netlink &= pfkey_x_debug->sadb_x_debug_netlink;
+			debug_xform   &= pfkey_x_debug->sadb_x_debug_xform;
+			debug_eroute  &= pfkey_x_debug->sadb_x_debug_eroute;
+			debug_spi     &= pfkey_x_debug->sadb_x_debug_spi;
+			debug_radij   &= pfkey_x_debug->sadb_x_debug_radij;
+			debug_esp     &= pfkey_x_debug->sadb_x_debug_esp;
+			debug_ah      &= pfkey_x_debug->sadb_x_debug_ah;
+			debug_rcv     &= pfkey_x_debug->sadb_x_debug_rcv;
+			debug_pfkey   &= pfkey_x_debug->sadb_x_debug_pfkey;
+#ifdef CONFIG_IPSEC_IPCOMP
+			sysctl_ipsec_debug_ipcomp  &= pfkey_x_debug->sadb_x_debug_ipcomp;
+#endif /* CONFIG_IPSEC_IPCOMP */
+			sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose;
+		}
+#else /* CONFIG_IPSEC_DEBUG */
+		printk("klips_debug:pfkey_x_debug_process: "
+		       "debugging not enabled\n");
+		SENDERR(EINVAL);
+#endif /* CONFIG_IPSEC_DEBUG */
+	
+errlab:
+	return error;
+}
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+DEBUG_NO_STATIC int
+pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)pfkey_ext;
+
+	if(!pfkey_x_nat_t_type) {
+		printk("klips_debug:pfkey_x_nat_t_type_process: "
+		       "null pointer passed in\n");
+		SENDERR(EINVAL);
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_nat_t_type_process: %d.\n",
+			pfkey_x_nat_t_type->sadb_x_nat_t_type_type);
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_nat_t_type_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	switch(pfkey_x_nat_t_type->sadb_x_nat_t_type_type) {
+		case ESPINUDP_WITH_NON_IKE: /* with Non-IKE */
+		case ESPINUDP_WITH_NON_ESP: /* with Non-ESP */
+			extr->tdb->ips_natt_type = pfkey_x_nat_t_type->sadb_x_nat_t_type_type;
+			break;
+		default:
+			KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_nat_t_type_process: "
+			    "unknown type %d.\n",
+			    pfkey_x_nat_t_type->sadb_x_nat_t_type_type);
+			SENDERR(EINVAL);
+			break;
+	}
+
+errlab:
+	return error;
+}
+DEBUG_NO_STATIC int
+pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)pfkey_ext;
+
+	if(!pfkey_x_nat_t_port) {
+		printk("klips_debug:pfkey_x_nat_t_port_process: "
+		       "null pointer passed in\n");
+		SENDERR(EINVAL);
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_nat_t_port_process: %d/%d.\n",
+			pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype,
+			pfkey_x_nat_t_port->sadb_x_nat_t_port_port);
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_nat_t_type_process: "
+			    "extr or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	switch(pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype) {
+		case SADB_X_EXT_NAT_T_SPORT:
+			extr->tdb->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port;
+			break;
+		case SADB_X_EXT_NAT_T_DPORT:
+			extr->tdb->ips_natt_dport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port;
+			break;
+		default:
+			KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_nat_t_port_process: "
+			    "unknown exttype %d.\n",
+			    pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype);
+			SENDERR(EINVAL);
+			break;
+	}
+
+errlab:
+	return error;
+}
+#endif
+
+DEBUG_NO_STATIC int
+pfkey_x_protocol_process(struct sadb_ext *pfkey_ext,
+			 struct pfkey_extracted_data *extr)
+{
+	int error = 0;
+	struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext;
+
+	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: %p\n", extr);
+        
+	if (extr == 0) {
+		KLIPS_PRINT(debug_pfkey,
+                      "klips_debug:pfkey_x_protocol_process:"
+			    "extr is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+	if (extr->eroute == 0) {
+		KLIPS_PRINT(debug_pfkey,
+                      "klips_debug:pfkey_x_protocol_process:"
+			    "extr->eroute is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+	extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto;
+	extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0:0;
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_protocol_process: protocol = %d.\n",
+		    p->sadb_protocol_proto);
+ errlab:
+	return error;
+}
+
+
+DEBUG_NO_STATIC int
+pfkey_ipsec_sa_init(struct ipsec_sa *tdbp, struct sadb_ext **extensions)
+{
+        int error = 0;
+        char sa[SATOA_BUF];
+	size_t sa_len;
+	char ipaddr_txt[ADDRTOA_BUF];
+	char ipaddr2_txt[ADDRTOA_BUF];
+#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1)
+        int i;
+	unsigned char kb[AHMD596_BLKLEN];
+#endif
+#ifdef CONFIG_IPSEC_ALG
+	struct ipsec_alg_enc *ixt_e = NULL;
+	struct ipsec_alg_auth *ixt_a = NULL;
+#endif /* CONFIG_IPSEC_ALG */
+
+	if(!tdbp) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_ipsec_sa_init: "
+			    "tdbp is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+
+        KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_ipsec_sa_init: "
+		    "(pfkey defined) called for SA:%s\n",
+		    sa_len ? sa : " (error)");
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_ipsec_sa_init: "
+		    "calling init routine of %s%s%s\n",
+		    IPS_XFORM_NAME(tdbp));
+	
+	switch(tdbp->tdb_said.proto) {
+		
+#ifdef CONFIG_IPSEC_IPIP
+	case IPPROTO_IPIP: {
+		addrtoa(((struct sockaddr_in*)(tdbp->tdb_addr_s))->sin_addr,
+			0,
+			ipaddr_txt, sizeof(ipaddr_txt));
+		addrtoa(((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr,
+			0,
+			ipaddr2_txt, sizeof(ipaddr_txt));
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_ipsec_sa_init: "
+			    "(pfkey defined) IPIP tdb set for %s->%s.\n",
+			    ipaddr_txt,
+			    ipaddr2_txt);
+	}
+	break;
+#endif /* !CONFIG_IPSEC_IPIP */
+#ifdef CONFIG_IPSEC_AH
+	case IPPROTO_AH:
+		switch(tdbp->tdb_authalg) {
+# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+		case AH_MD5: {
+			unsigned char *akp;
+			unsigned int aks;
+			MD5_CTX *ictx;
+			MD5_CTX *octx;
+			
+			if(tdbp->tdb_key_bits_a != (AHMD596_KLEN * 8)) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_ipsec_sa_init: "
+					    "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_a, AHMD596_KLEN * 8);
+				SENDERR(EINVAL);
+			}
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "hmac md5-96 key is 0x%08x %08x %08x %08x\n",
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+0)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+1)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+2)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+3)));
+#  endif
+			
+			tdbp->tdb_auth_bits = AHMD596_ALEN * 8;
+			
+			/* save the pointer to the key material */
+			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
+			
+			if((tdbp->tdb_key_a = (caddr_t)
+			    kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
+				SENDERR(ENOMEM);
+			}
+			tdbp->tdb_key_a_size = sizeof(struct md5_ctx);
+
+			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
+				kb[i] = akp[i] ^ HMAC_IPAD;
+			}
+			for (; i < AHMD596_BLKLEN; i++) {
+				kb[i] = HMAC_IPAD;
+			}
+
+			ictx = &(((struct md5_ctx*)(tdbp->tdb_key_a))->ictx);
+			MD5Init(ictx);
+			MD5Update(ictx, kb, AHMD596_BLKLEN);
+
+			for (i = 0; i < AHMD596_BLKLEN; i++) {
+				kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
+			}
+
+			octx = &(((struct md5_ctx*)(tdbp->tdb_key_a))->octx);
+			MD5Init(octx);
+			MD5Update(octx, kb, AHMD596_BLKLEN);
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
+				    ((__u32*)ictx)[0],
+				    ((__u32*)ictx)[1],
+				    ((__u32*)ictx)[2],
+				    ((__u32*)ictx)[3],
+				    ((__u32*)octx)[0],
+				    ((__u32*)octx)[1],
+				    ((__u32*)octx)[2],
+				    ((__u32*)octx)[3] );
+#  endif
+			
+			/* zero key buffer -- paranoid */
+			memset(akp, 0, aks);
+			kfree(akp);
+		}
+		break;
+# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+		case AH_SHA: {
+			unsigned char *akp;
+			unsigned int aks;
+			SHA1_CTX *ictx;
+			SHA1_CTX *octx;
+			
+			if(tdbp->tdb_key_bits_a != (AHSHA196_KLEN * 8)) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_ipsec_sa_init: "
+					    "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_a, AHSHA196_KLEN * 8);
+				SENDERR(EINVAL);
+			}
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+0)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+1)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+2)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+3)));
+#  endif
+			
+			tdbp->tdb_auth_bits = AHSHA196_ALEN * 8;
+			
+			/* save the pointer to the key material */
+			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
+			
+			if((tdbp->tdb_key_a = (caddr_t)
+			    kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
+				SENDERR(ENOMEM);
+			}
+			tdbp->tdb_key_a_size = sizeof(struct sha1_ctx);
+
+			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
+				kb[i] = akp[i] ^ HMAC_IPAD;
+			}
+			for (; i < AHMD596_BLKLEN; i++) {
+				kb[i] = HMAC_IPAD;
+			}
+
+			ictx = &(((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx);
+			SHA1Init(ictx);
+			SHA1Update(ictx, kb, AHSHA196_BLKLEN);
+
+			for (i = 0; i < AHSHA196_BLKLEN; i++) {
+				kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
+			}
+
+			octx = &(((struct sha1_ctx*)(tdbp->tdb_key_a))->octx);
+			SHA1Init(octx);
+			SHA1Update(octx, kb, AHSHA196_BLKLEN);
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", 
+				    ((__u32*)ictx)[0],
+				    ((__u32*)ictx)[1],
+				    ((__u32*)ictx)[2],
+				    ((__u32*)ictx)[3],
+				    ((__u32*)octx)[0],
+				    ((__u32*)octx)[1],
+				    ((__u32*)octx)[2],
+				    ((__u32*)octx)[3] );
+#  endif			
+			/* zero key buffer -- paranoid */
+			memset(akp, 0, aks);
+			kfree(akp);
+		}
+		break;
+# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+		default:
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "authalg=%d support not available in the kernel",
+				    tdbp->tdb_authalg);
+			SENDERR(EINVAL);
+		}
+	break;
+#endif /* CONFIG_IPSEC_AH */
+#ifdef CONFIG_IPSEC_ESP
+	case IPPROTO_ESP: {
+#if defined (CONFIG_IPSEC_AUTH_HMAC_MD5) || defined (CONFIG_IPSEC_AUTH_HMAC_SHA1)
+		unsigned char *akp;
+		unsigned int aks;
+#endif
+#if defined (CONFIG_IPSEC_ENC_3DES)
+		unsigned char *ekp;
+		unsigned int eks;
+#endif
+		
+		tdbp->tdb_iv_size = 0;
+#ifdef CONFIG_IPSEC_ALG
+		if ((ixt_e=IPSEC_ALG_SA_ESP_ENC(tdbp))) {
+			tdbp->tdb_iv_size = ixt_e->ixt_ivlen/8;
+		} else	
+#endif /* CONFIG_IPSEC_ALG */
+		switch(tdbp->tdb_encalg) {
+# ifdef CONFIG_IPSEC_ENC_3DES
+		case ESP_3DES:
+# endif /* CONFIG_IPSEC_ENC_3DES */
+# if defined(CONFIG_IPSEC_ENC_3DES)
+			tdbp->tdb_iv_size = EMT_ESPDES_IV_SZ;
+# endif /* defined(CONFIG_IPSEC_ENC_3DES) */
+                case ESP_NONE:
+			break;
+		default:
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "encalg=%d support not available in the kernel",
+				    tdbp->tdb_encalg);
+			SENDERR(EINVAL);
+		}
+
+		/* Create IV */
+		if (tdbp->tdb_iv_size) {
+			if((tdbp->tdb_iv = (caddr_t)
+			    kmalloc(tdbp->tdb_iv_size, GFP_ATOMIC)) == NULL) {
+				SENDERR(ENOMEM);
+			}
+			get_random_bytes((void *)tdbp->tdb_iv, tdbp->tdb_iv_size);
+			tdbp->tdb_iv_bits = tdbp->tdb_iv_size * 8;
+		}
+		
+#ifdef CONFIG_IPSEC_ALG
+		if (ixt_e) {
+			if ((error=ipsec_alg_enc_key_create(tdbp)) < 0)
+				SENDERR(-error);
+		} else
+#endif /* CONFIG_IPSEC_ALG */
+		switch(tdbp->tdb_encalg) {
+# ifdef CONFIG_IPSEC_ENC_3DES
+		case ESP_3DES:
+			if(tdbp->tdb_key_bits_e != (EMT_ESP3DES_KEY_SZ * 8)) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_ipsec_sa_init: "
+					    "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_e, EMT_ESP3DES_KEY_SZ * 8);
+				SENDERR(EINVAL);
+			}
+			
+			/* save encryption key pointer */
+			ekp = tdbp->tdb_key_e;
+			eks = tdbp->tdb_key_e_size;
+			
+			if((tdbp->tdb_key_e = (caddr_t)
+			    kmalloc(3 * sizeof(struct des_eks), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_e = ekp;
+				SENDERR(ENOMEM);
+			}
+			tdbp->tdb_key_e_size = 3 * sizeof(struct des_eks);
+
+			for(i = 0; i < 3; i++) {
+#if KLIPS_DIVULGE_CYPHER_KEY
+				KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+					    "klips_debug:pfkey_ipsec_sa_init: "
+					    "3des key %d/3 is 0x%08x%08x\n",
+					    i + 1,
+					    ntohl(*((__u32 *)ekp + i * 2)),
+					    ntohl(*((__u32 *)ekp + i * 2 + 1)));
+#  endif
+#if KLIPS_FIXES_DES_PARITY				
+				/* force parity */
+				des_set_odd_parity((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i));
+#endif
+				error = des_set_key((des_cblock *)(ekp + EMT_ESPDES_KEY_SZ * i),
+						    ((struct des_eks *)(tdbp->tdb_key_e))[i].ks);
+				if (error == -1)
+					printk("klips_debug:pfkey_ipsec_sa_init: "
+					       "parity error in des key %d/3\n",
+					       i + 1);
+				else if (error == -2)
+					printk("klips_debug:pfkey_ipsec_sa_init: "
+					       "illegal weak des key %d/3\n", i + 1);
+				if (error) {
+					memset(ekp, 0, eks);
+					kfree(ekp);
+					SENDERR(EINVAL);
+				}
+			}
+
+			/* paranoid */
+			memset(ekp, 0, eks);
+			kfree(ekp);
+			break;
+# endif /* CONFIG_IPSEC_ENC_3DES */
+                case ESP_NONE:
+			break;
+		default:
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "encalg=%d support not available in the kernel",
+				    tdbp->tdb_encalg);
+			SENDERR(EINVAL);
+		}
+
+#ifdef CONFIG_IPSEC_ALG
+		if ((ixt_a=IPSEC_ALG_SA_ESP_AUTH(tdbp))) {
+			if ((error=ipsec_alg_auth_key_create(tdbp)) < 0)
+				SENDERR(-error);
+		} else	
+#endif /* CONFIG_IPSEC_ALG */
+		
+		switch(tdbp->tdb_authalg) {
+# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+		case AH_MD5: {
+			MD5_CTX *ictx;
+			MD5_CTX *octx;
+
+			if(tdbp->tdb_key_bits_a != (AHMD596_KLEN * 8)) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_ipsec_sa_init: "
+					    "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_a,
+					    AHMD596_KLEN * 8);
+				SENDERR(EINVAL);
+			}
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "hmac md5-96 key is 0x%08x %08x %08x %08x\n",
+				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+0)),
+				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+1)),
+				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+2)),
+				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+3)));
+#  endif
+			tdbp->tdb_auth_bits = AHMD596_ALEN * 8;
+			
+			/* save the pointer to the key material */
+			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
+			
+			if((tdbp->tdb_key_a = (caddr_t)
+			    kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
+				SENDERR(ENOMEM);
+			}
+			tdbp->tdb_key_a_size = sizeof(struct md5_ctx);
+
+			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
+				kb[i] = akp[i] ^ HMAC_IPAD;
+			}
+			for (; i < AHMD596_BLKLEN; i++) {
+				kb[i] = HMAC_IPAD;
+			}
+
+			ictx = &(((struct md5_ctx*)(tdbp->tdb_key_a))->ictx);
+			MD5Init(ictx);
+			MD5Update(ictx, kb, AHMD596_BLKLEN);
+
+			for (i = 0; i < AHMD596_BLKLEN; i++) {
+				kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
+			}
+
+			octx = &(((struct md5_ctx*)(tdbp->tdb_key_a))->octx);
+			MD5Init(octx);
+			MD5Update(octx, kb, AHMD596_BLKLEN);
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
+				    ((__u32*)ictx)[0],
+				    ((__u32*)ictx)[1],
+				    ((__u32*)ictx)[2],
+				    ((__u32*)ictx)[3],
+				    ((__u32*)octx)[0],
+				    ((__u32*)octx)[1],
+				    ((__u32*)octx)[2],
+				    ((__u32*)octx)[3] );
+#  endif
+			/* paranoid */
+			memset(akp, 0, aks);
+			kfree(akp);
+			break;
+		}
+# endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+# ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+		case AH_SHA: {
+			SHA1_CTX *ictx;
+			SHA1_CTX *octx;
+
+			if(tdbp->tdb_key_bits_a != (AHSHA196_KLEN * 8)) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_ipsec_sa_init: "
+					    "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_a,
+					    AHSHA196_KLEN * 8);
+				SENDERR(EINVAL);
+			}
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+0)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+1)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+2)),
+				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+3)));
+#  endif
+			tdbp->tdb_auth_bits = AHSHA196_ALEN * 8;
+			
+			/* save the pointer to the key material */
+			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
+
+			if((tdbp->tdb_key_a = (caddr_t)
+			    kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
+				SENDERR(ENOMEM);
+			}
+			tdbp->tdb_key_a_size = sizeof(struct sha1_ctx);
+
+			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
+				kb[i] = akp[i] ^ HMAC_IPAD;
+			}
+			for (; i < AHMD596_BLKLEN; i++) {
+				kb[i] = HMAC_IPAD;
+			}
+
+			ictx = &(((struct sha1_ctx*)(tdbp->tdb_key_a))->ictx);
+			SHA1Init(ictx);
+			SHA1Update(ictx, kb, AHSHA196_BLKLEN);
+
+			for (i = 0; i < AHSHA196_BLKLEN; i++) {
+				kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
+			}
+
+			octx = &((struct sha1_ctx*)(tdbp->tdb_key_a))->octx;
+			SHA1Init(octx);
+			SHA1Update(octx, kb, AHSHA196_BLKLEN);
+			
+#  if 0 /* we don't really want to print these unless there are really big problems */
+			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
+				    ((__u32*)ictx)[0],
+				    ((__u32*)ictx)[1],
+				    ((__u32*)ictx)[2],
+				    ((__u32*)ictx)[3],
+				    ((__u32*)octx)[0],
+				    ((__u32*)octx)[1],
+				    ((__u32*)octx)[2],
+				    ((__u32*)octx)[3] );
+#  endif
+			memset(akp, 0, aks);
+			kfree(akp);
+			break;
+		}
+# endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+		case AH_NONE:
+			break;
+		default:
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_ipsec_sa_init: "
+				    "authalg=%d support not available in the kernel.\n",
+				    tdbp->tdb_authalg);
+			SENDERR(EINVAL);
+		}
+	}
+			break;
+#endif /* !CONFIG_IPSEC_ESP */
+#ifdef CONFIG_IPSEC_IPCOMP
+	case IPPROTO_COMP:
+		tdbp->tdb_comp_adapt_tries = 0;
+		tdbp->tdb_comp_adapt_skip = 0;
+		tdbp->tdb_comp_ratio_cbytes = 0;
+		tdbp->tdb_comp_ratio_dbytes = 0;
+		break;
+#endif /* CONFIG_IPSEC_IPCOMP */
+	default:
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_ipsec_sa_init: "
+			    "proto=%d unknown.\n",
+			    tdbp->tdb_said.proto);
+		SENDERR(EINVAL);
+	}
+	
+ errlab:
+	return(error);
+}
+
+
+int
+pfkey_safe_build(int error, struct sadb_ext *extensions[SADB_MAX+1])
+{
+	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: "
+		    "error=%d\n",
+		    error);
+	if (!error) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:"
+			    "success.\n");
+		return 1;
+	} else {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:"
+			    "caught error %d\n",
+			    error);
+		pfkey_extensions_free(extensions);
+		return 0;
+	}
+}
+
+
+DEBUG_NO_STATIC int
+pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L);
+	int found_avail = 0;
+	struct ipsec_sa *tdbq;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+ 
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_getspi_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_getspi_parse: "
+			    "error, extr or extr->tdb pointer NULL\n");
+		SENDERR(EINVAL);
+	}
+
+	if(extensions[SADB_EXT_SPIRANGE]) {
+		minspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_min;
+		maxspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_max;
+	}
+
+	if(maxspi == minspi) {
+		extr->tdb->tdb_said.spi = maxspi;
+		if((tdbq = ipsec_sa_getbyid(&(extr->tdb->tdb_said)))) {
+			sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_getspi_parse: "
+				    "EMT_GETSPI found an old Tunnel Descriptor Block for SA: %s, delete it first.\n",
+				    sa_len ? sa : " (error)");
+			SENDERR(EEXIST);
+		} else {
+			found_avail = 1;
+		}
+	} else {
+		int i = 0;
+		__u32 rand_val;
+		__u32 spi_diff;
+		while( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) {
+			get_random_bytes((void*) &(rand_val),
+					 /* sizeof(extr->tdb->tdb_said.spi) */
+					 ( (spi_diff < (2^8))  ? 1 :
+					   ( (spi_diff < (2^16)) ? 2 :
+					     ( (spi_diff < (2^24)) ? 3 :
+					   4 ) ) ) );
+			extr->tdb->tdb_said.spi = htonl(ntohl(minspi) +
+					      (rand_val %
+					      (spi_diff + 1)));
+			i++;
+			tdbq = ipsec_sa_getbyid(&(extr->tdb->tdb_said));
+			if(!tdbq) {
+				found_avail = 1;
+			}
+		}
+	}
+
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+
+	if (!found_avail) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_getspi_parse: "
+			    "found an old Tunnel Descriptor Block for SA: %s, delete it first.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(EEXIST);
+	}
+
+	if(ip_chk_addr((unsigned long)extr->tdb->tdb_said.dst.s_addr) == IS_MYADDR) {
+		extr->tdb->tdb_flags |= EMT_INBOUND;
+	}
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_getspi_parse: "
+		    "existing Tunnel Descriptor Block not found (this is good) for SA: %s, %s-bound, allocating.\n",
+		    sa_len ? sa : " (error)",
+		    extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
+
+	
+	/* XXX extr->tdb->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
+	extr->tdb->tdb_rcvif = NULL;
+	extr->tdb->ips_life.ipl_addtime.ipl_count = jiffies/HZ;
+
+	extr->tdb->tdb_state = SADB_SASTATE_LARVAL;
+
+	if(!extr->tdb->ips_life.ipl_allocations.ipl_count) {
+		extr->tdb->ips_life.ipl_allocations.ipl_count += 1;
+	}
+
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_GETSPI,
+							  satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+						SADB_EXT_SA,
+						extr->tdb->tdb_said.spi,
+						0,
+						SADB_SASTATE_LARVAL,
+						0,
+						0,
+						0),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
+						     SADB_EXT_ADDRESS_SRC,
+						     0, /*extr->tdb->tdb_said.proto,*/
+						     0,
+						     extr->tdb->tdb_addr_s),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+						     SADB_EXT_ADDRESS_DST,
+						     0, /*extr->tdb->tdb_said.proto,*/
+						     0,
+						     extr->tdb->tdb_addr_d),
+				 extensions_reply) )) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
+			    "failed to build the getspi reply message extensions\n");
+		goto errlab;
+	}
+	
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
+			    "failed to build the getspi reply message\n");
+		SENDERR(-error);
+	}
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
+				    "sending up getspi reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
+			    "sending up getspi reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+	if((error = ipsec_sa_put(extr->tdb))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
+			    "failed to add the larval SA=%s with error=%d.\n",
+			    sa_len ? sa : " (error)",
+			    error);
+		SENDERR(-error);
+	}
+	extr->tdb = NULL;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_getspi_parse: "
+		    "successful for SA: %s\n",
+		    sa_len ? sa : " (error)");
+	
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct ipsec_sa* tdbq;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+        struct ipsec_sa *nat_t_tdb_saved = NULL;
+#endif 
+
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_update_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_update_parse: "
+			    "error, sa_state=%d must be MATURE=%d\n",
+			    ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
+			    SADB_SASTATE_MATURE);
+		SENDERR(EINVAL);
+	}
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_update_parse: "
+			    "error, extr or extr->tdb pointer NULL\n");
+		SENDERR(EINVAL);
+	}
+
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+
+	spin_lock_bh(&tdb_lock);
+
+	tdbq = ipsec_sa_getbyid(&(extr->tdb->tdb_said));
+	if (!tdbq) {
+		spin_unlock_bh(&tdb_lock);
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_update_parse: "
+			    "reserved Tunnel Descriptor Block for SA: %s not found.  Call SADB_GETSPI first or call SADB_ADD instead.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(ENOENT);
+	}
+
+	if(ip_chk_addr((unsigned long)extr->tdb->tdb_said.dst.s_addr) == IS_MYADDR) {
+		extr->tdb->tdb_flags |= EMT_INBOUND;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_update_parse: "
+		    "existing Tunnel Descriptor Block found (this is good) for SA: %s, %s-bound, updating.\n",
+		    sa_len ? sa : " (error)",
+		    extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+        if (extr->tdb->ips_natt_sport || extr->tdb->ips_natt_dport) {
+                KLIPS_PRINT(debug_pfkey,
+                        "klips_debug:pfkey_update_parse: only updating NAT-T ports "
+                        "(%u:%u -> %u:%u)\n",
+                        tdbq->ips_natt_sport, tdbq->ips_natt_dport,
+                        extr->tdb->ips_natt_sport, extr->tdb->ips_natt_dport);
+
+                if (extr->tdb->ips_natt_sport) {
+                        tdbq->ips_natt_sport = extr->tdb->ips_natt_sport;
+                        if (tdbq->ips_addr_s->sa_family == AF_INET) {
+                                ((struct sockaddr_in *)(tdbq->ips_addr_s))->sin_port = htons(extr->tdb->ips_natt_sport);
+                        }
+                }
+                                               
+                if (extr->tdb->ips_natt_dport) {                         
+                        tdbq->ips_natt_dport = extr->tdb->ips_natt_dport;
+                        if (tdbq->ips_addr_d->sa_family == AF_INET) {
+                                ((struct sockaddr_in *)(tdbq->ips_addr_d))->sin_port = htons(extr->tdb->ips_natt_dport);
+                        }
+                }
+                nat_t_tdb_saved = extr->tdb;
+                extr->tdb = tdbq;
+	}
+	else {
+#endif 
+
+	
+	/* XXX extr->tdb->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
+	extr->tdb->tdb_rcvif = NULL;
+	if ((error = pfkey_ipsec_sa_init(extr->tdb, extensions))) {
+		spin_unlock_bh(&tdb_lock);
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_update_parse: "
+			    "not successful for SA: %s, deleting.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(-error);
+	}
+
+	extr->tdb->ips_life.ipl_addtime.ipl_count = tdbq->ips_life.ipl_addtime.ipl_count;
+	if((error = ipsec_sa_delchain(tdbq))) {
+		spin_unlock_bh(&tdb_lock);
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_update_parse: "
+			    "error=%d, trouble deleting intermediate tdb for SA=%s.\n",
+			    error,
+			    sa_len ? sa : " (error)");
+		SENDERR(-error);
+	}
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	}
+#endif
+
+	spin_unlock_bh(&tdb_lock);
+	
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_UPDATE,
+							  satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+							SADB_EXT_SA,
+							extr->tdb->tdb_said.spi,
+							extr->tdb->tdb_replaywin,
+							extr->tdb->tdb_state,
+							extr->tdb->tdb_authalg,
+							extr->tdb->tdb_encalg,
+							extr->tdb->tdb_flags),
+				 extensions_reply)
+	     /* The 3 lifetime extentions should only be sent if non-zero. */
+	     && (extensions[SADB_EXT_LIFETIME_HARD]
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD],
+								 SADB_EXT_LIFETIME_HARD,
+								 extr->tdb->ips_life.ipl_allocations.ipl_hard,
+								 extr->tdb->ips_life.ipl_bytes.ipl_hard,
+								 extr->tdb->ips_life.ipl_addtime.ipl_hard,
+								 extr->tdb->ips_life.ipl_usetime.ipl_hard,
+								 extr->tdb->ips_life.ipl_packets.ipl_hard),
+				    extensions_reply) : 1)
+	     && (extensions[SADB_EXT_LIFETIME_SOFT]
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT],
+								 SADB_EXT_LIFETIME_SOFT,
+								 extr->tdb->ips_life.ipl_allocations.ipl_count,
+								 extr->tdb->ips_life.ipl_bytes.ipl_count,
+								 extr->tdb->ips_life.ipl_addtime.ipl_count,
+								 extr->tdb->ips_life.ipl_usetime.ipl_count,
+								 extr->tdb->ips_life.ipl_packets.ipl_count),
+				    extensions_reply) : 1)
+	     && (extr->tdb->ips_life.ipl_allocations.ipl_count
+		 || extr->tdb->ips_life.ipl_bytes.ipl_count
+		 || extr->tdb->ips_life.ipl_addtime.ipl_count
+		 || extr->tdb->ips_life.ipl_usetime.ipl_count
+		 || extr->tdb->ips_life.ipl_packets.ipl_count
+
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT],
+								 SADB_EXT_LIFETIME_CURRENT,
+								 extr->tdb->ips_life.ipl_allocations.ipl_count,
+								 extr->tdb->ips_life.ipl_bytes.ipl_count,
+								 extr->tdb->ips_life.ipl_addtime.ipl_count,
+								 extr->tdb->ips_life.ipl_usetime.ipl_count,
+								 extr->tdb->ips_life.ipl_packets.ipl_count),
+				    extensions_reply) : 1)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
+							     SADB_EXT_ADDRESS_SRC,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_s),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+							     SADB_EXT_ADDRESS_DST,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_d),
+				 extensions_reply)
+	     && (extr->tdb->tdb_ident_s.data
+                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC],
+                                                              SADB_EXT_IDENTITY_SRC,
+							      extr->tdb->tdb_ident_s.type,
+							      extr->tdb->tdb_ident_s.id,
+                                                              extr->tdb->tdb_ident_s.len,
+							      extr->tdb->tdb_ident_s.data),
+                                    extensions_reply) : 1)
+	     && (extr->tdb->tdb_ident_d.data
+                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST],
+                                                              SADB_EXT_IDENTITY_DST,
+							      extr->tdb->tdb_ident_d.type,
+							      extr->tdb->tdb_ident_d.id,
+                                                              extr->tdb->tdb_ident_d.len,
+							      extr->tdb->tdb_ident_d.data),
+                                    extensions_reply) : 1)
+#if 0
+	     /* FIXME: This won't work yet because I have not finished
+		it. */
+	     && (extr->tdb->tdb_sens_
+		 ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY],
+							     extr->tdb->tdb_sens_dpd,
+							     extr->tdb->tdb_sens_sens_level,
+							     extr->tdb->tdb_sens_sens_len,
+							     extr->tdb->tdb_sens_sens_bitmap,
+							     extr->tdb->tdb_sens_integ_level,
+							     extr->tdb->tdb_sens_integ_len,
+							     extr->tdb->tdb_sens_integ_bitmap),
+				    extensions_reply) : 1)
+#endif
+		)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
+			    "failed to build the update reply message extensions\n");
+		SENDERR(-error);
+	}
+		
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
+			    "failed to build the update reply message\n");
+		SENDERR(-error);
+	}
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
+				    "sending up update reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
+			    "sending up update reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+        if (nat_t_tdb_saved) {
+                /**
+                 * As we _really_ update existing SA, we keep tdbq and need to delete
+                 * parsed tdb (nat_t_tdb_saved, was extr->tdb).
+                 *
+                 * goto errlab with extr->tdb = nat_t_tdb_saved will free it.
+                 */
+
+                extr->tdb = nat_t_tdb_saved;
+
+                error = 0;
+                KLIPS_PRINT(debug_pfkey,
+                    "klips_debug:pfkey_update_parse (NAT-T ports): "
+                    "successful for SA: %s\n",
+                    sa_len ? sa : " (error)");
+
+                goto errlab;
+        }
+#endif
+
+	if((error = ipsec_sa_put(extr->tdb))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
+			    "failed to update the mature SA=%s with error=%d.\n",
+			    sa_len ? sa : " (error)",
+			    error);
+		SENDERR(-error);
+	}
+	extr->tdb = NULL;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_update_parse: "
+		    "successful for SA: %s\n",
+		    sa_len ? sa : " (error)");
+	
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct ipsec_sa* tdbq;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_add_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_add_parse: "
+			    "error, sa_state=%d must be MATURE=%d\n",
+			    ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
+			    SADB_SASTATE_MATURE);
+		SENDERR(EINVAL);
+	}
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_add_parse: "
+			    "extr or extr->tdb pointer NULL\n");
+		SENDERR(EINVAL);
+	}
+
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+
+	tdbq = ipsec_sa_getbyid(&(extr->tdb->tdb_said));
+	if (tdbq) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_add_parse: "
+			    "found an old Tunnel Descriptor Block for SA%s, delete it first.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(EEXIST);
+	}
+
+	if(ip_chk_addr((unsigned long)extr->tdb->tdb_said.dst.s_addr) == IS_MYADDR) {
+		extr->tdb->tdb_flags |= EMT_INBOUND;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_add_parse: "
+		    "existing Tunnel Descriptor Block not found (this is good) for SA%s, %s-bound, allocating.\n",
+		    sa_len ? sa : " (error)",
+		    extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
+	
+	/* XXX extr->tdb->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
+	extr->tdb->tdb_rcvif = NULL;
+	
+	if ((error = pfkey_ipsec_sa_init(extr->tdb, extensions))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_add_parse: "
+			    "not successful for SA: %s, deleting.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(-error);
+	}
+
+	extr->tdb->ips_life.ipl_addtime.ipl_count = jiffies / HZ;
+	if(!extr->tdb->ips_life.ipl_allocations.ipl_count) {
+		extr->tdb->ips_life.ipl_allocations.ipl_count += 1;
+	}
+
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_ADD,
+							  satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+							SADB_EXT_SA,
+							extr->tdb->tdb_said.spi,
+							extr->tdb->tdb_replaywin,
+							extr->tdb->tdb_state,
+							extr->tdb->tdb_authalg,
+							extr->tdb->tdb_encalg,
+							extr->tdb->tdb_flags),
+				 extensions_reply)
+	     /* The 3 lifetime extentions should only be sent if non-zero. */
+	     && (extensions[SADB_EXT_LIFETIME_HARD]
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD],
+								 SADB_EXT_LIFETIME_HARD,
+								 extr->tdb->ips_life.ipl_allocations.ipl_hard,
+								 extr->tdb->ips_life.ipl_bytes.ipl_hard,
+								 extr->tdb->ips_life.ipl_addtime.ipl_hard,
+								 extr->tdb->ips_life.ipl_usetime.ipl_hard,
+								 extr->tdb->ips_life.ipl_packets.ipl_hard),
+				    extensions_reply) : 1)
+	     && (extensions[SADB_EXT_LIFETIME_SOFT]
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT],
+								 SADB_EXT_LIFETIME_SOFT,
+								 extr->tdb->ips_life.ipl_allocations.ipl_soft,
+								 extr->tdb->ips_life.ipl_bytes.ipl_soft,
+								 extr->tdb->ips_life.ipl_addtime.ipl_soft,
+								 extr->tdb->ips_life.ipl_usetime.ipl_soft,
+								 extr->tdb->ips_life.ipl_packets.ipl_soft),
+				    extensions_reply) : 1)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
+							     SADB_EXT_ADDRESS_SRC,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_s),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+							     SADB_EXT_ADDRESS_DST,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_d),
+				 extensions_reply)
+            && (extr->tdb->tdb_ident_s.data
+                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC],
+                                                              SADB_EXT_IDENTITY_SRC,
+							      extr->tdb->tdb_ident_s.type,
+							      extr->tdb->tdb_ident_s.id,
+                                                              extr->tdb->tdb_ident_s.len,
+							      extr->tdb->tdb_ident_s.data),
+                                    extensions_reply) : 1)
+            && (extr->tdb->tdb_ident_d.data
+                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST],
+                                                              SADB_EXT_IDENTITY_DST,
+							      extr->tdb->tdb_ident_d.type,
+							      extr->tdb->tdb_ident_d.id,
+                                                              extr->tdb->tdb_ident_d.len,
+							      extr->tdb->tdb_ident_d.data),
+                                    extensions_reply) : 1)
+#if 0
+	     /* FIXME: This won't work yet because I have not finished
+		it. */
+	     && (extr->tdb->tdb_sens_
+		 ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY],
+							     extr->tdb->tdb_sens_dpd,
+							     extr->tdb->tdb_sens_sens_level,
+							     extr->tdb->tdb_sens_sens_len,
+							     extr->tdb->tdb_sens_sens_bitmap,
+							     extr->tdb->tdb_sens_integ_level,
+							     extr->tdb->tdb_sens_integ_len,
+							     extr->tdb->tdb_sens_integ_bitmap),
+				    extensions_reply) : 1)
+#endif
+		)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
+			    "failed to build the add reply message extensions\n");
+		SENDERR(-error);
+	}
+		
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
+			    "failed to build the add reply message\n");
+		SENDERR(-error);
+	}
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
+				    "sending up add reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
+			    "sending up add reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+
+	if((error = ipsec_sa_put(extr->tdb))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
+			    "failed to add the mature SA=%s with error=%d.\n",
+			    sa_len ? sa : " (error)",
+			    error);
+		SENDERR(-error);
+	}
+	extr->tdb = NULL;
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_add_parse: "
+		    "successful for SA: %s\n",
+		    sa_len ? sa : " (error)");
+	
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	struct ipsec_sa *tdbp;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	int error = 0;
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_delete_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_delete_parse: "
+			    "extr or extr->tdb pointer NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+
+	spin_lock_bh(&tdb_lock);
+
+	tdbp = ipsec_sa_getbyid(&(extr->tdb->tdb_said));
+	if (tdbp == NULL) {
+		spin_unlock_bh(&tdb_lock);
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_delete_parse: "
+			    "Tunnel Descriptor Block not found for SA:%s, could not delete.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(ESRCH);
+	}
+
+	if((error = ipsec_sa_delchain(tdbp))) {
+		spin_unlock_bh(&tdb_lock);
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_delete_parse: "
+			    "error=%d returned trying to delete Tunnel Descriptor Block for SA:%s.\n",
+			    error,
+			    sa_len ? sa : " (error)");
+		SENDERR(-error);
+	}
+	spin_unlock_bh(&tdb_lock);
+
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_DELETE,
+							  satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+							SADB_EXT_SA,
+							extr->tdb->tdb_said.spi,
+							0,
+							0,
+							0,
+							0,
+							0),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
+							     SADB_EXT_ADDRESS_SRC,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_s),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+							     SADB_EXT_ADDRESS_DST,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_d),
+				 extensions_reply)
+		)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
+			    "failed to build the delete reply message extensions\n");
+		SENDERR(-error);
+	}
+	
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
+			    "failed to build the delete reply message\n");
+		SENDERR(-error);
+	}
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
+				    "sending up delete reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
+			    "sending up delete reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct ipsec_sa *tdbp;
+	char sa[SATOA_BUF];
+	size_t sa_len;
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_get_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_get_parse: "
+			    "extr or extr->tdb pointer NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+
+	spin_lock_bh(&tdb_lock);
+
+	tdbp = ipsec_sa_getbyid(&(extr->tdb->tdb_said));
+	if (tdbp == NULL) {
+		spin_unlock_bh(&tdb_lock);
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
+			    "Tunnel Descriptor Block not found for SA=%s, could not get.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(ESRCH);
+	}
+	
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_GET,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+							SADB_EXT_SA,
+							extr->tdb->tdb_said.spi,
+							extr->tdb->tdb_replaywin,
+							extr->tdb->tdb_state,
+							extr->tdb->tdb_authalg,
+							extr->tdb->tdb_encalg,
+							extr->tdb->tdb_flags),
+				 extensions_reply)
+	     /* The 3 lifetime extentions should only be sent if non-zero. */
+	     && (tdbp->ips_life.ipl_allocations.ipl_count
+		 || tdbp->ips_life.ipl_bytes.ipl_count
+		 || tdbp->ips_life.ipl_addtime.ipl_count
+		 || tdbp->ips_life.ipl_usetime.ipl_count
+		 || tdbp->ips_life.ipl_packets.ipl_count
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT],
+								 SADB_EXT_LIFETIME_CURRENT,
+								 tdbp->ips_life.ipl_allocations.ipl_count,
+								 tdbp->ips_life.ipl_bytes.ipl_count,
+								 tdbp->ips_life.ipl_addtime.ipl_count,
+								 tdbp->ips_life.ipl_usetime.ipl_count,
+								 tdbp->ips_life.ipl_packets.ipl_count),
+				    extensions_reply) : 1)
+	     && (tdbp->ips_life.ipl_allocations.ipl_hard
+		 || tdbp->ips_life.ipl_bytes.ipl_hard
+		 || tdbp->ips_life.ipl_addtime.ipl_hard
+		 || tdbp->ips_life.ipl_usetime.ipl_hard
+		 || tdbp->ips_life.ipl_packets.ipl_hard
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD],
+								 SADB_EXT_LIFETIME_HARD,
+								 tdbp->ips_life.ipl_allocations.ipl_hard,
+								 tdbp->ips_life.ipl_bytes.ipl_hard,
+								 tdbp->ips_life.ipl_addtime.ipl_hard,
+								 tdbp->ips_life.ipl_usetime.ipl_hard,
+								 tdbp->ips_life.ipl_packets.ipl_hard),
+				    extensions_reply) : 1)
+	     && (tdbp->ips_life.ipl_allocations.ipl_soft
+		 || tdbp->ips_life.ipl_bytes.ipl_soft
+		 || tdbp->ips_life.ipl_addtime.ipl_soft
+		 || tdbp->ips_life.ipl_usetime.ipl_soft
+		 || tdbp->ips_life.ipl_packets.ipl_soft
+		 ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT],
+								 SADB_EXT_LIFETIME_SOFT,
+								 tdbp->ips_life.ipl_allocations.ipl_soft,
+								 tdbp->ips_life.ipl_bytes.ipl_soft,
+								 tdbp->ips_life.ipl_addtime.ipl_soft,
+								 tdbp->ips_life.ipl_usetime.ipl_soft,
+								 tdbp->ips_life.ipl_packets.ipl_soft),
+				    extensions_reply) : 1)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
+							     SADB_EXT_ADDRESS_SRC,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_s),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+							     SADB_EXT_ADDRESS_DST,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_d),
+				 extensions_reply)
+	     && (extr->tdb->tdb_addr_p
+		 ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_PROXY],
+								SADB_EXT_ADDRESS_PROXY,
+								0, /*extr->tdb->tdb_said.proto,*/
+								0,
+								extr->tdb->tdb_addr_p),
+				    extensions_reply) : 1)
+#if 0
+	     /* FIXME: This won't work yet because the keys are not
+		stored directly in the tdb.  They are stored as
+		contexts. */
+	     && (extr->tdb->tdb_key_a_size
+		 ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_AUTH],
+							    SADB_EXT_KEY_AUTH,
+							    extr->tdb->tdb_key_a_size * 8,
+							    extr->tdb->tdb_key_a),
+				    extensions_reply) : 1)
+	     /* FIXME: This won't work yet because the keys are not
+		stored directly in the tdb.  They are stored as
+		key schedules. */
+	     && (extr->tdb->tdb_key_e_size
+		 ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_ENCRYPT],
+							    SADB_EXT_KEY_ENCRYPT,
+							    extr->tdb->tdb_key_e_size * 8,
+							    extr->tdb->tdb_key_e),
+				    extensions_reply) : 1)
+#endif
+	     && (extr->tdb->tdb_ident_s.data
+                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC],
+                                                              SADB_EXT_IDENTITY_SRC,
+							      extr->tdb->tdb_ident_s.type,
+							      extr->tdb->tdb_ident_s.id,
+                                                              extr->tdb->tdb_ident_s.len,
+							      extr->tdb->tdb_ident_s.data),
+                                    extensions_reply) : 1)
+	     && (extr->tdb->tdb_ident_d.data
+                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST],
+                                                              SADB_EXT_IDENTITY_DST,
+							      extr->tdb->tdb_ident_d.type,
+							      extr->tdb->tdb_ident_d.id,
+                                                              extr->tdb->tdb_ident_d.len,
+							      extr->tdb->tdb_ident_d.data),
+                                    extensions_reply) : 1)
+#if 0
+	     /* FIXME: This won't work yet because I have not finished
+		it. */
+	     && (extr->tdb->tdb_sens_
+		 ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY],
+							     extr->tdb->tdb_sens_dpd,
+							     extr->tdb->tdb_sens_sens_level,
+							     extr->tdb->tdb_sens_sens_len,
+							     extr->tdb->tdb_sens_sens_bitmap,
+							     extr->tdb->tdb_sens_integ_level,
+							     extr->tdb->tdb_sens_integ_len,
+							     extr->tdb->tdb_sens_integ_bitmap),
+				    extensions_reply) : 1)
+#endif
+		     )) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
+			    "failed to build the get reply message extensions\n");
+		spin_unlock_bh(&tdb_lock);
+		SENDERR(-error);
+	}
+		
+	spin_unlock_bh(&tdb_lock);
+	
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
+			    "failed to build the get reply message\n");
+		SENDERR(-error);
+	}
+	
+	if((error = pfkey_upmsg(sk->socket, pfkey_reply))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
+			    "failed to send the get reply message\n");
+		SENDERR(-error);
+	}
+	
+	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
+		    "succeeded in sending get reply message.\n");
+	
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_acquire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_acquire_parse: .\n");
+
+	/* XXX I don't know if we want an upper bound, since userspace may
+	   want to register itself for an satype > SADB_SATYPE_MAX. */
+	if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_acquire_parse: "
+			    "SATYPE=%d invalid.\n",
+			    satype);
+		SENDERR(EINVAL);
+	}
+
+	if(!(pfkey_registered_sockets[satype])) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
+			    "no sockets registered for SAtype=%d(%s).\n",
+			    satype,
+			    satype2name(satype));
+		SENDERR(EPROTONOSUPPORT);
+	}
+
+	for(pfkey_socketsp = pfkey_registered_sockets[satype];
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp,
+					((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
+				    "sending up acquire reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
+			    "sending up acquire reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_register_parse: .\n");
+
+	/* XXX I don't know if we want an upper bound, since userspace may
+	   want to register itself for an satype > SADB_SATYPE_MAX. */
+	if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_register_parse: "
+			    "SATYPE=%d invalid.\n",
+			    satype);
+		SENDERR(EINVAL);
+	}
+
+	if(!pfkey_list_insert_socket(sk->socket,
+				 &(pfkey_registered_sockets[satype]))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_register_parse: "
+			    "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n",
+			    satype,
+			    satype2name(satype),
+			    key_pid(sk));
+	};
+	
+	/* send up register msg with supported SATYPE algos */
+
+	error=pfkey_register_reply(satype, (struct sadb_msg*)extensions[SADB_EXT_RESERVED]);
+ errlab:
+	return error;
+}
+int
+pfkey_register_reply(int satype, struct sadb_msg *sadb_msg)
+{
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	struct supported_list *pfkey_supported_listp;
+	unsigned int alg_num_a = 0, alg_num_e = 0;
+	struct sadb_alg *alg_a = NULL, *alg_e = NULL, *alg_ap = NULL, *alg_ep = NULL;
+	int error = 0;
+
+	pfkey_extensions_init(extensions_reply);
+
+	if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
+			    "SAtype=%d unspecified or unknown.\n",
+			    satype);
+		SENDERR(EINVAL);
+	}
+	if(!(pfkey_registered_sockets[satype])) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
+			    "no sockets registered for SAtype=%d(%s).\n",
+			    satype,
+			    satype2name(satype));
+		SENDERR(EPROTONOSUPPORT);
+	}
+	/* send up register msg with supported SATYPE algos */
+	pfkey_supported_listp = pfkey_supported_list[satype];
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_register_reply: "
+		    "pfkey_supported_list[%d]=%p\n",
+		    satype,
+		    pfkey_supported_list[satype]);
+	while(pfkey_supported_listp) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_register_reply: "
+			    "checking supported=%p\n",
+			    pfkey_supported_listp);
+		if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_register_reply: "
+				    "adding auth alg.\n");
+			alg_num_a++;
+		}
+		if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_register_reply: "
+				    "adding encrypt alg.\n");
+			alg_num_e++;
+		}
+		pfkey_supported_listp = pfkey_supported_listp->next;
+	}
+
+	if(alg_num_a) {
+		if((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_register_reply: "
+				    "auth alg memory allocation error\n");
+			SENDERR(ENOMEM);
+		}
+		alg_ap = alg_a;
+	}
+	
+	if(alg_num_e) {
+		if((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_register_reply: "
+				    "enc alg memory allocation error\n");
+			SENDERR(ENOMEM);
+		}
+		alg_ep = alg_e;
+	}
+	
+	pfkey_supported_listp = pfkey_supported_list[satype];
+	while(pfkey_supported_listp) {
+		if(alg_num_a) {
+			if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_AUTH) {
+				alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id;
+				alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen;
+				alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits;
+				alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits;
+				alg_ap->sadb_alg_reserved = 0;
+				KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+					    "klips_debug:pfkey_register_reply: "
+					    "adding auth=%p\n",
+					    alg_ap);
+				alg_ap++;
+			}
+		}
+		if(alg_num_e) {
+			if(pfkey_supported_listp->supportedp->supported_alg_exttype == SADB_EXT_SUPPORTED_ENCRYPT) {
+				alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->supported_alg_id;
+				alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->supported_alg_ivlen;
+				alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->supported_alg_minbits;
+				alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits;
+				alg_ep->sadb_alg_reserved = 0;
+				KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
+					    "klips_debug:pfkey_register_reply: "
+					    "adding encrypt=%p\n",
+					    alg_ep);
+				alg_ep++;
+			}
+		}
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_register_reply: "
+			    "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_supported_listp->supportedp->supported_alg_exttype,
+			    pfkey_supported_listp->supportedp->supported_alg_id,
+			    pfkey_supported_listp->supportedp->supported_alg_ivlen,
+			    pfkey_supported_listp->supportedp->supported_alg_minbits,
+			    pfkey_supported_listp->supportedp->supported_alg_maxbits);
+		pfkey_supported_listp = pfkey_supported_listp->next;
+	}
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_REGISTER,
+							  satype,
+							  0,
+							  sadb_msg? sadb_msg->sadb_msg_seq : ++pfkey_msg_seq,
+							  sadb_msg? sadb_msg->sadb_msg_pid: current->pid),
+			      extensions_reply) &&
+	     (alg_num_a ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_AUTH],
+									SADB_EXT_SUPPORTED_AUTH,
+									alg_num_a,
+									alg_a),
+					  extensions_reply) : 1) &&
+	     (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_ENCRYPT],
+									SADB_EXT_SUPPORTED_ENCRYPT,
+									alg_num_e,
+									alg_e),
+					  extensions_reply) : 1))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
+			    "failed to build the register message extensions_reply\n");
+		SENDERR(-error);
+	}
+	
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
+			    "failed to build the register message\n");
+		SENDERR(-error);
+	}
+	/* this should go to all registered sockets for that satype only */
+	for(pfkey_socketsp = pfkey_registered_sockets[satype];
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
+				    "sending up acquire message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
+			    "sending up register message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+ errlab:
+	if(alg_a) {
+		kfree(alg_a);
+	}
+	if(alg_e) {
+		kfree(alg_e);
+	}
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_expire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct socket_list *pfkey_socketsp;
+#ifdef CONFIG_IPSEC_DEBUG
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+#endif /* CONFIG_IPSEC_DEBUG */
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_expire_parse: .\n");
+
+	if(pfkey_open_sockets) {
+		for(pfkey_socketsp = pfkey_open_sockets;
+		    pfkey_socketsp;
+		    pfkey_socketsp = pfkey_socketsp->next) {
+			if((error = pfkey_upmsg(pfkey_socketsp->socketp,
+						((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) {
+				KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: "
+					    "sending up expire reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+					    satype,
+					    satype2name(satype),
+					    pfkey_socketsp->socketp,
+					    error);
+				SENDERR(-error);
+			}
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: "
+				    "sending up expire reply message for satype=%d(%s) to socket=%p succeeded.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp);
+		}
+	}
+
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_flush_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+	uint8_t proto = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_flush_parse: "
+		    "flushing type %d SAs\n",
+		    satype);
+
+	if(satype && !(proto = satype2proto(satype))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_flush_parse: "
+			    "satype %d lookup failed.\n", 
+			    ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
+		SENDERR(EINVAL);
+	}
+
+	if ((error = ipsec_sadb_cleanup(proto))) {
+		SENDERR(-error);
+	}
+
+	if(pfkey_open_sockets) {
+		for(pfkey_socketsp = pfkey_open_sockets;
+		    pfkey_socketsp;
+		    pfkey_socketsp = pfkey_socketsp->next) {
+			if((error = pfkey_upmsg(pfkey_socketsp->socketp,
+						((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) {
+				KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: "
+					    "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=%p failed with error=%d.\n",
+					    satype,
+					    satype2name(satype),
+					    proto,
+					    pfkey_socketsp->socketp,
+					    error);
+				SENDERR(-error);
+			}
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: "
+				    "sending up flush reply message for satype=%d(%s) to socket=%p succeeded.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp);
+		}
+	}
+
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_dump_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_dump_parse: .\n");
+
+	SENDERR(ENOSYS);
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_promisc_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_promisc_parse: .\n");
+
+	SENDERR(ENOSYS);
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_pchange_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_pchange_parse: .\n");
+
+	SENDERR(ENOSYS);
+ errlab:
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	struct ipsec_sa *tdb1p, *tdb2p, *tdbp;
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+	char sa1[SATOA_BUF], sa2[SATOA_BUF];
+	size_t sa_len1, sa_len2 = 0;
+	int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_grpsa_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	if(!extr || !extr->tdb) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_grpsa_parse: "
+			    "extr or extr->tdb is NULL, fatal.\n");
+		SENDERR(EINVAL);
+	}
+
+	sa_len1 = satoa(extr->tdb->tdb_said, 0, sa1, SATOA_BUF);
+	if(extr->tdb2) {
+		sa_len2 = satoa(extr->tdb2->tdb_said, 0, sa2, SATOA_BUF);
+	}
+
+	spin_lock_bh(&tdb_lock);
+
+	if(!(tdb1p = ipsec_sa_getbyid(&(extr->tdb->tdb_said)))) {
+		spin_unlock_bh(&tdb_lock);
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_grpsa_parse: "
+			    "reserved Tunnel Descriptor Block for SA: %s not found.  Call SADB_ADD/UPDATE first.\n",
+			    sa_len1 ? sa1 : " (error)");
+		SENDERR(ENOENT);
+	}
+	if(extr->tdb2) { /* GRPSA */
+		if(!(tdb2p = ipsec_sa_getbyid(&(extr->tdb2->tdb_said)))) {
+			spin_unlock_bh(&tdb_lock);
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_grpsa_parse: "
+				    "reserved Tunnel Descriptor Block for SA: %s not found.  Call SADB_ADD/UPDATE first.\n",
+				    sa_len2 ? sa2 : " (error)");
+			SENDERR(ENOENT);
+		}
+
+		/* Is either one already linked? */
+		if(tdb1p->tdb_onext) {
+			spin_unlock_bh(&tdb_lock);
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_grpsa_parse: "
+				    "Tunnel Descriptor Block for SA: %s is already linked.\n",
+				    sa_len1 ? sa1 : " (error)");
+			SENDERR(EEXIST);
+		}
+		if(tdb2p->tdb_inext) {
+			spin_unlock_bh(&tdb_lock);
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_grpsa_parse: "
+				    "Tunnel Descriptor Block for SA: %s is already linked.\n",
+				    sa_len2 ? sa2 : " (error)");
+			SENDERR(EEXIST);
+		}
+		
+		/* Is extr->tdb already linked to extr->tdb2? */
+		tdbp = tdb2p;
+		while(tdbp) {
+			if(tdbp == tdb1p) {
+				spin_unlock_bh(&tdb_lock);
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_x_grpsa_parse: "
+					    "Tunnel Descriptor Block for SA: %s is already linked to %s.\n",
+					    sa_len1 ? sa1 : " (error)",
+					    sa_len2 ? sa2 : " (error)");
+				SENDERR(EEXIST);
+			}
+			tdbp = tdb2p->tdb_onext;
+		}
+		
+		/* link 'em */
+		tdb1p->tdb_onext = tdb2p;
+		tdb2p->tdb_inext = tdb1p;
+	} else { /* UNGRPSA */
+		while(tdb1p->tdb_onext) {
+			tdb1p = tdb1p->tdb_onext;
+		}
+		while(tdb1p->tdb_inext) {
+			tdbp = tdb1p;
+			tdb1p = tdb1p->tdb_inext;
+			tdbp->tdb_inext = NULL;
+			tdb1p->tdb_onext = NULL;
+		}
+	}
+
+	spin_unlock_bh(&tdb_lock);
+
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_X_GRPSA,
+							  satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+							SADB_EXT_SA,
+							extr->tdb->tdb_said.spi,
+							extr->tdb->tdb_replaywin,
+							extr->tdb->tdb_state,
+							extr->tdb->tdb_authalg,
+							extr->tdb->tdb_encalg,
+							extr->tdb->tdb_flags),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+							     SADB_EXT_ADDRESS_DST,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     extr->tdb->tdb_addr_d),
+				 extensions_reply)
+	     && (extr->tdb2
+		 ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2],
+								  ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype
+								  /* proto2satype(extr->tdb2->tdb_said.proto) */),
+								  extensions_reply)
+				     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_X_EXT_SA2],
+										SADB_X_EXT_SA2,
+										extr->tdb2->tdb_said.spi,
+										extr->tdb2->tdb_replaywin,
+										extr->tdb2->tdb_state,
+										extr->tdb2->tdb_authalg,
+										extr->tdb2->tdb_encalg,
+										extr->tdb2->tdb_flags),
+							 extensions_reply)
+				     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2],
+										     SADB_X_EXT_ADDRESS_DST2,
+										     0, /*extr->tdb->tdb_said.proto,*/
+										     0,
+										     extr->tdb2->tdb_addr_d),
+							 extensions_reply) ) : 1 )
+		     )) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
+			    "failed to build the x_grpsa reply message extensions\n");
+		SENDERR(-error);
+	}
+	   
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
+			    "failed to build the x_grpsa reply message\n");
+		SENDERR(-error);
+	}
+	
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
+				    "sending up x_grpsa reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
+			    "sending up x_grpsa reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
+		    "succeeded in sending x_grpsa reply message.\n");
+	
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+#ifdef CONFIG_IPSEC_DEBUG
+	char buf1[64], buf2[64];
+#endif /* CONFIG_IPSEC_DEBUG */
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+	ip_address srcflow, dstflow, srcmask, dstmask;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_addflow_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	memset((caddr_t)&srcflow, 0, sizeof(srcflow));
+	memset((caddr_t)&dstflow, 0, sizeof(dstflow));
+	memset((caddr_t)&srcmask, 0, sizeof(srcmask));
+	memset((caddr_t)&dstmask, 0, sizeof(dstmask));
+
+	if(!extr || !(extr->tdb) || !(extr->eroute)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_addflow_parse: "
+			    "missing extr, tdb or eroute data.\n");
+		SENDERR(EINVAL);
+	}
+
+	srcflow.u.v4.sin_family = AF_INET;
+	dstflow.u.v4.sin_family = AF_INET;
+	srcmask.u.v4.sin_family = AF_INET;
+	dstmask.u.v4.sin_family = AF_INET;
+	srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src;
+	dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst;
+	srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src;
+	dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst;
+
+#ifdef CONFIG_IPSEC_DEBUG
+	if (debug_pfkey) {
+		subnettoa(extr->eroute->er_eaddr.sen_ip_src,
+			  extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(extr->eroute->er_eaddr.sen_ip_dst,
+			  extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_addflow_parse: "
+			    "calling breakeroute and/or makeroute for %s->%s\n",
+			    buf1, buf2);
+	}
+#endif /* CONFIG_IPSEC_DEBUG */
+	if(extr->tdb->tdb_flags & SADB_X_SAFLAGS_INFLOW) {
+/*	if(ip_chk_addr((unsigned long)extr->tdb->tdb_said.dst.s_addr) == IS_MYADDR) */ 
+		struct ipsec_sa *tdbp;
+		char sa[SATOA_BUF];
+		size_t sa_len;
+
+		if((tdbp = ipsec_sa_getbyid(&(extr->tdb->tdb_said))) == NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_addflow_parse: "
+				    "tdb not found, cannot set incoming policy.\n");
+			SENDERR(ENOENT);
+		}
+
+		while(tdbp && tdbp->tdb_said.proto != IPPROTO_IPIP) {
+			tdbp = tdbp->tdb_inext;
+		}
+
+		if(tdbp == NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_addflow_parse: "
+				    "SA chain does not have an IPIP SA, cannot set incoming policy.\n");
+			SENDERR(ENOENT);
+		}
+
+		sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+
+/*		tdbp->tdb_flow_s.u.v4.sin_addr = srcflow.u.v4.sin_addr;
+		tdbp->tdb_flow_d.u.v4.sin_addr = dstflow.u.v4.sin_addr;
+		tdbp->tdb_mask_s.u.v4.sin_addr = srcmask.u.v4.sin_addr;
+		tdbp->tdb_mask_d.u.v4.sin_addr = dstmask.u.v4.sin_addr; */
+
+		tdbp->tdb_flags |= SADB_X_SAFLAGS_INFLOW;
+		tdbp->tdb_flow_s = srcflow;
+		tdbp->tdb_flow_d = dstflow;
+		tdbp->tdb_mask_s = srcmask;
+		tdbp->tdb_mask_d = dstmask;
+
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_addflow_parse: "
+			    "inbound eroute, setting incoming policy information in IPIP Tunnel Descriptor Block for SA: %s.\n",
+			    sa_len ? sa : " (error)");
+	} else {
+		struct sk_buff *first = NULL, *last = NULL;
+
+		if(extr->tdb->tdb_flags & SADB_X_SAFLAGS_REPLACEFLOW) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_addflow_parse: "
+				    "REPLACEFLOW flag set, calling breakeroute.\n");
+			if ((error = ipsec_breakroute(&(extr->eroute->er_eaddr),
+						      &(extr->eroute->er_emask),
+						      &first, &last))) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_x_addflow_parse: "
+					    "breakeroute returned %d.  first=%p, last=%p\n",
+					    error,
+					    first,
+					    last);
+				if(first != NULL) {
+					kfree_skb(first);
+				}
+				if(last != NULL) {
+					kfree_skb(last);
+				}
+				SENDERR(-error);
+			}
+		}
+		
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_addflow_parse: "
+			    "calling makeroute.\n");
+		
+		if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr),
+					     &(extr->eroute->er_emask),
+					     extr->tdb->tdb_said,
+					     ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid,
+					     NULL,
+					     &(extr->tdb->tdb_ident_s),
+					     &(extr->tdb->tdb_ident_d)))) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_addflow_parse: "
+				    "makeroute returned %d.\n", error);
+			SENDERR(-error);
+		}
+		if(first != NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_addflow_parse: "
+				    "first=%p HOLD packet re-injected.\n",
+				    first);
+			/* ipsec_tunnel_start_xmit(first, first->dev); */
+			DEV_QUEUE_XMIT(first, first->dev, SOPRI_NORMAL);
+		}
+		if(last != NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_addflow_parse: "
+				    "last=%p HOLD packet re-injected.\n",
+				    last);
+			/* ipsec_tunnel_start_xmit(last, last->dev); */
+			DEV_QUEUE_XMIT(last, last->dev, SOPRI_NORMAL);
+		}
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_addflow_parse: "
+		    "makeroute call successful.\n");
+
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_X_ADDFLOW,
+							  satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+							SADB_EXT_SA,
+							extr->tdb->tdb_said.spi,
+							extr->tdb->tdb_replaywin,
+							extr->tdb->tdb_state,
+							extr->tdb->tdb_authalg,
+							extr->tdb->tdb_encalg,
+							extr->tdb->tdb_flags),
+				 extensions_reply)
+	     && (extensions[SADB_EXT_ADDRESS_SRC]
+		 ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
+								SADB_EXT_ADDRESS_SRC,
+								0, /*extr->tdb->tdb_said.proto,*/
+								0,
+								extr->tdb->tdb_addr_s),
+				    extensions_reply) : 1)
+	     && (extensions[SADB_EXT_ADDRESS_DST]
+		 ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+								SADB_EXT_ADDRESS_DST,
+								0, /*extr->tdb->tdb_said.proto,*/
+								0,
+								extr->tdb->tdb_addr_d),
+				    extensions_reply) : 1)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW],
+							     SADB_X_EXT_ADDRESS_SRC_FLOW,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&srcflow),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW],
+							     SADB_X_EXT_ADDRESS_DST_FLOW,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&dstflow),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK],
+							     SADB_X_EXT_ADDRESS_SRC_MASK,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&srcmask),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK],
+							     SADB_X_EXT_ADDRESS_DST_MASK,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&dstmask),
+				 extensions_reply)
+		)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
+			    "failed to build the x_addflow reply message extensions\n");
+		SENDERR(-error);
+	}
+		
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
+			    "failed to build the x_addflow reply message\n");
+		SENDERR(-error);
+	}
+	
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
+				    "sending up x_addflow reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
+			    "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    extr->tdb->tdb_said.proto,
+			    pfkey_socketsp->socketp);
+	}
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_addflow_parse: "
+		    "extr->tdb cleaned up and freed.\n");
+
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_delflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+#ifdef CONFIG_IPSEC_DEBUG
+	char buf1[64], buf2[64];
+#endif /* CONFIG_IPSEC_DEBUG */
+	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_reply = NULL;
+	struct socket_list *pfkey_socketsp;
+	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
+	ip_address srcflow, dstflow, srcmask, dstmask;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_delflow_parse: .\n");
+
+	pfkey_extensions_init(extensions_reply);
+
+	memset((caddr_t)&srcflow, 0, sizeof(srcflow));
+	memset((caddr_t)&dstflow, 0, sizeof(dstflow));
+	memset((caddr_t)&srcmask, 0, sizeof(srcmask));
+	memset((caddr_t)&dstmask, 0, sizeof(dstmask));
+
+	if(!extr || !(extr->tdb)) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_delflow_parse: "
+			    "extr, or extr->tdb is NULL, fatal\n");
+		SENDERR(EINVAL);
+	}
+
+	if(extr->tdb->tdb_flags & SADB_X_SAFLAGS_CLEARFLOW) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_x_delflow_parse: "
+			    "CLEARFLOW flag set, calling cleareroutes.\n");
+		if ((error = ipsec_cleareroutes()))
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_delflow_parse: "
+				    "cleareroutes returned %d.\n", error);
+			SENDERR(-error);
+	} else {
+		struct sk_buff *first = NULL, *last = NULL;
+
+		if(!(extr->eroute)) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_delflow_parse: "
+				    "extr->eroute is NULL, fatal.\n");
+			SENDERR(EINVAL);
+		}
+		
+		srcflow.u.v4.sin_family = AF_INET;
+		dstflow.u.v4.sin_family = AF_INET;
+		srcmask.u.v4.sin_family = AF_INET;
+		dstmask.u.v4.sin_family = AF_INET;
+		srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src;
+		dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst;
+		srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src;
+		dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst;
+
+#ifdef CONFIG_IPSEC_DEBUG
+		if (debug_pfkey) {
+			subnettoa(extr->eroute->er_eaddr.sen_ip_src,
+				  extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
+			subnettoa(extr->eroute->er_eaddr.sen_ip_dst,
+				  extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_delflow_parse: "
+				    "calling breakeroute for %s->%s\n",
+				    buf1, buf2);
+		}
+#endif /* CONFIG_IPSEC_DEBUG */
+		if((error = ipsec_breakroute(&(extr->eroute->er_eaddr),
+					     &(extr->eroute->er_emask),
+					     &first, &last))) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_x_delflow_parse: "
+				    "breakeroute returned %d.  first=%p, last=%p\n",
+				    error,
+				    first,
+				    last);
+			if(first != NULL) {
+				kfree_skb(first);
+			}
+			if(last != NULL) {
+				kfree_skb(last);
+			}
+			SENDERR(-error);
+		}
+		if(first != NULL) {
+			kfree_skb(first);
+		}
+		if(last != NULL) {
+			kfree_skb(last);
+		}
+	}
+	
+	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
+							  SADB_X_DELFLOW,
+							  satype,
+							  0,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
+							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+			      extensions_reply)
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+							SADB_EXT_SA,
+							extr->tdb->tdb_said.spi,
+							extr->tdb->tdb_replaywin,
+							extr->tdb->tdb_state,
+							extr->tdb->tdb_authalg,
+							extr->tdb->tdb_encalg,
+							extr->tdb->tdb_flags),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW],
+							     SADB_X_EXT_ADDRESS_SRC_FLOW,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&srcflow),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW],
+							     SADB_X_EXT_ADDRESS_DST_FLOW,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&dstflow),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK],
+							     SADB_X_EXT_ADDRESS_SRC_MASK,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&srcmask),
+				 extensions_reply)
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK],
+							     SADB_X_EXT_ADDRESS_DST_MASK,
+							     0, /*extr->tdb->tdb_said.proto,*/
+							     0,
+							     (struct sockaddr*)&dstmask),
+				 extensions_reply)
+		)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
+			    "failed to build the x_delflow reply message extensions\n");
+		SENDERR(-error);
+	}
+		
+	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
+			    "failed to build the x_delflow reply message\n");
+		SENDERR(-error);
+	}
+	
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
+				    "sending up x_delflow reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
+			    "sending up x_delflow reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_delflow_parse: "
+		    "extr->tdb cleaned up and freed.\n");
+
+ errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_msg_debug_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	int error = 0;
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_msg_debug_parse: .\n");
+
+/* errlab:*/
+	return error;
+}
+
+/* pfkey_expire expects the tdb table to be locked before being called. */
+int
+pfkey_expire(struct ipsec_sa *tdbp, int hard)
+{
+	struct sadb_ext *extensions[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_msg = NULL;
+	struct socket_list *pfkey_socketsp;
+	int error = 0;
+	uint8_t satype;
+
+	pfkey_extensions_init(extensions);
+
+	if(!(satype = proto2satype(tdbp->tdb_said.proto))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_expire: "
+			    "satype lookup for protocol %d lookup failed.\n", 
+			    tdbp->tdb_said.proto);
+		SENDERR(EINVAL);
+	}
+	
+	if(!pfkey_open_sockets) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
+			    "no sockets listening.\n");
+		SENDERR(EPROTONOSUPPORT);
+	}
+
+	if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0],
+							   SADB_EXPIRE,
+							   satype,
+							   0,
+							   ++pfkey_msg_seq,
+							   0),
+			       extensions)
+	      && pfkey_safe_build(error = pfkey_sa_build(&extensions[SADB_EXT_SA],
+							 SADB_EXT_SA,
+							 tdbp->tdb_said.spi,
+							 tdbp->tdb_replaywin,
+							 tdbp->tdb_state,
+							 tdbp->tdb_authalg,
+							 tdbp->tdb_encalg,
+							 tdbp->tdb_flags),
+				  extensions)
+	      && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_CURRENT],
+							       SADB_EXT_LIFETIME_CURRENT,
+							       tdbp->ips_life.ipl_allocations.ipl_count,
+							       tdbp->ips_life.ipl_bytes.ipl_count,
+							       tdbp->ips_life.ipl_addtime.ipl_count,
+							       tdbp->ips_life.ipl_usetime.ipl_count,
+							       tdbp->ips_life.ipl_packets.ipl_count),
+				  extensions)
+	      && (hard ? 
+		  pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD],
+								SADB_EXT_LIFETIME_HARD,
+								tdbp->ips_life.ipl_allocations.ipl_hard,
+								tdbp->ips_life.ipl_bytes.ipl_hard,
+								tdbp->ips_life.ipl_addtime.ipl_hard,
+								tdbp->ips_life.ipl_usetime.ipl_hard,
+								tdbp->ips_life.ipl_packets.ipl_hard),
+				   extensions)
+		  : pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT],
+								  SADB_EXT_LIFETIME_SOFT,
+								  tdbp->ips_life.ipl_allocations.ipl_soft,
+								  tdbp->ips_life.ipl_bytes.ipl_soft,
+								  tdbp->ips_life.ipl_addtime.ipl_soft,
+								  tdbp->ips_life.ipl_usetime.ipl_soft,
+								  tdbp->ips_life.ipl_packets.ipl_soft),
+				     extensions))
+	      && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
+							      SADB_EXT_ADDRESS_SRC,
+							      0, /* tdbp->tdb_said.proto, */
+							      0,
+							      tdbp->tdb_addr_s),
+				  extensions)
+	      && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
+							      SADB_EXT_ADDRESS_DST,
+							      0, /* tdbp->tdb_said.proto, */
+							      0,
+							      tdbp->tdb_addr_d),
+				  extensions))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
+			    "failed to build the expire message extensions\n");
+		spin_unlock(&tdb_lock);
+		goto errlab;
+	}
+	
+	if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
+			    "failed to build the expire message\n");
+		SENDERR(-error);
+	}
+	
+	for(pfkey_socketsp = pfkey_open_sockets;
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
+				    "sending up expire message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
+			    "sending up expire message for satype=%d(%s) (proto=%d) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    tdbp->tdb_said.proto,
+			    pfkey_socketsp->socketp);
+	}
+	
+ errlab:
+	if (pfkey_msg) {
+		pfkey_msg_free(&pfkey_msg);
+	}
+	pfkey_extensions_free(extensions);
+	return error;
+}
+
+int
+pfkey_acquire(struct ipsec_sa *tdbp)
+{
+	struct sadb_ext *extensions[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_msg = NULL;
+	struct socket_list *pfkey_socketsp;
+	int error = 0;
+	struct sadb_comb comb[] = {
+		/* auth; encrypt; flags; */
+		/* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */
+		/* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */
+		/* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */
+		/* soft_packets; hard_packets; */
+		{ SADB_AALG_MD5HMAC,  SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS,
+		  128, 128, 168, 168,
+		  0, 0, 0, 0, 0,
+		  57600, 86400, 57600, 86400,
+		  0, 0 },
+		{ SADB_AALG_SHA1HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS,
+		  160, 160, 168, 168,
+		  0, 0, 0, 0, 0,
+		  57600, 86400, 57600, 86400,
+		  0, 0 }
+	};
+       
+	/* XXX This should not be hard-coded.  It should be taken from the spdb */
+	uint8_t satype = SADB_SATYPE_ESP;
+
+	pfkey_extensions_init(extensions);
+
+	if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+			    "SAtype=%d unspecified or unknown.\n",
+			    satype);
+		SENDERR(EINVAL);
+	}
+
+	if(!(pfkey_registered_sockets[satype])) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+			    "no sockets registered for SAtype=%d(%s).\n",
+			    satype,
+			    satype2name(satype));
+		SENDERR(EPROTONOSUPPORT);
+	}
+	
+	if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0],
+							  SADB_ACQUIRE,
+							  satype,
+							  0,
+							  ++pfkey_msg_seq,
+							  0),
+			      extensions)
+	      && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
+							      SADB_EXT_ADDRESS_SRC,
+							      tdbp->tdb_said.proto,
+							      0,
+							      tdbp->tdb_addr_s),
+				  extensions)
+	      && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
+							      SADB_EXT_ADDRESS_DST,
+							      tdbp->tdb_said.proto,
+							      0,
+							      tdbp->tdb_addr_d),
+				  extensions)
+#if 0
+	      && (tdbp->tdb_addr_p
+		  ? pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY],
+								 SADB_EXT_ADDRESS_PROXY,
+								 tdbp->tdb_said.proto,
+								 0,
+								 tdbp->tdb_addr_p),
+				     extensions) : 1)
+#endif
+	      && (tdbp->tdb_ident_s.type != SADB_IDENTTYPE_RESERVED
+		  ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC],
+							       SADB_EXT_IDENTITY_SRC,
+							       tdbp->tdb_ident_s.type,
+							       tdbp->tdb_ident_s.id,
+							       tdbp->tdb_ident_s.len,
+							       tdbp->tdb_ident_s.data),
+				     extensions) : 1)
+
+	      && (tdbp->tdb_ident_d.type != SADB_IDENTTYPE_RESERVED
+		  ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST],
+							       SADB_EXT_IDENTITY_DST,
+							       tdbp->tdb_ident_d.type,
+							       tdbp->tdb_ident_d.id,
+							       tdbp->tdb_ident_d.len,
+							       tdbp->tdb_ident_d.data),
+				     extensions) : 1)
+#if 0
+	      /* FIXME: This won't work yet because I have not finished
+		 it. */
+	      && (tdbp->tdb_sens_
+		  ? pfkey_safe_build(error = pfkey_sens_build(&extensions[SADB_EXT_SENSITIVITY],
+							      tdbp->tdb_sens_dpd,
+							      tdbp->tdb_sens_sens_level,
+							      tdbp->tdb_sens_sens_len,
+							      tdbp->tdb_sens_sens_bitmap,
+							      tdbp->tdb_sens_integ_level,
+							      tdbp->tdb_sens_integ_len,
+							      tdbp->tdb_sens_integ_bitmap),
+				     extensions) : 1)
+#endif
+	      && pfkey_safe_build(error = pfkey_prop_build(&extensions[SADB_EXT_PROPOSAL],
+							   64, /* replay */
+							   sizeof(comb)/sizeof(struct sadb_comb),
+							   &(comb[0])),
+				  extensions)
+		)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+			    "failed to build the acquire message extensions\n");
+		SENDERR(-error);
+	}
+	
+	if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+			    "failed to build the acquire message\n");
+		SENDERR(-error);
+	}
+
+#if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0
+	if(sysctl_ipsec_regress_pfkey_lossage) {
+		return(0);
+	}
+#endif	
+	
+	/* this should go to all registered sockets for that satype only */
+	for(pfkey_socketsp = pfkey_registered_sockets[satype];
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+				    "sending up acquire message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+			    "sending up acquire message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+ errlab:
+	if (pfkey_msg) {
+		pfkey_msg_free(&pfkey_msg);
+	}
+	pfkey_extensions_free(extensions);
+	return error;
+}
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+int
+pfkey_nat_t_new_mapping(struct ipsec_sa *tdbp, struct sockaddr *ipaddr,
+	__u16 sport)
+{
+	struct sadb_ext *extensions[SADB_EXT_MAX+1];
+	struct sadb_msg *pfkey_msg = NULL;
+	struct socket_list *pfkey_socketsp;
+	int error = 0;
+	uint8_t satype = (tdbp->tdb_said.proto==IPPROTO_ESP) ? SADB_SATYPE_ESP : 0;
+
+	/* Construct SADB_X_NAT_T_NEW_MAPPING message */
+
+	pfkey_extensions_init(extensions);
+
+	if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
+			    "SAtype=%d unspecified or unknown.\n",
+			    satype);
+		SENDERR(EINVAL);
+	}
+
+	if(!(pfkey_registered_sockets[satype])) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
+			    "no sockets registered for SAtype=%d(%s).\n",
+			    satype,
+			    satype2name(satype));
+		SENDERR(EPROTONOSUPPORT);
+	}
+
+	if (!(pfkey_safe_build
+		(error = pfkey_msg_hdr_build(&extensions[0], SADB_X_NAT_T_NEW_MAPPING,
+			satype, 0, ++pfkey_msg_seq, 0), extensions)
+		/* SA */
+		&& pfkey_safe_build
+		(error = pfkey_sa_build(&extensions[SADB_EXT_SA],
+			SADB_EXT_SA, tdbp->tdb_said.spi, 0, 0, 0, 0, 0), extensions)
+		/* ADDRESS_SRC = old addr */
+		&& pfkey_safe_build
+		(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
+			SADB_EXT_ADDRESS_SRC, tdbp->tdb_said.proto, 0, tdbp->tdb_addr_s),
+			extensions)
+		/* NAT_T_SPORT = old port */
+	    && pfkey_safe_build
+		(error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_SPORT],
+			SADB_X_EXT_NAT_T_SPORT, tdbp->ips_natt_sport), extensions)
+		/* ADDRESS_DST = new addr */
+		&& pfkey_safe_build
+		(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
+			SADB_EXT_ADDRESS_DST, tdbp->tdb_said.proto, 0, ipaddr), extensions)
+		/* NAT_T_DPORT = new port */
+	    && pfkey_safe_build
+		(error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_DPORT],
+			SADB_X_EXT_NAT_T_DPORT, sport), extensions)
+		)) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
+			    "failed to build the nat_t_new_mapping message extensions\n");
+		SENDERR(-error);
+	}
+	
+	if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
+			    "failed to build the nat_t_new_mapping message\n");
+		SENDERR(-error);
+	}
+
+	/* this should go to all registered sockets for that satype only */
+	for(pfkey_socketsp = pfkey_registered_sockets[satype];
+	    pfkey_socketsp;
+	    pfkey_socketsp = pfkey_socketsp->next) {
+		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
+				    "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
+		}
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
+			    "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
+	}
+	
+ errlab:
+	if (pfkey_msg) {
+		pfkey_msg_free(&pfkey_msg);
+	}
+	pfkey_extensions_free(extensions);
+	return error;
+}
+
+DEBUG_NO_STATIC int
+pfkey_x_nat_t_new_mapping_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
+{
+	/* SADB_X_NAT_T_NEW_MAPPING not used in kernel */
+	return -EINVAL;
+}
+#endif
+
+DEBUG_NO_STATIC int (*ext_processors[SADB_EXT_MAX+1])(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) =
+{
+  NULL, /* pfkey_msg_process, */
+        pfkey_sa_process,
+        pfkey_lifetime_process,
+        pfkey_lifetime_process,
+        pfkey_lifetime_process,
+        pfkey_address_process,
+        pfkey_address_process,
+        pfkey_address_process,
+        pfkey_key_process,
+        pfkey_key_process,
+        pfkey_ident_process,
+        pfkey_ident_process,
+        pfkey_sens_process,
+        pfkey_prop_process,
+        pfkey_supported_process,
+        pfkey_supported_process,
+        pfkey_spirange_process,
+        pfkey_x_kmprivate_process,
+        pfkey_x_satype_process,
+        pfkey_sa_process,
+        pfkey_address_process,
+        pfkey_address_process,
+        pfkey_address_process,
+        pfkey_address_process,
+        pfkey_address_process,
+	pfkey_x_debug_process,
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	pfkey_x_nat_t_type_process,
+	pfkey_x_nat_t_port_process,
+	pfkey_x_nat_t_port_process,
+	pfkey_address_process,
+#endif
+	pfkey_x_protocol_process
+};
+
+
+DEBUG_NO_STATIC int (*msg_parsers[SADB_MAX +1])(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr)
+ =
+{
+	NULL, /* RESERVED */
+	pfkey_getspi_parse,
+	pfkey_update_parse,
+	pfkey_add_parse,
+	pfkey_delete_parse,
+	pfkey_get_parse,
+	pfkey_acquire_parse,
+	pfkey_register_parse,
+	pfkey_expire_parse,
+	pfkey_flush_parse,
+	pfkey_dump_parse,
+	pfkey_x_promisc_parse,
+	pfkey_x_pchange_parse,
+	pfkey_x_grpsa_parse,
+	pfkey_x_addflow_parse,
+	pfkey_x_delflow_parse,
+	pfkey_x_msg_debug_parse
+#ifdef NAT_TRAVERSAL
+	, pfkey_x_nat_t_new_mapping_parse
+#endif
+};
+
+int
+pfkey_build_reply(struct sadb_msg *pfkey_msg, struct pfkey_extracted_data *extr,
+				struct sadb_msg **pfkey_reply)
+{
+	struct sadb_ext *extensions[SADB_EXT_MAX+1];
+	int error = 0;
+	int msg_type = pfkey_msg->sadb_msg_type;
+	int seq = pfkey_msg->sadb_msg_seq;
+
+	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
+		    "building reply with type: %d\n",
+		    msg_type);
+	pfkey_extensions_init(extensions);
+	if (!extr || !extr->tdb) {
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
+				    "bad TDB passed\n");
+			return EINVAL;
+	}
+	error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0],
+						     msg_type,
+						     proto2satype(extr->tdb->tdb_said.proto),
+						     0,
+						     seq,
+						     pfkey_msg->sadb_msg_pid),
+				 extensions) &&
+		(!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
+		   1 << SADB_EXT_SA)
+		 || pfkey_safe_build(pfkey_sa_build(&extensions[SADB_EXT_SA],
+						    SADB_EXT_SA,
+						    extr->tdb->tdb_said.spi,
+						    extr->tdb->tdb_replaywin,
+						    extr->tdb->tdb_state,
+						    extr->tdb->tdb_authalg,
+						    extr->tdb->tdb_encalg,
+						    extr->tdb->tdb_flags),
+				     extensions)) &&
+		(!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
+		   1 << SADB_EXT_LIFETIME_CURRENT)
+		 || pfkey_safe_build(pfkey_lifetime_build(&extensions
+							  [SADB_EXT_LIFETIME_CURRENT],
+							  SADB_EXT_LIFETIME_CURRENT,
+							  extr->tdb->ips_life.ipl_allocations.ipl_count,
+							  extr->tdb->ips_life.ipl_bytes.ipl_count,
+							  extr->tdb->ips_life.ipl_addtime.ipl_count,
+							  extr->tdb->ips_life.ipl_usetime.ipl_count,
+							  extr->tdb->ips_life.ipl_packets.ipl_count),
+				     extensions)) &&
+		(!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
+		   1 << SADB_EXT_ADDRESS_SRC)
+		 || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
+							 SADB_EXT_ADDRESS_SRC,
+							 extr->tdb->tdb_said.proto,
+							 0,
+							 extr->tdb->tdb_addr_s),
+				     extensions)) &&
+		(!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
+		   1 << SADB_EXT_ADDRESS_DST)
+		 || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
+							 SADB_EXT_ADDRESS_DST,
+							 extr->tdb->tdb_said.proto,
+							 0,
+							 extr->tdb->tdb_addr_d),
+				     extensions));
+
+	if (error == 0) {
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
+			    "building extensions failed\n");
+		return EINVAL;
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_build_reply: "
+		    "built extensions, proceed to build the message\n");
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_build_reply: "
+		    "extensions[1]= %p\n",
+		    extensions[1]);
+	error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT);
+	pfkey_extensions_free(extensions);
+
+	return error;
+}
+
+int
+pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg,
+				struct sadb_msg **pfkey_reply)
+{
+	int error = 0;
+	int i;
+	struct sadb_ext *extensions[SADB_EXT_MAX+1];
+	struct pfkey_extracted_data extr = {NULL, NULL, NULL};
+	
+	pfkey_extensions_init(extensions);
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_msg_interp: "
+		    "parsing message ver=%d, type=%d, errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", 
+		    pfkey_msg->sadb_msg_version,
+		    pfkey_msg->sadb_msg_type,
+		    pfkey_msg->sadb_msg_errno,
+		    pfkey_msg->sadb_msg_satype,
+		    satype2name(pfkey_msg->sadb_msg_satype),
+		    pfkey_msg->sadb_msg_len,
+		    pfkey_msg->sadb_msg_reserved,
+		    pfkey_msg->sadb_msg_seq,
+		    pfkey_msg->sadb_msg_pid);
+	
+	if((error = pfkey_alloc_ipsec_sa(&(extr.tdb)))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_msg_interp: "
+			    "something's really wrong, extr.tdb=%p should be NULL.\n",
+			    extr.tdb);
+		SENDERR(-error);
+	}
+
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_msg_interp: "
+		    "allocated extr->tdb=%p.\n",
+		    extr.tdb);
+	
+	if(pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_msg_interp: "
+			    "satype %d > max %d\n", 
+			    pfkey_msg->sadb_msg_satype,
+			    SADB_SATYPE_MAX);
+		SENDERR(EINVAL);
+	}
+	
+	switch(pfkey_msg->sadb_msg_type) {
+	case SADB_GETSPI:
+	case SADB_UPDATE:
+	case SADB_ADD:
+	case SADB_DELETE:
+	case SADB_X_GRPSA:
+	case SADB_X_ADDFLOW:
+		if(!(extr.tdb->tdb_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_msg_interp: "
+				    "satype %d lookup failed.\n", 
+				    pfkey_msg->sadb_msg_satype);
+			SENDERR(EINVAL);
+		} else {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_msg_interp: "
+				    "satype %d lookups to proto=%d.\n", 
+				    pfkey_msg->sadb_msg_satype,
+				    extr.tdb->tdb_said.proto);
+		}
+		break;
+	default:
+	}
+	
+	/* The NULL below causes the default extension parsers to be used */
+	/* Parse the extensions */
+	if((error = pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN)))
+	{
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_msg_interp: "
+			    "message parsing failed with error %d.\n",
+			    error); 
+		SENDERR(-error);
+	}
+	
+	/* Process the extensions */
+	for(i=1; i <= SADB_EXT_MAX;i++)	{
+		if(extensions[i] != NULL) {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_msg_interp: "
+				    "processing ext %d %p with processor %p.\n", 
+				    i, extensions[i], ext_processors[i]);
+			if((error = ext_processors[i](extensions[i], &extr))) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_msg_interp: "
+					    "extension processing for type %d failed with error %d.\n",
+					    i,
+					    error); 
+				SENDERR(-error);
+			}
+			
+		}
+		
+	}
+	
+	/* Parse the message types */
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_msg_interp: "
+		    "parsing message type %d with msg_parser %p.\n",
+		    pfkey_msg->sadb_msg_type,
+		    msg_parsers[pfkey_msg->sadb_msg_type]); 
+	if((error = msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_msg_interp: "
+			    "message parsing failed with error %d.\n",
+			    error); 
+		SENDERR(-error);
+	}
+
+#if 0
+	error = pfkey_build_reply(pfkey_msg, &extr, pfkey_reply);
+	if (error) {
+		*pfkey_reply = NULL;
+	}
+#endif	
+ errlab:
+	if(extr.tdb != NULL) {
+		ipsec_sa_wipe(extr.tdb);
+	}
+	if(extr.tdb2 != NULL) {
+		ipsec_sa_wipe(extr.tdb2);
+	}
+	if (extr.eroute != NULL) {
+		kfree(extr.eroute);
+	}
+	return(error);
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.14  2003/02/07 13:14:25  ken
+ * Pullin jjo's ALG 0.8.1rc branch
+ *
+ * Revision 1.13.2.1  2003/02/06 22:09:50  jjo
+ * sync to alg-0.8.1-rc4
+ *
+ * Revision 1.13  2003/01/19 22:32:30  ken
+ * X.509 0.9.19 -> 0.9.20
+ *
+ * Revision 1.12  2003/01/02 22:56:51  ken
+ * Relocate variable delcaration to correct function
+ *
+ * Revision 1.11  2003/01/02 22:48:42  ken
+ * Fix bad NAT-T 0.5 merge
+ *
+ * Revision 1.10  2003/01/02 21:54:27  ken
+ * NAT-T 0.5
+ *
+ * Revision 1.9  2002/12/28 01:45:14  ken
+ * Remove extra , line
+ *
+ * Revision 1.8  2002/12/26 02:28:50  ken
+ * Fix order of SADB definations
+ *
+ * Revision 1.7  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.6  2002/10/16 00:21:47  ken
+ * Applied JuanJo's NULL Patch
+ *
+ * Revision 1.5  2002/10/16 00:16:50  ken
+ * Backed out David patch in prep for JuanJo's
+ *
+ * Revision 1.4  2002/10/15 17:52:48  ken
+ * Added David De Reu's NULL ALG Bugfix
+ *
+ * Revision 1.3  2002/09/05 03:53:52  ken
+ * Added NAT-T Patch
+ *
+ * Revision 1.2  2002/09/05 03:27:09  ken
+ * Applied freeswan-alg-0.8.0-BASE-klips.diff
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:18  ken
+ * 1.98b
+ *
+ * Revision 1.102  2002/03/08 01:15:17  mcr
+ * 	put some internal structure only debug messages behind
+ * 	&& sysctl_ipsec_debug_verbose.
+ *
+ * Revision 1.101  2002/01/29 17:17:57  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.100  2002/01/29 04:00:54  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.99  2002/01/29 02:13:19  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.98  2002/01/12 02:57:57  mcr
+ * 	first regression test causes acquire messages to be lost
+ * 	100% of the time. This is to help testing of pluto.
+ *
+ * Revision 1.97  2001/11/26 09:23:52  rgb
+ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
+ *
+ * Revision 1.93.2.4  2001/10/23 04:20:27  mcr
+ * 	parity was forced on wrong structure! prototypes help here.
+ *
+ * Revision 1.93.2.3  2001/10/22 21:14:59  mcr
+ * 	include des.h, removed phony prototypes and fixed calling
+ * 	conventions to match real prototypes.
+ *
+ * Revision 1.93.2.2  2001/10/15 05:39:03  mcr
+ * 	%08lx is not the right format for u32. Use %08x. 64-bit safe? ha.
+ *
+ * Revision 1.93.2.1  2001/09/25 02:30:14  mcr
+ * 	struct tdb -> struct ipsec_sa.
+ * 	use new lifetime structure. common format routines for debug.
+ *
+ * Revision 1.96  2001/11/06 20:47:54  rgb
+ * Fixed user context call to ipsec_dev_start_xmit() bug.  Call
+ * dev_queue_xmit() instead.
+ *
+ * Revision 1.95  2001/11/06 19:47:46  rgb
+ * Added packet parameter to lifetime and comb structures.
+ *
+ * Revision 1.94  2001/10/18 04:45:23  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.93  2001/09/20 15:32:59  rgb
+ * Min/max cleanup.
+ *
+ * Revision 1.92  2001/09/19 16:35:48  rgb
+ * PF_KEY ident fix for getspi from NetCelo (puttdb duplication).
+ *
+ * Revision 1.91  2001/09/15 16:24:06  rgb
+ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
+ *
+ * Revision 1.90  2001/09/14 16:58:38  rgb
+ * Added support for storing the first and last packets through a HOLD.
+ *
+ * Revision 1.89  2001/09/08 21:14:07  rgb
+ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
+ * Better state coherency (error management) between pf_key and IKE daemon.
+ * (NetCelo)
+ *
+ * Revision 1.88  2001/08/27 19:42:44  rgb
+ * Fix memory leak of encrypt and auth structs in pfkey register.
+ *
+ * Revision 1.87  2001/07/06 19:50:46  rgb
+ * Removed unused debugging code.
+ * Added inbound policy checking code for IPIP SAs.
+ *
+ * Revision 1.86  2001/06/20 06:26:04  rgb
+ * Changed missing SA errors from EEXIST to ENOENT and added debug output
+ * for already linked SAs.
+ *
+ * Revision 1.85  2001/06/15 04:57:02  rgb
+ * Remove single error return condition check and check for all errors in
+ * the case of a replace eroute delete operation.  This means that
+ * applications must expect to be deleting something before replacing it
+ * and if nothing is found, complain.
+ *
+ * Revision 1.84  2001/06/14 19:35:12  rgb
+ * Update copyright date.
+ *
+ * Revision 1.83  2001/06/12 00:03:19  rgb
+ * Silence debug set/unset under normal conditions.
+ *
+ * Revision 1.82  2001/05/30 08:14:04  rgb
+ * Removed vestiges of esp-null transforms.
+ *
+ * Revision 1.81  2001/05/27 06:12:12  rgb
+ * Added structures for pid, packet count and last access time to eroute.
+ * Added packet count to beginning of /proc/net/ipsec_eroute.
+ *
+ * Revision 1.80  2001/05/03 19:43:59  rgb
+ * Check error return codes for all build function calls.
+ * Standardise on SENDERR() macro.
+ *
+ * Revision 1.79  2001/04/20 21:09:16  rgb
+ * Cleaned up fixed tdbwipes.
+ * Free pfkey_reply and clean up extensions_reply for grpsa, addflow and
+ * delflow (Per Cederqvist) plugging memleaks.
+ *
+ * Revision 1.78  2001/04/19 19:02:39  rgb
+ * Fixed extr.tdb freeing, stealing it for getspi, update and add.
+ * Refined a couple of spinlocks, fixed the one in update.
+ *
+ * Revision 1.77  2001/04/18 20:26:16  rgb
+ * Wipe/free eroute and both tdbs from extr at end of pfkey_msg_interp()
+ * instead of inside each message type parser.  This fixes two memleaks.
+ *
+ * Revision 1.76  2001/04/17 23:51:18  rgb
+ * Quiet down pfkey_x_debug_process().
+ *
+ * Revision 1.75  2001/03/29 01:55:05  rgb
+ * Fixed pfkey key init memleak.
+ * Fixed pfkey encryption key debug output.
+ *
+ * Revision 1.74  2001/03/27 05:29:14  rgb
+ * Debug output cleanup/silencing.
+ *
+ * Revision 1.73  2001/02/28 05:03:28  rgb
+ * Clean up and rationalise startup messages.
+ *
+ * Revision 1.72  2001/02/27 22:24:56  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.71  2001/02/27 06:59:30  rgb
+ * Added satype2name() conversions most places satype is debug printed.
+ *
+ * Revision 1.70  2001/02/26 22:37:08  rgb
+ * Fixed 'unknown proto' INT bug in new code.
+ * Added satype to protocol debugging instrumentation.
+ *
+ * Revision 1.69  2001/02/26 19:57:51  rgb
+ * Re-formatted debug output (split lines, consistent spacing).
+ * Fixed as yet undetected FLUSH bug which called ipsec_tdbcleanup()
+ * with an satype instead of proto.
+ * Checked for satype consistency and fixed minor bugs.
+ * Fixed undetected ungrpspi bug that tried to upmsg a second tdb.
+ * Check for satype sanity in pfkey_expire().
+ * Added satype sanity check to addflow.
+ *
+ * Revision 1.68  2001/02/12 23:14:40  rgb
+ * Remove double spin lock in pfkey_expire().
+ *
+ * Revision 1.67  2001/01/31 19:23:40  rgb
+ * Fixed double-unlock bug introduced by grpsa upmsg (found by Lars Heete).
+ *
+ * Revision 1.66  2001/01/29 22:20:04  rgb
+ * Fix minor add upmsg lifetime bug.
+ *
+ * Revision 1.65  2001/01/24 06:12:33  rgb
+ * Fixed address extension compile bugs just introduced.
+ *
+ * Revision 1.64  2001/01/24 00:31:15  rgb
+ * Added upmsg for addflow/delflow.
+ *
+ * Revision 1.63  2001/01/23 22:02:55  rgb
+ * Added upmsg to x_grpsa.
+ * Fixed lifetimes extentions to add/update/get upmsg.
+ *
+ * Revision 1.62  2000/11/30 21:47:51  rgb
+ * Fix error return bug after returning from pfkey_tdb_init().
+ *
+ * Revision 1.61  2000/11/17 18:10:29  rgb
+ * Fixed bugs mostly relating to spirange, to treat all spi variables as
+ * network byte order since this is the way PF_KEYv2 stored spis.
+ *
+ * Revision 1.60  2000/11/06 04:34:53  rgb
+ * Changed non-exported functions to DEBUG_NO_STATIC.
+ * Add Svenning's adaptive content compression.
+ * Ditched spin_lock_irqsave in favour of spin_lock/_bh.
+ * Fixed double unlock bug (Svenning).
+ * Fixed pfkey_msg uninitialized bug in pfkey_{expire,acquire}().
+ * Fixed incorrect extension type (prop) in pfkey)acquire().
+ *
+ * Revision 1.59  2000/10/11 15:25:12  rgb
+ * Fixed IPCOMP disabled compile bug.
+ *
+ * Revision 1.58  2000/10/11 14:54:03  rgb
+ * Fixed pfkey_acquire() satype to SADB_SATYPE_ESP and removed pfkey
+ * protocol violations of setting pfkey_address_build() protocol parameter
+ * to non-zero except in the case of pfkey_acquire().
+ *
+ * Revision 1.57  2000/10/10 20:10:18  rgb
+ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
+ *
+ * Revision 1.56  2000/10/06 20:24:36  rgb
+ * Fixes to pfkey_acquire to initialize extensions[] and use correct
+ * ipproto.
+ *
+ * Revision 1.55  2000/10/03 03:20:57  rgb
+ * Added brackets to get a?b:c scope right for pfkey_register reply.
+ *
+ * Revision 1.54  2000/09/29 19:49:30  rgb
+ * As-yet-unused-bits cleanup.
+ *
+ * Revision 1.53  2000/09/28 00:35:45  rgb
+ * Padded SATYPE printout in pfkey_register for vertical alignment.
+ *
+ * Revision 1.52  2000/09/20 16:21:58  rgb
+ * Cleaned up ident string alloc/free.
+ *
+ * Revision 1.51  2000/09/20 04:04:20  rgb
+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in
+ * oopsen.
+ *
+ * Revision 1.50  2000/09/16 01:10:53  rgb
+ * Fixed unused var warning with debug off.
+ *
+ * Revision 1.49  2000/09/15 11:37:02  rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.48  2000/09/15 04:57:57  rgb
+ * Cleaned up existing IPCOMP code before svenning addition.
+ * Initialize pfkey_reply and extensions_reply in case of early error in
+ * message parsing functions (thanks Kai!).
+ *
+ * Revision 1.47  2000/09/13 08:02:56  rgb
+ * Added KMd registration notification.
+ *
+ * Revision 1.46  2000/09/12 22:35:36  rgb
+ * Restructured to remove unused extensions from CLEARFLOW messages.
+ *
+ * Revision 1.45  2000/09/12 03:24:23  rgb
+ * Converted #if0 debugs to sysctl.
+ *
+ * Revision 1.44  2000/09/09 06:38:39  rgb
+ * Correct SADB message type for update, add and delete.
+ *
+ * Revision 1.43  2000/09/08 19:19:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ * Removed all references to CONFIG_IPSEC_PFKEYv2.
+ * Put in sanity checks in most msg type parsers to catch invalid satypes
+ * and empty socket lists.
+ * Moved spin-locks in pfkey_get_parse() to simplify.
+ * Added pfkey_acquire().
+ * Added upwards messages to update, add, delete, acquire_parse,
+ * expire_parse and flush.
+ * Fix pfkey_prop_build() parameter to be only single indirection.
+ * Changed all replies to use pfkey_reply.
+ * Check return code on puttdb() and deltdbchain() in getspi, update,
+ * add, delete.
+ * Fixed up all pfkey replies to open and registered sockets.
+ *
+ * Revision 1.42  2000/09/01 18:50:26  rgb
+ * Added a supported algorithms array lists, one per satype and registered
+ * existing algorithms.
+ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to
+ * list.
+ * Only send pfkey_expire() messages to sockets registered for that satype.
+ * Added reply to pfkey_getspi_parse().
+ * Added reply to pfkey_get_parse().
+ * Fixed debug output label bug in pfkey_lifetime_process().
+ * Cleaned up pfkey_sa_process a little.
+ * Moved pfkey_safe_build() above message type parsers to make it available
+ * for creating replies.
+ * Added comments for future work in pfkey_acquire_parse().
+ * Fleshed out guts of pfkey_register_parse().
+ *
+ * Revision 1.41  2000/08/24 16:58:11  rgb
+ * Fixed key debugging variables.
+ * Fixed error return code for a failed search.
+ * Changed order of pfkey_get operations.
+ *
+ * Revision 1.40  2000/08/21 16:32:27  rgb
+ * Re-formatted for cosmetic consistency and readability.
+ *
+ * Revision 1.39  2000/08/20 21:38:57  rgb
+ * Bugfixes to as-yet-unused pfkey_update_parse() and
+ * pfkey_register_parse(). (Momchil)
+ * Added functions pfkey_safe_build(), pfkey_expire() and
+ * pfkey_build_reply(). (Momchil)
+ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil)
+ *
+ * Revision 1.38  2000/08/18 21:30:41  rgb
+ * Purged all tdb_spi, tdb_proto and tdb_dst macros.  They are unclear.
+ *
+ * Revision 1.37  2000/08/18 18:18:02  rgb
+ * Cosmetic and descriptive changes made to debug test.
+ * getspi and update fixes from Momchil.
+ *
+ * Revision 1.36  2000/08/15 15:41:55  rgb
+ * Fixed the (as yet unused and untested) pfkey_getspi() routine.
+ *
+ * Revision 1.35  2000/08/01 14:51:52  rgb
+ * Removed _all_ remaining traces of DES.
+ *
+ * Revision 1.34  2000/07/28 14:58:32  rgb
+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
+ *
+ * Revision 1.33  2000/06/28 05:50:11  rgb
+ * Actually set iv_bits.
+ *
+ * Revision 1.32  2000/05/30 18:36:56  rgb
+ * Fix AH auth hash setup bug.  This breaks interop with previous PF_KEY
+ * FreeS/WAN, but fixes interop with other implementations.
+ *
+ * Revision 1.31  2000/03/16 14:05:48  rgb
+ * Fixed brace scope preventing non-debug compile.
+ * Added null parameter check for pfkey_x_debug().
+ *
+ * Revision 1.30  2000/01/22 23:21:13  rgb
+ * Use new function satype2proto().
+ *
+ * Revision 1.29  2000/01/22 08:40:21  rgb
+ * Invert condition to known value to avoid AF_INET6 in 2.0.36.
+ *
+ * Revision 1.28  2000/01/22 07:58:57  rgb
+ * Fixed REPLACEFLOW bug, missing braces around KLIPS_PRINT *and* SENDERR.
+ *
+ * Revision 1.27  2000/01/22 03:48:01  rgb
+ * Added extr pointer component debugging.
+ *
+ * Revision 1.26  2000/01/21 09:41:25  rgb
+ * Changed a (void*) to (char*) cast to do proper pointer math.
+ * Don't call tdbwipe if tdb2 is NULL.
+ *
+ * Revision 1.25  2000/01/21 06:21:01  rgb
+ * Added address cases for eroute flows.
+ * Tidied up compiler directive indentation for readability.
+ * Added ictx,octx vars for simplification.
+ * Added macros for HMAC padding magic numbers.
+ * Converted from double tdb arguments to one structure (extr)
+ * containing pointers to all temporary information structures
+ * and checking for valid arguments to all ext processors and
+ * msg type parsers.
+ * Added spiungrp'ing.
+ * Added klipsdebug switching capability.
+ * Removed sa_process() check for zero protocol.
+ * Added address case for DST2 for grouping.
+ * Added/changed minor debugging instrumentation.
+ * Fixed spigrp for single said, ungrouping case.
+ * Added code to parse addflow and delflow messages.
+ * Removed redundant statements duplicating tdbwipe() functionality
+ * and causing double kfrees.
+ * Permit addflow to have a protocol of 0.
+ *
+ * Revision 1.24  1999/12/09 23:23:00  rgb
+ * Added check to pfkey_sa_process() to do eroutes.
+ * Converted to DIVUP() macro.
+ * Converted if() to switch() in pfkey_register_parse().
+ * Use new pfkey_extensions_init() instead of memset().
+ *
+ * Revision 1.23  1999/12/01 22:18:13  rgb
+ * Preset minspi and maxspi values in case and spirange extension is not
+ * included and check for the presence of an spirange extension before
+ * using it.  Initialise tdb_sastate to LARVAL.
+ * Fixed debugging output typo.
+ * Fixed authentication context initialisation bugs (4 places).
+ *
+ * Revision 1.22  1999/11/27 11:53:08  rgb
+ * Moved pfkey_msg_parse prototype to pfkey.h
+ * Moved exts_permitted/required prototype to pfkey.h.
+ * Moved sadb_satype2proto protocol lookup table to lib/pfkey_v2_parse.c.
+ * Deleted SADB_X_EXT_SA2 code from pfkey_sa_process() since it will never
+ * be called.
+ * Moved protocol/algorithm checks to lib/pfkey_v2_parse.c
+ * Debugging error messages added.
+ * Enable lifetime_current checking.
+ * Remove illegal requirement for SA extension to be present in an
+ * originating GETSPI call.
+ * Re-instate requirement for UPDATE or ADD message to be MATURE.
+ * Add argument to pfkey_msg_parse() for direction.
+ * Fixed IPIP dst address bug and purged redundant, leaky code.
+ *
+ * Revision 1.21  1999/11/24 05:24:20  rgb
+ * hanged 'void*extensions' to 'struct sadb_ext*extensions'.
+ * Fixed indention.
+ * Ditched redundant replay check.
+ * Fixed debug message text from 'parse' to 'process'.
+ * Added more debug output.
+ * Forgot to zero extensions array causing bug, fixed.
+ *
+ * Revision 1.20  1999/11/23 23:08:13  rgb
+ * Move all common parsing code to lib/pfkey_v2_parse.c and rename
+ * remaining bits to *_process. (PJO)
+ * Add macros for dealing with alignment and rounding up more opaquely.
+ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
+ * Sort out pfkey and freeswan headers, putting them in a library path.
+ * Corrected a couple of bugs in as-yet-inactive code.
+ *
+ * Revision 1.19  1999/11/20 22:01:10  rgb
+ * Add more descriptive error messages for non-zero reserved fields.
+ * Add more descriptive error message for spirange parsing.
+ * Start on supported extension parsing.
+ * Start on register and get message parsing.
+ *
+ * Revision 1.18  1999/11/18 04:09:20  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.17  1999/11/17 15:53:41  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.16  1999/10/26 16:57:43  rgb
+ * Add shorter macros for compiler directives to visually clean-up.
+ * Give ipv6 code meaningful compiler directive.
+ * Add comments to other #if 0 debug code.
+ * Remove unused *_bh_atomic() calls.
+ * Fix mis-placed spinlock.
+ *
+ * Revision 1.15  1999/10/16 18:27:10  rgb
+ * Clean-up unused cruft.
+ * Fix-up lifetime_allocations_c and lifetime_addtime_c initialisations.
+ *
+ * Revision 1.14  1999/10/08 18:37:34  rgb
+ * Fix end-of-line spacing to sate whining PHMs.
+ *
+ * Revision 1.13  1999/10/03 18:49:12  rgb
+ * Spinlock fixes for 2.0.xx and 2.3.xx.
+ *
+ * Revision 1.12  1999/10/01 15:44:54  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.11  1999/10/01 00:05:45  rgb
+ * Added tdb structure locking.
+ * Use 'jiffies' instead of do_get_timeofday().
+ * Fix lifetime assignments.
+ *
+ * Revision 1.10  1999/09/21 15:24:45  rgb
+ * Rework spirange code to save entropy and prevent endless loops.
+ *
+ * Revision 1.9  1999/09/16 12:10:21  rgb
+ * Minor fixes to random spi selection for correctness and entropy conservation.
+ *
+ * Revision 1.8  1999/05/25 22:54:46  rgb
+ * Fix comparison that should be an assignment in an if.
+ *
+ * Revision 1.7  1999/05/09 03:25:37  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.6  1999/05/08 21:32:30  rgb
+ * Fix error return reporting.
+ *
+ * Revision 1.5  1999/05/05 22:02:33  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.4  1999/04/29 15:22:40  rgb
+ * Standardise an error return method.
+ * Add debugging instrumentation.
+ * Add check for existence of macros min/max.
+ * Add extensions permitted/required in/out filters.
+ * Add satype-to-protocol table.
+ * Add a second tdb pointer to each parser to accomodate GRPSA.
+ * Move AH & no_algo_set to GETSPI, UPDATE and ADD.
+ * Add OOO window check.
+ * Add support for IPPROTO_IPIP and hooks for IPPROTO_COMP.
+ * Add timestamp to lifetime parse.
+ * Fix address structure length checking bug.
+ * Fix address structure allocation bug (forgot to kmalloc!).
+ * Add checks for extension lengths.
+ * Add checks for extension reserved illegal values.
+ * Add check for spirange legal values.
+ * Add an extension type for parsing a second satype, SA and
+ * DST_ADDRESS.
+ * Make changes to tdb_init() template to get pfkey_tdb_init(),
+ * eliminating any mention of xformsw.
+ * Implement getspi, update and grpsa (not tested).
+ * Add stubs for as yet unimplemented message types.
+ * Add table of message parsers to substitute for msg_parse switch.
+ *
+ * Revision 1.3  1999/04/15 17:58:07  rgb
+ * Add RCSID labels.
+ *
+ * Revision 1.2  1999/04/15 15:37:26  rgb
+ * Forward check changes from POST1_00 branch.
+ *
+ * Revision 1.1.2.1  1999/03/26 20:58:56  rgb
+ * Add pfkeyv2 support to KLIPS.
+ *
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/radij.c linux-patched/net/ipsec/radij.c
--- linux/net/ipsec/radij.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/radij.c	Sun Jan 19 22:32:30 2003
@@ -0,0 +1,1201 @@
+char radij_c_version[] = "RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $";
+
+/*
+ * This file is defived from ${SRC}/sys/net/radix.c of BSD 4.4lite
+ *
+ * Variable and procedure names have been modified so that they don't
+ * conflict with the original BSD code, as a small number of modifications
+ * have been introduced and we may want to reuse this code in BSD.
+ * 
+ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek
+ * chi or a German ch sound (as `doch', not as in `milch'), or even a 
+ * spanish j as in Juan.  It is not as far back in the throat like
+ * the corresponding Hebrew sound, nor is it a soft breath like the English h.
+ * It has nothing to do with the Dutch ij sound.
+ * 
+ * Here is the appropriate copyright notice:
+ */
+
+/*
+ * Copyright (c) 1988, 1989, 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.
+ *
+ *	@(#)radix.c	8.2 (Berkeley) 1/4/94
+ */
+
+/*
+ * Routines to build and maintain radix trees for routing lookups.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h> /* printk() */
+
+#include "ipsec_param.h"
+
+#ifdef MALLOC_SLAB
+# include <linux/slab.h> /* kmalloc() */
+#else /* MALLOC_SLAB */
+# include <linux/malloc.h> /* kmalloc() */
+#endif /* MALLOC_SLAB */
+#include <linux/errno.h>  /* error codes */
+#include <linux/types.h>  /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+
+#include <linux/netdevice.h>   /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <linux/ip.h>          /* struct iphdr */
+#include <linux/skbuff.h>
+#ifdef NET_21
+# include <asm/uaccess.h>
+# include <linux/in6.h>
+#endif /* NET_21 */
+#include <asm/checksum.h>
+#include <net/ip.h>
+
+#include <freeswan.h>
+
+#include "radij.h"
+#include "ipsec_encap.h"
+#include "ipsec_radij.h"
+#include "ipsec_netlink.h"
+
+int	maj_keylen;
+struct radij_mask *rj_mkfreelist;
+struct radij_node_head *mask_rjhead;
+static int gotOddMasks;
+static char *maskedKey;
+static char *rj_zeroes, *rj_ones;
+
+#define rj_masktop (mask_rjhead->rnh_treetop)
+#ifdef Bcmp
+# undef Bcmp
+#endif /* Bcmp */
+#define Bcmp(a, b, l) (l == 0 ? 0 : memcmp((caddr_t)(b), (caddr_t)(a), (size_t)l))
+/*
+ * The data structure for the keys is a radix tree with one way
+ * branching removed.  The index rj_b at an internal node n represents a bit
+ * position to be tested.  The tree is arranged so that all descendants
+ * of a node n have keys whose bits all agree up to position rj_b - 1.
+ * (We say the index of n is rj_b.)
+ *
+ * There is at least one descendant which has a one bit at position rj_b,
+ * and at least one with a zero there.
+ *
+ * A route is determined by a pair of key and mask.  We require that the
+ * bit-wise logical and of the key and mask to be the key.
+ * We define the index of a route to associated with the mask to be
+ * the first bit number in the mask where 0 occurs (with bit number 0
+ * representing the highest order bit).
+ * 
+ * We say a mask is normal if every bit is 0, past the index of the mask.
+ * If a node n has a descendant (k, m) with index(m) == index(n) == rj_b,
+ * and m is a normal mask, then the route applies to every descendant of n.
+ * If the index(m) < rj_b, this implies the trailing last few bits of k
+ * before bit b are all 0, (and hence consequently true of every descendant
+ * of n), so the route applies to all descendants of the node as well.
+ *
+ * The present version of the code makes no use of normal routes,
+ * but similar logic shows that a non-normal mask m such that
+ * index(m) <= index(n) could potentially apply to many children of n.
+ * Thus, for each non-host route, we attach its mask to a list at an internal
+ * node as high in the tree as we can go. 
+ */
+
+struct radij_node *
+rj_search(v_arg, head)
+	void *v_arg;
+	struct radij_node *head;
+{
+	register struct radij_node *x;
+	register caddr_t v;
+
+	for (x = head, v = v_arg; x->rj_b >= 0;) {
+		if (x->rj_bmask & v[x->rj_off])
+			x = x->rj_r;
+		else
+			x = x->rj_l;
+	}
+	return (x);
+};
+
+struct radij_node *
+rj_search_m(v_arg, head, m_arg)
+	struct radij_node *head;
+	void *v_arg, *m_arg;
+{
+	register struct radij_node *x;
+	register caddr_t v = v_arg, m = m_arg;
+
+	for (x = head; x->rj_b >= 0;) {
+		if ((x->rj_bmask & m[x->rj_off]) &&
+		    (x->rj_bmask & v[x->rj_off]))
+			x = x->rj_r;
+		else
+			x = x->rj_l;
+	}
+	return x;
+};
+
+int
+rj_refines(m_arg, n_arg)
+	void *m_arg, *n_arg;
+{
+	register caddr_t m = m_arg, n = n_arg;
+	register caddr_t lim, lim2 = lim = n + *(u_char *)n;
+	int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
+	int masks_are_equal = 1;
+
+	if (longer > 0)
+		lim -= longer;
+	while (n < lim) {
+		if (*n & ~(*m))
+			return 0;
+		if (*n++ != *m++)
+			masks_are_equal = 0;
+			
+	}
+	while (n < lim2)
+		if (*n++)
+			return 0;
+	if (masks_are_equal && (longer < 0))
+		for (lim2 = m - longer; m < lim2; )
+			if (*m++)
+				return 1;
+	return (!masks_are_equal);
+}
+
+
+struct radij_node *
+rj_match(v_arg, head)
+	void *v_arg;
+	struct radij_node_head *head;
+{
+	caddr_t v = v_arg;
+	register struct radij_node *t = head->rnh_treetop, *x;
+	register caddr_t cp = v, cp2, cp3;
+	caddr_t cplim, mstart;
+	struct radij_node *saved_t, *top = t;
+	int off = t->rj_off, vlen = *(u_char *)cp, matched_off;
+
+	/*
+	 * Open code rj_search(v, top) to avoid overhead of extra
+	 * subroutine call.
+	 */
+	for (; t->rj_b >= 0; ) {
+		if (t->rj_bmask & cp[t->rj_off])
+			t = t->rj_r;
+		else
+			t = t->rj_l;
+	}
+	/*
+	 * See if we match exactly as a host destination
+	 */
+	KLIPS_PRINT(debug_radij,
+		    "klips_debug:rj_match: "
+		    "* See if we match exactly as a host destination\n");
+	
+	cp += off; cp2 = t->rj_key + off; cplim = v + vlen;
+	for (; cp < cplim; cp++, cp2++)
+		if (*cp != *cp2)
+			goto on1;
+	/*
+	 * This extra grot is in case we are explicitly asked
+	 * to look up the default.  Ugh!
+	 */
+	if ((t->rj_flags & RJF_ROOT) && t->rj_dupedkey)
+		t = t->rj_dupedkey;
+	return t;
+on1:
+	matched_off = cp - v;
+	saved_t = t;
+	KLIPS_PRINT(debug_radij,
+		    "klips_debug:rj_match: "
+		    "** try to match a leaf, t=0x%p\n", t);
+	do {
+	    if (t->rj_mask) {
+		/*
+		 * Even if we don't match exactly as a hosts;
+		 * we may match if the leaf we wound up at is
+		 * a route to a net.
+		 */
+		cp3 = matched_off + t->rj_mask;
+		cp2 = matched_off + t->rj_key;
+		for (; cp < cplim; cp++)
+			if ((*cp2++ ^ *cp) & *cp3++)
+				break;
+		if (cp == cplim)
+			return t;
+		cp = matched_off + v;
+	    }
+	} while ((t = t->rj_dupedkey));
+	t = saved_t;
+	/* start searching up the tree */
+	KLIPS_PRINT(debug_radij,
+		    "klips_debug:rj_match: "
+		    "*** start searching up the tree, t=0x%p\n",
+		    t);
+	do {
+		register struct radij_mask *m;
+		
+		t = t->rj_p;
+		KLIPS_PRINT(debug_radij,
+			    "klips_debug:rj_match: "
+			    "**** t=0x%p\n",
+			    t);
+		if ((m = t->rj_mklist)) {
+			/*
+			 * After doing measurements here, it may
+			 * turn out to be faster to open code
+			 * rj_search_m here instead of always
+			 * copying and masking.
+			 */
+			/* off = min(t->rj_off, matched_off); */
+			off = t->rj_off;
+			if (matched_off < off)
+				off = matched_off;
+			mstart = maskedKey + off;
+			do {
+				cp2 = mstart;
+				cp3 = m->rm_mask + off;
+				KLIPS_PRINT(debug_radij,
+					    "klips_debug:rj_match: "
+					    "***** cp2=0x%p cp3=0x%p\n",
+					    cp2, cp3);
+				for (cp = v + off; cp < cplim;)
+					*cp2++ =  *cp++ & *cp3++;
+				x = rj_search(maskedKey, t);
+				while (x && x->rj_mask != m->rm_mask)
+					x = x->rj_dupedkey;
+				if (x &&
+				    (Bcmp(mstart, x->rj_key + off,
+					vlen - off) == 0))
+					    return x;
+			} while ((m = m->rm_mklist));
+		}
+	} while (t != top);
+	KLIPS_PRINT(debug_radij,
+		    "klips_debug:rj_match: "
+		    "***** not found.\n");
+	return 0;
+};
+		
+#ifdef RJ_DEBUG
+int	rj_nodenum;
+struct	radij_node *rj_clist;
+int	rj_saveinfo;
+DEBUG_NO_STATIC void traverse(struct radij_node *);
+#ifdef RJ_DEBUG2
+int	rj_debug =  1;
+#else
+int	rj_debug =  0;
+#endif /* RJ_DEBUG2 */
+#endif /* RJ_DEBUG */
+
+struct radij_node *
+rj_newpair(v, b, nodes)
+	void *v;
+	int b;
+	struct radij_node nodes[2];
+{
+	register struct radij_node *tt = nodes, *t = tt + 1;
+	t->rj_b = b; t->rj_bmask = 0x80 >> (b & 7);
+	t->rj_l = tt; t->rj_off = b >> 3;
+	tt->rj_b = -1; tt->rj_key = (caddr_t)v; tt->rj_p = t;
+	tt->rj_flags = t->rj_flags = RJF_ACTIVE;
+#ifdef RJ_DEBUG
+	tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++;
+	tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt;
+#endif /* RJ_DEBUG */
+	return t;
+}
+
+struct radij_node *
+rj_insert(v_arg, head, dupentry, nodes)
+	void *v_arg;
+	struct radij_node_head *head;
+	int *dupentry;
+	struct radij_node nodes[2];
+{
+	caddr_t v = v_arg;
+	struct radij_node *top = head->rnh_treetop;
+	int head_off = top->rj_off, vlen = (int)*((u_char *)v);
+	register struct radij_node *t = rj_search(v_arg, top);
+	register caddr_t cp = v + head_off;
+	register int b;
+	struct radij_node *tt;
+    	/*
+	 *find first bit at which v and t->rj_key differ
+	 */
+    {
+	register caddr_t cp2 = t->rj_key + head_off;
+	register int cmp_res;
+	caddr_t cplim = v + vlen;
+
+	while (cp < cplim)
+		if (*cp2++ != *cp++)
+			goto on1;
+	*dupentry = 1;
+	return t;
+on1:
+	*dupentry = 0;
+	cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
+	for (b = (cp - v) << 3; cmp_res; b--)
+		cmp_res >>= 1;
+    }
+    {
+	register struct radij_node *p, *x = top;
+	cp = v;
+	do {
+		p = x;
+		if (cp[x->rj_off] & x->rj_bmask) 
+			x = x->rj_r;
+		else x = x->rj_l;
+	} while (b > (unsigned) x->rj_b); /* x->rj_b < b && x->rj_b >= 0 */
+#ifdef RJ_DEBUG
+	if (rj_debug)
+		printk("klips_debug:rj_insert: Going In:\n"), traverse(p);
+#endif /* RJ_DEBUG */
+	t = rj_newpair(v_arg, b, nodes); tt = t->rj_l;
+	if ((cp[p->rj_off] & p->rj_bmask) == 0)
+		p->rj_l = t;
+	else
+		p->rj_r = t;
+	x->rj_p = t; t->rj_p = p; /* frees x, p as temp vars below */
+	if ((cp[t->rj_off] & t->rj_bmask) == 0) {
+		t->rj_r = x;
+	} else {
+		t->rj_r = tt; t->rj_l = x;
+	}
+#ifdef RJ_DEBUG
+	if (rj_debug)
+		printk("klips_debug:rj_insert: Coming out:\n"), traverse(p);
+#endif /* RJ_DEBUG */
+    }
+	return (tt);
+}
+
+struct radij_node *
+rj_addmask(n_arg, search, skip)
+	int search, skip;
+	void *n_arg;
+{
+	caddr_t netmask = (caddr_t)n_arg;
+	register struct radij_node *x;
+	register caddr_t cp, cplim;
+	register int b, mlen, j;
+	int maskduplicated;
+
+	mlen = *(u_char *)netmask;
+	if (search) {
+		x = rj_search(netmask, rj_masktop);
+		mlen = *(u_char *)netmask;
+		if (Bcmp(netmask, x->rj_key, mlen) == 0)
+			return (x);
+	}
+	R_Malloc(x, struct radij_node *, maj_keylen + 2 * sizeof (*x));
+	if (x == 0)
+		return (0);
+	Bzero(x, maj_keylen + 2 * sizeof (*x));
+	cp = (caddr_t)(x + 2);
+	Bcopy(netmask, cp, mlen);
+	netmask = cp;
+	x = rj_insert(netmask, mask_rjhead, &maskduplicated, x);
+	/*
+	 * Calculate index of mask.
+	 */
+	cplim = netmask + mlen;
+	for (cp = netmask + skip; cp < cplim; cp++)
+		if (*(u_char *)cp != 0xff)
+			break;
+	b = (cp - netmask) << 3;
+	if (cp != cplim) {
+		if (*cp != 0) {
+			gotOddMasks = 1;
+			for (j = 0x80; j; b++, j >>= 1)  
+				if ((j & *cp) == 0)
+					break;
+		}
+	}
+	x->rj_b = -1 - b;
+	return (x);
+}
+
+#if 0
+struct radij_node *
+#endif
+int
+rj_addroute(v_arg, n_arg, head, treenodes)
+	void *v_arg, *n_arg;
+	struct radij_node_head *head;
+	struct radij_node treenodes[2];
+{
+	caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
+	register struct radij_node *t, *x=NULL, *tt;
+	struct radij_node *saved_tt, *top = head->rnh_treetop;
+	short b = 0, b_leaf;
+	int mlen, keyduplicated;
+	caddr_t cplim;
+	struct radij_mask *m, **mp;
+
+	/*
+	 * In dealing with non-contiguous masks, there may be
+	 * many different routes which have the same mask.
+	 * We will find it useful to have a unique pointer to
+	 * the mask to speed avoiding duplicate references at
+	 * nodes and possibly save time in calculating indices.
+	 */
+	if (netmask)  {
+		x = rj_search(netmask, rj_masktop);
+		mlen = *(u_char *)netmask;
+		if (Bcmp(netmask, x->rj_key, mlen) != 0) {
+			x = rj_addmask(netmask, 0, top->rj_off);
+			if (x == 0)
+				return -ENOMEM; /* (0) rgb */
+		}
+		netmask = x->rj_key;
+		b = -1 - x->rj_b;
+	}
+	/*
+	 * Deal with duplicated keys: attach node to previous instance
+	 */
+	saved_tt = tt = rj_insert(v, head, &keyduplicated, treenodes);
+	if (keyduplicated) {
+		do {
+			if (tt->rj_mask == netmask)
+				return -EEXIST; /* -ENXIO; (0) rgb */
+			t = tt;
+			if (netmask == 0 ||
+			    (tt->rj_mask && rj_refines(netmask, tt->rj_mask)))
+				break;
+		} while ((tt = tt->rj_dupedkey));
+		/*
+		 * If the mask is not duplicated, we wouldn't
+		 * find it among possible duplicate key entries
+		 * anyway, so the above test doesn't hurt.
+		 *
+		 * We sort the masks for a duplicated key the same way as
+		 * in a masklist -- most specific to least specific.
+		 * This may require the unfortunate nuisance of relocating
+		 * the head of the list.
+		 */
+		if (tt && t == saved_tt) {
+			struct	radij_node *xx = x;
+			/* link in at head of list */
+			(tt = treenodes)->rj_dupedkey = t;
+			tt->rj_flags = t->rj_flags;
+			tt->rj_p = x = t->rj_p;
+			if (x->rj_l == t) x->rj_l = tt; else x->rj_r = tt;
+			saved_tt = tt; x = xx;
+		} else {
+			(tt = treenodes)->rj_dupedkey = t->rj_dupedkey;
+			t->rj_dupedkey = tt;
+		}
+#ifdef RJ_DEBUG
+		t=tt+1; tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++;
+		tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt;
+#endif /* RJ_DEBUG */
+		t = saved_tt;
+		tt->rj_key = (caddr_t) v;
+		tt->rj_b = -1;
+		tt->rj_flags = t->rj_flags & ~RJF_ROOT;
+	}
+	/*
+	 * Put mask in tree.
+	 */
+	if (netmask) {
+		tt->rj_mask = netmask;
+		tt->rj_b = x->rj_b;
+	}
+	t = saved_tt->rj_p;
+	b_leaf = -1 - t->rj_b;
+	if (t->rj_r == saved_tt) x = t->rj_l; else x = t->rj_r;
+	/* Promote general routes from below */
+	if (x->rj_b < 0) { 
+		if (x->rj_mask && (x->rj_b >= b_leaf) && x->rj_mklist == 0) {
+			MKGet(m);
+			if (m) {
+				Bzero(m, sizeof *m);
+				m->rm_b = x->rj_b;
+				m->rm_mask = x->rj_mask;
+				x->rj_mklist = t->rj_mklist = m;
+			}
+		}
+	} else if (x->rj_mklist) {
+		/*
+		 * Skip over masks whose index is > that of new node
+		 */
+		for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist)
+			if (m->rm_b >= b_leaf)
+				break;
+		t->rj_mklist = m; *mp = 0;
+	}
+	/* Add new route to highest possible ancestor's list */
+	if ((netmask == 0) || (b > t->rj_b ))
+		return 0; /* tt rgb */ /* can't lift at all */
+	b_leaf = tt->rj_b;
+	do {
+		x = t;
+		t = t->rj_p;
+	} while (b <= t->rj_b && x != top);
+	/*
+	 * Search through routes associated with node to
+	 * insert new route according to index.
+	 * For nodes of equal index, place more specific
+	 * masks first.
+	 */
+	cplim = netmask + mlen;
+	for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) {
+		if (m->rm_b < b_leaf)
+			continue;
+		if (m->rm_b > b_leaf)
+			break;
+		if (m->rm_mask == netmask) {
+			m->rm_refs++;
+			tt->rj_mklist = m;
+			return 0; /* tt rgb */
+		}
+		if (rj_refines(netmask, m->rm_mask))
+			break;
+	}
+	MKGet(m);
+	if (m == 0) {
+		printk("klips_debug:rj_addroute: "
+		       "Mask for route not entered\n");
+		return 0; /* (tt) rgb */
+	}
+	Bzero(m, sizeof *m);
+	m->rm_b = b_leaf;
+	m->rm_mask = netmask;
+	m->rm_mklist = *mp;
+	*mp = m;
+	tt->rj_mklist = m;
+	return 0; /* tt rgb */
+}
+
+int
+rj_delete(v_arg, netmask_arg, head, node)
+	void *v_arg, *netmask_arg;
+	struct radij_node_head *head;
+	struct radij_node **node;
+{
+	register struct radij_node *t, *p, *x, *tt;
+	struct radij_mask *m, *saved_m, **mp;
+	struct radij_node *dupedkey, *saved_tt, *top;
+	caddr_t v, netmask;
+	int b, head_off, vlen;
+
+	v = v_arg;
+	netmask = netmask_arg;
+	x = head->rnh_treetop;
+	tt = rj_search(v, x);
+	head_off = x->rj_off;
+	vlen =  *(u_char *)v;
+	saved_tt = tt;
+	top = x;
+	if (tt == 0 ||
+	    Bcmp(v + head_off, tt->rj_key + head_off, vlen - head_off))
+		return -EFAULT; /* (0) rgb */
+	/*
+	 * Delete our route from mask lists.
+	 */
+	if ((dupedkey = tt->rj_dupedkey)) {
+		if (netmask) 
+			netmask = rj_search(netmask, rj_masktop)->rj_key;
+		while (tt->rj_mask != netmask)
+			if ((tt = tt->rj_dupedkey) == 0)
+				return -ENOENT; /* -ENXIO; (0) rgb */
+	}
+	if (tt->rj_mask == 0 || (saved_m = m = tt->rj_mklist) == 0)
+		goto on1;
+	if (m->rm_mask != tt->rj_mask) {
+		printk("klips_debug:rj_delete: "
+		       "inconsistent annotation\n");
+		goto on1;
+	}
+	if (--m->rm_refs >= 0)
+		goto on1;
+	b = -1 - tt->rj_b;
+	t = saved_tt->rj_p;
+	if (b > t->rj_b)
+		goto on1; /* Wasn't lifted at all */
+	do {
+		x = t;
+		t = t->rj_p;
+	} while (b <= t->rj_b && x != top);
+	for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist)
+		if (m == saved_m) {
+			*mp = m->rm_mklist;
+			MKFree(m);
+			break;
+		}
+	if (m == 0)
+		printk("klips_debug:rj_delete: "
+		       "couldn't find our annotation\n");
+on1:
+	/*
+	 * Eliminate us from tree
+	 */
+	if (tt->rj_flags & RJF_ROOT)
+		return -EFAULT; /* (0) rgb */
+#ifdef RJ_DEBUG
+	/* Get us out of the creation list */
+	for (t = rj_clist; t && t->rj_ybro != tt; t = t->rj_ybro) {}
+	if (t) t->rj_ybro = tt->rj_ybro;
+#endif /* RJ_DEBUG */
+	t = tt->rj_p;
+	if (dupedkey) {
+		if (tt == saved_tt) {
+			x = dupedkey; x->rj_p = t;
+			if (t->rj_l == tt) t->rj_l = x; else t->rj_r = x;
+		} else {
+			for (x = p = saved_tt; p && p->rj_dupedkey != tt;)
+				p = p->rj_dupedkey;
+			if (p) p->rj_dupedkey = tt->rj_dupedkey;
+			else printk("klips_debug:rj_delete: "
+				       "couldn't find us\n");
+		}
+		t = tt + 1;
+		if  (t->rj_flags & RJF_ACTIVE) {
+#ifndef RJ_DEBUG
+			*++x = *t; p = t->rj_p;
+#else
+			b = t->rj_info; *++x = *t; t->rj_info = b; p = t->rj_p;
+#endif /* RJ_DEBUG */
+			if (p->rj_l == t) p->rj_l = x; else p->rj_r = x;
+			x->rj_l->rj_p = x; x->rj_r->rj_p = x;
+		}
+		goto out;
+	}
+	if (t->rj_l == tt) x = t->rj_r; else x = t->rj_l;
+	p = t->rj_p;
+	if (p->rj_r == t) p->rj_r = x; else p->rj_l = x;
+	x->rj_p = p;
+	/*
+	 * Demote routes attached to us.
+	 */
+	if (t->rj_mklist) {
+		if (x->rj_b >= 0) {
+			for (mp = &x->rj_mklist; (m = *mp);)
+				mp = &m->rm_mklist;
+			*mp = t->rj_mklist;
+		} else {
+			for (m = t->rj_mklist; m;) {
+				struct radij_mask *mm = m->rm_mklist;
+				if (m == x->rj_mklist && (--(m->rm_refs) < 0)) {
+					x->rj_mklist = 0;
+					MKFree(m);
+				} else 
+					printk("klips_debug:rj_delete: "
+					    "Orphaned Mask %p at %p\n", m, x);
+				m = mm;
+			}
+		}
+	}
+	/*
+	 * We may be holding an active internal node in the tree.
+	 */
+	x = tt + 1;
+	if (t != x) {
+#ifndef RJ_DEBUG
+		*t = *x;
+#else
+		b = t->rj_info; *t = *x; t->rj_info = b;
+#endif /* RJ_DEBUG */
+		t->rj_l->rj_p = t; t->rj_r->rj_p = t;
+		p = x->rj_p;
+		if (p->rj_l == x) p->rj_l = t; else p->rj_r = t;
+	}
+out:
+	tt->rj_flags &= ~RJF_ACTIVE;
+	tt[1].rj_flags &= ~RJF_ACTIVE;
+	*node = tt;
+	return 0; /* (tt) rgb */
+}
+
+int
+rj_walktree(h, f, w)
+	struct radij_node_head *h;
+	register int (*f)(struct radij_node *,void *);
+	void *w;
+{
+	int error;
+	struct radij_node *base, *next;
+	register struct radij_node *rn;
+
+	if(!h || !f /* || !w */) {
+		return -ENODATA;
+	}
+
+	rn = h->rnh_treetop;
+	/*
+	 * This gets complicated because we may delete the node
+	 * while applying the function f to it, so we need to calculate
+	 * the successor node in advance.
+	 */
+	/* First time through node, go left */
+	while (rn->rj_b >= 0)
+		rn = rn->rj_l;
+	for (;;) {
+#ifdef CONFIG_IPSEC_DEBUG
+		if(debug_radij) {
+			printk("klips_debug:rj_walktree: "
+			       "for: rn=%p rj_b=%d rj_flags=%x",
+			       rn,
+			       rn->rj_b,
+			       rn->rj_flags);
+			rn->rj_b >= 0 ?
+				printk(" node off=%x\n",
+				       rn->rj_off) :
+				printk(" leaf key = %08x->%08x\n",
+				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
+				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr))
+				;
+		}
+#endif /* CONFIG_IPSEC_DEBUG */
+		base = rn;
+		/* If at right child go back up, otherwise, go right */
+		while (rn->rj_p->rj_r == rn && (rn->rj_flags & RJF_ROOT) == 0)
+			rn = rn->rj_p;
+		/* Find the next *leaf* since next node might vanish, too */
+		for (rn = rn->rj_p->rj_r; rn->rj_b >= 0;)
+			rn = rn->rj_l;
+		next = rn;
+#ifdef CONFIG_IPSEC_DEBUG
+		if(debug_radij) {
+			printk("klips_debug:rj_walktree: "
+			       "processing leaves, rn=%p rj_b=%d rj_flags=%x",
+			       rn,
+			       rn->rj_b,
+			       rn->rj_flags);
+			rn->rj_b >= 0 ?
+				printk(" node off=%x\n",
+				       rn->rj_off) :
+				printk(" leaf key = %08x->%08x\n",
+				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
+				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr))
+				;
+		}
+#endif /* CONFIG_IPSEC_DEBUG */
+		/* Process leaves */
+		while ((rn = base)) {
+			base = rn->rj_dupedkey;
+#ifdef CONFIG_IPSEC_DEBUG
+			if(debug_radij) {
+				printk("klips_debug:rj_walktree: "
+				       "while: base=%p rn=%p rj_b=%d rj_flags=%x",
+				       base,
+				       rn,
+				       rn->rj_b,
+				       rn->rj_flags);
+				rn->rj_b >= 0 ?
+					printk(" node off=%x\n",
+					       rn->rj_off) :
+					printk(" leaf key = %08x->%08x\n",
+					       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
+					       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr))
+					;
+			}
+#endif /* CONFIG_IPSEC_DEBUG */
+			if (!(rn->rj_flags & RJF_ROOT) && (error = (*f)(rn, w)))
+				return (-error);
+		}
+		rn = next;
+		if (rn->rj_flags & RJF_ROOT)
+			return (0);
+	}
+	/* NOTREACHED */
+}
+
+int
+rj_inithead(head, off)
+	void **head;
+	int off;
+{
+	register struct radij_node_head *rnh;
+	register struct radij_node *t, *tt, *ttt;
+	if (*head)
+		return (1);
+	R_Malloc(rnh, struct radij_node_head *, sizeof (*rnh));
+	if (rnh == NULL)
+		return (0);
+	Bzero(rnh, sizeof (*rnh));
+	*head = rnh;
+	t = rj_newpair(rj_zeroes, off, rnh->rnh_nodes);
+	ttt = rnh->rnh_nodes + 2;
+	t->rj_r = ttt;
+	t->rj_p = t;
+	tt = t->rj_l;
+	tt->rj_flags = t->rj_flags = RJF_ROOT | RJF_ACTIVE;
+	tt->rj_b = -1 - off;
+	*ttt = *tt;
+	ttt->rj_key = rj_ones;
+	rnh->rnh_addaddr = rj_addroute;
+	rnh->rnh_deladdr = rj_delete;
+	rnh->rnh_matchaddr = rj_match;
+	rnh->rnh_walktree = rj_walktree;
+	rnh->rnh_treetop = t;
+	return (1);
+}
+
+void
+rj_init()
+{
+	char *cp, *cplim;
+
+	if (maj_keylen == 0) {
+		printk("klips_debug:rj_init: "
+		       "radij functions require maj_keylen be set\n");
+		return;
+	}
+	R_Malloc(rj_zeroes, char *, 3 * maj_keylen);
+	if (rj_zeroes == NULL)
+		panic("rj_init");
+	Bzero(rj_zeroes, 3 * maj_keylen);
+	rj_ones = cp = rj_zeroes + maj_keylen;
+	maskedKey = cplim = rj_ones + maj_keylen;
+	while (cp < cplim)
+		*cp++ = -1;
+	if (rj_inithead((void **)&mask_rjhead, 0) == 0)
+		panic("rj_init 2");
+}
+
+void
+rj_preorder(struct radij_node *rn, int l)
+{
+	int i;
+	
+	if (rn == NULL){
+		printk("klips_debug:rj_preorder: "
+		       "NULL pointer\n");
+		return;
+	}
+	
+	if (rn->rj_b >= 0){
+		rj_preorder(rn->rj_l, l+1);
+		rj_preorder(rn->rj_r, l+1);
+		printk("klips_debug:");
+		for (i=0; i<l; i++)
+			printk("*");
+		printk(" off = %d\n",
+		       rn->rj_off);
+	} else {
+		printk("klips_debug:");
+		for (i=0; i<l; i++)
+			printk("@");
+		printk(" flags = %x",
+		       (u_int)rn->rj_flags);
+		if (rn->rj_flags & RJF_ACTIVE) {
+			printk(" @key = %p",
+			       rn->rj_key);
+			printk(" key = %08x->%08x",
+			       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
+			       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr));
+			printk(" @mask = %p",
+			       rn->rj_mask);
+			if (rn->rj_mask)
+				printk(" mask = %08x->%08x",
+				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_src.s_addr),
+				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_dst.s_addr));
+			if (rn->rj_dupedkey)
+				printk(" dupedkey = %08x",
+				       (u_int)rn->rj_dupedkey);
+		}
+		printk("\n");
+	}
+}
+
+#ifdef RJ_DEBUG
+DEBUG_NO_STATIC void traverse(struct radij_node *p)
+{
+  rj_preorder(p, 0);
+}
+#endif /* RJ_DEBUG */
+
+void
+rj_dumptrees(void)
+{
+	rj_preorder(rnh->rnh_treetop, 0);
+}
+
+void
+rj_free_mkfreelist(void)
+{
+	struct radij_mask *mknp, *mknp2;
+
+	mknp = rj_mkfreelist;
+	while(mknp)
+	{
+		mknp2 = mknp;
+		mknp = mknp->rm_mklist;
+		kfree(mknp2);
+	}
+}
+
+int
+radijcleartree(void)
+{
+	return rj_walktree(rnh, ipsec_rj_walker_delete, NULL);
+}
+
+int
+radijcleanup(void)
+{
+	int error = 0;
+
+	error = radijcleartree();
+
+	rj_free_mkfreelist();
+
+/*	rj_walktree(mask_rjhead, ipsec_rj_walker_delete, NULL); */
+  	if(mask_rjhead) {
+		kfree(mask_rjhead);
+	}
+
+	if(rj_zeroes) {
+		kfree(rj_zeroes);
+	}
+
+	if(rnh) {
+		kfree(rnh);
+	}
+
+	return error;
+}
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.3  2003/01/19 22:32:30  ken
+ * X.509 0.9.19 -> 0.9.20
+ *
+ * Revision 1.2  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:18  ken
+ * 1.98b
+ *
+ * Revision 1.40  2002/01/29 17:17:58  mcr
+ * 	moved include of ipsec_param.h to after include of linux/kernel.h
+ * 	otherwise, it seems that some option that is set in ipsec_param.h
+ * 	screws up something subtle in the include path to kernel.h, and
+ * 	it complains on the snprintf() prototype.
+ *
+ * Revision 1.39  2002/01/29 04:00:55  mcr
+ * 	more excise of kversions.h header.
+ *
+ * Revision 1.38  2002/01/29 02:13:19  mcr
+ * 	introduction of ipsec_kversion.h means that include of
+ * 	ipsec_param.h must preceed any decisions about what files to
+ * 	include to deal with differences in kernel source.
+ *
+ * Revision 1.37  2001/10/18 04:45:23  rgb
+ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
+ * lib/freeswan.h version macros moved to lib/kversions.h.
+ * Other compiler directive cleanups.
+ *
+ * Revision 1.36  2001/08/22 13:43:51  henry
+ * eliminate the single use of min() to avoid problems with Linus changing it
+ *
+ * Revision 1.35  2001/06/15 04:57:29  rgb
+ * Clarified error return codes.
+ * Changed mask add already exists to EEXIST.
+ * Changed mask delete did not exist to ENOENT.
+ *
+ * Revision 1.34  2001/05/03 19:44:26  rgb
+ * Fix sign of error return codes for rj_addroute().
+ *
+ * Revision 1.33  2001/02/27 22:24:56  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
+ * Revision 1.32  2001/02/27 06:23:15  rgb
+ * Debug line splitting.
+ *
+ * Revision 1.31  2000/11/06 04:35:21  rgb
+ * Clear table *before* releasing other items in radijcleanup.
+ *
+ * Revision 1.30  2000/09/20 04:07:40  rgb
+ * Changed static functions to DEBUG_NO_STATIC to reveal function names in
+ * oopsen.
+ *
+ * Revision 1.29  2000/09/12 03:25:02  rgb
+ * Moved radij_c_version printing to ipsec_version_get_info().
+ *
+ * Revision 1.28  2000/09/08 19:12:56  rgb
+ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
+ *
+ * Revision 1.27  2000/07/28 14:58:32  rgb
+ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
+ *
+ * Revision 1.26  2000/05/10 23:11:37  rgb
+ * Comment out most of the startup version information.
+ *
+ * Revision 1.25  2000/01/21 06:21:47  rgb
+ * Change return codes to negative on error.
+ *
+ * Revision 1.24  1999/11/18 04:09:20  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.23  1999/11/17 15:53:41  rgb
+ * Changed all occurrences of #include "../../../lib/freeswan.h"
+ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
+ * klips/net/ipsec/Makefile.
+ *
+ * Revision 1.22  1999/10/15 22:17:28  rgb
+ * Modify radijcleanup() to call radijcleartree().
+ *
+ * Revision 1.21  1999/10/08 18:37:34  rgb
+ * Fix end-of-line spacing to sate whining PHMs.
+ *
+ * Revision 1.20  1999/10/01 15:44:54  rgb
+ * Move spinlock header include to 2.1> scope.
+ *
+ * Revision 1.19  1999/10/01 08:35:52  rgb
+ * Add spinlock include to shut up compiler for 2.0.38.
+ *
+ * Revision 1.18  1999/09/23 18:02:52  rgb
+ * De-alarm the search failure message so it doesn't sound so grave.
+ *
+ * Revision 1.17  1999/05/25 21:26:01  rgb
+ * Fix rj_walktree() sanity checking bug.
+ *
+ * Revision 1.16  1999/05/09 03:25:38  rgb
+ * Fix bug introduced by 2.2 quick-and-dirty patch.
+ *
+ * Revision 1.15  1999/05/05 22:02:33  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.14  1999/04/29 15:24:15  rgb
+ * Add sanity checking for null pointer arguments.
+ * Standardise an error return method.
+ *
+ * Revision 1.13  1999/04/11 00:29:02  henry
+ * GPL boilerplate
+ *
+ * Revision 1.12  1999/04/06 04:54:28  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.11  1999/02/17 16:52:53  rgb
+ * Convert DEBUG_IPSEC to KLIPS_PRINT
+ * Clean out unused cruft.
+ *
+ * Revision 1.10  1999/01/22 06:30:05  rgb
+ * Cruft clean-out.
+ * 64-bit clean-up.
+ *
+ * Revision 1.9  1998/12/01 13:22:04  rgb
+ * Added support for debug printing of version info.
+ *
+ * Revision 1.8  1998/11/30 13:22:55  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.7  1998/10/25 02:43:26  rgb
+ * Change return type on rj_addroute and rj_delete and add and argument
+ * to the latter to be able to transmit more infomation about errors.
+ *
+ * Revision 1.6  1998/10/19 14:30:06  rgb
+ * Added inclusion of freeswan.h.
+ *
+ * Revision 1.5  1998/10/09 04:33:27  rgb
+ * Added 'klips_debug' prefix to all klips printk debug statements.
+ * Fixed output formatting slightly.
+ *
+ * Revision 1.4  1998/07/28 00:06:59  rgb
+ * Add debug detail to tree traversing.
+ *
+ * Revision 1.3  1998/07/14 18:07:58  rgb
+ * Add a routine to clear the eroute tree.
+ *
+ * Revision 1.2  1998/06/25 20:03:22  rgb
+ * Cleanup #endif comments.  Debug output for rj_init.
+ *
+ * Revision 1.1  1998/06/18 21:30:22  henry
+ * move sources from klips/src to klips/net/ipsec to keep stupid kernel
+ * build scripts happier about symlinks
+ *
+ * Revision 1.8  1998/05/25 20:34:15  rgb
+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
+ *
+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
+ * add ipsec_rj_walker_delete.
+ *
+ * Recover memory for eroute table on unload of module.
+ *
+ * Revision 1.7  1998/05/21 12:58:58  rgb
+ * Moved 'extern' definitions to ipsec_radij.h to support /proc 3k limit fix.
+ *
+ * Revision 1.6  1998/04/23 20:57:29  rgb
+ * Cleaned up compiler warnings for unused debugging functions.
+ *
+ * Revision 1.5  1998/04/22 16:51:38  rgb
+ * Tidy up radij debug code from recent rash of modifications to debug code.
+ *
+ * Revision 1.4  1998/04/21 21:28:56  rgb
+ * Rearrange debug switches to change on the fly debug output from user
+ * space.  Only kernel changes checked in at this time.  radij.c was also
+ * changed to temporarily remove buggy debugging code in rj_delete causing
+ * an OOPS and hence, netlink device open errors.
+ *
+ * Revision 1.3  1998/04/14 17:30:37  rgb
+ * Fix up compiling errors for radij tree memory reclamation.
+ *
+ * Revision 1.2  1998/04/12 22:03:25  rgb
+ * Updated ESP-3DES-HMAC-MD5-96,
+ * 	ESP-DES-HMAC-MD5-96,
+ * 	AH-HMAC-MD5-96,
+ * 	AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
+ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
+ *
+ * Fixed eroute references in /proc/net/ipsec*.
+ *
+ * Started to patch module unloading memory leaks in ipsec_netlink and
+ * radij tree unloading.
+ *
+ * Revision 1.1  1998/04/09 03:06:15  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:39:04  ji
+ * Minor cleanups.
+ * Rationalized debugging code.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/radij.h linux-patched/net/ipsec/radij.h
--- linux/net/ipsec/radij.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/radij.h	Sun Jan 19 22:32:30 2003
@@ -0,0 +1,283 @@
+/*
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/*
+ * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite
+ *
+ * Variable and procedure names have been modified so that they don't
+ * conflict with the original BSD code, as a small number of modifications
+ * have been introduced and we may want to reuse this code in BSD.
+ * 
+ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek
+ * chi or a German ch sound (as `doch', not as in `milch'), or even a 
+ * spanish j as in Juan.  It is not as far back in the throat like
+ * the corresponding Hebrew sound, nor is it a soft breath like the English h.
+ * It has nothing to do with the Dutch ij sound.
+ * 
+ * Here is the appropriate copyright notice:
+ */
+
+/*
+ * Copyright (c) 1988, 1989, 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.
+ *
+ *	@(#)radix.h	8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _RADIJ_H_
+#define	_RADIJ_H_
+
+/* 
+#define RJ_DEBUG
+*/
+
+#ifdef __KERNEL__
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x)  x
+#else
+#define __P(x)  ()
+#endif
+#endif
+
+/*
+ * Radix search tree node layout.
+ */
+
+struct radij_node
+{
+	struct	radij_mask *rj_mklist;	/* list of masks contained in subtree */
+	struct	radij_node *rj_p;	/* parent */
+	short	rj_b;			/* bit offset; -1-index(netmask) */
+	char	rj_bmask;		/* node: mask for bit test*/
+	u_char	rj_flags;		/* enumerated next */
+#define RJF_NORMAL	1		/* leaf contains normal route */
+#define RJF_ROOT	2		/* leaf is root leaf for tree */
+#define RJF_ACTIVE	4		/* This node is alive (for rtfree) */
+	union {
+		struct {			/* leaf only data: */
+			caddr_t	rj_Key;	/* object of search */
+			caddr_t	rj_Mask;	/* netmask, if present */
+			struct	radij_node *rj_Dupedkey;
+		} rj_leaf;
+		struct {			/* node only data: */
+			int	rj_Off;		/* where to start compare */
+			struct	radij_node *rj_L;/* progeny */
+			struct	radij_node *rj_R;/* progeny */
+		}rj_node;
+	}		rj_u;
+#ifdef RJ_DEBUG
+	int rj_info;
+	struct radij_node *rj_twin;
+	struct radij_node *rj_ybro;
+#endif
+};
+
+#define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey
+#define rj_key rj_u.rj_leaf.rj_Key
+#define rj_mask rj_u.rj_leaf.rj_Mask
+#define rj_off rj_u.rj_node.rj_Off
+#define rj_l rj_u.rj_node.rj_L
+#define rj_r rj_u.rj_node.rj_R
+
+/*
+ * Annotations to tree concerning potential routes applying to subtrees.
+ */
+
+extern struct radij_mask {
+	short	rm_b;			/* bit offset; -1-index(netmask) */
+	char	rm_unused;		/* cf. rj_bmask */
+	u_char	rm_flags;		/* cf. rj_flags */
+	struct	radij_mask *rm_mklist;	/* more masks to try */
+	caddr_t	rm_mask;		/* the mask */
+	int	rm_refs;		/* # of references to this struct */
+} *rj_mkfreelist;
+
+#define MKGet(m) {\
+	if (rj_mkfreelist) {\
+		m = rj_mkfreelist; \
+		rj_mkfreelist = (m)->rm_mklist; \
+	} else \
+		R_Malloc(m, struct radij_mask *, sizeof (*(m))); }\
+
+#define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m);}
+
+struct radij_node_head {
+	struct	radij_node *rnh_treetop;
+	int	rnh_addrsize;		/* permit, but not require fixed keys */
+	int	rnh_pktsize;		/* permit, but not require fixed keys */
+#if 0
+	struct	radij_node *(*rnh_addaddr)	/* add based on sockaddr */
+		__P((void *v, void *mask,
+		     struct radij_node_head *head, struct radij_node nodes[]));
+#endif
+	int (*rnh_addaddr)	/* add based on sockaddr */
+		__P((void *v, void *mask,
+		     struct radij_node_head *head, struct radij_node nodes[]));
+	struct	radij_node *(*rnh_addpkt)	/* add based on packet hdr */
+		__P((void *v, void *mask,
+		     struct radij_node_head *head, struct radij_node nodes[]));
+#if 0
+	struct	radij_node *(*rnh_deladdr)	/* remove based on sockaddr */
+		__P((void *v, void *mask, struct radij_node_head *head));
+#endif
+	int (*rnh_deladdr)	/* remove based on sockaddr */
+		__P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node));
+	struct	radij_node *(*rnh_delpkt)	/* remove based on packet hdr */
+		__P((void *v, void *mask, struct radij_node_head *head));
+	struct	radij_node *(*rnh_matchaddr)	/* locate based on sockaddr */
+		__P((void *v, struct radij_node_head *head));
+	struct	radij_node *(*rnh_matchpkt)	/* locate based on packet hdr */
+		__P((void *v, struct radij_node_head *head));
+	int	(*rnh_walktree)			/* traverse tree */
+		__P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w));
+	struct	radij_node rnh_nodes[3];	/* empty tree for common case */
+};
+
+
+#define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n))
+#define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n))
+#define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n))
+#define R_Malloc(p, t, n) ((p = (t) kmalloc((size_t)(n), GFP_ATOMIC)), Bzero((p),(n)))
+#define Free(p) kfree((caddr_t)p);
+
+void	 rj_init __P((void));
+int	 rj_inithead __P((void **, int));
+int	 rj_refines __P((void *, void *));
+int	 rj_walktree __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w));
+struct radij_node
+	 *rj_addmask __P((void *, int, int)) /* , rgb */ ;
+int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *,
+			struct radij_node [2])) /* , rgb */ ;
+int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */ ;
+struct radij_node /* rgb */
+	 *rj_insert __P((void *, struct radij_node_head *, int *,
+			struct radij_node [2])),
+	 *rj_match __P((void *, struct radij_node_head *)),
+	 *rj_newpair __P((void *, int, struct radij_node[2])),
+	 *rj_search __P((void *, struct radij_node *)),
+	 *rj_search_m __P((void *, struct radij_node *, void *));
+
+void rj_deltree(struct radij_node_head *);
+void rj_delnodes(struct radij_node *);
+void rj_free_mkfreelist(void);
+int radijcleartree(void);
+int radijcleanup(void);
+
+extern struct radij_node_head *mask_rjhead;
+extern int maj_keylen;
+#endif /* __KERNEL__ */
+
+#endif /* _RADIJ_H_ */
+
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.3  2003/01/19 22:32:30  ken
+ * X.509 0.9.19 -> 0.9.20
+ *
+ * Revision 1.2  2002/12/12 03:32:07  ken
+ * Upgraded to X.509 0.9.16 w/manual merges for NAT-T support
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:18  ken
+ * 1.98b
+ *
+ * Revision 1.11  2001/09/20 15:33:00  rgb
+ * Min/max cleanup.
+ *
+ * Revision 1.10  1999/11/18 04:09:20  rgb
+ * Replaced all kernel version macros to shorter, readable form.
+ *
+ * Revision 1.9  1999/05/05 22:02:33  rgb
+ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
+ *
+ * Revision 1.8  1999/04/29 15:24:58  rgb
+ * Add check for existence of macros min/max.
+ *
+ * Revision 1.7  1999/04/11 00:29:02  henry
+ * GPL boilerplate
+ *
+ * Revision 1.6  1999/04/06 04:54:29  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ * Revision 1.5  1999/01/22 06:30:32  rgb
+ * 64-bit clean-up.
+ *
+ * Revision 1.4  1998/11/30 13:22:55  rgb
+ * Rationalised all the klips kernel file headers.  They are much shorter
+ * now and won't conflict under RH5.2.
+ *
+ * Revision 1.3  1998/10/25 02:43:27  rgb
+ * Change return type on rj_addroute and rj_delete and add and argument
+ * to the latter to be able to transmit more infomation about errors.
+ *
+ * Revision 1.2  1998/07/14 18:09:51  rgb
+ * Add a routine to clear eroute table.
+ * Added #ifdef __KERNEL__ directives to restrict scope of header.
+ *
+ * Revision 1.1  1998/06/18 21:30:22  henry
+ * move sources from klips/src to klips/net/ipsec to keep stupid kernel
+ * build scripts happier about symlinks
+ *
+ * Revision 1.4  1998/05/25 20:34:16  rgb
+ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
+ *
+ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
+ * add ipsec_rj_walker_delete.
+ *
+ * Recover memory for eroute table on unload of module.
+ *
+ * Revision 1.3  1998/04/22 16:51:37  rgb
+ * Tidy up radij debug code from recent rash of modifications to debug code.
+ *
+ * Revision 1.2  1998/04/14 17:30:38  rgb
+ * Fix up compiling errors for radij tree memory reclamation.
+ *
+ * Revision 1.1  1998/04/09 03:06:16  henry
+ * sources moved up from linux/net/ipsec
+ *
+ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
+ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
+ *
+ * Revision 0.4  1997/01/15 01:28:15  ji
+ * No changes.
+ *
+ * Revision 0.3  1996/11/20 14:44:45  ji
+ * Release update only.
+ *
+ * Revision 0.2  1996/11/02 00:18:33  ji
+ * First limited release.
+ *
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/sysctl_net_ipsec.c linux-patched/net/ipsec/sysctl_net_ipsec.c
--- linux/net/ipsec/sysctl_net_ipsec.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/sysctl_net_ipsec.c	Thu Sep  5 04:13:18 2002
@@ -0,0 +1,190 @@
+/*
+ * sysctl interface to net IPSEC subsystem.
+ * Copyright (C) 1998, 1999, 2000, 2001	  Richard Guy Briggs.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+ */
+
+/* -*- linux-c -*-
+ *
+ * Initiated April 3, 1998, Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+ */
+
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+
+#include "ipsec_param.h"
+
+#ifdef CONFIG_SYSCTL
+
+#define NET_IPSEC 2112 /* Random number */                                        
+#ifdef CONFIG_IPSEC_DEBUG
+extern int       debug_ah;
+extern int       debug_esp;
+extern int       debug_tunnel;
+extern int       debug_eroute;
+extern int       debug_spi;
+extern int       debug_radij;
+extern int       debug_netlink;
+extern int       debug_xform;
+extern int       debug_rcv;
+extern int       debug_pfkey;
+extern int sysctl_ipsec_debug_verbose;
+#ifdef CONFIG_IPSEC_IPCOMP
+extern int sysctl_ipsec_debug_ipcomp;
+#endif /* CONFIG_IPSEC_IPCOMP */
+#endif /* CONFIG_IPSEC_DEBUG */
+
+extern int sysctl_ipsec_icmp;
+extern int sysctl_ipsec_inbound_policy_check;
+extern int sysctl_ipsec_tos;
+int sysctl_ipsec_regress_pfkey_lossage;
+
+enum {
+#ifdef CONFIG_IPSEC_DEBUG
+	NET_IPSEC_DEBUG_AH=1,
+	NET_IPSEC_DEBUG_ESP=2,
+	NET_IPSEC_DEBUG_TUNNEL=3,
+	NET_IPSEC_DEBUG_EROUTE=4,
+	NET_IPSEC_DEBUG_SPI=5,
+	NET_IPSEC_DEBUG_RADIJ=6,
+	NET_IPSEC_DEBUG_NETLINK=7,
+	NET_IPSEC_DEBUG_XFORM=8,
+	NET_IPSEC_DEBUG_RCV=9,
+	NET_IPSEC_DEBUG_PFKEY=10,
+	NET_IPSEC_DEBUG_VERBOSE=11,
+	NET_IPSEC_DEBUG_IPCOMP=12,
+#endif /* CONFIG_IPSEC_DEBUG */
+	NET_IPSEC_ICMP=13,
+	NET_IPSEC_INBOUND_POLICY_CHECK=14,
+	NET_IPSEC_TOS=15,
+	NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16,
+};
+
+static ctl_table ipsec_table[] = {
+#ifdef CONFIG_IPSEC_DEBUG
+	{ NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_DEBUG_VERBOSE, "debug_verbose",&sysctl_ipsec_debug_verbose,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+#ifdef CONFIG_IPSEC_IPCOMP
+	{ NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+#endif /* CONFIG_IPSEC_IPCOMP */
+
+#ifdef CONFIG_IPSEC_REGRESS
+	{ NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage",
+	  &sysctl_ipsec_regress_pfkey_lossage,
+	  sizeof(int), 0644, NULL, &proc_dointvec},
+#endif /* CONFIG_IPSEC_REGRESS */
+
+#endif /* CONFIG_IPSEC_DEBUG */
+	{ NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{ NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos,
+	  sizeof(int), 0644, NULL, &proc_dointvec},    
+	{0}
+};
+
+static ctl_table ipsec_net_table[] = {
+        { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table },
+        { 0 }
+};
+ 
+static ctl_table ipsec_root_table[] = {
+        { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table },
+        { 0 }
+};
+ 
+static struct ctl_table_header *ipsec_table_header;
+
+int ipsec_sysctl_register(void)
+{
+        ipsec_table_header = register_sysctl_table(ipsec_root_table, 0);
+        if (!ipsec_table_header) {
+                return -ENOMEM;
+	}
+        return 0;
+}
+ 
+void ipsec_sysctl_unregister(void)
+{
+        unregister_sysctl_table(ipsec_table_header);
+}
+
+#endif /* CONFIG_SYSCTL */
+
+/*
+ * $Log: super-freeswan-1.99.8-delsol1.diff,v $
+ * Revision 1.1  2003/09/09 09:20:34  john
+ * Initial import
+ *
+ * Revision 1.1.1.1  2002/09/05 03:13:18  ken
+ * 1.98b
+ *
+ * Revision 1.13  2002/01/12 02:58:32  mcr
+ * 	first regression test causes acquire messages to be lost
+ * 	100% of the time. This is to help testing of pluto.
+ *
+ * Revision 1.12  2001/06/14 19:35:13  rgb
+ * Update copyright date.
+ *
+ * Revision 1.11  2001/02/26 19:58:13  rgb
+ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs.
+ *
+ * Revision 1.10  2000/09/16 01:50:15  rgb
+ * Protect sysctl_ipsec_debug_ipcomp with compiler defines too so that the
+ * linker won't blame rj_delete() for missing symbols.  ;->  Damn statics...
+ *
+ * Revision 1.9  2000/09/15 23:17:51  rgb
+ * Moved stuff around to compile with debug off.
+ *
+ * Revision 1.8  2000/09/15 11:37:02  rgb
+ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
+ * IPCOMP zlib deflate code.
+ *
+ * Revision 1.7  2000/09/15 07:37:15  rgb
+ * Munged silly log comment that was causing a warning.
+ *
+ * Revision 1.6  2000/09/15 04:58:23  rgb
+ * Added tos runtime switch.
+ * Removed 'sysctl_ipsec_' prefix from /proc/sys/net/ipsec/ filenames.
+ *
+ * Revision 1.5  2000/09/12 03:25:28  rgb
+ * Filled in and implemented sysctl.
+ *
+ * Revision 1.4  1999/04/11 00:29:03  henry
+ * GPL boilerplate
+ *
+ * Revision 1.3  1999/04/06 04:54:29  rgb
+ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
+ * patch shell fixes.
+ *
+ */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/Makefile linux-patched/net/ipsec/zlib/Makefile
--- linux/net/ipsec/zlib/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/Makefile	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,112 @@
+# (kernel) Makefile for IPCOMP zlib deflate code
+# Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
+# Copyright (C) 2000  Svenning Soerensen
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# RCSID $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $
+#
+
+
+
+include ../Makefile.inc
+
+
+
+ifndef TOPDIR
+TOPDIR  := /usr/src/linux
+endif
+
+
+L_TARGET := zlib.a
+obj-y := adler32.o deflate.o infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o trees.o zutil.o
+
+EXTRA_CFLAGS += $(KLIPSCOMPILE)
+
+EXTRA_CFLAGS += -Wall 
+#EXTRA_CFLAGS += -Wconversion 
+#EXTRA_CFLAGS += -Wmissing-prototypes 
+EXTRA_CFLAGS += -Wpointer-arith 
+#EXTRA_CFLAGS += -Wcast-qual 
+#EXTRA_CFLAGS += -Wmissing-declarations 
+EXTRA_CFLAGS += -Wstrict-prototypes
+#EXTRA_CFLAGS += -pedantic
+#EXTRA_CFLAGS += -W
+#EXTRA_CFLAGS += -Wwrite-strings 
+EXTRA_CFLAGS += -Wbad-function-cast 
+EXTRA_CFLAGS += -DIPCOMP_PREFIX
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ -DNO_UNDERLINE -traditional -c $< -o $*.o
+
+asm-obj-$(CONFIG_M586)		+= match586.o
+asm-obj-$(CONFIG_M586TSC)	+= match586.o
+asm-obj-$(CONFIG_M586MMX)	+= match586.o
+asm-obj-$(CONFIG_M686)		+= match686.o
+asm-obj-$(CONFIG_MPENTIUMIII)	+= match686.o
+asm-obj-$(CONFIG_MPENTIUM4)	+= match686.o
+asm-obj-$(CONFIG_MK6)		+= match586.o
+asm-obj-$(CONFIG_MK7)		+= match686.o
+asm-obj-$(CONFIG_MCRUSOE)	+= match586.o
+asm-obj-$(CONFIG_MWINCHIPC6)	+= match586.o
+asm-obj-$(CONFIG_MWINCHIP2)	+= match686.o
+asm-obj-$(CONFIG_MWINCHIP3D)	+= match686.o
+
+obj-y += $(asm-obj-y)
+ifneq ($(strip $(asm-obj-y)),)
+  EXTRA_CFLAGS += -DASMV
+endif
+
+active-objs     := $(sort $(obj-y) $(obj-m))
+L_OBJS          := $(obj-y)
+M_OBJS          := $(obj-m)
+MIX_OBJS        := $(filter $(export-objs), $(active-objs))
+
+include $(TOPDIR)/Rules.make
+
+$(obj-y) :  $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h
+
+
+clean:
+	-rm -f *.o *.a
+
+checkprograms:
+programs: $(L_TARGET)
+
+#
+# $Log: super-freeswan-1.99.8-delsol1.diff,v $
+# Revision 1.1  2003/09/09 09:20:34  john
+# Initial import
+#
+# Revision 1.1.1.1  2002/09/05 03:13:22  ken
+# 1.98b
+#
+# Revision 1.7  2002/03/27 23:34:35  mcr
+# 	added programs: target
+#
+# Revision 1.6  2001/12/05 20:19:08  henry
+# use new compile-control variable
+#
+# Revision 1.5  2001/11/27 16:38:08  mcr
+# 	added new "checkprograms" target to deal with programs that
+# 	are required for "make check", but that may not be ready to
+# 	build for every user due to external dependancies.
+#
+# Revision 1.4  2001/10/24 14:46:24  henry
+# Makefile.inc
+#
+# Revision 1.3  2001/04/21 23:05:24  rgb
+# Update asm directives for 2.4 style makefiles.
+#
+# Revision 1.2  2001/01/29 22:22:00  rgb
+# Convert to 2.4 new style with back compat.
+#
+# Revision 1.1.1.1  2000/09/29 18:51:33  rgb
+# zlib_beginnings
+#
+#
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/adler32.c linux-patched/net/ipsec/zlib/adler32.c
--- linux/net/ipsec/zlib/adler32.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/adler32.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+	    buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+	    s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/deflate.c linux-patched/net/ipsec/zlib/deflate.c
--- linux/net/ipsec/zlib/deflate.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/deflate.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,1351 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in ftp://ds.internic.net/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $ */
+
+#include "deflate.h"
+
+local const char deflate_copyright[] =
+   " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* maximum speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+			 Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+		  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int noheader = 0;
+    static const char* my_version = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+	return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == Z_NULL) {
+      return Z_STREAM_ERROR;
+/*	strm->zalloc = zcalloc;
+	strm->opaque = (voidpf)0;*/
+    }
+    if (strm->zfree == Z_NULL) return Z_STREAM_ERROR; /* strm->zfree = zcfree; */
+
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#ifdef FASTEST
+    level = 1;
+#endif
+
+    if (windowBits < 0) { /* undocumented feature: suppress zlib header */
+        noheader = 1;
+        windowBits = -windowBits;
+    }
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
+	strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+        return Z_STREAM_ERROR;
+    }
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->noheader = noheader;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        strm->msg = ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
+
+    s = strm->state;
+    strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > MAX_DIST(s)) {
+	length = MAX_DIST(s);
+#ifndef USE_DICT_HEAD
+	dictionary += dictLength - length; /* use the tail of the dictionary */
+#endif
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+	INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+    
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->noheader < 0) {
+        s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
+    }
+    s->status = s->noheader ? BUSY_STATE : INIT_STATE;
+    strm->adler = 1;
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+    if (level == Z_DEFAULT_COMPRESSION) {
+	level = 6;
+    }
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+	return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if (func != configuration_table[level].func && strm->total_in != 0) {
+	/* Flush the last buffer: */
+	err = deflate(strm, Z_PARTIAL_FLUSH);
+    }
+    if (s->level != level) {
+	s->level = level;
+	s->max_lazy_match   = configuration_table[level].max_lazy;
+	s->good_match       = configuration_table[level].good_length;
+	s->nice_match       = configuration_table[level].nice_length;
+	s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}   
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+	flush > Z_FINISH || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+	(s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the zlib header */
+    if (s->status == INIT_STATE) {
+
+        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+        uInt level_flags = (s->level-1) >> 1;
+
+        if (level_flags > 3) level_flags = 3;
+        header |= (level_flags << 6);
+	if (s->strstart != 0) header |= PRESET_DICT;
+        header += 31 - (header % 31);
+
+        s->status = BUSY_STATE;
+        putShortMSB(s, header);
+
+	/* Save the adler32 of the preset dictionary: */
+	if (s->strstart != 0) {
+	    putShortMSB(s, (uInt)(strm->adler >> 16));
+	    putShortMSB(s, (uInt)(strm->adler & 0xffff));
+	}
+	strm->adler = 1L;
+    }
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+	    /* Since avail_out is 0, deflate will be called again with
+	     * more output space, but possibly with both pending and
+	     * avail_in equal to zero. There won't be anything to do,
+	     * but this is not an error situation so make sure we
+	     * return OK instead of BUF_ERROR at next call of deflate:
+             */
+	    s->last_flush = -1;
+	    return Z_OK;
+	}
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUFF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+	       flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+	bstate = (*(configuration_table[s->level].func))(s, flush);
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+	    if (strm->avail_out == 0) {
+	        s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+	    }
+	    return Z_OK;
+	    /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+	     * of deflate should use the same flush parameter to make sure
+	     * that the flush is complete. So we don't have to output an
+	     * empty block here, this will be done at next call. This also
+	     * ensures that for a very small output buffer, we emit at most
+	     * one empty block.
+	     */
+	}
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                }
+            }
+            flush_pending(strm);
+	    if (strm->avail_out == 0) {
+	      s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+	      return Z_OK;
+	    }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->noheader) return Z_STREAM_END;
+
+    /* Write the zlib trailer (adler32) */
+    putShortMSB(s, (uInt)(strm->adler >> 16));
+    putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    s->noheader = -1; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE && status != BUSY_STATE &&
+	status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    *dest = *source;
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    *ds = *ss;
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (!strm->state->noheader) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+#ifndef FASTEST
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2:
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+
+#else /* FASTEST */
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 only
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     *++scan == *++match && *++scan == *++match &&
+	     scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return len <= s->lookahead ? len : s->lookahead;
+}
+#endif /* FASTEST */
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+		start, match, length);
+        do {
+	    fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+	} while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+            more = wsize;
+
+        } else if (more == (unsigned)(-1)) {
+            /* Very unlikely, but possible on 16 bit machine if strstart == 0
+             * and lookahead == 1 (input done one byte at time)
+             */
+            more--;
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        } else if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+	    n = s->hash_size;
+	    p = &s->head[n];
+	    do {
+		m = *--p;
+		*p = (Pos)(m >= wsize ? m-wsize : NIL);
+	    } while (--n);
+
+	    n = wsize;
+#ifndef FASTEST
+	    p = &s->prev[n];
+	    do {
+		m = *--p;
+		*p = (Pos)(m >= wsize ? m-wsize : NIL);
+		/* If n is not on any hash chain, prev[n] is garbage but
+		 * its value will never be used.
+		 */
+	    } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+		(ulg)((long)s->strstart - s->block_start), \
+		(eof)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+   FLUSH_BLOCK_ONLY(s, eof); \
+   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+		   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+	Assert(s->block_start >= 0L, "block gone");
+
+	s->strstart += s->lookahead;
+	s->lookahead = 0;
+
+	/* Emit a stored block if pending_buf will be full: */
+ 	max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+	    /* strstart == 0 is possible when wraparound on 16-bit machine */
+	    s->lookahead = (uInt)(s->strstart - max_start);
+	    s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+	}
+	/* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+	}
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL; /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+	        return need_more;
+	    }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            }
+            /* longest_match() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in hash table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++; 
+            } else
+#endif
+	    {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++; 
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL;    /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+	        return need_more;
+	    }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy != Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            }
+            /* longest_match() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
+                 (s->match_length == MIN_MATCH &&
+                  s->strstart - s->match_start > TOO_FAR))) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+			   s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+	    _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+	    if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/deflate.h linux-patched/net/ipsec/zlib/deflate.h
--- linux/net/ipsec/zlib/deflate.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/deflate.h	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,318 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2002 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: super-freeswan-1.99.8-delsol1.diff,v 1.1 2003/09/09 09:20:34 john Exp $ */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H
+
+#include "zutil.h"
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    int   pending;       /* nb of bytes in the pending buffer */
+    int   noheader;      /* suppress zlib header and adler32 */
+    Byte  data_type;     /* UNKNOWN, BINARY or ASCII */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+        /* in trees.c */
+void _tr_init         OF((deflate_state *s));
+int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
+			  int eof));
+void _tr_align        OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch _length_code[];
+  extern uch _dist_code[];
+#else
+  extern const uch _length_code[];
+  extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (length); \
+    ush dist = (distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length) 
+#endif
+
+#endif /* _DEFLATE_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/infblock.c linux-patched/net/ipsec/zlib/infblock.c
--- linux/net/ipsec/zlib/infblock.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/infblock.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,403 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+  if (c != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens);
+  if (s->mode == CODES)
+    inflate_codes_free(s->sub.decode.codes, z);
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+  Tracev((stderr, "inflate:   blocks reset\n"));
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->hufts =
+       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+  {
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s->hufts);
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Tracev((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, Z_NULL);
+  return s;
+}
+
+
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Tracev((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Tracev((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BAD;
+          z->msg = (char*)"invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+      {
+        s->mode = BAD;
+        z->msg = (char*)"invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BAD;
+        z->msg = (char*)"too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, s->hufts, z);
+      if (t != Z_OK)
+      {
+        r = t;
+        if (r == Z_DATA_ERROR)
+        {
+          ZFREE(z, s->sub.trees.blens);
+          s->mode = BAD;
+        }
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->bits;
+        c = h->base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            ZFREE(z, s->sub.trees.blens);
+            s->mode = BAD;
+            z->msg = (char*)"invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
+                                  s->hufts, z);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+          {
+            ZFREE(z, s->sub.trees.blens);
+            s->mode = BAD;
+          }
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        s->sub.decode.codes = c;
+      }
+      ZFREE(z, s->sub.trees.blens);
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONE;
+    case DONE:
+      r = Z_STREAM_END;
+      LEAVE
+    case BAD:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+int inflate_blocks_free(s, z)
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_blocks_reset(s, z, Z_NULL);
+  ZFREE(z, s->window);
+  ZFREE(z, s->hufts);
+  ZFREE(z, s);
+  Tracev((stderr, "inflate:   blocks freed\n"));
+  return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt  n;
+{
+  zmemcpy(s->window, d, n);
+  s->read = s->write = s->window + n;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
+ * IN assertion: s != Z_NULL
+ */
+int inflate_blocks_sync_point(s)
+inflate_blocks_statef *s;
+{
+  return s->mode == LENS;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/infblock.h linux-patched/net/ipsec/zlib/infblock.h
--- linux/net/ipsec/zlib/infblock.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/infblock.h	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,39 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+    z_streamp z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+extern int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));                      /* initial return code */
+
+extern void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    uLongf *));                  /* check value on output */
+
+extern int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_streamp));
+
+extern void inflate_set_dictionary OF((
+    inflate_blocks_statef *s,
+    const Bytef *d,  /* dictionary */
+    uInt  n));       /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+    inflate_blocks_statef *s));
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/infcodes.c linux-patched/net/ipsec/zlib/infcodes.c
--- linux/net/ipsec/zlib/infcodes.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/infcodes.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,251 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  inflate_codes_mode mode;      /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+      f = q - c->sub.copy.dist;
+      while (f < s->window)             /* modulo window size-"while" instead */
+        f += s->end - s->window;        /* of "if" handles invalid distances */
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      if (k > 7)        /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;            /* can always return one */
+      }
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+  ZFREE(z, c);
+  Tracev((stderr, "inflate:       codes free\n"));
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/infcodes.h linux-patched/net/ipsec/zlib/infcodes.h
--- linux/net/ipsec/zlib/infcodes.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/infcodes.h	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,31 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFCODES_H
+#define _INFCODES_H
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_streamp ));
+
+extern int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+extern void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_streamp ));
+
+#endif /* _INFCODES_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/inffast.c linux-patched/net/ipsec/zlib/inffast.c
--- linux/net/ipsec/zlib/inffast.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/inffast.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,183 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  uInt ml;              /* mask for literal/length tree */
+  uInt md;              /* mask for distance tree */
+  uInt c;               /* bytes to copy */
+  uInt d;               /* distance back to copy from */
+  Bytef *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {                          /* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+    {
+      DUMPBITS(t->bits)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
+
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            r = q - d;
+            if (r < s->window)                  /* wrap if needed */
+            {
+              do {
+                r += s->end - s->window;        /* force pointer in window */
+              } while (r < s->window);          /* covers invalid distances */
+              e = s->end - r;
+              if (c > e)
+              {
+                c -= e;                         /* wrapped copy */
+                do {
+                    *q++ = *r++;
+                } while (--e);
+                r = s->window;
+                do {
+                    *q++ = *r++;
+                } while (--c);
+              }
+              else                              /* normal copy */
+              {
+                *q++ = *r++;  c--;
+                *q++ = *r++;  c--;
+                do {
+                    *q++ = *r++;
+                } while (--c);
+              }
+            }
+            else                                /* normal copy */
+            {
+              *q++ = *r++;  c--;
+              *q++ = *r++;  c--;
+              do {
+                *q++ = *r++;
+              } while (--c);
+            }
+            break;
+          }
+          else if ((e & 64) == 0)
+          {
+            t += t->base;
+            e = (t += ((uInt)b & inflate_mask[e]))->exop;
+          }
+          else
+          {
+            z->msg = (char*)"invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        t += t->base;
+        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = (char*)"invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/inffast.h linux-patched/net/ipsec/zlib/inffast.h
--- linux/net/ipsec/zlib/inffast.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/inffast.h	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,22 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFFAST_H
+#define _INFFAST_H
+
+extern int inflate_fast OF((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    inflate_blocks_statef *,
+    z_streamp ));
+
+#endif /* _INFFAST_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/inffixed.h linux-patched/net/ipsec/zlib/inffixed.h
--- linux/net/ipsec/zlib/inffixed.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/inffixed.h	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+local uInt fixed_bl = 9;
+local uInt fixed_bd = 5;
+local inflate_huft fixed_tl[] = {
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+  };
+local inflate_huft fixed_td[] = {
+    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+  };
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/inflate.c linux-patched/net/ipsec/zlib/inflate.c
--- linux/net/ipsec/zlib/inflate.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/inflate.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,368 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+typedef enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      DICT4,    /* four dictionary check bytes to go */
+      DICT3,    /* three dictionary check bytes to go */
+      DICT2,    /* two dictionary check bytes to go */
+      DICT1,    /* one dictionary check byte to go */
+      DICT0,    /* waiting for inflateSetDictionary */
+      BLOCKS,   /* decompressing blocks */
+      CHECK4,   /* four check bytes to go */
+      CHECK3,   /* three check bytes to go */
+      CHECK2,   /* two check bytes to go */
+      CHECK1,   /* one check byte to go */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  inflate_mode  mode;   /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef 
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+int ZEXPORT inflateReset(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+  Tracev((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateEnd(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z);
+  ZFREE(z, z->state);
+  z->state = Z_NULL;
+  Tracev((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+      stream_size != sizeof(z_stream))
+      return Z_VERSION_ERROR;
+
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->msg = Z_NULL;
+  if (z->zalloc == Z_NULL)
+  {
+    return Z_STREAM_ERROR;
+/*    z->zalloc = zcalloc;
+    z->opaque = (voidpf)0;
+*/
+  }
+  if (z->zfree == Z_NULL) return Z_STREAM_ERROR; /* z->zfree = zcfree; */
+  if ((z->state = (struct internal_state FAR *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Tracev((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+  return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int ZEXPORT inflate(z, f)
+z_streamp z;
+int f;
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      b = NEXTBYTE;
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib header ok\n"));
+      if (!(b & PRESET_DICT))
+      {
+        z->state->mode = BLOCKS;
+        break;
+      }
+      z->state->mode = DICT4;
+    case DICT4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = DICT3;
+    case DICT3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = DICT2;
+    case DICT2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = DICT1;
+    case DICT1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+      z->adler = z->state->sub.check.need;
+      z->state->mode = DICT0;
+      return Z_NEED_DICT;
+    case DICT0:
+      z->state->mode = BAD;
+      z->msg = (char*)"need dictionary";
+      z->state->sub.marker = 0;       /* can try inflateSync */
+      return Z_STREAM_ERROR;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r == Z_OK)
+        r = f;
+      if (r != Z_STREAM_END)
+        return r;
+      r = f;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = DONE;
+        break;
+      }
+      z->state->mode = CHECK4;
+    case CHECK4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
+z_streamp z;
+const Bytef *dictionary;
+uInt  dictLength;
+{
+  uInt length = dictLength;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
+    return Z_STREAM_ERROR;
+
+  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
+  z->adler = 1L;
+
+  if (length >= ((uInt)1<<z->state->wbits))
+  {
+    length = (1<<z->state->wbits)-1;
+    dictionary += dictLength - length;
+  }
+  inflate_set_dictionary(z->state->blocks, dictionary, length);
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateSync(z)
+z_streamp z;
+{
+  uInt n;       /* number of bytes to look at */
+  Bytef *p;     /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != BAD)
+  {
+    z->state->mode = BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
+    return Z_STREAM_ERROR;
+  return inflate_blocks_sync_point(z->state->blocks);
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/inftrees.c linux-patched/net/ipsec/zlib/inftrees.c
--- linux/net/ipsec/zlib/inftrees.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/inftrees.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,454 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#if !defined(BUILDFIXED) && !defined(STDC)
+#  define BUILDFIXED   /* non ANSI compilers may not accept inffixed.h */
+#endif
+
+local const char inflate_copyright[] =
+   " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+struct internal_state  {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    const uIntf *,      /* list of base values for non-simple codes */
+    const uIntf *,      /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    inflate_huft *,     /* space for trees */
+    uInt *,             /* hufts used in space */
+    uIntf * ));         /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+
+local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
+uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
+uInt n;                 /* number of codes (assumed <= 288) */
+uInt s;                 /* number of simple-valued codes (0..s-1) */
+const uIntf *d;         /* list of base values for non-simple codes */
+const uIntf *e;         /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t;  /* result: starting table */
+uIntf *m;               /* maximum lookup bits, returns actual */
+inflate_huft *hp;       /* space for trees */
+uInt *hn;               /* hufts used in space */
+uIntf *v;               /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), or Z_DATA_ERROR if the input is invalid. */
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
+  register uIntf *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = g - w;
+        z = z > (uInt)l ? l : z;        /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate new table */
+        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
+          return Z_DATA_ERROR;  /* overflow of MANY */
+        u[h] = q = hp + *hn;
+        *hn += z;
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          j = i >> (w - l);
+          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+        else
+          *t = q;               /* first table is returned result */
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
+      while ((i & mask) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+        mask = (1 << w) - 1;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, hp, z)
+uIntf *c;               /* 19 code lengths */
+uIntf *bb;              /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+                 tb, bb, hp, &hn, v);
+  if (r == Z_DATA_ERROR)
+    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR || *bb == 0)
+  {
+    z->msg = (char*)"incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  ZFREE(z, v);
+  return r;
+}
+
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
+uInt nl;                /* number of literal/length codes */
+uInt nd;                /* number of distance codes */
+uIntf *c;               /* that many (total) code lengths */
+uIntf *bl;              /* literal desired/actual bit depth */
+uIntf *bd;              /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+
+  /* allocate work area */
+  if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+
+  /* build literal/length tree */
+  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+  if (r != Z_OK || *bl == 0)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed literal/length tree";
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+  }
+
+  /* build distance tree */
+  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+  if (r != Z_OK || (*bd == 0 && nl > 257))
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed distance tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      z->msg = (char*)"incomplete distance tree";
+      r = Z_DATA_ERROR;
+    }
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"empty distance tree with lengths";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+#endif
+  }
+
+  /* done */
+  ZFREE(z, v);
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#ifdef BUILDFIXED
+local int fixed_built = 0;
+#define FIXEDH 544      /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+#else
+#include "inffixed.h"
+#endif
+
+
+int inflate_trees_fixed(bl, bd, tl, td, z)
+uIntf *bl;               /* literal desired/actual bit depth */
+uIntf *bd;               /* distance desired/actual bit depth */
+inflate_huft * FAR *tl;  /* literal/length tree result */
+inflate_huft * FAR *td;  /* distance tree result */
+z_streamp z;             /* for memory allocation */
+{
+#ifdef BUILDFIXED
+  /* build fixed tables if not already */
+  if (!fixed_built)
+  {
+    int k;              /* temporary variable */
+    uInt f = 0;         /* number of hufts used in fixed_mem */
+    uIntf *c;           /* length list for huft_build */
+    uIntf *v;           /* work area for huft_build */
+
+    /* allocate memory */
+    if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+      return Z_MEM_ERROR;
+    if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    {
+      ZFREE(z, c);
+      return Z_MEM_ERROR;
+    }
+
+    /* literal table */
+    for (k = 0; k < 144; k++)
+      c[k] = 8;
+    for (; k < 256; k++)
+      c[k] = 9;
+    for (; k < 280; k++)
+      c[k] = 7;
+    for (; k < 288; k++)
+      c[k] = 8;
+    fixed_bl = 9;
+    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
+               fixed_mem, &f, v);
+
+    /* distance table */
+    for (k = 0; k < 30; k++)
+      c[k] = 5;
+    fixed_bd = 5;
+    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
+               fixed_mem, &f, v);
+
+    /* done */
+    ZFREE(z, v);
+    ZFREE(z, c);
+    fixed_built = 1;
+  }
+#endif
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/inftrees.h linux-patched/net/ipsec/zlib/inftrees.h
--- linux/net/ipsec/zlib/inftrees.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/inftrees.h	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,63 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+#ifndef _INFTREES_H
+#define _INFTREES_H
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
+  uInt base;            /* literal, length base, distance base,
+                           or table offset */
+};
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1004 huft structures (850 for length/literals
+   and 154 for distances, the latter actually the result of an
+   exhaustive search).  The actual maximum is not known, but the
+   value below is more than safe. */
+#define MANY 1440
+
+extern int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    z_streamp));                /* for memory allocation */
+
+#endif /* _INFTREES_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/infutil.c linux-patched/net/ipsec/zlib/infutil.c
--- linux/net/ipsec/zlib/infutil.c	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/infutil.c	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt n;
+  Bytef *p;
+  Bytef *q;
+
+  /* local copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as far as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  zmemcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/infutil.h linux-patched/net/ipsec/zlib/infutil.h
--- linux/net/ipsec/zlib/infutil.h	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/infutil.h	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONE,     /* finished last block, done */
+      BAD}      /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  inflate_block_mode  mode;     /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_codes_statef 
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  inflate_huft *hufts;  /* single malloc for tree space */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+struct internal_state      {int dummy;}; /* for buggy compilers */
+
+#endif /* _INFUTIL_H */
diff -Nru -x '*.ipsecmd5' -x '*.preipsec' -x '*.ipsecmd5' -x '*.wipsec' linux/net/ipsec/zlib/match586.S linux-patched/net/ipsec/zlib/match586.S
--- linux/net/ipsec/zlib/match586.S	Thu Jan  1 01:00:00 1970
+++ linux-patched/net/ipsec/zlib/match586.S	Thu Sep  5 04:13:22 2002
@@ -0,0 +1,357 @@
+/* match.s -- Pentium-optimized version of longest_match()
+ * Written for zlib 1.1.2
+ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License.
+ */
+
+#ifndef NO_UNDERLINE
+#define	match_init	_ipcomp_match_init
+#define	longest_match	_ipcomp_longest_match
+#else
+#define match_init	ipcomp_match_init
+#define longest_match	ipcomp_longest_match
+#endif
+
+#define	MAX_MATCH	(258)
+#define	MIN_MATCH	(3)
+#define	MIN_LOOKAHEAD	(MAX_MATCH + MIN_MATCH + 1)
+#define	MAX_MATCH_8	((MAX_MATCH + 7) & ~7)
+
+/* stack frame offsets */
+
+#define	wmask			0	/* local copy of s->wmask	*/
+#define	window			4	/* local copy of s->window	*/
+#define	windowbestlen		8	/* s->window + bestlen		*/
+#define	chainlenscanend		12	/* high word: current chain len	*/
+					/* low word: last bytes sought	*/
+#define	scanstart		16	/* first two bytes of string	*/
+#define	scanalign		20	/* dword-misalignment of string	*/
+#define	nicematch		24	/* a good enough match size	*/
+#define	bestlen			28	/* size of best match so far	*/
+#define	scan			32	/* ptr to string wanting match	*/
+
+#define	LocalVarsSize		(36)
+/*	saved ebx		36 */
+/*	saved edi		40 */
+/*	saved esi		44 */
+/*	saved ebp		48 */
+/*	return address		52 */
+#define	deflatestate		56	/* the function arguments	*/
+#define	curmatch		60
+
+/* Offsets for fields in the deflate_state structure. These numbers
+ * are calculated from the definition of deflate_state, with the
+ * assumption that the compiler will dword-align the fields. (Thus,
+ * changing the definition of deflate_state could easily cause this
+ * program to crash horribly, without so much as a warning at
+ * compile time. Sigh.)
+ */
+#define	dsWSize			36
+#define	dsWMask			44
+#define	dsWindow		48
+#define	dsPrev			56
+#define	dsMatchLen		88
+#define	dsPrevMatch		92
+#define	dsStrStart		100
+#define	dsMatchStart		104
+#define	dsLookahead		108
+#define	dsPrevLen		112
+#define	dsMaxChainLen		116
+#define	dsGoodMatch		132
+#define	dsNiceMatch		136
+
+
+.file "match.S"
+
+.globl	match_init, longest_match
+
+.text
+
+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
+
+longest_match:
+
+/* Save registers that the compiler may be using, and adjust %esp to	*/
+/* make room for our stack frame.					*/
+
+		pushl	%ebp
+		pushl	%edi
+		pushl	%esi
+		pushl	%ebx
+		subl	$LocalVarsSize, %esp
+
+/* Retrieve the function arguments. %ecx will hold cur_match		*/
+/* throughout the entire function. %edx will hold the pointer to the	*/
+/* deflate_state structure during the function's setup (before		*/
+/* entering the main loop).						*/
+
+		movl	deflatestate(%esp), %edx
+		movl	curmatch(%esp), %ecx
+
+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;	*/
+
+		movl	dsNiceMatch(%edx), %eax
+		movl	dsLookahead(%edx), %ebx
+		cmpl	%eax, %ebx
+		jl	LookaheadLess
+		movl	%eax, %ebx
+LookaheadLess:	movl	%ebx, nicematch(%esp)
+
+/* register Bytef *scan = s->window + s->strstart;			*/
+
+		movl	dsWindow(%edx), %esi
+		movl	%esi, window(%esp)
+		movl	dsStrStart(%edx), %ebp
+		lea	(%esi,%ebp), %edi
+		movl	%edi, scan(%esp)
+
+/* Determine how many bytes the scan ptr is off from being		*/
+/* dword-aligned.							*/
+
+		movl	%edi, %eax
+		negl	%eax
+		andl	$3, %eax
+		movl	%eax, scanalign(%esp)
+
+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?			*/
+/*     s->strstart - (IPos)MAX_DIST(s) : NIL;				*/
+
+		movl	dsWSize(%edx), %eax
+		subl	$MIN_LOOKAHEAD, %eax
+		subl	%eax, %ebp
+		jg	LimitPositive
+		xorl	%ebp, %ebp
+LimitPositive:
+
+/* unsigned chain_length = s->max_chain_length;				*/
+/* if (s->prev_length >= s->good_match) {				*/
+/*     chain_length >>= 2;						*/
+/* }									*/
+
+		movl	dsPrevLen(%edx), %eax
+		movl	dsGoodMatch(%edx), %ebx
+		cmpl	%ebx, %eax
+		movl	dsMaxChainLen(%edx), %ebx
+		jl	LastMatchGood
+		shrl	$2, %ebx
+LastMatchGood:
+
+/* chainlen is decremented once beforehand so that the function can	*/
+/* use the sign flag instead of the zero flag for the exit test.	*/
+/* It is then shifted into the high word, to make room for the scanend	*/
+/* scanend value, which it will always accompany.			*/
+
+		decl	%ebx
+		shll	$16, %ebx
+
+/* int best_len = s->prev_length;					*/
+
+		movl	dsPrevLen(%edx), %eax
+		movl	%eax, bestlen(%esp)
+
+/* Store the sum of s->window + best_len in %esi locally, and in %esi.	*/
+
+		addl	%eax, %esi
+		movl	%esi, windowbestlen(%esp)
+
+/* register ush scan_start = *(ushf*)scan;				*/
+/* register ush scan_end   = *(ushf*)(scan+best_len-1);			*/
+
+		movw	(%edi), %bx
+		movw	%bx, scanstart(%esp)
+		movw	-1(%edi,%eax), %bx
+		movl	%ebx, chainlenscanend(%esp)
+
+/* Posf *prev = s->prev;						*/
+/* uInt wmask = s->w_mask;						*/
+
+		movl	dsPrev(%edx), %edi
+		movl	dsWMask(%edx), %edx
+		mov	%edx, wmask(%esp)
+
+/* Jump into the main loop.						*/
+
+		jmp	LoopEntry
+
+.balign 16
+
+/* do {
+ *     match = s->window + cur_match;
+ *     if (*(ushf*)(match+best_len-1) != scan_end ||
+ *         *(ushf*)match != scan_start) continue;
+ *     [...]
+ * } while ((cur_match = prev[cur_match & wmask]) > limit
+ *          && --chain_length != 0);
+ *
+ * Here is the inner loop of the function. The function will spend the
+ * majority of its time in this loop, and majority of that time will
+ * be spent in the first ten instructions.
+ *
+ * Within this loop:
+ * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
+ * %ecx = curmatch
+ * %edx = curmatch & wmask
+ * %esi = windowbestlen - i.e., (window + bestlen)
+ * %edi = prev
+ * %ebp = limit
+ *
+ * Two optimization notes on the choice of instructions:
+ *
+ * The first instruction uses a 16-bit address, which costs an extra,
+ * unpairable cycle. This is cheaper than doing a 32-bit access and
+ * zeroing the high word, due to the 3-cycle misalignment penalty which
+ * would occur half the time. This also turns out to be cheaper than
+ * doing two separate 8-bit accesses, as the memory is so rarely in the
+ * L1 cache.
+ *
+ * The window buffer, however, apparently spends a lot of time in the
+ * cache, and so it is faster to retrieve the word at the end of the
+ * match string with two 8-bit loads. The instructions that test the
+ * word at the beginning of the match string, however, are executed
+ * much less frequently, and there it was cheaper to use 16-bit
+ * instructions, which avoided the necessity of saving off and
+ * subsequently reloading one of the other registers.
+ */
+LookupLoop:
+							/* 1 U & V  */
+		movw	(%edi,%edx,2), %cx		/* 2 U pipe */
+		movl	wmask(%esp), %edx		/* 2 V pipe */
+		cmpl	%ebp, %ecx			/* 3 U pipe */
+		jbe	LeaveNow			/* 3 V pipe */
+		subl	$0x00010000, %ebx		/* 4 U pipe */
+		js	LeaveNow			/* 4 V pipe */
+LoopEntry:	movb	-1(%esi,%ecx), %al		/* 5 U pipe */
+		andl	%ecx, %edx			/* 5 V pipe */
+		cmpb	%bl, %al			/* 6 U pipe */
+		jnz	LookupLoop			/* 6 V pipe */
+		movb	(%esi,%ecx), %ah
+		cmpb	%bh, %ah
+		jnz	LookupLoop
+		movl	window(%esp), %eax
+		movw	(%eax,%ecx), %ax
+		cmpw	scanstart(%esp), %ax
+		jnz	LookupLoop
+
+/* Store the current value of chainlen.					*/
+
+		movl	%ebx, chainlenscanend(%esp)
+
+/* Point %edi to the string under scrutiny, and %esi to the string we	*/
+/* are hoping to match it up with. In actuality, %esi and %edi are	*/
+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is	*/
+/* initialized to -(MAX_MATCH_8 - scanalign).				*/
+
+		movl	window(%esp), %esi
+		movl	scan(%esp), %edi
+		addl	%ecx, %esi
+		movl	scanalign(%esp), %eax
+		movl	$(-MAX_MATCH_8), %edx
+		lea	MAX_MATCH_8(%edi,%eax), %edi
+		lea	MAX_MATCH_8(%esi,%eax), %esi
+
+/* Test the strings for equality, 8 bytes at a time. At the end,
+ * adjust %edx so that it is offset to the exact byte that mismatched.
+ *
+ * We already know at this point that the first three bytes of the
+ * strings match each other, and they can be safely passed over before
+ * starting the compare loop. So what this code does is skip over 0-3
+ * bytes, as much as necessary in order to dword-align the %edi
+ * pointer. (%esi will still be misaligned three times out of four.)
+ *
+ * It should be confessed that this loop usually does not represent
+ * much of the total running time. Replacing it with a more
+ * straightforward "rep cmpsb" would not drastically degrade
+ * performance.
+ */
+LoopCmps:
+		movl	(%e
