=== freeswan-ext-v0.6-1.94-BASE.diff ===
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/CHANGES.ipsec_ext freeswan-1.94.jjo/CHANGES.ipsec_ext
--- freeswan-1.94/CHANGES.ipsec_ext	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/CHANGES.ipsec_ext	Wed Dec 26 19:45:00 2001
@@ -0,0 +1,72 @@
+v0.6: "esp= support"
+ Changes from v0.5:
+	* KLIPS: _no_changes_
+	* PLUTO: esp= configurabilty
+	- added enum_search() to constants.c: returns value if strcmp()==0
+	  Used by parsing logic tricks to allow searching in enum_names
+	  arrays (thus avoiding yetanother duplication), eg:         
+	  	"3des"  -> "ESP_3DES"
+		"md5"   -> "AUTH_ALGORITHM_HMAC_MD5"
+	- added "esp" parsing to utils/auto, default=3des
+        - added msg.esp (string 7) to whack->pluto protocol 
+	- new file alg_info.c for esp algo parsing logic
+	  . build proposals with esp= ordered list only _ANDed_
+	    with registered (runtime kernel) ESP algos
+	  Eg: (assuming all these algos are loaded) in ipsec.conf
+	    connection section:
+	     <none> or esp=	# default: 3DES+{MD5,SHA1}
+	     esp=3des-sha1	# only this: 3DES+SHA1
+	     esp=aes,cast	# AES+{MD5,SHA1}, CAST+{MD5,SHA1}
+	- alg_info_test: test utility for esp algo parsing, eg:
+	      $ cd pluto
+	      $ make alg_info_test    
+	      $ ./alg_info_test  aes,cast,3des-sha1
+		(12 = "ESP_AES", 1 = "AUTH_ALGORITHM_HMAC_MD5")
+		(12 = "ESP_AES", 2 = "AUTH_ALGORITHM_HMAC_SHA1")
+		(6 = "ESP_CAST", 1 = "AUTH_ALGORITHM_HMAC_MD5")
+		(6 = "ESP_CAST", 2 = "AUTH_ALGORITHM_HMAC_SHA1")
+		(3 = "ESP_3DES", 2 = "AUTH_ALGORITHM_HMAC_SHA1")
+
+v0.5: "kidnapped CPU hero"
+ Changes from v0.4:
+  NOTE: you must _really_ clean the build area (*.o ) because some _MAX
+        values have changed.
+
+	* KLIPS
+	- Changed SADB_EALG_MAX from 12 to 256 (to accomodate ESP enc ids
+	  like ESP_SERPENT=252, ESP_TWOFISH=253)
+	- Added timing measurement tests (cipher "bandwidth"), eg:
+	   # modprobe ipsec_twofish test=1
+	   # dmesg | tail -9
+	   ipsec_twofish_init(enc_alg=253 name=twofish): ret=0
+	   klips_debug:ipsec_ext_test: enc_alg=253 blocksize=16 \
+	   		key_e_size=8892 keysize=16
+	   klips_debug:ipsec_ext_test: cbc_encrypt=1 ret=1024
+	   klips_debug:ipsec_ext_test: memcmp(enc, tmp) ret=1: OK.
+	   klips_debug:ipsec_ext_test: cbc_encrypt=0 ret=1024
+	   klips_debug:ipsec_ext_test: memcmp(dec,tmp) ret=0: OK.
+	   klips_debug:ipsec_ext_test: decrypt speed=25200 KB/s
+	   klips_debug:ipsec_ext_test: encrypt speed=28600 KB/s
+	   ipsec_twofish_init(enc_alg=253): test_ret=0
+
+	- Changed BLOWFISH to use asm versions if possible
+	- Added SERPENT, TWOFISH from
+		Dr Brian Gladman http://fp.gladman.plus.com/index.html
+		(nicely hacked to un-global-ize sources)
+	- Added CAST from 
+		OpenBSD sources ("public domain")
+		*tested Ok against OpenBSD 3.0*
+	- Added NULL from
+		me :)
+
+	* PLUTO
+	- (also touched by SADB_EALG_MAX changes) please _really_ clean
+	  lib/*.o pluto/*.o before recompiling
+	- esp_transform_name bumped to 256 entries (from about 12)
+	- first attr.key_len processing (be careful, may break)
+	  no negotiation, just use peers attr.key_len  if it's lower
+	  than maxkeybits
+	- patch from Nigel Metheringham to allow RH62/2.2.20 compilation
+
+v0.4: 
+	First release (should fill-in here :)
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/Makefile freeswan-1.94.jjo/Makefile
--- freeswan-1.94/Makefile	Wed Dec  5 15:35:01 2001
+++ freeswan-1.94.jjo/Makefile	Mon Dec 17 11:58:10 2001
@@ -52,6 +52,8 @@
 	ln -s `pwd`/klips/net/ipsec/Config.in $(KERNELKLIPS)
 	ln -s `pwd`/klips/net/ipsec/defconfig $(KERNELKLIPS)
 	ln -s `pwd`/klips/net/ipsec/*.[ch] $(KERNELKLIPS)
+	mkdir $(KERNELKLIPS)/ext
+	ln -s `pwd`/klips/net/ipsec/ext/* $(KERNELKLIPS)/ext
 	ln -s `pwd`/lib/Makefile.kernel $(KERNELKLIPS)/libfreeswan/Makefile
 	ln -s `pwd`/lib/*.[ch] $(KERNELKLIPS)/libfreeswan
 	ln -s `pwd`/libdes/Makefile $(KERNELKLIPS)/libdes
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/Config.in freeswan-1.94.jjo/klips/net/ipsec/Config.in
--- freeswan-1.94/klips/net/ipsec/Config.in	Thu Jun 14 16:35:07 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/Config.in	Tue Dec 18 11:41:00 2001
@@ -32,3 +32,10 @@
 bool '   IPSEC: IP Compression' CONFIG_IPSEC_IPCOMP
 
 bool '   IPSEC Debugging Option' CONFIG_IPSEC_DEBUG
+bool '   IPSEC Modular Extensions' CONFIG_IPSEC_EXT
+if [ "$CONFIG_IPSEC_EXT" != "n" ]; then
+	bool '     IPSEC Extensions Algorithms (eg. AES) ' CONFIG_IPSEC_EXT_ALG
+	if [ "$CONFIG_IPSEC_EXT_ALG" != "n" ]; then
+		source net/ipsec/ext/Config.in
+	fi
+fi
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/Makefile freeswan-1.94.jjo/klips/net/ipsec/Makefile
--- freeswan-1.94/klips/net/ipsec/Makefile	Tue Nov 27 02:28:07 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/Makefile	Thu Dec 13 14:18:57 2001
@@ -37,6 +37,11 @@
 export-objs := radij.o
 obj-m += $(O_TARGET)
 
+obj-$(CONFIG_IPSEC_EXT) +=ipsec_ext.o
+export-objs += ipsec_ext.o
+subdir-m += ext
+subdir-$(CONFIG_IPSEC_EXT_ALG)= ext
+
 # 'override CFLAGS' should really be 'EXTRA_CFLAGS'
 EXTRA_CFLAGS += -Ilibfreeswan -Ilibdes
 ifeq ($(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION),2.4.2-2)
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/defconfig freeswan-1.94.jjo/klips/net/ipsec/defconfig
--- freeswan-1.94/klips/net/ipsec/defconfig	Thu Nov 30 14:26:56 2000
+++ freeswan-1.94.jjo/klips/net/ipsec/defconfig	Thu Dec 13 13:15:16 2001
@@ -50,6 +50,14 @@
 # To enable userspace-switchable KLIPS debugging, say 'y'.
 CONFIG_IPSEC_DEBUG=y
 
+# modular extensions (and new ALGOs)
+CONFIG_IPSEC_EXT=y
+CONFIG_IPSEC_EXT_ALG=y
+CONFIG_IPSEC_ENC_AES=m
+CONFIG_IPSEC_ENC_BF=m
+CONFIG_IPSEC_ENC_TWOFISH=m
+CONFIG_IPSEC_ENC_SERPENT=m
+
 #
 #
 # $Log: defconfig,v $
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/ipsec_esp.h freeswan-1.94.jjo/klips/net/ipsec/ipsec_esp.h
--- freeswan-1.94/klips/net/ipsec/ipsec_esp.h	Tue Dec 11 20:22:06 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/ipsec_esp.h	Wed Dec 12 09:54:14 2001
@@ -31,6 +31,9 @@
 #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
@@ -150,6 +153,7 @@
 	int redo,
 	struct inet_protocol *protocol);
 
+/* XXX: only for 64 bits IVs, eg. ESP_3DES */
 struct esp
 {
 	__u32	esp_spi;		/* Security Parameters Index */
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/ipsec_ext.c freeswan-1.94.jjo/klips/net/ipsec/ipsec_ext.c
--- freeswan-1.94/klips/net/ipsec/ipsec_ext.c	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/klips/net/ipsec/ipsec_ext.c	Thu Dec 20 11:26:08 2001
@@ -0,0 +1,532 @@
+/*
+ * Modular extensions service and registration functions
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ * 
+ * Version: 1.4
+ *
+ * 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 <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_ext.h"
+#include "ipsec_sa.h"
+
+static rwlock_t ipsec_ext_lock = RW_LOCK_UNLOCKED;
+
+static struct ipsec_ext *ipsec_ext_w[SADB_EALG_MAX];
+#if SADB_EALG_MAX < 255
+#warning Compiling with limited ESP support ( SADB_EALG_MAX < 256 )
+#endif
+/* #define ipsec_ext_funcname(field) ipsec_ext_##field */
+#define IPSEC_EXT_FIELD(type, name) \
+type ipsec_ext_##name(int enc_alg) { \
+	type ret; \
+	struct ipsec_ext *ixt; \
+	if (enc_alg >= SADB_EALG_MAX) \
+		return -1; \
+	read_lock(&ipsec_ext_lock); \
+	ret=(ixt=ipsec_ext_w[enc_alg])? ixt->name : 0; \
+	read_unlock(&ipsec_ext_lock); \
+	return ret; \
+}
+IPSEC_EXT_FIELD(int, blocksize)
+IPSEC_EXT_FIELD(int, keyminbits)
+IPSEC_EXT_FIELD(int, keymaxbits)
+IPSEC_EXT_FIELD(int, key_e_size)
+
+/*
+ * 	Read-only kernel,user context -> no bh disabling 
+ */
+struct ipsec_ext *ipsec_ext_get(int enc_alg) {
+	struct ipsec_ext *ixt = NULL;
+	if (enc_alg >= SADB_EALG_MAX)
+		goto out;
+	read_lock(&ipsec_ext_lock);
+	ixt=ipsec_ext_w[enc_alg];
+	if (ixt==NULL) 
+		goto out;
+	atomic_inc(&ixt->refcnt);
+out:
+	read_unlock(&ipsec_ext_lock);
+	return ixt;
+}
+void ipsec_ext_put(struct ipsec_ext *ixt) {
+	atomic_dec(&ixt->refcnt);
+}
+/*
+ * iv = espp->esp_iv
+ */
+int ipsec_ext_esp_iv_get(const struct ipsec_sa *sa_p, const struct esp *espp, caddr_t iv_buf, int iv_buf_size) {
+	int iv_size=ipsec_ext_blocksize(sa_p->ips_encalg);
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_ext_esp_iv_get: "
+		    "encalg=%d iv_size=%d\n",
+		    sa_p->ips_encalg, iv_size);
+	if (iv_buf_size < iv_size) {
+		KLIPS_PRINT(debug_rcv||debug_tunnel,
+			"klips_debug:ipsec_ext_esp_iv_get: "
+			"encalg=%d: iv_size=%d > iv_buf_size=%d < ret=-1\n", 
+			sa_p->ips_encalg, iv_size, iv_buf_size);
+		return -1;
+	}
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		"klips_debug:ipsec_ext_esp_iv_get: "
+		"encalg=%d copying iv_size=%d iv_buf_size=%d bytes"
+		"from esp_iv=%p to iv_buf=%p\n", 
+			sa_p->ips_encalg, iv_size, iv_buf_size,
+			espp->esp_iv, iv_buf);
+	memcpy(iv_buf, espp->esp_iv, iv_size);
+	return iv_size;
+}
+/*
+ * iv,espp->esp_iv = sa_p->ips_iv
+ */
+int ipsec_ext_esp_iv_put(const struct ipsec_sa *sa_p, struct esp *espp, caddr_t iv_buf, int iv_buf_size) {
+	int iv_size=ipsec_ext_blocksize (sa_p->ips_encalg);
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_ext_esp_iv_put: "
+		    "encalg=%d iv_size=%d\n",
+		    sa_p->ips_encalg, iv_size);
+	if (iv_buf_size < iv_size) {
+		KLIPS_PRINT(debug_rcv||debug_tunnel,
+			"klips_debug:ipsec_ext_esp_iv_put: "
+			"encalg=%d: iv_size=%d > iv_buf_size=%d < ret=-1\n", 
+			sa_p->ips_encalg,iv_size, iv_buf_size);
+		return -1;
+	}
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		"klips_debug:ipsec_ext_esp_iv_put: "
+		"encalg=%d copying iv_size=%d bytes iv_buf_size=%d"
+		"from ips_iv=%p to iv_buf=%p,esp_iv=%p\n", 
+			sa_p->ips_encalg, iv_size, iv_buf_size,
+			sa_p->ips_iv, iv_buf, espp->esp_iv);
+	memcpy(iv_buf, sa_p->ips_iv , iv_size);
+	memcpy(espp->esp_iv, iv_buf , iv_size);
+	return iv_size;
+}
+/*
+ * update IV with the last octets of the encryption 
+ * sa_p->ips_iv = iv(from last payload bits)
+ */
+int ipsec_ext_esp_iv_update(struct ipsec_sa *sa_p, const struct esp *espp, const caddr_t idat, int ilen) {
+	int blocksize=ipsec_ext_blocksize (sa_p->ips_encalg);
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_ext_esp_iv_update: "
+		    "encalg=%d blocksize=%d\n",
+		    sa_p->ips_encalg, blocksize);
+	if (blocksize) {
+		caddr_t iv;
+		iv = idat + ilen - blocksize;
+		KLIPS_PRINT(debug_rcv||debug_tunnel,
+			"klips_debug:ipsec_ext_esp_iv_update: "
+			"encalg=%d updating blocksize=%d packet bytes"
+			"from iv=%p to ips_iv=%p\n", 
+			sa_p->ips_encalg, blocksize, iv, sa_p->ips_iv);
+		memcpy(sa_p->ips_iv, iv , blocksize);
+	}
+	return blocksize;
+}
+/* XXX: jjo check interface (ret values) */
+int ipsec_ext_esp_head(struct ipsec_sa *sa_p, int *block_size_p) {
+	int ret;
+	struct ipsec_ext *ixt;
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_ext_esp_head: "
+		    "entering with encalg=%d block_size_p=%p\n",
+		    sa_p->ips_encalg, block_size_p);
+	ixt=ipsec_ext_get(sa_p->ips_encalg);
+	if (!ixt) {
+		KLIPS_PRINT(debug_rcv||debug_tunnel,
+			    "klips_debug:ipsec_ext_esp_head: "
+			    "encalg=%d object not found\n",
+			    sa_p->ips_encalg);
+		return -1;
+	}
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_esp_head: "
+		    "found name=%s for encalg=%d, blocksize=%d\n",
+		    ixt->name, sa_p->ips_encalg, ixt->blocksize);
+	if (block_size_p) *block_size_p=ixt->blocksize;
+	ret=ixt->esphlen;
+	ipsec_ext_put(ixt);
+	return ret;
+}
+/* XXX: jjo check interface (ret values) */
+int ipsec_ext_esp_encrypt(struct ipsec_sa *sa_p, caddr_t in, caddr_t out, int ilen, caddr_t iv, int encrypt) {
+	int ret;
+	struct ipsec_ext *ixt=ipsec_ext_get(sa_p->ips_encalg);
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_ext_esp_encrypt: "
+		    "entering with encalg=%d\n",
+		    sa_p->ips_encalg);
+	if (!ixt) {
+		KLIPS_PRINT(debug_rcv||debug_tunnel,
+			    "klips_debug:ipsec_ext_esp_encrypt: "
+			    "encalg=%d object not found\n",
+			    sa_p->ips_encalg);
+		return -1;
+	}
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_ext_esp_encrypt: "
+		    "calling cbc_encrypt encalg=%d "
+		    "ips_key_e=%p in=%p out=%p ilen=%d iv=%p, encrypt=%d\n",
+			sa_p->ips_encalg, 
+			sa_p->ips_key_e, in, out, ilen, iv, encrypt);
+	ret=ixt->cbc_encrypt(sa_p->ips_key_e, in, out, ilen, iv, encrypt);
+	KLIPS_PRINT(debug_rcv||debug_tunnel,
+		    "klips_debug:ipsec_ext_esp_encrypt: "
+		    "returned ret=%d\n",
+		    ret);
+	ret=ixt->esphlen;
+	ipsec_ext_put(ixt);
+	return ret;
+}
+/* called from pfkey_v2_parser.c:pfkey_ips_init() */
+int ipsec_ext_key_create(struct ipsec_sa *sa_p) {
+	struct ipsec_ext *ixt;
+	int ret=-EINVAL;
+	int enc_alg, keyminbits, keymaxbits;
+	caddr_t ekp;
+
+	enc_alg= sa_p->ips_encalg;
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:ipsec_ext_key_create: "
+		    "entering with encalg=%d\n",
+		    enc_alg);
+	if ((ixt=ipsec_ext_get (enc_alg))==NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_ext_key_create: "
+			    "encalg=%d object not found\n",
+			    enc_alg);
+		return -EINVAL;
+	}
+	if (ixt->new_key) {
+		ret=ixt->new_key(sa_p);
+		goto ixt_out;
+	}
+	keyminbits=ixt->keyminbits;
+	keymaxbits=ixt->keymaxbits;
+	if(sa_p->ips_key_bits_e< keyminbits || sa_p->ips_key_bits_e > keymaxbits) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_ext_key_create: incorrect encryption"
+			    "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/,
+			    sa_p->ips_key_bits_e, keyminbits, keymaxbits);
+		ret=-EINVAL;
+		goto ixt_out;
+	}
+	/* save encryption key pointer */
+	ekp = sa_p->ips_key_e;
+
+	if((sa_p->ips_key_e = (caddr_t)
+	    kmalloc((sa_p->ips_key_e_size = ixt->key_e_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_ext_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->set_key((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:
+	ipsec_ext_put(ixt);
+	return ret;
+}
+/* called from pfkey_v2_parser.c:pfkey_ips_init() */
+int ipsec_ext_iv_create(struct ipsec_sa *sa_p) {
+	struct ipsec_ext *ixt;
+	int ret=-EINVAL;
+	int enc_alg, iv_size;
+
+	enc_alg= sa_p->ips_encalg;
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:ipsec_ext_iv_create: "
+		    "entering with encalg=%d\n",
+		    enc_alg);
+	if ((ixt=ipsec_ext_get (enc_alg))==NULL) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:ipsec_ext_iv_create: "
+			    "encalg=%d object not found\n",
+			    enc_alg);
+		return -EINVAL;
+	}
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:ipsec_ext_iv_create: "
+		    "found name=%s for encalg=%d\n",
+		    ixt->name, enc_alg);
+	iv_size=ixt->blocksize;
+	if((sa_p->ips_iv = (caddr_t)
+		kmalloc((sa_p->ips_iv_size = iv_size), GFP_ATOMIC)) == NULL) {
+		ret= -ENOMEM;
+		goto ixt_out;
+	}
+	get_random_bytes((void *)sa_p->ips_iv, iv_size);
+	sa_p->ips_iv_bits = sa_p->ips_iv_size * 8;
+	ret=0;
+ixt_out:
+	ipsec_ext_put(ixt);
+	return ret;
+}
+/*	Old gcc's will fail here 	*/
+#define barf_out(fmt, args...)  do { printk(KERN_ERR __FUNCTION__ ": (%s) " fmt, ixt->name , ## args)\
+	; goto out; } while(0)
+int register_ipsec_ext(struct ipsec_ext *ixt) {
+	int ret=-EINVAL;
+	static struct supported *supp=NULL;
+	/*	Validation 	*/
+	if (ixt==NULL)
+		barf_out("NULL ipsec_ext object passed\n");
+	if (ixt->enc_alg==0 || ixt->enc_alg > SADB_EALG_MAX)
+		barf_out("invalid enc_alg=%d >= %d\n", ixt->enc_alg, SADB_EALG_MAX);
+	if (ixt->blocksize==0 || ixt->blocksize%2)
+		barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->blocksize);
+	if (ixt->keyminbits==0 && ixt->keymaxbits==0 && ixt->keysize==0)
+		goto zero_key_ok;
+	if (ixt->keyminbits==0)
+		barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->keyminbits);
+	if (ixt->keymaxbits==0)
+		barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->keymaxbits);
+	if (ixt->keysize==0)
+		barf_out(KERN_ERR "invalid keysize=%d\n", ixt->keysize);
+zero_key_ok:
+	if (ixt->key_e_size==0)
+		barf_out(KERN_ERR "invalid key_e_size=%d\n", ixt->key_e_size);
+	if (ixt->new_key==NULL && ixt->set_key==NULL)
+		barf_out(KERN_ERR "new_key() or set_key() must be not NULL\n");
+	if (ixt->cbc_encrypt==NULL)
+		barf_out(KERN_ERR "cbc_encrypt() must be not NULL\n");
+
+	/*	Allocate and register support pointer 	*/
+	supp = kmalloc (sizeof (*supp), GFP_KERNEL);
+	if (!supp) {
+		ret=-ENOMEM;
+		barf_out(KERN_ERR "kmalloc (%d) failed", sizeof(*supp));
+	}
+	supp->supported_alg_exttype=SADB_EXT_SUPPORTED_ENCRYPT;
+	supp->supported_alg_id=ixt->enc_alg;
+	supp->supported_alg_ivlen=ixt->blocksize*8;
+	supp->supported_alg_minbits=ixt->keyminbits;
+	supp->supported_alg_maxbits=ixt->keymaxbits;
+
+	ret = pfkey_list_insert_supported(supp, &(pfkey_supported_list[SADB_SATYPE_ESP]));
+	if (ret!=0)
+		barf_out(KERN_ERR "pfkey_list_insert_supported returned %d\n", ret);
+	ixt->support_p=supp;
+
+	write_lock_bh(&ipsec_ext_lock);
+	ipsec_ext_w[ixt->enc_alg]=ixt;
+	write_unlock_bh(&ipsec_ext_lock);
+	/*	send register event to userspace	*/
+	pfkey_register_reply(SADB_SATYPE_ESP, NULL);
+	return 0;
+out:
+	if (supp) kfree(supp);
+	return ret;
+}
+int unregister_ipsec_ext(struct ipsec_ext *ixt) {
+	int ret= -EINVAL;
+	static struct supported *supp=NULL;
+	struct ipsec_ext **ixt_p;
+	write_lock_bh(&ipsec_ext_lock);
+	ixt_p=&ipsec_ext_w[ixt->enc_alg];
+	if (*ixt_p != ixt) 
+		barf_out("array element #%d doesn't point to me\n", ixt->enc_alg);
+	*ixt_p=NULL;
+	ret=0;
+out:
+	write_unlock_bh(&ipsec_ext_lock);
+	supp=ixt->support_p;
+	if (supp) {
+		pfkey_list_remove_supported(supp, &(pfkey_supported_list[SADB_SATYPE_ESP]));
+		kfree(supp);
+		/*	send register event to userspace	*/
+		pfkey_register_reply(SADB_SATYPE_ESP, NULL);
+	}
+	return ret;
+}
+/*
+ * 	Must be called from user context
+ */
+int ipsec_ext_test(int enc_alg, int test) {
+	int ret;
+	caddr_t buf;
+	int iv_size, keysize, key_e_size;
+	struct ipsec_ext *ixt;
+	#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_iv2   (test_iv+iv_size+MARGIN)
+	#define test_key   (test_iv2+iv_size+MARGIN)
+	#define test_size  (BUFSZ*3+key_e_size+iv_size*2+keysize+MARGIN*8)
+	ixt=ipsec_ext_get(enc_alg);
+	if (ixt==NULL) {
+		KLIPS_PRINT(1, 
+			    "klips_debug:ipsec_ext_test: "
+			    "encalg=%d object not found\n",
+			    enc_alg);
+		ret=-EINVAL;
+		goto out;
+	}
+	iv_size=ixt->blocksize;
+	key_e_size=ixt->key_e_size;
+	keysize=ixt->keysize;
+	KLIPS_PRINT(1, 
+		    "klips_debug:ipsec_ext_test: "
+		    "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);
+	memcpy(test_iv2, test_iv, iv_size);
+	ixt->set_key(test_key_e, test_key, keysize);
+	get_random_bytes(test_enc, BUFSZ);
+	memcpy(test_tmp, test_enc, BUFSZ);
+	ret=ixt->cbc_encrypt(test_key_e, test_enc, test_enc, BUFSZ, test_iv, 1);
+	printk(KERN_INFO
+		    "klips_info:ipsec_ext_test: "
+		    "cbc_encrypt=1 ret=%d\n", 
+		    	ret);
+	ret=memcmp(test_enc, test_tmp, BUFSZ);
+	printk(KERN_INFO
+		    "klips_info:ipsec_ext_test: "
+		    "memcmp(enc, tmp) ret=%d: %s\n", ret,
+			ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" );
+	memcpy(test_dec, test_enc, BUFSZ);
+	ret=ixt->cbc_encrypt(test_key_e, test_dec, test_dec, BUFSZ, test_iv2, 0);
+	printk(KERN_INFO
+		    "klips_info:ipsec_ext_test: "
+		    "cbc_encrypt=0 ret=%d\n", ret);
+	ret=memcmp(test_dec, test_tmp, BUFSZ);
+	printk(KERN_INFO
+		    "klips_info:ipsec_ext_test: "
+		    "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->cbc_encrypt(test_key_e, test_tmp, 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_ext_test: "
+				    "%s speed=%d KB/s\n", 
+				    encrypt? "encrypt": "decrypt", speed);
+		}
+	}
+	kfree(buf);
+out:
+	return ret;
+}
+int ipsec_ext_init(void) {
+	
+	KLIPS_PRINT(1, "klips_info:ipsec_ext_init: "
+			"KLIPS ext (SADB_EALG_MAX=%d)\n",
+			SADB_EALG_MAX);
+	write_lock_bh(&ipsec_ext_lock);
+	memset(ipsec_ext_w, 0, sizeof(ipsec_ext_w)); 
+	write_unlock_bh(&ipsec_ext_lock);
+	return 0;
+}
+
+/*
+ * 	As the author of this module, I ONLY ALLOW using it from
+ * 	GPL (or same LICENSE TERMS as kernel source) modules.
+ * 	--JJ
+ */
+
+/*	
+ *	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_ext);
+EXPORT_SYMBOL_GPL(unregister_ipsec_ext);
+EXPORT_SYMBOL_GPL(ipsec_ext_test);
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/ipsec_ext.h freeswan-1.94.jjo/klips/net/ipsec/ipsec_ext.h
--- freeswan-1.94/klips/net/ipsec/ipsec_ext.h	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/klips/net/ipsec/ipsec_ext.h	Fri Dec 14 12:37:11 2001
@@ -0,0 +1,120 @@
+/*
+ * Modular extensions service and registration functions interface
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * Version: 1.4
+ *
+ * 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_EXT_H
+#define IPSEC_EXT_H
+/*	
+ *	The following structs are used via pointers in ipsec_ext object to
+ *	avoid ipsec_ext.h coupling with freeswan headers, thus simplifying
+ *	module development
+ */
+struct ipsec_sa;
+struct esp;
+struct supported;
+/**************************************
+ *
+ *	Main registration object 
+ *
+ *************************************/
+struct ipsec_ext {
+	char name[16];		/* descriptive short name, eg. "3des" */
+	unsigned enc_alg;	/* enc. alg. number, eg. ESP_3DES */
+	unsigned blocksize;	/* blocksize in bytes for CBC, equals IV size */
+	unsigned esphlen;	/* ESP header len (depends on IV size) */
+	unsigned keyminbits;	/* min. keybits (of entropy) */
+	unsigned keymaxbits;	/* max. keybits (of entropy) */
+	unsigned keysize;	/* key size in bytes (storage) */
+	unsigned key_e_size;	/* sa_p->key_e_size */
+	struct supported *support_p;	/* support registration pointer */
+	atomic_t refcnt;
+	int (*new_key)(struct ipsec_sa *sa_p); /* if NULL will call set_key() */
+	int (*set_key)(caddr_t key_e, caddr_t key, int keysize);
+	int (*cbc_encrypt)(caddr_t key_e, caddr_t in, caddr_t out, int ilen, caddr_t iv, int encrypt);
+};
+/**************************************
+ *
+ * 	ipsec_ext modules interface
+ *
+ **************************************/
+/*	-  registration calls 	*/
+int register_ipsec_ext(struct ipsec_ext *);
+int unregister_ipsec_ext(struct ipsec_ext *);
+/*	-  optional (simple test) for algos 	*/
+int ipsec_ext_test(int enc_alg, int testparm);
+
+/************************************** 	
+ *
+ * 	ipsec_ext service functions
+ *
+ **************************************/
+/*
+ * ipsec_ext_get(): get ipsec_ext object by enc_alg number
+ * ipsec_ext_put(): decrease ipsec_ext object reference count
+ */
+
+struct ipsec_ext * ipsec_ext_get(int enc_alg);
+void ipsec_ext_put(struct ipsec_ext *);
+
+/* 
+ * ipsec_ext_esp_head(): returns esphlen or 0 if not found 
+ * 	(called from ipsec_tunnel.c and ipsec_rcv.c)
+ */
+int ipsec_ext_esp_head(struct ipsec_sa *sa_p, int *block_size_p);
+
+/* 
+ * ipsec_ext_esp_encrypt(): encrypt ilen bytes from in to out
+ * 	It locates ipsec_ext object by sa_p->ips_encalg
+ * 	returns <0 if not found 
+ */
+int ipsec_ext_esp_encrypt(struct ipsec_sa *sa_p, caddr_t in, caddr_t out, int ilen, caddr_t iv, int action);
+/************************************** 	
+ *
+ * 	IV operations
+ *
+ **************************************/
+/* 
+ * ipsec_ext_esp_iv_get(): get IV into iv pointer from espp payload
+ * 	iv = espp->esp_iv
+ */
+int ipsec_ext_esp_iv_get(const struct ipsec_sa *sa_p, const struct esp *espp, caddr_t iv, int iv_size);
+
+/*
+ * ipsec_ext_esp_iv_put(): put stored IV (sa_p) into iv buffer and espp payload
+ * 	iv,espp->esp_iv = sa_p->ips_iv
+ */
+int ipsec_ext_esp_iv_put(const struct ipsec_sa *sa_p, struct esp *espp, caddr_t iv, int iv_size);
+
+/*
+ * ipsec_ext_esp_iv_put(): update stored IV (sa_p) with last payload octets
+ * 	sa_p->ips_iv = iv
+ */
+int ipsec_ext_esp_iv_update(struct ipsec_sa *sa_p, const struct esp *espp, const caddr_t idat, int ilen);
+
+/*
+ * ipsec_ext_iv_create(): create IV (called from pfkey_v2_parser.c)
+ */
+int ipsec_ext_iv_create(struct ipsec_sa *sa_p);
+/* 
+ * ipsec_ext_key_create(): called from pfkey_v2_parser.c:pfkey_ips_init()
+ */
+int ipsec_ext_key_create(struct ipsec_sa *sa_p);
+
+/* only called from ipsec_init.c */
+int ipsec_ext_init(void);
+
+#endif /* IPSEC_EXT_H */
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/ipsec_init.c freeswan-1.94.jjo/klips/net/ipsec/ipsec_init.c
--- freeswan-1.94/klips/net/ipsec/ipsec_init.c	Mon Nov 26 06:23:48 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/ipsec_init.c	Thu Dec  6 09:45:32 2001
@@ -80,6 +80,7 @@
 #endif /* CONFIG_IPSEC_IPCOMP */
 
 #include "ipsec_proto.h"
+#include "ipsec_ext.h"
 
 #include <pfkeyv2.h>
 #include <pfkey.h>
@@ -154,6 +155,9 @@
 #ifdef CONFIG_SYSCTL
         error |= ipsec_sysctl_register();
 #endif                                                                          
+#ifdef CONFIG_IPSEC_EXT
+	ipsec_ext_init();
+#endif
 	return error;
 }	
 
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/ipsec_rcv.c freeswan-1.94.jjo/klips/net/ipsec/ipsec_rcv.c
--- freeswan-1.94/klips/net/ipsec/ipsec_rcv.c	Mon Nov 26 06:23:49 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/ipsec_rcv.c	Thu Dec  6 09:42:47 2001
@@ -81,6 +81,8 @@
 
 #include "ipsec_proto.h"
 
+#include "ipsec_ext.h"
+
 #ifdef CONFIG_IPSEC_DEBUG
 int debug_ah = 0;
 int debug_esp = 0;
@@ -197,7 +199,7 @@
 #ifdef CONFIG_IPSEC_ESP
 	struct esp *espp = NULL;
 	int esphlen = 0;
-	__u32 iv[2];
+	__u32 iv[ESP_IV_MAXSZ_INT];
 #endif /* !CONFIG_IPSEC_ESP */
 #ifdef CONFIG_IPSEC_AH
 	struct ah *ahp = NULL;
@@ -961,6 +963,17 @@
 				esphlen = sizeof(struct esp);
 				break;
 			default:
+#ifdef CONFIG_IPSEC_EXT
+				if ((esphlen = ipsec_ext_esp_head(tdbp, NULL)) > 0) {
+
+					KLIPS_PRINT(debug_rcv,
+						    "klips_debug:ipsec_rcv: "
+						    "encalg=%d returned esphlen=%d\n",
+						    tdbp->tdb_encalg, esphlen);
+					ipsec_ext_esp_iv_get(tdbp, espp, (caddr_t)iv, sizeof (iv));
+					break;
+				}
+#endif /* CONFIG_IPSEC_EXT */
 				tdbp->tdb_alg_errs += 1;
 				spin_unlock(&tdb_lock);
 				if(stats) {
@@ -993,6 +1006,19 @@
 						     ((struct des_eks *)(tdbp->tdb_key_e))[2].ks,
 						     (des_cblock *)iv, 0);
 				break;
+			default:
+#ifdef CONFIG_IPSEC_EXT
+				if (ipsec_ext_esp_encrypt(tdbp, idat, idat, ilen, (caddr_t)iv, 0) <= 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;
+				}
+#endif /* CONFIG_IPSEC_EXT */
 			}
 			next_header = idat[ilen - 1];
 			padlen = idat[ilen - 2];
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/ipsec_tunnel.c freeswan-1.94.jjo/klips/net/ipsec/ipsec_tunnel.c
--- freeswan-1.94/klips/net/ipsec/ipsec_tunnel.c	Wed Dec  5 06:36:10 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/ipsec_tunnel.c	Wed Dec 12 09:54:14 2001
@@ -58,6 +58,8 @@
 # include <linux/netfilter_ipv4.h>
 #endif /* NETDEV_23 */
 
+#include "ipsec_ext.h"
+
 #include <linux/if_arp.h>
 #ifdef MSS_HACK
 # include <net/tcp.h>		/* TCP options */
@@ -456,6 +458,10 @@
 /*	struct device *virtdev; */
 	short physmtu;
 	short mtudiff;
+#ifdef CONFIG_IPSEC_EXT
+	int esphlen;
+#endif
+	int blocksize = 8;
 #ifdef NET_21
 	struct rtable *rt = NULL;
 #endif /* NET_21 */
@@ -1076,6 +1082,16 @@
 					break;
 #endif /* CONFIG_IPSEC_ENC_3DES */
 				default:
+#ifdef CONFIG_IPSEC_EXT
+					if ((esphlen = ipsec_ext_esp_head(tdbp, &blocksize)) > 0) {
+						KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+						"klips_debug:ipsec_tunnel_start_xmit:"
+						"return from ipsec_ext_esp_head: headroom=%d, esphlen=%d\n",
+						headroom, esphlen);
+						headroom += esphlen;
+						break;
+					}
+#endif /* CONFIG_IPSEC_EXT */
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
 					goto cleanup;
@@ -1098,7 +1114,7 @@
 					stats->tx_errors++;
 					goto cleanup;
 				}			
-				tailroom += ((8 - ((pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2;
+				tailroom += ((blocksize - ((pyldsz + 2 * sizeof(unsigned char)) % blocksize)) % blocksize) + 2;
 				break;
 #endif /* !CONFIG_IPSEC_ESP */
 #ifdef CONFIG_IPSEC_IPIP
@@ -1314,7 +1330,7 @@
 		while (tdbp) {
 #ifdef CONFIG_IPSEC_ESP
 			struct esp *espp;
-			__u32 iv[2];
+			__u32 iv[ESP_IV_MAXSZ_INT];
 			unsigned char *idat, *pad;
 			int authlen = 0, padlen = 0, i;
 #endif /* !CONFIG_IPSEC_ESP */
@@ -1360,6 +1376,12 @@
 					break;
 #endif /* CONFIG_IPSEC_ENC_3DES */
 				default:
+#ifdef CONFIG_IPSEC_EXT
+					if ((esphlen = ipsec_ext_esp_head(tdbp, &blocksize)) > 0) {
+						headroom += esphlen;
+						break;
+					}
+#endif /* CONFIG_IPSEC_EXT */
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
 					goto cleanup;
@@ -1382,7 +1404,7 @@
 					stats->tx_errors++;
 					goto cleanup;
 				}		
-				tailroom += ((8 - ((pyldsz + 2 * sizeof(unsigned char)) % 8)) % 8) + 2;
+				tailroom += ((blocksize - ((pyldsz + 2 * sizeof(unsigned char)) % blocksize)) % blocksize) + 2;
 				tailroom += authlen;
 				break;
 #endif /* !CONFIG_IPSEC_ESP */
@@ -1462,6 +1484,10 @@
 					break;
 #endif /* defined(CONFIG_IPSEC_ENC_3DES) */
 				default:
+#ifdef CONFIG_IPSEC_EXT
+					if (ipsec_ext_esp_iv_put(tdbp, espp, (caddr_t)iv, sizeof (iv)) > 0)
+						break;
+#endif /* CONFIG_IPSEC_EXT */
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
 					goto cleanup;
@@ -1494,6 +1520,10 @@
 					break;
 #endif /* CONFIG_IPSEC_ENC_3DES */
 				default:
+#ifdef CONFIG_IPSEC_EXT
+					if ((ipsec_ext_esp_encrypt(tdbp, idat, idat, ilen, (caddr_t)iv, 1 )) >0) 
+							break;
+#endif /* CONFIG_IPSEC_EXT */
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
 					goto cleanup;
@@ -1512,6 +1542,11 @@
 					break;
 #endif /* defined(CONFIG_IPSEC_ENC_3DES) */
 				default:
+					/* update IV with the last octets of the encryption */
+#ifdef CONFIG_IPSEC_EXT
+					if (ipsec_ext_esp_iv_update(tdbp, espp, idat, ilen) >= 0)
+						break;
+#endif /* CONFIG_IPSEC_EXT */
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
 					goto cleanup;
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/ipsec_xform.h freeswan-1.94.jjo/klips/net/ipsec/ipsec_xform.h
--- freeswan-1.94/klips/net/ipsec/ipsec_xform.h	Mon Nov 26 06:23:51 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/ipsec_xform.h	Tue Dec 18 11:36:00 2001
@@ -58,7 +58,14 @@
 #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
@@ -87,6 +94,23 @@
 		 "_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 == 248 ? "_ID248" : \
+ 	(x)->ips_encalg == 251 ? "_ID251" : \
+ 	(x)->ips_encalg == 254 ? "_ID254" : \
+ 	(x)->ips_encalg == 255 ? "_ID255" : \
+ 	(x)->ips_encalg == 256 ? "_ID256" : \
 	"_UNKNOWN_encr", \
 	(x)->ips_authalg == AH_NONE ? "" : \
 	(x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/klips/net/ipsec/pfkey_v2_parser.c freeswan-1.94.jjo/klips/net/ipsec/pfkey_v2_parser.c
--- freeswan-1.94/klips/net/ipsec/pfkey_v2_parser.c	Mon Nov 26 06:23:52 2001
+++ freeswan-1.94.jjo/klips/net/ipsec/pfkey_v2_parser.c	Thu Dec  6 09:42:47 2001
@@ -85,6 +85,7 @@
 
 #include "ipsec_proto.h"
 
+#include "ipsec_ext.h"
 
 #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
 
@@ -1006,9 +1007,15 @@
 			tdbp->tdb_iv_bits = tdbp->tdb_iv_size * 8;
 			break;
 # endif /* defined(CONFIG_IPSEC_ENC_3DES) */
-		case ESP_NONE:
+                case ESP_NONE:
 			break;
 		default:
+#ifdef CONFIG_IPSEC_EXT
+			if ((error=ipsec_ext_iv_create(tdbp)) >=0)
+				break;
+			else	
+				SENDERR(-error);
+#endif
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_ipsec_sa_init: "
 				    "encalg=%d support not available in the kernel",
@@ -1072,9 +1079,15 @@
 			kfree(ekp);
 			break;
 # endif /* CONFIG_IPSEC_ENC_3DES */
-		case ESP_NONE:
+                case ESP_NONE:
 			break;
 		default:
+#ifdef CONFIG_IPSEC_EXT
+			if ((error=ipsec_ext_key_create(tdbp)) >=0)
+				break;
+			else
+				SENDERR(-error);
+#endif
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_ipsec_sa_init: "
 				    "encalg=%d support not available in the kernel",
@@ -2242,20 +2255,12 @@
 DEBUG_NO_STATIC int
 pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
 {
-	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;
-	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
-	struct sadb_msg *pfkey_reply = NULL;
-	struct supported_list *pfkey_supported_listp;
-	struct socket_list *pfkey_socketsp;
 	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");
 
-	pfkey_extensions_init(extensions_reply);
-
 	/* 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)) {
@@ -2277,36 +2282,68 @@
 	};
 	
 	/* send up register msg with supported SATYPE algos */
+
+	error=pfkey_register_reply(satype, (struct sadb_msg*)extensions[SADB_EXT_RESERVED]);
+ errlab:
+	return error;
+}
+DEBUG_NO_STATIC 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_parse: "
+		    "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_parse: "
+			    "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_parse: "
+				    "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_parse: "
+				    "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_parse: "
+				    "klips_debug:pfkey_register_reply: "
 				    "auth alg memory allocation error\n");
 			SENDERR(ENOMEM);
 		}
@@ -2316,7 +2353,7 @@
 	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_parse: "
+				    "klips_debug:pfkey_register_reply: "
 				    "enc alg memory allocation error\n");
 			SENDERR(ENOMEM);
 		}
@@ -2333,7 +2370,7 @@
 				alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits;
 				alg_ap->sadb_alg_reserved = 0;
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_register_parse: "
+					    "klips_debug:pfkey_register_reply: "
 					    "adding auth=%p\n",
 					    alg_ap);
 				alg_ap++;
@@ -2347,14 +2384,14 @@
 				alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->supported_alg_maxbits;
 				alg_ep->sadb_alg_reserved = 0;
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_register_parse: "
+					    "klips_debug:pfkey_register_reply: "
 					    "adding encrypt=%p\n",
 					    alg_ep);
 				alg_ep++;
 			}
 		}
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_register_parse: "
+			    "klips_debug:pfkey_register_reply: "
 			    "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n",
 			    satype,
 			    satype2name(satype),
@@ -2365,13 +2402,12 @@
 			    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,
-							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
-							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
+							  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,
@@ -2383,30 +2419,31 @@
 									alg_num_e,
 									alg_e),
 					  extensions_reply) : 1))) {
-		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: "
-			    "failed to build the register message extensions\n");
+		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_parse: "
+		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_parse: "
-				    "sending up register reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+			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_parse: "
-			    "sending up register reply message for satype=%d(%s) to socket=%p succeeded.\n",
+		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);
@@ -2419,7 +2456,6 @@
 	if(alg_e) {
 		kfree(alg_e);
 	}
-
 	if (pfkey_reply) {
 		pfkey_msg_free(&pfkey_reply);
 	}
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/lib/cbc_generic.h freeswan-1.94.jjo/lib/cbc_generic.h
--- freeswan-1.94/lib/cbc_generic.h	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/lib/cbc_generic.h	Tue Dec 18 09:36:22 2001
@@ -0,0 +1,91 @@
+/*
+ * 	Heavily inspired in loop_AES
+ */
+#include <linux/types.h>
+#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \
+int name(ctx_type *ctx, unsigned char * in, unsigned char * out, int ilen, unsigned char * iv, int encrypt) { \
+	int ret=ilen, pos; \
+	u_int32_t *iv_i; \
+	if ((ilen) % 16) return 0; \
+	if (encrypt) { \
+		pos=0; \
+		while(pos<ilen) { \
+			if (pos==0) \
+				iv_i=(u_int32_t*) iv; \
+			else \
+				iv_i=(u_int32_t*) (out-16); \
+			*((u_int32_t *)(&out[ 0])) = iv_i[0]^*((u_int32_t *)(&in[ 0])); \
+			*((u_int32_t *)(&out[ 4])) = iv_i[1]^*((u_int32_t *)(&in[ 4])); \
+			*((u_int32_t *)(&out[ 8])) = iv_i[2]^*((u_int32_t *)(&in[ 8])); \
+			*((u_int32_t *)(&out[12])) = iv_i[3]^*((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, (addr_type) in, (addr_type) out); \
+			if (pos==0) \
+				iv_i=(u_int32_t*) (iv); \
+			else \
+				iv_i=(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, unsigned char * in, unsigned char * out, int ilen, unsigned char * iv, int encrypt) { \
+	int ret=ilen, pos; \
+	u_int32_t *iv_i; \
+	if ((ilen) % 8) return 0; \
+	if (encrypt) { \
+		pos=0; \
+		while(pos<ilen) { \
+			if (pos==0) \
+				iv_i=(u_int32_t*) iv; \
+			else \
+				iv_i=(u_int32_t*) (out-8); \
+			*((u_int32_t *)(&out[ 0])) = iv_i[0]^*((u_int32_t *)(&in[ 0])); \
+			*((u_int32_t *)(&out[ 4])) = iv_i[1]^*((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, (addr_type)in, (addr_type)out); \
+			if (pos==0) \
+				iv_i=(u_int32_t*) (iv); \
+			else \
+				iv_i=(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, unsigned char * in, unsigned char * out, int ilen, unsigned char * iv, int encrypt)
+/*
+Eg.:
+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, caddr_t, aes_encrypt, aes_decrypt);
+CBC_DECL(AES_cbc_encrypt, aes_context);
+*/
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/lib/pfkey.h freeswan-1.94.jjo/lib/pfkey.h
--- freeswan-1.94/lib/pfkey.h	Tue Nov 27 02:27:47 2001
+++ freeswan-1.94.jjo/lib/pfkey.h	Thu Dec  6 09:43:50 2001
@@ -75,6 +75,7 @@
 	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 *);
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/lib/pfkeyv2.h freeswan-1.94.jjo/lib/pfkeyv2.h
--- freeswan-1.94/lib/pfkeyv2.h	Tue Nov  6 16:47:47 2001
+++ freeswan-1.94.jjo/lib/pfkeyv2.h	Wed Dec 12 13:08:54 2001
@@ -257,8 +257,10 @@
 #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_MAX         11
+#define SADB_EALG_AESCBC      12
+#define SADB_EALG_MAX         255
 
 #define SADB_X_CALG_NONE          0
 #define SADB_X_CALG_OUI           1
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/Makefile freeswan-1.94.jjo/pluto/Makefile
--- freeswan-1.94/pluto/Makefile	Tue Nov 27 13:33:42 2001
+++ freeswan-1.94.jjo/pluto/Makefile	Wed Dec 26 16:41:40 2001
@@ -117,6 +117,8 @@
 	id.c id.h \
 	ipsec_doi.c ipsec_doi.h \
 	kernel.c kernel.h \
+	kernel_alg.c kernel_alg.h \
+	alg_info.c alg_info.h \
 	kernel_comm.c kernel_comm.h \
 	log.c log.h \
 	main.c \
@@ -139,15 +141,22 @@
 # OBJSGCRYPT =  gcryptfix.o dsa.o elgamal.o primegen.o smallprime.o
 OBJSGCRYPT =
 
+
 OBJSPLUTO = connections.o constants.o cookie.o crypto.o defs.o log.o \
 	state.o main.o server.o timer.o id.o ipsec_doi.o kernel.o \
+	kernel_alg.o alg_info.o \
 	kernel_comm.o demux.o packet.o preshared.o dnskey.o rnd.o spdb.o \
 	sha1.o md5.o $(OBJSGCRYPT) $(LIBDESLITE) $(FREESWANLIB)
+	
 
 OBJSWHACK = whack.o $(FREESWANLIB)
 
 all: $(BINNAMEPLUTO) $(BINNAMEWHACK)
 
+
+alg_info_test: alg_info_test.o alg_info.o constants.o defs.o log.o $(FREESWANLIB)
+	$(CC) -o $@ $^ $(LIBSPLUTO) 
+
 install: all
 	$(INSTALL) $(INSTBINFLAGS) $(BINNAMEPLUTO) $(BINNAMEWHACK) $(BINDIR)
 	$(INSTALL) $(INSTMANFLAGS) pluto.8 $(PMANDIR)/ipsec_pluto.8
@@ -215,7 +224,7 @@
 		sed -e 's/\.c:#[ 	]*include[ 	]*"/.o: /' -e 's/".*//'
 
 # Dependencies generated by "make gatherdeps":
-
+alg_info.o: alg_info.c
 connections.o: connections.c
 constants.o: constants.c
 cookie.o: cookie.c
@@ -228,6 +237,7 @@
 gcryptfix.o: gcryptfix.c
 id.o: id.c
 ipsec_doi.o: ipsec_doi.c
+kernel_alg.o: kernel_alg.c
 kernel.o: kernel.c
 kernel_comm.o: kernel_comm.c
 log.o: log.c
@@ -245,6 +255,9 @@
 timer.o: timer.c
 whack.o: whack.c
 
+alg_info.o: alg_info.h
+alg_info.o: constants.h
+alg_info.o: defs.h
 connections.o: constants.h
 connections.o: defs.h
 connections.o: id.h
@@ -260,6 +273,7 @@
 connections.o: preshared.h
 connections.o: dnskey.h
 connections.o: whack.h
+connections.o: alg_info.h
 constants.o: constants.h
 constants.o: defs.h
 constants.o: packet.h
@@ -347,6 +361,16 @@
 ipsec_doi.o: sha1.h
 ipsec_doi.o: md5.h
 ipsec_doi.o: crypto.h
+ipsec_doi.o: kernel_alg.h
+kernel_alg.o: constants.h
+kernel_alg.o: defs.h
+kernel_alg.o: state.h
+kernel_alg.o: packet.h
+kernel_alg.o: spdb.h
+kernel_alg.o: kernel.h
+kernel_alg.o: kernel_alg.h
+kernel_alg.o: alg_info.h
+kernel_alg.o: log.h
 kernel.o: constants.h
 kernel.o: defs.h
 kernel.o: rnd.h
@@ -358,6 +382,8 @@
 kernel.o: log.h
 kernel.o: server.h
 kernel.o: whack.h
+kernel.o: alg_info.h
+kernel.o: kernel_alg.h
 kernel_comm.o: constants.h
 kernel_comm.o: defs.h
 kernel_comm.o: id.h
@@ -454,6 +480,8 @@
 spdb.o: sha1.h
 spdb.o: md5.h
 spdb.o: crypto.h
+spdb.o: kernel_alg.h
+spdb.o: alg_info.h
 state.o: constants.h
 state.o: defs.h
 state.o: id.h
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/alg_info.c freeswan-1.94.jjo/pluto/alg_info.c
--- freeswan-1.94/pluto/alg_info.c	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/pluto/alg_info.c	Wed Dec 26 15:48:06 2001
@@ -0,0 +1,208 @@
+/*
+ * Algorithm info parsing and creation functions
+ * 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.
+ */
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <freeswan.h>
+
+#include "alg_info.h"
+#include "constants.h"
+#include "defs.h"
+
+/*
+ * 	Search enum_name array with in prefixed uppercase
+ */
+static int
+enum_search_prefix (enum_names *ed, const char *prefix, const char *str, int strlen)
+{
+	char buf[64];
+	char *ptr;
+	int ret;
+	int len=sizeof(buf)-1;	/* reserve space for final \0 */
+	for (ptr=buf; *prefix; *ptr++=*prefix++, len--);
+	while (strlen--&&len--&&*str) *ptr++=toupper(*str++);
+	*ptr=0;
+	/* printf("enum_search(ed, %s)\n", buf); */
+	ret=enum_search(ed, buf);
+	return ret;
+}
+/*
+ * 	Search esp_transformid_names for a match, eg:
+ * 		"3des" <=> "ESP_3DES"
+ */
+static int
+esp_ealg_getbyname(const char *const str, int len)
+{
+	int ret=-1;
+	if (!str||!*str)
+		goto out;
+	ret=enum_search_prefix(&esp_transformid_names, "ESP_", str, len);
+out:
+	return ret;
+}
+/*
+ * 	Search auth_alg_names for a match, eg:
+ * 		"md5" <=> "AUTH_ALGORITHM_HMAC_MD5"
+ */
+static int
+esp_aalg_getbyname(const char *const str, int len)
+{
+	int ret=-1;
+	if (!str||!*str)
+		goto out;
+	ret=enum_search_prefix(&auth_alg_names, "AUTH_ALGORITHM_HMAC_", str, len);
+out:
+	return ret;
+}
+void alg_info_free(struct alg_info *alg_info) {
+	pfreeany(alg_info);
+}
+/*	
+ *	Raw add routine: only checks for no duplicates		
+ */
+static void
+__alg_info_esp_add (struct alg_info *alg_info, int ealg_id, int aalg_id)
+{
+	struct alg_info_esp *ai_e=alg_info->alg_info_esp;
+	unsigned cnt=alg_info->alg_info_cnt, i;
+	/* 	check for overflows 	*/
+	passert(cnt < elemsof(alg_info->alg_info_esp));
+	/*	dont add duplicates	*/
+	for (i=0;i<cnt;i++) 
+		if (	ai_e[i].esp_ealg_id==ealg_id &&
+			ai_e[i].esp_aalg_id==aalg_id)
+			return;
+	ai_e[cnt].esp_ealg_id=ealg_id;
+	ai_e[cnt].esp_aalg_id=aalg_id;
+	alg_info->alg_info_cnt++;
+	/* fprintf(stderr, "ealg=%d aalg=%d cnt=%d\n ", ealg_id, aalg_id, alg_info->alg_info_cnt); */
+} 
+
+/*	
+ *	Add ESP alg info _with_ logic (policy):
+ */
+static void
+alg_info_esp_add (struct alg_info *alg_info, int ealg_id, int aalg_id)
+{
+	/*	Policy: default to 3DES */
+	if (ealg_id==0)
+		ealg_id=ESP_3DES;
+	if (ealg_id>0) {
+		if (aalg_id>0) 
+			__alg_info_esp_add(alg_info, ealg_id, aalg_id);
+		else {
+			/*	Policy: default to MD5 and SHA1 */
+			__alg_info_esp_add(alg_info, ealg_id,\
+					AUTH_ALGORITHM_HMAC_MD5);
+			__alg_info_esp_add(alg_info, ealg_id,\
+					AUTH_ALGORITHM_HMAC_SHA1);
+		}
+	}
+}
+/*	
+ *	Creates a new alg_info by parsing passed string		
+ */
+struct alg_info *
+alg_info_create_from_str (const char *alg_str)
+{
+	struct alg_info *alg_info;
+	const char *ptr;	/* "current" esp id ptr */
+	const char *nptr;	/* next ESP id ptr, eg: after a comma */
+	const char *aptr;	/* auth string ptr */
+	int ealg_id, aalg_id;	/* enc,auth algos ids */
+	int len;		/* "current" remaining lenght */
+	int elen, alen;		/* enc,auth length */ 
+	/*
+	 * 	alg_info storage should be sized dynamically
+	 * 	but this may require 2passes to know 
+	 * 	transform count in advance.
+	 */
+	alg_info=alloc_thing (struct alg_info, "alg_info");
+	for (ptr=alg_str ; ptr&&*ptr ; ptr=nptr? nptr+1 : 0) {
+		while(*ptr==' ') ptr++;
+		if (!*ptr) break;
+		/* next transform delimiter: ',' */
+		nptr=strchr(ptr, ',');
+		len = nptr? nptr-ptr : (int) strlen(ptr);
+
+		/* auth alg delimiter: '-' */
+		aptr=strchr(ptr, '-');
+		if (aptr && (aptr-ptr)>len) aptr=NULL;
+		elen= aptr? aptr-ptr : len;
+
+		/*
+		fprintf(stderr, "ptr=%s len=%d, aptr=%s, elen=%d\n", ptr, len,
+				aptr, elen);
+		*/
+		/* no more to parse ... */
+		if (!len) break;	
+		ealg_id=esp_ealg_getbyname(ptr, elen);
+		if (ealg_id < 0)
+			continue;
+		/* mark aalg as not found (yet) */
+		aalg_id=0;
+		if (aptr) {
+			/*	parse keybits specs: ignored for now */
+			const char *kptr;
+
+			/* skip first '-' */
+			alen = len-elen-1;
+			aptr++;
+			
+			/* search for '-' keybits start */
+			kptr=strchr(aptr, '-');
+			if (kptr && (kptr-aptr)< alen)
+				alen=kptr-aptr;
+			aalg_id=esp_aalg_getbyname(aptr, alen);
+		}
+		/*	
+		 *	if aalg found or none(0) specified => add  
+		 * 	search in  alg_info_esp_add() for "Policy" 
+		 */
+		if (aalg_id >= 0)
+			alg_info_esp_add(alg_info, ealg_id, aalg_id);
+	}
+	/* if didn't find any, call for defaults,
+	 * search in  alg_info_esp_add() for "Policy" 
+	 */
+	if (alg_info->alg_info_cnt==0)
+		alg_info_esp_add(alg_info, 0, 0);
+	return alg_info;
+}
+
+int 
+alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
+{
+	char *ptr=buf;
+	int ret;
+	struct alg_info_esp *ai_e;
+	int cnt;
+	ptr+=sprintf(buf, "ealg, aalg = ");
+	ALG_INFO_FOREACH(alg_info, ai_e, cnt) {
+		ret=snprintf(ptr, buflen, "(%d, %d) ", 
+				ai_e->esp_ealg_id, ai_e->esp_aalg_id);
+		ptr+=ret;
+		buflen-=ret;
+	}
+	return buflen;
+}
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/alg_info.h freeswan-1.94.jjo/pluto/alg_info.h
--- freeswan-1.94/pluto/alg_info.h	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/pluto/alg_info.h	Wed Dec 26 15:51:57 2001
@@ -0,0 +1,46 @@
+/*
+ * Algorithm info parsing and creation functions
+ * 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 ALG_INFO_H
+#define ALG_INFO_H
+/*
+struct alg_info_esp {
+	int esp_ealg_id;
+	int esp_aalg_id;
+};
+*/
+struct esp_info {
+	u_int8_t transid;	/* ESP transform */
+	u_int16_t auth;		/* AUTH */
+	size_t enckeylen;	/* keylength for ESP transform */
+	size_t authkeylen;	/* keylength for AUTH */
+	u_int8_t encryptalg;	/* normally  encryptalg=transid */
+	u_int8_t authalg;	/* normally  authalg=auth+1 */
+};
+#define alg_info_esp esp_info
+struct alg_info  {
+	int alg_info_cnt;
+	struct alg_info_esp alg_info_esp[64];	/* static for now */
+};
+#define esp_ealg_id transid
+#define esp_aalg_id auth
+#define esp_ealg_keylen enckeylen	/* bits */
+#define esp_aalg_keylen authkeylen	/* bits */
+void alg_info_free(struct alg_info *alg_info);
+struct alg_info *alg_info_create_from_str(const char *alg_str);
+int alg_info_parse(const char *str);
+int alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info);
+#define ALG_INFO_FOREACH(ai, ai_e, i) \
+	for (i=ai->alg_info_cnt,ai_e=ai->alg_info_esp; i--; ai_e++) 
+#endif /* ALG_INFO_H */
Binary files freeswan-1.94/pluto/alg_info_test and freeswan-1.94.jjo/pluto/alg_info_test differ
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/alg_info_test.c freeswan-1.94.jjo/pluto/alg_info_test.c
--- freeswan-1.94/pluto/alg_info_test.c	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/pluto/alg_info_test.c	Wed Dec 26 16:38:44 2001
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <freeswan.h>
+#include "alg_info.h"
+#include "constants.h"
+#include "defs.h"
+#define STR_EXAMPLE "3des, cast-sha1,  3des-md5-96,aes-md5-96,cast "
+int main(int argc, char *argv[]) {
+	char *str=argv[1];
+	int i;
+	struct alg_info *ai;
+	struct alg_info_esp *ai_e;
+	if (argc<2) {
+		fprintf(stderr,"Must pass algo string, eg: \""
+				STR_EXAMPLE "\"\n");
+		return 1;
+	}
+	ai=alg_info_create_from_str(str);
+	ALG_INFO_FOREACH(ai, ai_e, i) {
+		printf("(%d = \"%s\", ", 
+				ai_e->esp_ealg_id, 
+				enum_name(&esp_transformid_names, ai_e->esp_ealg_id));
+		printf("%d = \"%s\")\n", 
+				ai_e->esp_aalg_id,
+				enum_name(&auth_alg_names, ai_e->esp_aalg_id));
+	}
+	alg_info_free(ai);
+	return 0;
+}
+/* Fake to allow build */
+void exit_pluto(int);
+void exit_pluto(int st) {
+    exit(st);
+}
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/connections.c freeswan-1.94.jjo/pluto/connections.c
--- freeswan-1.94/pluto/connections.c	Thu Dec  6 14:25:07 2001
+++ freeswan-1.94.jjo/pluto/connections.c	Wed Dec 26 17:30:52 2001
@@ -42,6 +42,7 @@
 #include "preshared.h"
 #include "dnskey.h"	/* needs preshared.h */
 #include "whack.h"
+#include "alg_info.h"
 
 static void flush_pending_by_connection(struct connection *c);	/* forward */
 
@@ -288,6 +289,7 @@
     free_id_content(&c->that.id);
     pfreeany(c->that.updown);
     gw_delref(&c->gw_info);
+    alg_info_free(c->alg_info);
     pfree(c);
 }
 
@@ -628,6 +630,12 @@
 	    loglog(RC_COMMENT
 		, "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP"
 		, c->name);
+
+	if (wm->esp) {
+		struct alg_info *ai=alg_info_create_from_str(wm->esp);
+		DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: NULL);
+		c->alg_info=ai;
+	}
 
 	c->sa_ike_life_seconds = wm->sa_ike_life_seconds;
 	c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds;
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/connections.h freeswan-1.94.jjo/pluto/connections.h
--- freeswan-1.94/pluto/connections.h	Mon Nov 26 06:31:22 2001
+++ freeswan-1.94.jjo/pluto/connections.h	Fri Dec 21 02:45:16 2001
@@ -132,6 +132,7 @@
     sa_family_t tunnel_addr_family;	/* between clients */
 
     struct gw_info *gw_info;
+    struct alg_info *alg_info;
 
     struct host_pair *host_pair;
     struct connection *hp_next;	/* host pair list link */
@@ -191,6 +192,7 @@
  * is looking through state objects.
  */
 struct gw_info;	/* forward declaration of tag (defined in dnskey.h) */
+struct alg_info;	/* forward declaration of tag (defined in alg_info.h) */
 extern struct connection
     *rw_instantiate(const struct connection *c, const ip_address *him
 	, const struct id *his_id),
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/constants.c freeswan-1.94.jjo/pluto/constants.c
--- freeswan-1.94/pluto/constants.c	Wed Nov 28 02:59:50 2001
+++ freeswan-1.94.jjo/pluto/constants.c	Wed Dec 26 17:27:39 2001
@@ -275,11 +275,24 @@
 	"ESP_DES_IV32",
 	"ESP_RC4",
 	"ESP_NULL",
-	"ESP_AES",
+	"ESP_AES"
+};
+
+/*
+ * ipsec drafts suggest "high" ESP ids values for testing,
+ * assign generic ESP_ID<num> if not officially defined 
+ */
+static const char *const esp_transform_name_high[] = {
+	/* id=248 */	"ESP_ID248","ESP_MARS","ESP_RC6","ESP_ID251",
+	/* id=252 */	"ESP_SERPENT", "ESP_TWOFISH", "ESP_ID254", "ESP_ID255",
+	/* id=256 */	"ESP_ID256"
     };
 
+enum_names esp_transformid_names_high =
+    { 248, 256, esp_transform_name_high, NULL };
+
 enum_names esp_transformid_names =
-    { ESP_DES_IV64, ESP_AES, esp_transform_name, NULL };
+    { ESP_DES_IV64, ESP_AES, esp_transform_name, &esp_transformid_names_high };
 
 /* IPCOMP transform values */
 
@@ -789,6 +802,23 @@
     return p;
 }
 
+int 
+enum_search(enum_names *ed, const char *str) 
+{
+    enum_names	*p;
+    const char *ptr;
+    unsigned en;
+
+    for (p = ed; p != NULL; p = p->en_next_range)
+	for (en=p->en_first;en<=p->en_last;en++) {
+	    ptr=p->en_names[en - p->en_first];
+	    if (ptr==0) continue;
+	    /* if (strncmp(ptr, str, strlen(ptr))==0) */
+	    if (strcmp(ptr, str)==0)
+		    return en;
+	}
+    return -1;
+}
 /* construct a string to name the bits on in a set
  * Result may be in STATIC buffer!
  */
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/constants.h freeswan-1.94.jjo/pluto/constants.h
--- freeswan-1.94/pluto/constants.h	Wed Nov 28 02:59:50 2001
+++ freeswan-1.94.jjo/pluto/constants.h	Fri Dec 21 02:45:16 2001
@@ -76,6 +76,7 @@
 
 extern const char *enum_name(enum_names *ed, unsigned long val);
 extern const char *enum_show(enum_names *ed, unsigned long val);
+extern int enum_search(enum_names *ed, const char *string);
 
 extern bool testset(const char *const table[], lset_t val);
 extern const char *bitnamesof(const char *const table[], lset_t val);
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/ipsec_doi.c freeswan-1.94.jjo/pluto/ipsec_doi.c
--- freeswan-1.94/pluto/ipsec_doi.c	Thu Nov 29 02:13:49 2001
+++ freeswan-1.94.jjo/pluto/ipsec_doi.c	Thu Dec 13 14:08:58 2001
@@ -49,6 +49,7 @@
 #include "md5.h"
 #include "crypto.h" /* requires sha1.h and md5.h */
 
+#include "kernel_alg.h"
 /* MAGIC: perform f, a function that returns notification_t
  * and return from the ENCLOSING stf_status returning function if it fails.
  */
@@ -1867,6 +1868,18 @@
 		needed_len = DES_CBC_BLOCK_SIZE * 3;
 		break;
 	    default:
+#ifndef NO_KERNEL_ALG
+		if((needed_len=kernel_alg_esp_keylen(pi->attrs.transid))>0) {
+			/* XXX: check key_len "coupling with kernel.c's */
+			if (pi->attrs.key_len) {
+				needed_len=pi->attrs.key_len/8;
+				DBG(DBG_PARSING, DBG_log("compute_proto_keymat:"
+						"key_len=%d from peer",
+						needed_len));
+			}
+			break;
+		}
+#endif
 		exit_log("transform %s not implemented yet",
 		    enum_show(&esp_transformid_names, pi->attrs.transid));
 	    }
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/kernel.c freeswan-1.94.jjo/pluto/kernel.c
--- freeswan-1.94/pluto/kernel.c	Wed Dec  5 16:43:38 2001
+++ freeswan-1.94.jjo/pluto/kernel.c	Sat Dec 22 09:58:18 2001
@@ -50,6 +50,8 @@
 #include "server.h"
 #include "whack.h"	/* for RC_LOG_SERIOUS */
 
+#include "alg_info.h"
+#include "kernel_alg.h"
 
 bool can_do_IPcomp = TRUE;  /* can system actually perform IPCOMP? */
 
@@ -355,8 +357,12 @@
 	    log("pfkey_get read PF_KEY message with length %d that doesn't equal sadb_msg_len %u * %d; ignoring message"
 		, len, (unsigned) buf->msg.sadb_msg_len, IPSEC_PFKEYv2_ALIGN);
 	}
+	/*	for now, unsolicited messages can be: 
+	 *	SADB_ACQUIRE, SADB_REGISTER 
+	 */
 	else if (!(buf->msg.sadb_msg_pid == (unsigned)pid
-	|| (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE)))
+	|| (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE)
+	|| (buf->msg.sadb_msg_type == SADB_REGISTER)))
 	{
 	    /* not for us: ignore */
 	    DBG(DBG_KLIPS,
@@ -429,6 +435,9 @@
     case SADB_SATYPE_AH:
 	break;
     case SADB_SATYPE_ESP:
+#ifndef NO_KERNEL_ALG
+	kernel_alg_register_pfkey(buf, sizeof (pfkey_buf));
+#endif
 	break;
     case SADB_X_SATYPE_COMP:
 	/* ??? There ought to be an extension to list the
@@ -1890,6 +1899,7 @@
 	ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi;
 	u_char *esp_dst_keymat = inbound? st->st_esp.our_keymat : st->st_esp.peer_keymat;
 
+#if 0+MOVED_TO_alg_info_h
 	struct esp_info {
 	    u_int8_t transid;	/* negotiated ESP transform */
 	    u_int16_t auth;	/* negotiated AUTH */
@@ -1899,8 +1909,10 @@
 	    u_int8_t encryptalg;
 	    u_int8_t authalg;
 	};
+#endif
 
 	const struct esp_info *ei;
+	u_int16_t key_len;
 
 	static const struct esp_info esp_info[] = {
 	    { ESP_NULL, AUTH_ALGORITHM_HMAC_MD5,
@@ -1935,6 +1947,13 @@
 	{
 	    if (ei == &esp_info[elemsof(esp_info)])
 	    {
+		/* Check for additional kernel alg */
+#ifndef NO_KERNEL_ALG
+		if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid,
+					st->st_esp.attrs.auth))!=NULL)
+			break;
+#endif
+
 		/* note: enum_show may use a static buffer, so two
 		 * calls in one printf would be a mistake.
 		 * enum_name does the same job, without a static buffer,
@@ -1951,8 +1970,20 @@
 		break;
 	}
 
+	key_len = st->st_esp.attrs.key_len/8;
+	if (key_len) {
+		/* XXX: must change to check valid _range_ key_len */
+		if (key_len > ei->enckeylen) {
+			loglog(RC_LOG_SERIOUS, "ESP transform %s passed key_len=%d > %d",
+			enum_name(&esp_transformid_names, st->st_esp.attrs.transid),
+			key_len, ei->enckeylen);
+			goto fail;
+		}
+	} else
+		key_len = ei->enckeylen;
+
 	/* divide up keying material */
-	passert(st->st_esp.keymat_len == ei->enckeylen + ei->authkeylen);
+	passert(st->st_esp.keymat_len == key_len + ei->authkeylen);
 
 	set_text_said(text_said, &dst, esp_spi, SA_ESP);
 
@@ -1974,12 +2005,12 @@
 	&& (ei->authkeylen == 0
 	    || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH]
 		    , SADB_EXT_KEY_AUTH, ei->authkeylen * IPSEC_PFKEYv2_ALIGN
-		    , esp_dst_keymat + ei->enckeylen)
+		    , esp_dst_keymat + key_len)
 		, "pfkey_key_a Add ESP SA", text_said, extensions))
 
-	&& (ei->enckeylen == 0
+	&& (key_len == 0
 	    || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT]
-		    , SADB_EXT_KEY_ENCRYPT, ei->enckeylen * IPSEC_PFKEYv2_ALIGN
+		    , SADB_EXT_KEY_ENCRYPT, key_len * IPSEC_PFKEYv2_ALIGN
 		    , esp_dst_keymat)
 		, "pfkey_key_a Add ESP SA", text_said, extensions))
 
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/kernel_alg.c freeswan-1.94.jjo/pluto/kernel_alg.c
--- freeswan-1.94/pluto/kernel_alg.c	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/pluto/kernel_alg.c	Sat Dec 22 10:20:15 2001
@@ -0,0 +1,367 @@
+/*
+ * Kernel runtime algorithm handling interface
+ * 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.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#ifdef KLIPS
+# include <pfkeyv2.h>
+# include <pfkey.h>
+#endif /* KLIPS */
+
+#include <freeswan.h>
+
+#include "constants.h"
+#include "defs.h"
+#include "state.h"
+#include "packet.h"
+#include "spdb.h"
+#include "kernel.h"
+#include "kernel_alg.h"
+#include "alg_info.h"
+#include "log.h"
+
+/* WARNING: this is duplicated in kernel.c, I did't want to export
+ * this definition further
+ */
+/* ALG storage */
+static struct sadb_alg esp_aalg[SADB_AALG_MAX+1];
+static struct sadb_alg esp_ealg[SADB_EALG_MAX+1];
+static int esp_ealg_num=0;
+static int esp_aalg_num=0;
+
+#define ESP_EALG_PRESENT(algo) ((algo<=SADB_EALG_MAX)&&(esp_ealg[(algo)].sadb_alg_id==(algo)))
+#define ESP_EALG_FOR_EACH(algo) \
+	for (algo=1; algo <= SADB_EALG_MAX; algo++) \
+		if (ESP_EALG_PRESENT(algo))
+#define ESP_EALG_FOR_EACH_UPDOWN(algo) \
+	for (algo=SADB_EALG_MAX; algo >0 ; algo--) \
+		if (ESP_EALG_PRESENT(algo))
+#define ESP_AALG_PRESENT(algo) ((algo<=SADB_AALG_MAX)&&(esp_aalg[(algo)].sadb_alg_id==(algo)))
+#define ESP_AALG_FOR_EACH(algo) \
+	for (algo=1; algo <= SADB_AALG_MAX; algo++) \
+		if (ESP_AALG_PRESENT(algo))
+#define ESP_AALG_FOR_EACH_UPDOWN(algo) \
+	for (algo=SADB_AALG_MAX; algo >0 ; algo--) \
+		if (ESP_AALG_PRESENT(algo))
+/*
+ * 	Forget previous registration
+ */
+static void kernel_alg_init(void) {
+	DBG(DBG_KLIPS, DBG_log("alg_init():"
+		"memset(%p, 0, %d) "
+		"memset(%p, 0, %d) ",
+		&esp_aalg,  sizeof (esp_aalg),
+		&esp_ealg,  sizeof (esp_ealg)));
+	memset (&esp_aalg, 0, sizeof (esp_aalg));
+	memset (&esp_ealg, 0, sizeof (esp_ealg));
+	esp_ealg_num=esp_aalg_num=0;
+}
+static int kernel_alg_add(int satype, int exttype, const struct sadb_alg *sadb_alg) {
+	int ret=-1;
+	struct sadb_alg *alg_p=NULL;
+	int alg_id=sadb_alg->sadb_alg_id;
+	DBG(DBG_KLIPS, DBG_log("kernel_alg_add():"
+		"satype=%d, exttype=%d, alg_id=%d",
+		satype, exttype, sadb_alg->sadb_alg_id));
+	switch(exttype) {
+		case SADB_EXT_SUPPORTED_AUTH:
+			if (alg_id<=SADB_AALG_MAX)
+				break;
+			goto fail;		
+		case SADB_EXT_SUPPORTED_ENCRYPT:
+			if (alg_id<=SADB_EALG_MAX)
+				break;
+			goto fail;		
+		default:
+			goto fail;
+	}
+	switch(satype) {
+		case SADB_SATYPE_ESP:
+			alg_p=(exttype == SADB_EXT_SUPPORTED_ENCRYPT)? 
+				&esp_ealg[alg_id] : &esp_aalg[alg_id];
+			(exttype == SADB_EXT_SUPPORTED_ENCRYPT)?
+				esp_ealg_num++ : esp_aalg_num++;
+			break;
+		case SADB_SATYPE_AH:
+			ret=0;
+			goto fail;
+		default:
+			goto fail;
+	}
+	if (!alg_p) 
+		goto fail;
+
+	DBG(DBG_KLIPS, DBG_log("kernel_alg_add(): assign *%p=*%p",
+			alg_p, sadb_alg));
+	*alg_p=*sadb_alg;
+	ret=1;
+fail:
+	return ret;
+}
+int kernel_alg_esp_present(int alg_id) {
+	struct sadb_alg *alg_p;
+	int ret=ESP_EALG_PRESENT(alg_id);
+	alg_p=&esp_ealg[alg_id];
+	DBG(DBG_KLIPS, DBG_log("kernel_alg_esp_present(%d)"
+		"alg_id=%d, "
+		"alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
+		"res=%d, ret=%d",
+		alg_id,
+		alg_p->sadb_alg_id,
+		alg_p->sadb_alg_ivlen,
+		alg_p->sadb_alg_minbits,
+		alg_p->sadb_alg_maxbits,
+		alg_p->sadb_alg_reserved,
+		ret));
+	return ret;
+}
+void
+kernel_alg_register_pfkey(void *buf, int buflen) {
+	/*	
+	 *	Trick: one 'type-mangle-able' pointer to
+	 *	ease offset/assing 
+	 */
+	union {
+		const struct sadb_msg *msg;
+		const struct sadb_supported *supported;
+		const struct sadb_ext *ext;
+		const struct sadb_alg *alg;
+		const char *ch;
+	} sadb;
+	const struct sadb_msg *msg_buf=buf;
+	int satype;
+	int msglen;
+	int i=0;
+	/*	Initialize alg arrays 	*/
+	kernel_alg_init();
+	satype=msg_buf->sadb_msg_satype;
+	sadb.msg=msg_buf;
+	msglen=sadb.msg->sadb_msg_len*IPSEC_PFKEYv2_ALIGN;
+	msglen-=sizeof(struct sadb_msg);
+	buflen-=sizeof(struct sadb_msg);
+	passert(buflen>0);
+	sadb.msg++;
+	while(msglen) {
+		int supp_exttype=sadb.supported->sadb_supported_exttype;
+		int supp_len;
+		supp_len=sadb.supported->sadb_supported_len*IPSEC_PFKEYv2_ALIGN;
+		DBG(DBG_KLIPS, DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
+			"sadb_msg_len=%d sadb_supported_len=%d",
+			satype==SADB_SATYPE_ESP? "ESP" : "AH",
+			msg_buf->sadb_msg_len, 
+			supp_len));
+		sadb.supported++;
+		msglen-=supp_len;
+		buflen-=supp_len;
+		passert(buflen>=0);
+		for (supp_len-=sizeof(struct sadb_supported);
+			supp_len;
+			supp_len-=sizeof(struct sadb_alg), sadb.alg++,i++) {
+			int ret;
+			ret=kernel_alg_add(satype, supp_exttype, sadb.alg);
+			DBG(DBG_KLIPS, DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: "
+				"alg[%d], exttype=%d, satype=%d, alg_id=%d, "
+				"alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, "
+				"res=%d, ret=%d",
+				satype==SADB_SATYPE_ESP? "ESP" : "AH",
+				i,
+				supp_exttype,
+				satype,
+				sadb.alg->sadb_alg_id,
+				sadb.alg->sadb_alg_ivlen,
+				sadb.alg->sadb_alg_minbits,
+				sadb.alg->sadb_alg_maxbits,
+				sadb.alg->sadb_alg_reserved,
+				ret));
+		}
+	}
+}
+int kernel_alg_esp_keylen(int alg_id) {
+	int keylen=0;
+	if (!ESP_EALG_PRESENT(alg_id))
+		goto none;
+	keylen=esp_ealg[alg_id].sadb_alg_maxbits/BITS_PER_BYTE;
+none:	
+	DBG(DBG_KLIPS, DBG_log("kernel_alg_esp_keylen():"
+		"alg_id=%d, keylen=%d",
+		alg_id, keylen));
+	
+	return keylen;
+}
+struct sadb_alg *kernel_alg_esp_sadb_alg(int alg_id) {
+	struct sadb_alg *sadb_alg=NULL;
+	if (!ESP_EALG_PRESENT(alg_id))
+		goto none;
+	sadb_alg=&esp_ealg[alg_id];
+none:
+	DBG(DBG_KLIPS, DBG_log("kernel_alg_esp_sadb_alg():"
+		"alg_id=%d, sadb_alg=%p",
+		alg_id, sadb_alg));
+	return sadb_alg;
+}
+struct esp_info *kernel_alg_esp_info(int transid, int auth) {
+	int sadb_aalg, sadb_ealg;
+	int aklen;
+	static struct esp_info ei_buf;
+	if (!ESP_EALG_PRESENT(transid))
+		goto none;
+	/* XXX hardcoded   :*/
+	switch(auth) {
+		case AUTH_ALGORITHM_HMAC_MD5:
+			aklen=HMAC_MD5_KEY_LEN;
+			sadb_aalg=auth+1;
+			break;
+		case AUTH_ALGORITHM_HMAC_SHA1:
+			aklen=HMAC_SHA1_KEY_LEN;
+			sadb_aalg=auth+1;
+			break;
+		default:
+			goto none;
+	}
+	sadb_ealg=transid;
+
+	memset(&ei_buf, 0, sizeof (ei_buf));
+	ei_buf.transid=transid;
+	ei_buf.auth=auth;
+	ei_buf.enckeylen=esp_ealg[transid].sadb_alg_maxbits/BITS_PER_BYTE;
+	ei_buf.authkeylen=aklen;
+	ei_buf.encryptalg=sadb_ealg;
+	ei_buf.authalg=sadb_aalg;
+	DBG(DBG_PARSING, DBG_log("kernel_alg_esp_info():"
+		"transid=%d, auth=%d, ei=%p"
+		"enckeylen=%d, authkeylen=%d, encryptalg=%d, authalg=%d",
+		transid, auth, &ei_buf,
+		ei_buf.enckeylen, ei_buf.authkeylen,
+		ei_buf.encryptalg, ei_buf.authalg
+	       ));
+	return &ei_buf;		
+none:
+	DBG(DBG_PARSING, DBG_log("kernel_alg_esp_info():"
+		"transid=%d, auth=%d, ei=NULL",
+		transid, auth));
+	return NULL;
+}
+#define AD(x) x, elemsof(x)	/* Array Description */
+
+/*	
+ *	Create proposal with runtime kernel algos, merging
+ *	with passed proposal if not NULL
+ *
+ *	for now this function does free() previous returned
+ *	malloced pointer (this quirk allows easier spdb.c change)
+ */
+struct db_prop * 
+kernel_alg_db_prop_new(const struct db_prop *p, struct alg_info *alg_info)
+{
+	int ealg_i, aalg_i, tn=0;
+	int i;
+	struct alg_info_esp *ai_e;
+	struct db_prop *p_new=NULL;
+	static struct db_prop *p_last=NULL;
+	struct db_trans *t;
+	struct db_attr  *attr;
+	int alloc_size;
+	int trans_cnt;
+
+	trans_cnt=(esp_ealg_num*esp_aalg_num);
+	trans_cnt+=(p? p->trans_cnt : 0);
+	DBG(DBG_EMITTING, DBG_log("kernel_alg_db_prop_new() "
+		"initial trans_cnt=%d",
+		trans_cnt));
+	alloc_size=sizeof(struct db_prop)+		/* proposal */
+		trans_cnt*sizeof(struct db_trans)+	/* all transf. */
+		trans_cnt*sizeof(struct db_attr)*2;	/* AUTH [,KEY_LENGTH] */
+	p_new=alloc_bytes(alloc_size, "kernel_alg_runtime_db_prop");
+	t=(struct db_trans *)(((char*)(p_new)) + sizeof (struct db_prop));
+	attr=(struct db_attr *)(((char*)t)+trans_cnt*sizeof(struct db_trans));
+	p_new->trans=t;
+	p_new->protoid=PROTO_IPSEC_ESP;
+	trans_cnt=0;
+	passert(alg_info!=0);
+	ALG_INFO_FOREACH(alg_info, ai_e, i) {
+		int eklen;
+		ealg_i=ai_e->esp_ealg_id;
+		aalg_i=ai_e->esp_aalg_id+1;
+		eklen=ai_e->esp_ealg_keylen;
+		if (ESP_EALG_PRESENT(ealg_i) && ESP_AALG_PRESENT(aalg_i)) {
+			t->transid=ealg_i;
+			t->attr_cnt=1;
+			t->attrs=attr;
+			//attr->type=esp_aalg_db_attr[aalg_i]->type;
+			//attr->val=esp_aalg_db_attr[aalg_i]->val;
+			attr->type=AUTH_ALGORITHM;
+			attr->val=aalg_i-1;
+			attr++;
+			/*
+			 * 	Heuristic: if kernel module has
+			 * 	minbits != maxbits for EALG, 
+			 * 	addr KEY_LENGTH attr
+			 * 	(need this for BLOWFISH against OpenBSD30)
+			 */
+			if (!eklen && esp_ealg[ealg_i].sadb_alg_minbits!=esp_ealg[ealg_i].sadb_alg_maxbits) {
+				eklen=esp_ealg[ealg_i].sadb_alg_maxbits;
+			}
+			if (eklen) {
+				attr->type=KEY_LENGTH;
+				attr->val=eklen;
+				attr++;
+				t->attr_cnt++;
+			}
+			t++;
+			tn++;
+			trans_cnt++;
+		}
+	}
+
+	/* 	Merge passed proposal at tail	*/
+	if (p) {
+		memcpy(t, p->trans, p->trans_cnt*sizeof (struct db_trans));
+		trans_cnt+=p->trans_cnt;
+	}
+	p_new->trans_cnt=trans_cnt;
+
+	/*	
+	 *	true-ly poor man's garbage collector  :)	
+	 *	done HERE will still allow calling me "in a stack"
+	 *	(passed p is not used here anymore in this function)
+	 */
+	if (p_last) pfree(p_last);
+	p_last=p_new;
+
+	DBG(DBG_EMITTING, DBG_log("kernel_alg_db_prop_new() "
+		"will return p_new->trans_id=%d, p_new->trans_cnt=%d",
+		p_new->protoid, p_new->trans_cnt));
+	for(t=p_new->trans,tn=0; tn<p_new->trans_cnt; tn++) {
+		DBG(DBG_EMITTING, DBG_log("kernel_alg_db_prop_new() "
+			"    trans[%d]: transid=%d, attr_cnt=%d, "
+			"attrs[0].type=%d, attrs[0].val=%d",
+			tn,
+			t[tn].transid, t[tn].attr_cnt,
+			t[tn].attrs[0].type, t[tn].attrs[0].val
+			));
+	}
+	return p_new;
+}
+/*
+void kernel_alg_db_prop_free(const struct db_prop *p, struct db_prop *p_new) {
+	if (p!=p_new)
+		pfree(p_new);
+}
+*/
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/kernel_alg.h freeswan-1.94.jjo/pluto/kernel_alg.h
--- freeswan-1.94/pluto/kernel_alg.h	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/pluto/kernel_alg.h	Sat Dec 22 09:48:45 2001
@@ -0,0 +1,30 @@
+/*
+ * Kernel runtime algorithm handling interface definitions
+ * 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.
+ */
+
+/* Registration messages from pluto */
+extern void kernel_alg_register_pfkey(void *buf, int buflen);
+
+/* ESP interface */
+extern int kernel_alg_esp_present(int alg_id);
+extern struct sadb_alg *kernel_alg_esp_sadb_alg(int alg_id);
+extern int kernel_alg_esp_keylen(int alg_id);
+extern int kernel_alg_esp_ivlen(int alg_id);
+
+struct alg_info;
+struct esp_info;
+extern struct db_prop * kernel_alg_db_prop_new(const struct db_prop *p, struct alg_info *ai);
+void kernel_alg_db_prop_free(const struct db_prop *p, struct db_prop *p_new);
+/* returns pointer to static buffer, no reentrant */
+struct esp_info * kernel_alg_esp_info(int esp_id, int auth_id);
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/kernel_comm.c freeswan-1.94.jjo/pluto/kernel_comm.c
--- freeswan-1.94/pluto/kernel_comm.c	Mon Nov 26 06:31:24 2001
+++ freeswan-1.94.jjo/pluto/kernel_comm.c	Fri Dec 21 02:45:16 2001
@@ -116,6 +116,7 @@
 	|| !unpack_str(&msg.right.id)	/* string 4 */
 	|| !unpack_str(&msg.right.updown)	/* string 5 */
 	|| !unpack_str(&msg.keyid)	/* string 6 */
+	|| !unpack_str(&msg.esp)	/* string 7 */
 	|| str_roof - next_str != (ptrdiff_t)msg.keyval.len)	/* check chunk */
 	{
 	    ugh = "message from whack contains bad string";
Binary files freeswan-1.94/pluto/pluto and freeswan-1.94.jjo/pluto/pluto differ
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/spdb.c freeswan-1.94.jjo/pluto/spdb.c
--- freeswan-1.94/pluto/spdb.c	Mon Nov 26 06:56:28 2001
+++ freeswan-1.94.jjo/pluto/spdb.c	Fri Dec 21 17:00:27 2001
@@ -39,6 +39,8 @@
 #include "md5.h"
 #include "crypto.h" /* requires sha1.h and md5.h */
 
+#include "kernel_alg.h"
+#include "alg_info.h"
 #define AD(x) x, elemsof(x)	/* Array Description */
 #define AD_NULL NULL, 0
 
@@ -434,6 +436,22 @@
 	    proposal.isap_spisize = oakley_mode ? 0
 		: p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE
 		: IPSEC_DOI_SPI_SIZE;
+#ifndef NO_KERNEL_ALG
+	    /*	
+	     *	In quick mode ONLY, create proposal for
+	     *	runtime kernel algos
+	     *
+	     *  XXX (hack): for now "replace" esp_pc proposal
+	     *  with runtime created one
+	     */
+	    if (!oakley_mode && p==esp_pc) {
+		    static char buf[256]="";
+		    alg_info_snprint(buf, sizeof (buf), st->st_connection->alg_info);
+		    DBG(DBG_CONTROL | DBG_CRYPT,
+			    DBG_log(buf));
+		    p=kernel_alg_db_prop_new(NULL, st->st_connection->alg_info);
+	    }
+#endif
 	    proposal.isap_notrans = p->trans_cnt;
 	    if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs))
 		return FALSE;
@@ -1823,6 +1841,10 @@
 #endif
 
 		    default:
+#ifndef NO_KERNEL_ALG
+			if (kernel_alg_esp_present(esp_attrs.transid))
+				break;
+#endif
 			DBG(DBG_CONTROL | DBG_CRYPT
 			    , DBG_log("unsupported ESP Transform %s from %s"
 				, enum_show(&esp_transformid_names, esp_attrs.transid)
Binary files freeswan-1.94/pluto/whack and freeswan-1.94.jjo/pluto/whack differ
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/whack.c freeswan-1.94.jjo/pluto/whack.c
--- freeswan-1.94/pluto/whack.c	Wed Nov 28 02:59:55 2001
+++ freeswan-1.94.jjo/pluto/whack.c	Wed Dec 26 17:29:37 2001
@@ -63,7 +63,6 @@
 	    " [--nexthop <ip-address>]"
 	    " [--client <subnet>]"
 	    " [--updown <updown>]"
-	    " \\\n   "
 	    " --to"
 	    " (--host <ip-address> | --id <identity>)"
 	    " [--ikeport <port-number>]"
@@ -72,7 +71,6 @@
 	    " [--nexthop <ip-address>]"
 	    " [--client <subnet>]"
 	    " [--updown <updown>]"
-	    " \\\n   "
 	    " [--psk]"
 	    " [--rsasig]"
 	    " \\\n   "
@@ -89,6 +87,9 @@
 	    " [--reykeyfuzz <percentage>]"
 	    " \\\n   "
 	    " [--keyingtries <count>]"
+	    " \\\n   "
+	    " [--esp <esp-algos>]"
+	    " \\\n   "
 	    " [--dontrekey]"
 	    "\n\n"
 	"routing: whack"
@@ -256,8 +257,9 @@
     CD_IPSECLIFETIME,
     CD_RKMARGIN,
     CD_RKFUZZ,
-    CD_KTRIES
-#   define CD_LAST CD_KTRIES	/* last connection description */
+    CD_KTRIES,
+    CD_ESP	
+#   define CD_LAST CD_ESP	/* last connection description */
 
 #ifdef DEBUG	/* must be last so others are less than 32 to fit in lset_t */
 #   define DBGOPT_FIRST DBGOPT_NONE
@@ -348,6 +350,7 @@
     { "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },	/* OBSOLETE */
     { "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG },
     { "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG },
+    { "esp", required_argument, NULL, CD_ESP + OO },
 
 #ifdef DEBUG
     { "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
@@ -496,6 +499,7 @@
     msg.right.updown = NULL;
     msg.keyid = NULL;
     msg.keyval.ptr = NULL;
+    msg.esp = NULL;
 
     msg.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
     msg.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
@@ -755,7 +759,6 @@
 	    msg.right.updown = optarg;
 	    continue;
 
-
 	case CD_TO:		/* --to */
 	    /* process right end, move it to left, reset it */
 	    if ((cd_seen & LELEM(CD_HOST-CD_FIRST)) == 0)
@@ -766,7 +769,7 @@
 	    msg.right.updown = NULL;
 	    msg.right.host_port = IKE_UDP_PORT;
 	    cd_seen_before_to = cd_seen;
-	    cd_seen &= ~LRANGE(CD_HOST-CD_FIRST, CD_UPDOWN-CD_FIRST);
+	    cd_seen &= ~LRANGE(CD_HOST-CD_FIRST, CD_ESP-CD_FIRST);
 	    continue;
 
 	case CD_PSK:		/* --psk */
@@ -803,6 +806,10 @@
 	    msg.sa_keying_tries = opt_whole;
 	    continue;
 
+	case CD_ESP:	/* --esp <esp_alg1,esp_alg2,...> */
+	    msg.esp = optarg;
+	    continue;
+
 	case CD_CONNIPV4:
 	    if (cd_seen & LELEM(CD_CONNIPV6 - CD_FIRST))
 		diag("--ipv4 conflicts with --ipv6");
@@ -984,6 +991,7 @@
     || !pack_str(&msg.right.id)	/* string 4 */
     || !pack_str(&msg.right.updown)	/* string 5 */
     || !pack_str(&msg.keyid)	/* string 6 */
+    || !pack_str(&msg.esp)	/* string 7 */
     || str_roof - next_str < (ptrdiff_t)msg.keyval.len)    /* chunk (sort of string 5) */
 	diag("too many bytes of strings to fit in message to pluto");
 
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/pluto/whack.h freeswan-1.94.jjo/pluto/whack.h
--- freeswan-1.94/pluto/whack.h	Wed Nov 28 02:59:56 2001
+++ freeswan-1.94.jjo/pluto/whack.h	Fri Dec 21 02:45:16 2001
@@ -77,6 +77,8 @@
     sa_family_t addr_family;	/* between gateways */
     sa_family_t tunnel_addr_family;	/* between clients */
 
+    char *esp;		/* esp alg ids (separated by commas) */
+
     /* for WHACK_KEY: */
     bool whack_key;
     bool whack_addkey;
diff -urN --exclude *.sw? --exclude *.S --exclude **lib/*.h --exclude **klips**lib** --exclude *.[oa]* --exclude GNUmakefile --exclude .GNUmakefile --exclude *.unk --exclude tags --exclude local_modversions.h --exclude *.bak --exclude des.h --exclude version.c --exclude ext --exclude .gdb_history --exclude whack-1.sh --ignore-matching-lines=[.]unk --ignore-matching-lines=-Wpointer-arith --ignore-matching-lines=\.ver freeswan-1.94/utils/auto freeswan-1.94.jjo/utils/auto
--- freeswan-1.94/utils/auto	Wed Oct 31 10:30:46 2001
+++ freeswan-1.94.jjo/utils/auto	Fri Dec 21 02:45:16 2001
@@ -360,6 +360,9 @@
 			fail("unknown authby value " v(s["authby"]))
 
 		settings = "--encrypt"
+		default("esp", "3des")
+		if (s["esp"] != "")
+			settings = settings " --esp " qs("esp")
 		if (s["type"] != "transport")
 			settings = settings " --tunnel"
 		if (s["auth"] == "ah")
--- freeswan-1.94.jjo/klips/net/ipsec/ext/Config.in	Sun Dec 16 10:24:55 2001
+++ freeswan-1.94/klips/net/ipsec/ext/Config.in	Sun Dec 16 10:24:52 2001
@@ -0,0 +1 @@
+#Placeholder
--- freeswan-1.94/klips/net/ipsec/ext/Makefile	Wed Dec 31 21:00:00 1969
+++ freeswan-1.94.jjo/klips/net/ipsec/ext/Makefile	Wed Dec 19 16:50:26 2001
@@ -0,0 +1,17 @@
+EXTRA_CFLAGS:=-I$(TOPDIR)/net/ipsec -I$(TOPDIR)/net/ipsec/libfreeswan
+MOD_LIST_NAME := NET_MISC_MODULES
+M_OBJS :=
+O_OBJS :=
+
+makefiles=$(wildcard Makefile.ext_*)
+ifneq ($(makefiles), "")
+include $(makefiles)
+endif
+
+M_OBJS += $(obj-m)
+O_OBJS += $(obj-m)
+
+ext_modules: $(EXT_MODULES)
+	@echo "EXT_MODULES=$(EXT_MODULES)"
+
+include $(TOPDIR)/Rules.make

