cipe

Tom 'spot' Callaway tcallawa at redhat.com
Fri Jul 25 16:25:12 UTC 2003


On Thu, 2003-07-24 at 03:52, Joe Orton wrote:

> > it only includes Blowfish, just like with Cipe 1.5.x.
> > 
> > RH has, AFAIK, only shipped Cipe with Blowfish only, and I don't know of any
> > reason why it would be necessary or even desirable to include IDEA support
> > suddenly just because of moving to 1.5.x.
> 
> Indeed, IDEA is patent encumbered, we couldn't ship this at all.

Both valid points. Attached are the four patches to add Cipe 1.5.4
support into the kernel. The cipe3 and cipe4 patch add the two cipe
protocol trees, configured for blowfish. These patches include all
relevant diffs from Red Hat's 1.4.6 cipe implementation. I also removed
the check for VERSION_MAGIC, since IMHO, it was just useless to force
the daemon to be built at the same time as the kernel modules.
The third patch is simply a fixed version of Patch5000: 
linux-2.4.9-addon.patch
The fourth patch is simply a fixed version of Patch10010:
linux-2.4.1-compilefailure.patch.

All these patches obsolete the pre-existant core cipe patches in the RHL
kernel tree (Patch5190-5193). Config files will need to be updated to
point to CONFIG_CIPE3 and CONFIG_CIPE4 instead of CONFIG_CIPE.

This is also attached to
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=68066.

~spot
---
Tom "spot" Callaway <tcallawa(a)redhat*com> SAIR LCA, RHCE
Red Hat Enterprise Architect :: http://www.redhat.com
Project Leader for Aurora Sparc Linux :: http://auroralinux.org
GPG: D786 8B22 D9DB 1F8B 4AB7  448E 3C5E 99AD 9305 4260

The words and opinions reflected in this message do not necessarily
reflect those of my employer, Red Hat, and belong solely to me.

"Immature poets borrow, mature poets steal." --- T. S. Eliot
-------------- next part --------------
--- linux-2.4.21/drivers/addon/cipe3/Makefile.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/Makefile	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,23 @@
+#   -*-Makefile-*- template for the CIPE kernel module and driver.
+#   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+#
+#   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.
+
+O_TARGET := cipcb.o
+
+obj-y := module.o device.o sock.o output.o encaps.o crc32.o bf.o
+obj-m := $(O_TARGET)
+
+ifeq ($(ARCH),i386)
+  obj-y += bf-i386.o
+endif
+
+include $(TOPDIR)/Rules.make
+
+ifeq ($(ARCH),i386)
+bf-i386.o: bf-i386.S
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+endif
--- linux-2.4.21/drivers/addon/cipe3/bf.c.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/bf.c	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,552 @@
+/*
+	Bruce Schneier's Blowfish.
+	Author: Olaf Titz <olaf at bigred.inka.de>
+
+	This code is in the public domain.
+
+	$Id: bf.c,v 1.4 2000/10/26 10:11:08 olaf Exp $
+*/
+
+#include "bf.h"
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+#ifndef ASM_BF_Crypt
+
+/* The generic big/little endian routines use the following imported
+   from <asm/byteorder.h> under Linux:
+   __u32 __be32_to_cpup(__u32 *p);
+   __u32 __cpu_to_be32(__u32 x);
+   __u32 __le32_to_cpup(__u32 *p);
+   __u32 __cpu_to_le32(__u32 x);
+   These are macros. We provide replacements if necessary (non-Linux).
+   XXX the pointer types are wrong, but else a cast would be necessary.
+*/
+
+#ifdef __GNUC__
+#define INLINE static inline
+#else
+#define INLINE static
+#endif
+
+#ifndef __be32_to_cpup
+INLINE  __u32 __be32_to_cpup(unsigned char *p)
+{
+    return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
+}
+#endif
+
+#ifndef __cpu_to_be32
+INLINE __u32 __cpu_to_be32(__u32 x)
+{
+    register unsigned char *p=(unsigned char *)&x;
+    return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
+}
+#endif
+
+#ifndef __le32_to_cpup
+INLINE  __u32 __le32_to_cpup(unsigned char *p)
+{
+    return (p[3]<<24)+(p[2]<<16)+(p[1]<<8)+p[0];
+}
+#endif
+
+#ifndef __cpu_to_le32
+INLINE __u32 __cpu_to_le32(__u32 x)
+{
+    register unsigned char *p=(unsigned char *)&x;
+    return (p[3]<<24)+(p[2]<<16)+(p[1]<<8)+p[0];
+}
+#endif
+
+/* Macros to implement the round function. */
+
+/* access the P and S boxes in key array */
+#define P(n)	(key[(n)])
+#define S0(n) 	(key[(n)+18])
+#define S1(n) 	(key[(n)+274])
+#define S2(n) 	(key[(n)+530])
+#define S3(n) 	(key[(n)+786])
+/* access byte in word */
+#define B0(x)	(((x)>>24)&255)
+#define B1(x)	(((x)>>16)&255)
+#define B2(x)	(((x)>>8)&255)
+#define B3(x)	(((x))&255)
+/* one raw round sans swap. p is running ptr into P box array */
+#define F(x)	(((S0(B0(x))+S1(B1(x)))^S2(B2(x)))+S3(B3(x)))
+#define RoundP(a,b) (a)^=(*p++)^F(b)
+#define RoundN(a,b) (a)^=(*p--)^F(b)
+
+/* 16 rounds with running pointer and word swapping */
+#define RoundsP \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r)
+
+#define RoundsN \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r)
+
+/* Native byte order routines */
+
+void _N_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			 const Blowfish_Key key)
+{
+    register const __u32 *p=(const __u32 *)key;
+    register unsigned long
+	l=((__u32 *)dataIn)[0]^(*p++),
+	r=((__u32 *)dataIn)[1];
+    RoundsP;
+    ((__u32 *)dataOut)[0]=r^(*p);
+    ((__u32 *)dataOut)[1]=l;
+}
+
+void _N_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			 const Blowfish_Key key)
+{
+    register const __u32 *p=((const __u32 *)key)+17;
+    register unsigned long
+	l=((__u32 *)dataIn)[0]^(*p--),
+	r=((__u32 *)dataIn)[1];
+    RoundsN;
+    ((__u32 *)dataOut)[0]=r^(*p);
+    ((__u32 *)dataOut)[1]=l;
+}
+
+/* Big-endian routines (i.e. real Blowfish) */
+
+#ifndef BF_DONTNEED_BE
+#ifndef BF_NATIVE_BE
+void B_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=(const __u32 *)key;
+    register unsigned long
+	l=__be32_to_cpup(dataIn)^(*p++),
+	r=__be32_to_cpup(dataIn+4);
+    RoundsP;
+    ((__u32 *)dataOut)[0]=__cpu_to_be32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_be32(l);
+}
+
+void B_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=((const __u32 *)key)+17;
+    register unsigned long
+	l=__be32_to_cpup(dataIn)^(*p--),
+	r=__be32_to_cpup(dataIn+4);
+    RoundsN;
+    ((__u32 *)dataOut)[0]=__cpu_to_be32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_be32(l);
+}
+#endif
+#endif
+
+/* Little-endian routines */
+
+#ifndef BF_DONTNEED_LE
+#ifndef BF_NATIVE_LE
+void L_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=key;
+    register unsigned long
+	l=__le32_to_cpup(dataIn)^(*p++),
+	r=__le32_to_cpup(dataIn+4);
+    RoundsP;
+    ((__u32 *)dataOut)[0]=__cpu_to_le32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_le32(l);
+}
+
+void L_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=key+17;
+    register unsigned long
+	l=__le32_to_cpup(dataIn)^(*p--),
+	r=__le32_to_cpup(dataIn+4);
+    RoundsN;
+    ((__u32 *)dataOut)[0]=__cpu_to_le32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_le32(l);
+}
+#endif
+#endif
+
+/* Key setup */
+
+void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen,
+			    Blowfish_Key key)
+{
+    char d[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    int i, j;
+    __u32 u;
+
+    #define UK	(userKey[j]&255)
+    #define UKI	if (++j>=userKeyLen) j=0
+    for (i=j=0; i<18; ++i) {
+	u=UK;	     UKI;
+	u=(u<<8)+UK; UKI;
+	u=(u<<8)+UK; UKI;
+	u=(u<<8)+UK; UKI;
+	key[i]=Blowfish_Init_Key[i]^u;
+    }
+    memcpy(key+18, Blowfish_Init_Key+18, 4096);
+    for (i=0; i<1042; i+=2) {
+	_N_Blowfish_Encrypt(d, d, key);
+	key[i]=((__u32 *)d)[0];
+	key[i+1]=((__u32 *)d)[1];
+    }
+}
+
+#endif
+
+/* The initialization key. According to Schneier, this is not a magic
+   pattern but simply the first 33344 (after point) bits of "pi". */
+
+const Blowfish_Key Blowfish_Init_Key = {
+    /* The eighteen P boxes @ 1 word */
+    0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+    0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+    0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+    0x9216d5d9, 0x8979fb1b,
+    /* The four S boxes @ 256 words */
+    0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+    0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+    0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+    0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+    0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+    0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+    0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+    0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+    0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+    0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+    0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+    0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+    0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+    0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+    0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+    0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+    0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+    0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+    0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+    0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+    0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+    0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+    0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+    0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+    0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+    0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+    0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+    0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+    0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+    0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+    0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+    0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+    0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+    0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+    0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+    0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+    0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+    0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+    0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+    0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+    0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+    0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+    0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+    0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+    0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+    0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+    0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+    0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+    0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+    0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+    0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+    0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+    0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+    0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+    0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+    0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+    0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+    0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+    0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+    0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+    0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+    0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+    0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+    0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+    0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+    0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+    0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+    0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+    0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+    0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+    0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+    0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+    0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+    0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+    0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+    0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+    0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+    0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+    0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+    0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+    0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+    0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+    0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+    0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+    0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+    0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+    0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+    0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+    0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+    0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+    0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+    0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+    0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+    0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+    0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+    0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+    0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+    0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+    0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+    0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+    0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+    0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+    0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+    0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+    0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+    0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+    0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+    0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+    0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+    0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+    0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+    0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+    0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+    0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+    0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+    0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+    0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+    0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+    0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+    0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+    0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+    0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+    0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+    0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+    0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+    0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+    0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+    0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+    0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+    0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+    0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+    0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+    0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+    0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+    0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+    0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+    0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+    0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+    0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+    0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+    0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+    0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+    0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+    0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+    0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+    0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+    0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+    0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+    0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+    0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+    0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+    0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+    0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+    0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+    0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+    0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+    0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+    0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+    0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+    0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+    0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+    0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+    0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+    0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+    0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+    0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+    0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+    0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+    0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+    0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+    0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+    0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+    0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+    0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+    0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+    0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+    0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+    0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+    0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+    0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+    0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+    0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+    0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+    0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+    0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+    0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+    0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+    0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+    0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+    0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+    0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+    0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+    0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+    0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+    0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+    0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+    0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+    0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+    0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+    0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+    0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+    0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+    0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+    0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+    0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+    0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+    0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+    0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+    0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+    0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+    0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+    0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+    0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+    0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+    0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+    0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+    0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+    0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+    0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+    0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+    0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+    0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+    0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+    0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+    0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+    0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+    0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+    0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+    0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+    0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+    0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+    0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+    0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+    0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+    0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+    0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+    0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+    0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+    0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+    0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+    0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+    0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+    0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+    0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+    0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+    0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+    0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+    0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+    0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+    0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+    0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+    0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+    0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+    0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+    0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+    0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+};
+
+#if (defined(TEST) && !defined(__KERNEL__))
+
+#include <stdio.h>
+
+/* Test vectors from Schneier's reference implementation */
+
+char test1k[] = "abcdefghijklmnopqrstuvwxyz";
+char btest1p[] = { 0x42, 0x4c, 0x4f, 0x57, 0x46, 0x49, 0x53, 0x48 };
+char btest1c[] = { 0x32, 0x4e, 0xd0, 0xfe, 0xf4, 0x13, 0xa2, 0x03 };
+
+char test2k[] = "Who is John Galt?";
+char btest2p[] = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
+char btest2c[] = { 0xcc, 0x91, 0x73, 0x2b, 0x80, 0x22, 0xf6, 0x84 };
+
+/* Non-official little endian test ciphertext vectors */
+char btest1l[] = { 0x82, 0x4d, 0x92, 0x0d, 0x00, 0x4d, 0x7e, 0xe3 };
+char btest2l[] = { 0xd4, 0xf9, 0xb0, 0x06, 0xd3, 0x84, 0x92, 0x7e };
+
+typedef void (*BFTransform)(void *dataIn, void *dataOut,
+			    const Blowfish_Key key);
+
+int ftest(char *k, char *p, char *c,
+	  BFTransform Encrypt, BFTransform Decrypt)
+{
+    Blowfish_Key kk;
+    unsigned char dd[8];
+    int e=0;
+
+    Blowfish_ExpandUserKey(k, strlen(k), kk);
+    Encrypt(p, dd, kk);
+    printf("    %02x%02x%02x%02x %02x%02x%02x%02x ",
+	   dd[0], dd[1], dd[2], dd[3], dd[4], dd[5], dd[6], dd[7]);
+    if (memcmp(dd, c, 8)) {
+	printf("encrypt failed ");
+	++e;
+    }
+    Decrypt(dd, dd, kk);
+    printf("    %02x%02x%02x%02x %02x%02x%02x%02x ",
+	   dd[0], dd[1], dd[2], dd[3], dd[4], dd[5], dd[6], dd[7]);
+    if (memcmp(dd, p, 8)) {
+	printf("decrypt failed ");
+	++e;
+    }
+    printf("%s\n", e?"":"passed");
+    return e;
+}
+
+int main()
+{
+    int e=0;
+    printf("Big-endian:\n");
+    printf("  Test 1: ");
+    e+=ftest(test1k, btest1p, btest1c, B_Blowfish_Encrypt, B_Blowfish_Decrypt);
+    printf("  Test 2: ");
+    e+=ftest(test2k, btest2p, btest2c, B_Blowfish_Encrypt, B_Blowfish_Decrypt);
+    printf("Little-endian:\n");
+    printf("  Test 1: ");
+    e+=ftest(test1k, btest1p, btest1l, L_Blowfish_Encrypt, L_Blowfish_Decrypt);
+    printf("  Test 2: ");
+    e+=ftest(test2k, btest2p, btest2l, L_Blowfish_Encrypt, L_Blowfish_Decrypt);
+    return e;
+}
+
+#endif
--- linux-2.4.21/drivers/addon/cipe3/bf.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/bf.h	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,100 @@
+/*
+	Bruce Schneier's Blowfish.
+	Author: Olaf Titz <olaf at bigred.inka.de>
+
+	This code is in the public domain.
+
+	$Id: bf.h,v 1.4 2000/10/06 23:15:05 olaf Exp $
+*/
+
+#ifndef _BF_H_
+#define _BF_H_
+
+#include <asm/types.h>       	/* gives __u32 as an unsigned 32bit integer */
+/* PORTABILITY: under non-Linux,
+   omit this include and insert an appropriate typedef
+*/
+
+#ifdef __KERNEL__
+#include <asm/byteorder.h>
+#endif
+/* PORTABILITY: under non-Linux, omit this include.
+   Generic, endian-neutral, slower C routines will be used instead of
+   the assembler versions found in the kernel includes.
+*/
+
+/* This is ugly, but seems the easiest way to find an endianness test
+   which works both in kernel and user mode.
+   This is only an optimization - everything works even if none of the
+   tests are defined.
+*/
+#ifdef __BYTE_ORDER
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define BF_NATIVE_BE
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define BF_NATIVE_LE
+#endif
+#else
+#ifdef __BIG_ENDIAN
+#define BF_NATIVE_BE
+#endif
+#ifdef __LITTLE_ENDIAN
+#define BF_NATIVE_LE
+#endif
+#endif
+
+/* The data block processed by the encryption algorithm - 64 bits */
+typedef __u32 Blowfish_Data[2];
+/* The key as entered by the user - size may vary */
+typedef char Blowfish_UserKey[16];
+/* The expanded key for internal use - 18+4*256 words*/
+typedef __u32 Blowfish_Key[1042];
+
+/* Byteorder-dependent handling of data encryption: Blowfish is by
+   definition big-endian. However, there are broken implementations on
+   little-endian machines which treat the data as little-endian.
+   This module provides both variants.
+ */
+
+/* Native byte order. For internal use ONLY. */
+extern void _N_Blowfish_Encrypt(void *dataIn, void *dataOut,
+				const Blowfish_Key key);
+extern void _N_Blowfish_Decrypt(void *dataIn, void *dataOut,
+				const Blowfish_Key key);
+
+#ifndef BF_DONTNEED_BE
+/* Big endian. This is the "real" Blowfish. */
+#ifdef BF_NATIVE_BE
+#define B_Blowfish_Encrypt _N_Blowfish_Encrypt
+#define B_Blowfish_Decrypt _N_Blowfish_Decrypt
+#else
+extern void B_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+extern void B_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+#endif
+#endif
+
+#ifndef BF_DONTNEED_LE
+/* Little endian. To be compatible with other LE implementations. */
+#ifdef BF_NATIVE_LE
+#define L_Blowfish_Encrypt _N_Blowfish_Encrypt
+#define L_Blowfish_Decrypt _N_Blowfish_Decrypt
+#else
+extern void L_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+extern void L_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+#endif
+#endif
+
+/* User key expansion. This is not byteorder dependent as all common
+   implementations get it right (i.e. big-endian). */
+
+extern void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen,
+				   Blowfish_Key key);
+
+extern const Blowfish_Key Blowfish_Init_Key;
+
+#endif
--- linux-2.4.21/drivers/addon/cipe3/bf-i386.S.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/bf-i386.S	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,272 @@
+/*
+	Bruce Schneier's Blowfish in i386 assembler (for linux/gcc)
+	Author: Olaf Titz <olaf at bigred.inka.de>
+
+	This code is in the public domain.
+
+	$Id: bf-i386.S,v 1.6 2000/11/16 16:45:00 olaf Exp $
+*/
+
+#ifdef ASM_BF_Crypt
+
+#ifndef __ASSEMBLY__
+#define __ASSEMBLY__
+#endif
+
+/* This header just defines ENTRY to make an appropriate global symbol */
+#include <linux/linkage.h>
+
+/* Look for CONFIG_X86_BSWAP (defined for 486 and up) */
+#include <linux/config.h>
+
+#define PosP0	   0
+#define PosP17 	  68
+#define PosS0	  72
+#define PosS1	1096
+#define PosS2	2120
+#define PosS3	3144
+#define KeyLenL 1042
+#define KeyLenB  521
+
+/* This code is optimized for speed rather than size - loops unrolled. etc. */
+
+/*
+  Endian-ness is taken care of by (a) the order of shifts in the Round
+  macro and (b) the order of shifts below under the ukx label.
+  The key tables and user data are stored and processed in the CPU
+  byte order.
+*/
+
+/* Do one round */
+#define Round(lw,rw)				\
+	movl	rw, %edx;			\
+	shrl	$24, %edx;			\
+	movl	PosS0(%edi,%edx,4), %eax;	\
+	movl	rw, %edx;			\
+	shrl	$16, %edx;			\
+	andl	$0xFF, %edx;			\
+	addl	PosS1(%edi,%edx,4), %eax;	\
+	movl	rw, %edx;			\
+	shrl	$8, %edx;			\
+	andl	$0xFF, %edx;			\
+	xorl	PosS2(%edi,%edx,4), %eax;	\
+	movl	rw, %edx;			\
+	andl	$0xFF, %edx;			\
+	addl	PosS3(%edi,%edx,4), %eax;	\
+	xorl	%eax, lw;			\
+	lodsl;					\
+	xorl	%eax, lw
+
+/* Words in %ebx, %ecx - Key in %edi - P-index in %esi - result swapped */
+blowfish:
+	lodsl
+	xorl	%eax, %ebx
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	lodsl
+	xorl	%eax, %ecx
+	ret
+
+/* Endianness swap operation. Is there an easier way to decompose
+   %ebx into %bl and %bh within a macro? */
+#ifdef CONFIG_X86_BSWAP
+#define swab32(x,h,l) bswap x
+#else
+#define swab32(x,h,l) 		\
+	xchgb	h, l;		\
+	rorl	$16, x;		\
+	xchgb	h, l
+#endif
+
+
+/* Function prototype prologue/epilogue. Sets up registers etc.
+   This is all code common to the six encrypt/decrypt functions.
+   They have the prototype
+   extern void FUNCTION(void *dataIn, void *dataOut, const Blowfish_Key key);
+   for the following FUNCTIONs:
+   _N_Blowfish_Encrypt, _N_Blowfish_Decrypt  (native-endian)
+   B_Blowfish_Encrypt,  B_Blowfish_Decrypt   (big-endian)
+   L_Blowfish_Encrypt,  L_Blowfish_Decrypt   (little-endian)
+   Of course, in the i386 implementation, native==little-endian.
+*/
+
+/* saved regs relative to %esp */
+#define sebx	0
+#define sebp	4
+#define sesi	8
+#define sedi	12
+#define SAVE	16 /* no. of bytes the saved registers occupy */
+/* arguments relative to %esp */
+#define dataIn	SAVE+4(%esp)
+#define dataOut	SAVE+8(%esp)
+#define key	SAVE+12(%esp)
+
+#define PROLOG				\
+	/* save registers */		\
+	subl	$SAVE, %esp;		\
+	movl	%ebx, sebx(%esp);	\
+	movl	%ebp, sebp(%esp);	\
+	movl	%esi, sesi(%esp);	\
+	movl	%edi, sedi(%esp);	\
+	/* load data */			\
+	movl	dataIn, %esi;		\
+	movl	(%esi), %ebx;		\
+	movl	4(%esi), %ecx;		\
+	/* load key */			\
+	movl	key, %edi;
+
+#define EPILOG				\
+	/* store data */		\
+	movl	dataOut, %edi;		\
+	movl	%ebx, 4(%edi);		\
+	movl	%ecx, (%edi);		\
+	/* restore registers */		\
+	movl	sedi(%esp), %edi;	\
+	movl	sesi(%esp), %esi;	\
+	movl	sebp(%esp), %ebp;	\
+	movl	sebx(%esp), %ebx;	\
+	addl	$SAVE, %esp;		\
+	ret
+
+#define FORWARD				\
+	movl	%edi, %esi;		\
+	cld
+
+#define BACKWARD			\
+	leal	PosP17(%edi), %esi;	\
+	std
+
+#define SWAP				\
+	swab32(%ebx,%bh,%bl);		\
+	swab32(%ecx,%ch,%cl)
+
+/* N.B. In Linux 2.3, the D flag is assumed to be zero all the time.
+   Thus after BACKWARD an additional cld is necessary. */
+
+#ifndef BF_DONTNEED_LE
+ENTRY(L_Blowfish_Encrypt)
+#endif
+ENTRY(_N_Blowfish_Encrypt)
+	PROLOG
+	FORWARD
+	call	blowfish
+	EPILOG
+
+#ifndef BF_DONTNEED_LE
+ENTRY(L_Blowfish_Decrypt)
+#endif
+ENTRY(_N_Blowfish_Decrypt)
+	PROLOG
+	BACKWARD
+	call	blowfish
+	cld
+	EPILOG
+
+#ifndef BF_DONTNEED_BE
+ENTRY(B_Blowfish_Encrypt)
+	PROLOG
+	SWAP
+	FORWARD
+	call	blowfish
+	SWAP
+	EPILOG
+
+ENTRY(B_Blowfish_Decrypt)
+	PROLOG
+	SWAP
+	BACKWARD
+	call	blowfish
+	cld
+	SWAP
+	EPILOG
+#endif
+
+
+/* load byte from key, start over if exhausted */
+#define lodsbw(base,len)		\
+	lodsb;				\
+	decl	%ecx;			\
+	cmpl	$0, %ecx;		\
+	jg	1f;			\
+	movl	base, %esi;		\
+	movl	len, %ecx;		\
+1:
+
+/*
+   void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen,
+			       Blowfish_Key key);
+*/
+
+ENTRY(Blowfish_ExpandUserKey)
+	pushl	%ebx
+	pushl	%ebp
+	pushl	%esi
+	pushl	%edi
+#define SAVE	16 /* no. of bytes the saved registers occupy */
+/* arguments relative to %esp */
+#define	userKey		SAVE+4(%esp)
+#define userKeyLen	SAVE+8(%esp)
+#define key		SAVE+12(%esp)
+#define key_push	SAVE+16(%esp) /* key with one word pushed */
+
+	/* Copy the init vector into key */
+	leal	SYMBOL_NAME(Blowfish_Init_Key), %esi
+	movl	key, %edi
+	movl	$KeyLenL, %ecx
+	cld
+	rep;	movsl
+	/* XOR the user key into the P table */
+	movl	key, %edi
+	movl	$18, %ebp
+	movl	userKey, %esi
+	movl	userKeyLen, %ecx
+ukx:
+	/* process one 32-bit word swapped */
+	lodsbw(userKey, userKeyLen)
+	shll	$8, %eax
+	lodsbw(userKey, userKeyLen)
+	shll	$8, %eax
+	lodsbw(userKey, userKeyLen)
+	shll	$8, %eax
+	lodsbw(userKey, userKeyLen)
+	xorl	%eax, (%edi)
+	addl	$4, %edi
+	decl	%ebp
+	cmpl	$0, %ebp
+	jg	ukx
+
+	/* Now do the repeated encryption process */
+	xorl	%ebx, %ebx
+	xorl	%ecx, %ecx
+	movl	$KeyLenB, %ebp
+	movl	key, %edi
+ukb:
+	pushl	%edi
+	movl	key_push, %edi
+	movl	%edi, %esi
+	call	blowfish
+	popl	%edi
+	xchgl	%ebx, %ecx
+	movl	%ebx, (%edi)
+	movl	%ecx, 4(%edi)
+	addl	$8, %edi
+	decl	%ebp
+	cmpl	$0, %ebp
+	jg	ukb
+
+	popl	%edi
+	popl	%esi
+	popl	%ebp
+	popl	%ebx
+	ret
+#undef	dataIn
+#undef	dataOut
+#undef	key
+
+#endif /* ASM_BF_Crypt */
--- linux-2.4.21/drivers/addon/cipe3/ciped.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/ciped.h	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,43 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   ciped.h - prototypes for user level routines
+
+   Copyright 1997 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: ciped.h,v 1.6 2000/12/16 17:49:06 olaf Exp $ */
+
+#include <signal.h>
+#include <netinet/in.h>
+#include "cipe.h"
+#include "options.h"
+
+/* options.c */
+struct options {
+    const char * const oname;
+    const char otyp;
+    union {
+	int ovint;
+	char *ovstr;
+	struct sockaddr_in *ovsaddr;
+    } ov;
+};
+extern struct options opts[];
+#define Tbool	0
+#define Tint	1
+#define Tstr	2
+#define Taddr	3
+#define Tuaddr	4
+#define Ttaddr	5
+#define Tsecret 6
+
+#define OI(x)      (opts[O##x].ov.ovint)
+#define OS(x)      (opts[O##x].ov.ovstr)
+#define OA(x)      (opts[O##x].ov.ovsaddr)
+#define OAaddr(x)  (OA(x)->sin_addr)
+#define OAport(x)  (OA(x)->sin_port)
--- linux-2.4.21/drivers/addon/cipe3/cipe.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/cipe.h	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,426 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   cipe.h - contains definitions, includes etc. common to all modules
+
+   Copyright 1996-2000 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: cipe.h,v 1.38.2.2 2002/06/28 23:38:53 olaf Exp $ */
+
+#ifndef _CIPE_H_
+#define _CIPE_H_
+
+#include "crypto.h"
+#ifdef __KERNEL__
+#include <linux/if.h>
+#else
+#include <net/if.h>
+#endif
+
+/*** The kernel/user IOCTL interface ***/
+
+/* ioctls for setup and key exchange */
+/* #define SIOCxIFCIPxxx   (SIOCDEVPRIVATE+x) */
+/* All ioctls are passed a struct ifreq <net/if.h> which contains the
+   device name in ifr_name and a pointer to the actual control struct
+   in ifr_data. */
+
+#if 0
+/* Get interface parameters. Currently unused */
+#define SIOCGIFCIPPAR   (SIOCDEVPRIVATE+0)
+struct  siocgifcippar {
+    unsigned long       magic;
+    /* SOCKS5 relayer */
+    unsigned long       sockshost;
+    unsigned short      socksport;
+    /* Timeouts (in seconds) */
+    int                 tmo_keyxchg;
+    int                 tmo_keylife;
+    /* Flags */
+    int                 flags;
+    int		        cttl;
+};
+#endif
+
+/* Set interface parameters. */
+#define SIOCSIFCIPPAR   (SIOCDEVPRIVATE+1)
+struct  siocsifcippar {
+    unsigned long       magic;
+    /* SOCKS5 relayer */
+    unsigned long       sockshost;
+    unsigned short      socksport;
+    /* Timeouts (in seconds) */
+    int                 tmo_keyxchg;
+    int                 tmo_keylife;
+    /* Flags */
+    int                 flags;
+    int		        cttl;
+};
+
+/* Set a key. */
+#define SIOCSIFCIPKEY   (SIOCDEVPRIVATE+2)
+#define KEY_STATIC      1
+#define KEY_SEND        2
+#define KEY_RECV        3
+#define KEY_INVAL       8
+#define KEY_MAXLEN      32
+struct  siocsifcipkey {
+    unsigned long       magic;
+    int                 which;
+    char                thekey[KEY_MAXLEN];
+    int                 keylen;
+};
+
+/* Attach a socket. */
+#define SIOCSIFCIPATT   (SIOCDEVPRIVATE+3)
+struct  siocsifcipatt {
+    unsigned long       magic;
+    int                 fd;
+};
+
+/* Allocate/deallocate a device. */
+#define SIOCSIFCIPALL   (SIOCDEVPRIVATE+4)
+#define SIOCSIFCIPUNA   (SIOCDEVPRIVATE+5)
+struct  siocsifcipall {
+    unsigned long       magic;
+    int                 num;
+    char                name[IFNAMSIZ];
+};
+
+/* Flag values. */
+#define CIPF_MAY_CLEAR          0x0100
+#define CIPF_MAY_STKEY          0x0200
+#define CIPF_MAY_DYNIP          0x0400
+#define CIPF_DO_CSUM		0x0800
+
+/*** Key exchange related definitions ***/
+
+/* Minimum kxc block. */
+#define KEYXCHGBLKMIN   64
+/* Maximum kxc block, padded with random bytes */
+#define KEYXCHGBLKMAX   (KEYXCHGBLKMIN+256)
+/* Position of the timestamp */
+#define KEYXCHGTSPOS    56
+/* Type words. Only 4 are possible. */
+#define TW_DATA         0
+#define TW_NEWKEY       2
+#define TW_CTRL         4
+#define TW_RSVD2        6
+/* error indication, no valid type word */
+#define TW_ERROR        1
+
+/* NEWKEY (key exchange mode 1) subtypes. */
+#define NK_RREQ         0 /* not used in protocol */
+#define NK_REQ          1 /* send me your new key */
+#define NK_IND          2 /* this is my new key   */
+#define NK_ACK          3 /* i have your new key  */
+
+/* CTRL subtypes. By now sent in a TW_NEWKEY packet. */
+#define CT_DUMMY     0x70 /* ignore */
+#define CT_DEBUG     0x71 /* log */
+#define CT_PING      0x72 /* send PONG */
+#define CT_PONG      0x73
+#define CT_KILL      0x74 /* exit */
+#define CT_CONFREQ   0x75 /* log, send CONF */
+#define CT_CONF	     0x76 /* log */
+
+/*** Kernel-module internal stuff ***/
+
+#ifdef __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/sockios.h>
+#include <linux/sched.h>
+#include <linux/if_ether.h>
+#include <linux/net.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <net/sock.h>
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define LINUX_21
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#define LINUX_23
+#endif
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)) && defined(__i386__)
+#define REGPARM /* __attribute__((regparm,3)) XX needs testing */
+#else
+#define REGPARM
+#endif
+
+#ifdef LINUX_21
+#ifndef SPIN_LOCK_UNLOCKED /* 2.2/2.4 incompat */
+#include <asm/spinlock.h>
+#endif
+#endif
+
+#if 1 /* Lock tracing */
+#define DOLOCK(s) ({ printk(KERN_DEBUG DEVNAME ": " #s " at %s:%d\n", \
+			    __FILE__, __LINE__); s; })
+#else
+#define DOLOCK(s) s
+#endif
+
+#ifdef LINUX_23
+#define tasklist_LOCK()		DOLOCK(read_lock(&tasklist_lock))
+#define tasklist_UNLOCK()	DOLOCK(read_unlock(&tasklist_lock))
+#else
+#define tasklist_LOCK()		/* nop */
+#define tasklist_UNLOCK()	/* nop */
+#endif
+
+#ifdef LINUX_21
+/* In 2.1 the ioctl operations are run under lock. Beware of deadlocks. */
+#define cipe_alloc_LOCK()       0 /* nop */
+#define cipe_alloc_UNLOCK()	  /* nop */
+#else
+extern struct semaphore cipe_alloc_sem;
+#define cipe_alloc_LOCK()       DOLOCK(down_interruptible(&cipe_alloc_sem))
+#define cipe_alloc_UNLOCK()     DOLOCK(up(&cipe_alloc_sem))
+#endif
+
+#ifdef LINUX_21
+#define FLEN "%d"
+#else
+#define FLEN "%ld"
+#endif
+
+#ifdef LINUX_23
+#define rtnl_LOCK()		DOLOCK(rtnl_lock())
+#define rtnl_UNLOCK()		DOLOCK(rtnl_unlock())
+#else
+#define rtnl_LOCK()		/* nop */
+#define rtnl_UNLOCK()		/* nop */
+#endif
+
+#ifdef LINUX_23
+#define NET_DEVICE net_device
+#define DEV_STATS  net_device_stats
+#else
+#define NET_DEVICE device
+#define DEV_STATS  enet_statistics
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127)
+#define timeout_t unsigned long
+#else
+#define timeout_t long
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99)
+#define HAVE_DEVNAME_ARRAY
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17)
+#define get_fast_time do_gettimeofday
+#endif
+
+/* The header we add to each packet */
+#ifdef VER_ETH
+#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr)+blockSize+ETH_HLEN)
+#else
+#ifdef VER_SHORT
+#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr))
+#else
+#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr)+blockSize)
+#endif
+#endif
+/* ...plus a real hardware header (common case) */
+#define cipexhdrl  (cipehdrlen+((ETH_HLEN+15)&~15))
+/* max. padding at the end */
+#if ProtocolVersion >= 3
+#define cipefootlen 12 /* 7 bytes pad, 1 byte type, 4 bytes CRC */
+#else
+#define cipefootlen 10 /* 8 bytes pad, 2 bytes CRC */
+#endif
+
+/* A CIPE device's parameter block */
+
+#define CIPE_MAGIC  (htonl(0x43495045))
+struct cipe {
+    __u32               magic;
+    struct NET_DEVICE   *dev;
+     /* Set by user process */
+    __u32               peeraddr;
+    __u32               myaddr;
+    __u16               peerport;
+    __u16               myport;
+    __u32               sockshost;
+    __u16               socksport;
+    short	        cttl;
+#ifdef Crypto_IDEA
+    Key                 key_e, key_d, skey_e, rkey_d;
+#endif
+#ifdef Crypto_Blowfish
+    Key                 key, skey, rkey;
+    #define key_e       key
+    #define key_d       key
+    #define skey_e      skey
+    #define rkey_d      rkey
+#endif
+    unsigned long       tmo_keyxchg;
+    unsigned long       tmo_keylife;
+     /* Internal */
+    unsigned long       timekx;
+    unsigned long       timeskey;
+    unsigned long       timerkey;
+    int                 cntskey;
+    int                 cntrkey;
+    struct sock         *sock;
+    int                 flags;
+#ifdef LINUX_21
+    char                recursion;
+#endif
+    pid_t               owner;
+    /* Statistics */
+#ifdef LINUX_21
+    struct net_device_stats stat;
+#else
+    struct enet_statistics stat;
+#endif
+    /* Socket interface stuff */
+    struct proto        *udp_prot;
+    struct proto        cipe_proto;
+};
+
+/* Flag values (internally used) */
+#define CIPF_HAVE_KEY           0x0001
+#define CIPF_HAVE_SKEY          0x0002
+#define CIPF_HAVE_RKEY          0x0004
+#define CIPF_MASK_INT           0x00FF
+#define CIPF_MASK_EXT           0xFF00
+
+#define MAXBLKS         32767  /* max # blocks to encrypt using one key */
+
+/* Define, init and check a struct cipe * variable. */
+#define DEVTOCIPE(dev,c,err) \
+    struct cipe *c = (struct cipe*)(dev->priv); \
+    if (!c || c->magic!=CIPE_MAGIC) return err;
+
+/* Master control struct */
+struct cipe_ctrl {
+#ifndef HAVE_DEVNAME_ARRAY
+    char                name[IFNAMSIZ];
+#endif
+    struct cipe         cipe;
+    struct NET_DEVICE 	dev;
+};
+
+extern struct cipe_ctrl **cipe_ctrls;
+extern int cipe_maxdev;
+
+/* SOCKS5 encapsulation header */
+struct sockshdr {
+    char                rsv[2];
+    char                frag;
+    char                atyp;
+    __u32               dstaddr __attribute__((packed));
+    __u16               dstport __attribute__((packed));
+};
+
+#ifdef DEBUG
+extern int cipe_debug;
+
+#if 0
+/* Lock around our printks, to avoid mixing up dumps. NOT for regular use. */
+extern spinlock_t cipe_printk_lock;
+#define LOCK_PRINTK unsigned long flags; spin_lock_irqsave(&cipe_printk_lock, flags)
+#define UNLOCK_PRINTK spin_unlock_irqrestore(&cipe_printk_lock, flags)
+#else
+#define LOCK_PRINTK	/* nop */
+#define UNLOCK_PRINTK	/* nop */
+#endif
+
+#define DEB_CALL        1
+#define DEB_INP         2
+#define DEB_OUT         4
+#define DEB_CRYPT       8
+#define DEB_KXC         16
+#define DEB_PKIN        32
+#define DEB_PKOU        64
+#define DEB_CHKP	128
+
+#define dprintk(l,p)	if(cipe_debug&l){LOCK_PRINTK; printk p; UNLOCK_PRINTK;}
+
+#else
+#define dprintk(l,p)	/* nop */
+
+#endif /* DEBUG */
+
+#if defined(DEBUG) && defined(LINUX_23)
+#define __CHECKPOINT(F,L) printk(KERN_DEBUG "CHECKPOINT " F ":%d\n", L)
+#define CHECKPOINT if (cipe_debug&DEB_CHKP){\
+    LOCK_PRINTK; __CHECKPOINT(__FILE__,__LINE__); UNLOCK_PRINTK;\
+    current->state=TASK_INTERRUPTIBLE; schedule_timeout(HZ/20); }
+#else
+#define CHECKPOINT	/* nop */
+#endif
+
+static inline void nf_conntrack_null(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETFILTER
+    nf_conntrack_put(skb->nfct);
+    skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+    skb->nf_debug = 0;
+#endif
+#endif
+}
+
+/* internal routines */
+/* module.c */
+extern void cipe_use_module(void);
+extern void cipe_unuse_module(void);
+extern int cipe_check_kernel(void);
+/* device.c */
+extern void cipe_prnpad(unsigned char *buf, int len) REGPARM;
+extern void cipe_close(struct cipe *c);
+extern const char *cipe_ntoa(__u32 addr) REGPARM;
+/* sock.c */
+extern int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm)
+    REGPARM;
+extern void cipe_fakenkey(struct cipe *c, char typ) REGPARM;
+/* output.c */
+#ifdef DEBUG
+extern void cipe_dump_packet(char *title, struct sk_buff *skb, int dumpskb)
+    REGPARM;
+#endif
+extern int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev);
+/* encaps.c */
+extern void cipe_encrypt(struct cipe *c, unsigned char *buf,
+			 int *len, int typcode) REGPARM;
+extern unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf,
+				   int *len) REGPARM;
+#ifndef VER_SHORT
+extern void cipe_cryptpad(unsigned char *buf) REGPARM;
+extern void cipe_cryptpad_iv(unsigned char *buf) REGPARM;
+#endif
+
+#endif /* __KERNEL__ */
+
+#ifdef VER_CRC32
+/* crc32.c */
+extern unsigned long crc32(const unsigned char *s, unsigned int len);
+#else
+/* crc.c */
+extern unsigned short block_crc(unsigned char *d, int len);
+#endif
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+#ifndef DEVNAME
+#define DEVNAME "cip" VERNAME CRNAME
+#endif
+
+#endif /* _CIPE_H_ */
--- linux-2.4.21/drivers/addon/cipe3/config.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/config.h	Fri Jul 25 15:09:02 2003
@@ -0,0 +1,54 @@
+/* config.h.  Generated automatically by configure.  */
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   Copyright 1999 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+
+/* Config-dependent defines. Always include this first. */
+/* @api means the next line is used for determining the version magic */
+
+/* Version of the CIPE package @api */
+#define VERSION "1.5.4"
+#define VERSION_MAJ 1
+
+/* Encapsulation protocol version @api */
+#define ProtocolVersion 3
+
+/* Cipher algorithm selection @api */
+/* #undef Crypto_IDEA */
+/* Cipher algorithm selection @api */
+#define Crypto_Blowfish 1
+
+/* Assembler module selection */
+/* #undef ASM_Idea_Crypt */
+#ifdef __i386
+#define ASM_BF_Crypt 1
+#endif
+
+/* Debug code in kernel */
+#define DEBUG 1
+
+/* Use old key parser */
+/* #undef BUG_COMPATIBLE */
+
+/* Dynamic device allocation @api */
+/* #undef NO_DYNDEV */
+
+/* Syslog facility */
+#define LOGFAC LOG_DAEMON
+
+/* Memory management functions (kernel version dependent?) */
+#define HAVE_MLOCK 1
+#define HAVE_MLOCKALL 1
+
+/* End of autoconf options */
+
+/* This tells the Blowfish module to omit unneeded code */
+#define BF_DONTNEED_BE
+
--- linux-2.4.21/drivers/addon/cipe3/crc32.c.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/crc32.c	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,111 @@
+  /* ============================================================= */
+  /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or       */
+  /*  code or tables extracted from it, as desired without restriction.     */
+  /*                                                                        */
+  /*  First, the polynomial itself and its table of feedback terms.  The    */
+  /*  polynomial is                                                         */
+  /*  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0   */
+  /*                                                                        */
+  /*  Note that we take it "backwards" and put the highest-order term in    */
+  /*  the lowest-order bit.  The X^32 term is "implied"; the LSB is the     */
+  /*  X^31 term, etc.  The X^0 term (usually shown as "+1") results in      */
+  /*  the MSB being 1.                                                      */
+  /*                                                                        */
+  /*  Note that the usual hardware shift register implementation, which     */
+  /*  is what we're using (we're merely optimizing it by doing eight-bit    */
+  /*  chunks at a time) shifts bits into the lowest-order term.  In our     */
+  /*  implementation, that means shifting towards the right.  Why do we     */
+  /*  do it this way?  Because the calculated CRC must be transmitted in    */
+  /*  order from highest-order term to lowest-order term.  UARTs transmit   */
+  /*  characters in order from LSB to MSB.  By storing the CRC this way,    */
+  /*  we hand it to the UART in the order low-byte to high-byte; the UART   */
+  /*  sends each low-bit to hight-bit; and the result is transmission bit   */
+  /*  by bit from highest- to lowest-order term without requiring any bit   */
+  /*  shuffling on our part.  Reception works similarly.                    */
+  /*                                                                        */
+  /*  The feedback terms table consists of 256, 32-bit entries.  Notes:     */
+  /*                                                                        */
+  /*      The table can be generated at runtime if desired; code to do so   */
+  /*      is shown later.  It might not be obvious, but the feedback        */
+  /*      terms simply represent the results of eight shift/xor opera-      */
+  /*      tions for all combinations of data and CRC register values.       */
+  /*                                                                        */
+  /*      The values must be right-shifted by eight bits by the "updcrc"    */
+  /*      logic; the shift must be unsigned (bring in zeroes).  On some     */
+  /*      hardware you could probably optimize the shift in assembler by    */
+  /*      using byte-swap instructions.                                     */
+  /*      polynomial $edb88320                                              */
+  /*                                                                        */
+  /*  --------------------------------------------------------------------  */
+
+static unsigned long crc32_tab[] = {
+      0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+      0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+      0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+      0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+      0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+      0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+      0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+      0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+      0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+      0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+      0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+      0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+      0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+      0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+      0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+      0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+      0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+      0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+      0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+      0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+      0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+      0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+      0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+      0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+      0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+      0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+      0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+      0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+      0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+      0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+      0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+      0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+      0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+      0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+      0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+      0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+      0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+      0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+      0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+      0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+      0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+      0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+      0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+      0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+      0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+      0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+      0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+      0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+      0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+      0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+      0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+      0x2d02ef8dL
+   };
+
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+unsigned long crc32(const unsigned char *s, unsigned int len)
+{
+  unsigned int i;
+  unsigned long crc32val;
+  
+  crc32val = 0;
+  for (i = 0;  i < len;  i ++)
+    {
+      crc32val =
+	crc32_tab[(crc32val ^ s[i]) & 0xff] ^
+	  (crc32val >> 8);
+    }
+  return crc32val;
+}
--- linux-2.4.21/drivers/addon/cipe3/crypto.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/crypto.h	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,100 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   crypto.h - configuration of the crypto algorithm
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: crypto.h,v 1.8 2000/09/13 21:46:41 olaf Exp $ */
+
+#ifndef _CRYPTO_H_
+#define _CRYPTO_H_
+
+#include "version.h"
+
+typedef unsigned long part;
+/* the longest integer so that sizeof(part) divides blockSize.
+   Used only for optimizing block-copy and block-XOR operations. */
+
+#if     ProtocolVersion == 1
+
+#ifdef  OLDNAMES
+#define VERNAME "1"
+#else
+#define VERNAME "a"
+#endif
+#define VER_BACK                /* encryption progress backwards */
+#define VER_SHORT               /* no IV in packet */
+
+#elif   ProtocolVersion == 2
+
+#ifdef  OLDNAMES
+#define VERNAME "2"
+#else
+#define VERNAME "b"
+#endif
+
+#elif   ProtocolVersion == 3
+
+#ifdef  OLDNAMES
+#define VERNAME "3"
+#else
+#define VERNAME "c"
+#endif
+#define VER_CRC32               /* checksums are 32bit */
+
+#elif   ProtocolVersion == 4
+
+#ifdef  OLDNAMES
+#define VERNAME "4"
+#else
+#define VERNAME "d"
+#endif
+#define VER_CRC32
+#define VER_ETH
+
+#else
+#error  "Must specify correct ProtocolVersion"
+#endif
+
+
+#ifdef  Crypto_IDEA
+#define CRYPTO                  "IDEA"
+#define CRNAME			"i"
+#define CRNAMEC			'i'
+#define CRNUM			0
+#include "idea0.h"
+#define Key                     Idea_Key
+#define keySize                 Idea_keySize
+#define UserKey                 Idea_UserKey
+#define userKeySize             Idea_userKeySize
+#define ExpandUserKey           Idea_ExpandUserKey
+#define InvertKey               Idea_InvertKey
+#define blockSize               Idea_dataSize
+
+#else
+#ifdef  Crypto_Blowfish
+#define CRYPTO                  "Blowfish"
+#define CRNAME			"b"
+#define CRNAMEC			'b'
+#define CRNUM			1
+#include "bf.h"
+#define Key                     Blowfish_Key
+#define keySize                 sizeof(Blowfish_Key)
+#define UserKey                 Blowfish_UserKey
+#define userKeySize             16 /* arbitrary, but matches IDEA */
+#define ExpandUserKey(u,k)      Blowfish_ExpandUserKey(u,userKeySize,k)
+#define InvertKey(x,y)          /* noop */
+#define blockSize               sizeof(Blowfish_Data)
+
+#else
+#error  "Must specify Crypto_IDEA or Crypto_Blowfish"
+#endif
+#endif
+
+#endif
--- linux-2.4.21/drivers/addon/cipe3/device.c.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/device.c	Fri Jul 25 15:08:13 2003
@@ -0,0 +1,636 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   device.c - the net device driver
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: device.c,v 1.42 2000/11/19 23:08:34 olaf Exp $ */
+
+#include "cipe.h"
+#include "version.h"
+#include <stddef.h>
+#include <linux/if_arp.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+
+#ifdef LINUX_21
+#include <asm/uaccess.h>
+#include <linux/rtnetlink.h>
+#else
+#define register_netdevice register_netdev
+#define unregister_netdevice unregister_netdev
+#endif
+
+/*** Globals ***/
+
+static const char driver_version[]=VERSION;
+
+struct cipe_ctrl **cipe_ctrls = NULL;
+#ifdef NO_DYNDEV
+int cipe_maxdev = 4;            /* changeable via insmod */
+#else
+int cipe_maxdev = 100;          /* changeable via insmod */
+#endif
+#ifdef DEBUG
+int cipe_debug = DEB_CALL;      /* changeable via insmod */
+#endif
+
+/* clear all potentially sensitive info and stats */
+static void cipe_zero_c(struct cipe *c)
+{
+    memset(&(c->peeraddr), 0,
+           offsetof(struct cipe, udp_prot)-offsetof(struct cipe, peeraddr));
+    /* reset these to sensible values */
+    c->tmo_keyxchg = 10*HZ;
+    c->tmo_keylife = 10*60*HZ;
+}
+
+/* weak but fast PRNG, used for padding only */
+static __u32 prnseed;
+void cipe_prnpad(unsigned char *buf, int len)
+{
+    while (len>0) {
+	prnseed=prnseed*0x01001001+1;
+	if (len>=2) {
+	    *(__u16 *)buf=prnseed>>16;
+	    len-=2; buf+=2;
+	} else {
+	    *buf=(prnseed>>24)^jiffies; return;
+	}
+    }
+}
+
+#ifdef DO_LOCK_PRINTK
+spinlock_t cipe_printk_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
+/* inet_ntoa() for multiple use. */
+#ifdef __SMP__
+#define NTOABUFS	16
+#else
+#define NTOABUFS	4
+#endif
+static char ntoabuf[NTOABUFS][16];
+static int ntoaptr=0;
+#ifdef LINUX_21
+spinlock_t cipe_ntoa_lock=SPIN_LOCK_UNLOCKED;
+#endif
+
+const char *cipe_ntoa(const __u32 addr)
+{
+    const unsigned char *x=(const unsigned char *)&addr;
+    char *p;
+    int b, i;
+#ifdef LINUX_21
+    unsigned long flags;
+    spin_lock_irqsave(&cipe_ntoa_lock, flags);
+#endif
+    b=ntoaptr;
+    if (++b>=NTOABUFS)
+	b=0;
+    ntoaptr=b;
+#ifdef LINUX_21
+    spin_unlock_irqrestore(&cipe_ntoa_lock, flags);
+#endif
+    p=ntoabuf[b];
+    for (i=0; i<4; ++i) {
+        int k=x[i]/100;
+        int l=(x[i]/10)%10;
+        if (k)
+            *p++=k+'0';
+        if (k || l)
+            *p++=l+'0';
+        *p++=(x[i]%10)+'0';
+        if (i<3)
+            *p++='.';
+    }
+    *p='\0';
+    return ntoabuf[b];
+}
+
+/*** IOCTL handlers ***/
+
+#ifdef SIOCGIFCIPPAR
+static int cipe_getpar(struct NET_DEVICE *dev, struct siocgifcippar *parm)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    parm->sockshost=c->sockshost;
+    parm->socksport=c->socksport;
+    parm->tmo_keyxchg=c->tmo_keyxchg/HZ;
+    parm->tmo_keylife=c->tmo_keylife/HZ;
+    parm->flags=c->flags;
+    parm->cttl=c->cttl;
+    return 0;
+}
+#endif
+
+static int cipe_setpar(struct NET_DEVICE *dev, struct siocsifcippar *parm)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    if (parm->sockshost)
+	c->sockshost=parm->sockshost;
+    if (parm->socksport)
+	c->socksport=parm->socksport;
+    if (parm->tmo_keyxchg>10*60*HZ)
+	return -EINVAL;
+    if (parm->tmo_keyxchg)
+	c->tmo_keyxchg=parm->tmo_keyxchg*HZ;
+    if (parm->tmo_keylife>24*60*60*HZ)
+	return -EINVAL;
+    if (parm->tmo_keylife)
+	c->tmo_keylife=parm->tmo_keylife*HZ;
+    c->flags=(parm->flags&CIPF_MASK_EXT)|(c->flags&CIPF_MASK_INT);
+    c->cttl=parm->cttl;
+    dprintk(DEB_CALL, (KERN_DEBUG "%s: setpar %s:%d %ld %ld %04x %d\n",
+                       dev->name,
+                       cipe_ntoa(c->sockshost), ntohs(c->socksport),
+                       c->tmo_keyxchg, c->tmo_keylife,
+                       c->flags, c->cttl));
+    return 0;
+}
+
+static int cipe_setkey(struct NET_DEVICE *dev, struct siocsifcipkey *parm)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    dprintk(DEB_KXC, (KERN_INFO "%s: setkey %d\n", dev->name, parm->which));
+    switch (parm->which) {
+    case KEY_STATIC:
+	ExpandUserKey(parm->thekey, c->key_e);
+#if 0
+	dprintk(DEB_CRYPT, (KERN_DEBUG "ExpandUserKey: %08x\n",
+			    *(__u32*)(c->key_e)));
+#endif
+	InvertKey(c->key_e, c->key_d);
+	c->flags|=CIPF_HAVE_KEY;
+	break;
+    case KEY_SEND:
+	ExpandUserKey(parm->thekey, c->skey_e);
+	c->timeskey=jiffies+c->tmo_keylife;
+	c->cntskey=0;
+	c->flags|=CIPF_HAVE_SKEY;
+	break;
+    case KEY_RECV:
+	ExpandUserKey(parm->thekey, c->rkey_d);
+	InvertKey(c->rkey_d, c->rkey_d);
+	c->timerkey=jiffies+2*c->tmo_keylife; /* allow for fuzz */
+	c->cntrkey=0;
+	c->flags|=CIPF_HAVE_RKEY;
+	break;
+    case KEY_STATIC+KEY_INVAL:
+        c->flags&=~(CIPF_HAVE_KEY|CIPF_HAVE_SKEY|CIPF_HAVE_RKEY);
+	memset(&(c->key_e), 0, sizeof(c->key_e));
+	memset(&(c->key_d), 0, sizeof(c->key_d));
+	break;
+    case KEY_SEND+KEY_INVAL:
+        c->flags&=~CIPF_HAVE_SKEY;
+	memset(&(c->skey_e), 0, sizeof(c->skey_e));
+	c->timeskey=jiffies+c->tmo_keyxchg;
+	break;
+    case KEY_RECV+KEY_INVAL:
+        c->flags&=~CIPF_HAVE_RKEY;
+	memset(&(c->rkey_d), 0, sizeof(c->rkey_d));
+	c->timerkey=jiffies+c->tmo_keyxchg;
+	break;
+    default:
+	return -EINVAL;
+    }
+    return 0;
+}
+
+static int cipe_alloc_dev(int n);
+static void cipe_unalloc_dev(int n);
+
+static int cipe_owner(struct cipe *c)
+{
+    struct task_struct *p;
+    pid_t pid=c->owner;
+    if (!pid) return 0;
+    tasklist_LOCK();
+    p=current;
+    do {
+	if (p->pid==pid) {
+	    tasklist_UNLOCK();
+	    return pid;
+	}
+	p=p->next_task;
+    } while (p!=current);
+    tasklist_UNLOCK();
+    return 0;
+}
+
+#define cipe_nowner(n) cipe_owner(&cipe_ctrls[(n)]->cipe)
+
+static int cipe_alloc(struct NET_DEVICE *dev, struct siocsifcipall *parm)
+{
+#ifdef NO_DYNDEV
+    return -ENOSYS;
+#else
+    int n=parm->num;
+    int e;
+    if (n>=cipe_maxdev)
+        return -EINVAL;
+    if ((e=cipe_alloc_LOCK()))
+        return e;
+    if (n>=0) {
+        if (cipe_ctrls[n]) {
+            if (cipe_ctrls[n]->cipe.sock || (e=cipe_nowner(n))) {
+		printk(KERN_DEBUG DEVNAME ": dev %d busy pid=%d\n", n, e);
+                e=-EBUSY;
+            } else {
+                cipe_ctrls[n]->cipe.owner=current->pid;
+	    }
+        } else {
+            e=cipe_alloc_dev(n);
+        }
+    } else {
+        e=-EMFILE;
+        for (n=0; n<cipe_maxdev; ++n) {
+            if (!cipe_ctrls[n]) {
+                e=cipe_alloc_dev(n);
+                break;
+            }
+            if (!cipe_nowner(n)) {
+                cipe_ctrls[n]->cipe.owner=current->pid;
+                e=0;
+                break;
+            }
+        }
+    }
+    if (!e) {
+        parm->num=n;
+        strncpy(parm->name, cipe_ctrls[n]->dev.name, sizeof(parm->name)-1);
+        parm->name[sizeof(parm->name)-1]='\0';
+    }
+    cipe_alloc_UNLOCK();
+    return e;
+#endif
+}
+
+static int cipe_unalloc(struct NET_DEVICE *dev, struct siocsifcipall *parm)
+{
+#ifdef NO_DYNDEV
+    return -ENOSYS;
+#else
+    int e;
+    if (parm->num<0 || parm->num>=cipe_maxdev)
+        return -EINVAL;
+    if ((e=cipe_alloc_LOCK()))
+        return e;
+    if (cipe_ctrls[parm->num]->cipe.sock) {
+        e=-EBUSY;
+    } else {
+        if (parm->num>0)
+            cipe_unalloc_dev(parm->num);
+    }
+    cipe_alloc_UNLOCK();
+    return e;
+#endif
+}
+
+
+/*** Device operation handlers ***/
+
+int cipe_dev_ioctl(struct NET_DEVICE *dev, struct ifreq *ifr, int cmd)
+{
+    int e=-EINVAL;
+
+#ifdef LINUX_21
+
+    if (!capable(CAP_NET_ADMIN))
+	return -EPERM;
+
+#define doioctl(nam,fun,str) {                                          \
+    struct str parm;                                                    \
+    dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name));          \
+    if ((e=copy_from_user((void*)&parm,(void*)ifr->ifr_data,            \
+                          sizeof(parm)))<0)                             \
+        goto out;                                                       \
+    if ((e=fun(dev, &parm))<0)                                          \
+        goto out;                                                       \
+    e=copy_to_user((void*)ifr->ifr_data, (void*)&parm, sizeof(parm));   \
+    goto out;                                                           \
+  }
+
+#else
+
+    if (!suser())
+	return -EPERM;
+
+#define doioctl(nam,fun,str) {                                              \
+    struct str parm;                                                        \
+    dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name));              \
+    if ((e=verify_area(VERIFY_READ, ifr->ifr_data, sizeof(parm)))<0)        \
+        goto out;                                                           \
+    memcpy_fromfs((void*)&parm, (void*)ifr->ifr_data, sizeof(parm));        \
+    if ((e=fun(dev, &parm))<0)                                              \
+        goto out;                                                           \
+    if ((e=verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(parm)))<0)       \
+        goto out;                                                           \
+    memcpy_tofs((void*)ifr->ifr_data, (void*)&parm, sizeof(parm));          \
+    goto out;                                                               \
+  }
+
+#endif
+
+    cipe_use_module();
+    switch (cmd) {
+#ifdef SIOCGIFCIPPAR
+    case SIOCGIFCIPPAR:
+	doioctl("getpar", cipe_getpar, siocgifcippar);
+#endif
+    case SIOCSIFCIPPAR:
+	doioctl("setpar", cipe_setpar, siocsifcippar);
+    case SIOCSIFCIPKEY:
+	doioctl("setkey", cipe_setkey, siocsifcipkey);
+    case SIOCSIFCIPATT:
+	doioctl("attach", cipe_attach, siocsifcipatt);
+    case SIOCSIFCIPALL:
+	doioctl("alloc", cipe_alloc, siocsifcipall);
+    case SIOCSIFCIPUNA:
+	doioctl("unalloc", cipe_unalloc, siocsifcipall);
+    /* default: e=-EINVAL; */
+    }
+
+ out:
+    cipe_unuse_module();
+    return e;
+
+#undef doioctl
+}
+
+int cipe_dev_open(struct NET_DEVICE *dev)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+    if (!c->sock)
+	return -ENXIO;
+    dprintk(DEB_CALL, (KERN_INFO "%s: opened\n", dev->name));
+    return 0;
+}
+
+void cipe_close(struct cipe *c)
+{
+    cipe_zero_c(c);
+    dprintk(DEB_CALL, (KERN_INFO "%s: closed\n", c->dev->name));
+    cipe_unuse_module();
+}
+
+int cipe_dev_close(struct NET_DEVICE *dev)
+{
+    struct cipe *c = (struct cipe*)(dev->priv);
+    if ((!c) || (c->magic!=CIPE_MAGIC)) {
+	printk(KERN_WARNING "%s: cipe_dev_close: no valid struct\n",
+               dev->name);
+	return 0;
+    }
+    if (c->sock) {
+	dprintk(DEB_CALL, (KERN_INFO "%s: closing\n", c->dev->name));
+	/* Tell the attached socket we're going down */
+	c->sock->shutdown=SHUTDOWN_MASK;
+	c->sock->zapped=1;
+	c->sock->err=ENXIO;
+	c->sock->error_report(c->sock);
+#ifdef LINUX_21
+	if (!cipe_owner(c)) {
+	    /* SHOULD NOT HAPPEN. Socket is probably left orphaned.
+	       This is really only an emergency path to allow closing
+	       the device after an Oops. */
+	    printk(KERN_ERR "cipe_dev_close: not owned??\n");
+	    cipe_close(c);
+	}
+#endif
+    } else {
+	cipe_close(c);
+    }
+    return 0;
+}
+
+struct DEV_STATS *cipe_get_stats(struct NET_DEVICE *dev)
+{
+    DEVTOCIPE(dev,c,NULL);
+    return &(c->stat);
+}
+
+int cipe_set_mac(struct NET_DEVICE *dev, void *p)
+{
+    struct sockaddr *addr=p;
+    memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+    return 0;
+}
+
+
+/*** Initialization and finalization stuff ***/
+
+#ifndef LINUX_21
+static inline void dev_init_buffers(struct NET_DEVICE *dev)
+{
+    int i;
+    for (i = 0; i < DEV_NUMBUFFS; i++)  {
+        skb_queue_head_init(&dev->buffs[i]);
+    }
+}
+#endif
+
+static int cipe_init_dev(struct NET_DEVICE *dev)
+{
+    struct cipe *c = (struct cipe*)(dev->priv);
+    if (!c)
+	return -ENODEV;
+
+    memset(c, 0, sizeof(struct cipe)); /* zero the device struct along */
+    c->magic       = CIPE_MAGIC;
+    c->dev         = dev;
+    cipe_zero_c(c);
+
+    /* Device parameters. */
+#ifdef VER_ETH
+    ether_setup(dev); /* sets hard_header etc. */
+#endif
+    /* Procedural */
+    dev->open                   = cipe_dev_open;
+    dev->stop                   = cipe_dev_close;
+    dev->hard_start_xmit        = cipe_xmit;
+    dev->set_mac_address	= cipe_set_mac;
+    dev->do_ioctl               = cipe_dev_ioctl;
+    dev->get_stats              = cipe_get_stats;
+
+    /* "Hardware" */
+#ifndef VER_ETH
+    dev->type		        = ARPHRD_TUNNEL;
+    dev->hard_header_len        = 0; /* we copy anyway to expand */
+    dev->tx_queue_len	        = 100; /* matches ethernet */
+#endif
+    dev->mtu		        = ETH_DATA_LEN
+                                     -sizeof(struct sockshdr)
+                                     -cipehdrlen
+                                     -cipefootlen;
+
+
+#ifdef LINUX_21
+    dev->iflink         = -1;
+#else
+    dev->family		= AF_INET;
+    dev->pa_alen	= 4;
+    dev->metric         = 1;
+#endif
+    dev_init_buffers(dev);
+
+    /* New-style flags */
+#ifndef VER_ETH
+    dev->flags		= IFF_POINTOPOINT|IFF_NOARP;
+#endif
+    return 0;
+}
+
+#ifndef LINUX_21
+struct semaphore cipe_alloc_sem=MUTEX;
+#endif
+
+static int cipe_alloc_dev(int n)
+{
+    int e=0;
+    struct cipe_ctrl *cc;
+    struct NET_DEVICE *d;
+
+    dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_alloc_dev %d\n", n));
+    if (!(cc=kmalloc(sizeof(struct cipe_ctrl), GFP_KERNEL))) {
+        cipe_ctrls[n]=NULL;
+	printk(KERN_ERR DEVNAME ": failed to allocate device %d\n", n);
+        return -ENOMEM;
+    }
+
+    memset((void *)cc, 0, sizeof(*cc));
+/* If this doesn't compile, define or undefine HAVE_DEVNAME_ARRAY
+   in cipe.h accordingly. */
+#ifdef HAVE_DEVNAME_ARRAY
+    sprintf(cc->dev.name, DEVNAME "%d", n);
+#else
+    sprintf(cc->name, DEVNAME "%d", n);
+    cc->dev.name      = cc->name;
+#endif
+    cc->dev.base_addr = n; /* dummy */
+    cc->dev.priv      = (void*)&(cc->cipe);
+    cc->dev.next      = NULL;
+    cc->dev.init      = cipe_init_dev; /* called by register_netdevice */
+
+#if 1
+    /* Generate a dummy MAC address. This code seems to be in accordance
+       to the address assignments as of RFC1700, pp.172f.
+       We use 00-00-5E-vv-nn-zz with
+       vv=1pppccc0, p=protocol, c=crypto,
+       nn=device number, zz=from MAC of first eth device.
+    */
+    cc->dev.dev_addr[2]=0x5E;
+    cc->dev.dev_addr[3]=0x80+(ProtocolVersion<<4)+(CRNUM<<1);
+    cc->dev.dev_addr[4]=n;
+    for (d=dev_base; d; d=d->next)
+	if (d->type==ARPHRD_ETHER) {
+	    cc->dev.dev_addr[5]=d->dev_addr[5];
+	    break;
+	}
+#else
+    /* MAC address will be generated from IP as with PLIP. FC-FC-ip-ip-ip-ip */
+    cc->dev.dev_addr[1]=cc->dev.dev_addr[0]=0xFC;
+#endif
+    memset(d->broadcast, 0xFF, ETH_ALEN);
+    cc->dev.addr_len=ETH_ALEN;
+
+    e=register_netdevice(&(cc->dev));
+    if (e<0) {
+	kfree(cc);
+	printk(KERN_ERR
+	       "%s: register_netdevice() failed\n", cc->dev.name);
+        cc=NULL;
+    } else {
+        cc->cipe.owner=current->pid;
+    }
+    cipe_ctrls[n]=cc;
+    return e;
+}
+
+static void cipe_unalloc_dev(int n)
+{
+    struct cipe_ctrl *cc=cipe_ctrls[n];
+    if (!cc)
+	return;
+    dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_unalloc_dev %d\n", n));
+    if (cc->cipe.magic!=CIPE_MAGIC) {
+        printk(KERN_WARNING DEVNAME ": Ouch: cipe_unalloc_dev() wrong struct\n");
+        return;
+    }
+    unregister_netdevice(&(cc->dev));
+    cipe_ctrls[n]=NULL;
+    kfree(cc);
+}
+
+int init_module(void)
+{
+    int e=cipe_check_kernel();
+    if (e<0)
+	return e;
+
+    /* sanity check on insmod-provided data */
+    if (cipe_maxdev<1)  cipe_maxdev=1;
+#ifdef NO_DYNDEV
+    if (cipe_maxdev>100) cipe_maxdev=100;
+#else
+    if (cipe_maxdev>10000) cipe_maxdev=10000;
+#endif
+
+#ifdef DEBUG
+    printk(KERN_INFO
+	   DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels, debug=%d\n",
+	   driver_version, cipe_maxdev, cipe_debug);
+#else
+    printk(KERN_INFO
+	   DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels\n",
+	   driver_version, cipe_maxdev);
+#endif
+
+    prnseed=(~jiffies)^CURRENT_TIME;
+    cipe_ctrls = (struct cipe_ctrl **) kmalloc(sizeof(void*)*cipe_maxdev,
+					       GFP_KERNEL);
+    if (!cipe_ctrls) {
+	printk(KERN_ERR
+	       DEVNAME ": failed to allocate master control structure\n");
+	return -ENOMEM;
+    }
+    memset(cipe_ctrls, 0, sizeof(void*)*cipe_maxdev);
+#ifdef NO_DYNDEV
+    {
+        int i;
+	rtnl_LOCK();
+        for (i=0; i<cipe_maxdev; ++i)
+            if ((e=cipe_alloc_dev(i))) {
+		rtnl_UNLOCK();
+                return e;
+	    }
+	rtnl_UNLOCK();
+        return 0;
+    }
+#else
+    rtnl_LOCK();
+    e=cipe_alloc_dev(0);
+    rtnl_UNLOCK();
+    return e;
+#endif
+}
+
+void cleanup_module(void)
+{
+    int i;
+    rtnl_LOCK();
+    for (i=0; i<cipe_maxdev; ++i)
+	cipe_unalloc_dev(i);
+    rtnl_UNLOCK();
+    kfree(cipe_ctrls);
+}
+
--- linux-2.4.21/drivers/addon/cipe3/encaps.c.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/encaps.c	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,313 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   encaps.c - do encryption
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: encaps.c,v 1.18 2000/09/13 21:46:41 olaf Exp $ */
+
+#include "cipe.h"
+#include <asm/string.h>
+#include <linux/socket.h>
+
+static inline void xorbuf(part *dst, part *src)
+{
+    int i;
+    for (i=0; i<blockSize/sizeof(part); ++i)
+	*dst++^=*src++;
+}
+
+#ifdef Crypto_IDEA
+/* This seems to be the only way to typecast an array.
+   Important: GCC is able to swallow the overhead when optimizing. */
+static inline void ecb_enc(part *src, part *dst, Idea_Key k)
+{
+    Idea_Data *s=(Idea_Data *)src;
+    Idea_Data *d=(Idea_Data *)dst;
+    Idea_Crypt(*s, *d, k);
+}
+#define ecb_dec(s,d,k) ecb_enc(s,d,k)
+#endif
+
+#ifdef Crypto_Blowfish
+#define ecb_enc(s,d,k) L_Blowfish_Encrypt(s,d,k)
+#define ecb_dec(s,d,k) L_Blowfish_Decrypt(s,d,k)
+#endif
+
+#ifdef VER_BACK
+
+/* Encrypt/decrypt message in CBC mode backwards.
+   Key must be set up accordingly */
+static void cbc_b(unsigned char *msg, int len, Idea_Key *key, int dec)
+{
+    int i=len/blockSize;
+    unsigned char iv[blockSize], iw[blockSize];
+    part *p=(part*)(msg+len-blockSize);
+    part *q=(part*)iv;
+    part *r=(part*)iw;
+    part *s;
+
+    memset(iv, 0, blockSize);
+    if (dec) {
+	while (i-->0) {
+	    memcpy(r, p, blockSize);
+	    ecb_dec(p, p, key);
+	    xorbuf(p, q);
+	    s=q; q=r; r=s;
+	    p-=blockSize/sizeof(part);
+	}
+    } else {
+	while (i-->0) {
+	    xorbuf(p, q);
+	    ecb_enc(p, p, key);
+	    q=p;
+	    p-=blockSize/sizeof(part);
+	}
+    }
+}
+
+#else
+
+/*
+  CBC encryption/decryption routines.
+  Note: the block to encrypt includes the IV, while decryption swallows
+  the IV. Length is always including IV.
+*/
+
+#define partinc(p) ((p)+blockSize/sizeof(part))
+
+static void cbc_enc(unsigned char *msg, int len, Key * const key)
+{
+    part *p=(part *)msg;
+    int i=len/blockSize;
+
+#if 0
+    dprintk(DEB_CRYPT, (KERN_DEBUG "cbc_enc: %08x %08x ",
+			*((__u32*)partinc(msg)), *(__u32*)key));
+#endif
+    while (--i>0) {
+	xorbuf(partinc(p), p);
+	p=partinc(p);
+	ecb_enc(p, p, *key);
+    }
+#if 0
+    dprintk(DEB_CRYPT, ("%08x\n", *((__u32*)partinc(msg))));
+#endif
+}
+
+static void cbc_dec(unsigned char *msg, int len, Key * const key)
+{
+    part *p=(part *)msg;
+    int i=len/blockSize;
+    part r[blockSize/sizeof(part)];
+
+#if 0
+    dprintk(DEB_CRYPT, (KERN_DEBUG "cbc_dec: %08x %08x ",
+			*(__u32*)msg, *(__u32*)key));
+#endif
+    while (--i>0) {
+	ecb_dec(partinc(p), r, *key);
+	xorbuf(p, r);
+	p=partinc(p);
+    }
+#if 0
+    dprintk(DEB_CRYPT, ("%08x\n", *(__u32*)msg));
+#endif
+}
+
+#endif
+
+#ifndef VER_SHORT
+/* Fill a block of length blockSize with strong random numbers.
+   Used for generating IVs. */
+void cipe_cryptpad(unsigned char *buf)
+{
+    static int padcnt=MAXBLKS;
+    static Key padkey;
+
+    if (++padcnt>MAXBLKS) {
+	/* make a new random key */
+	UserKey k;
+	dprintk(DEB_CRYPT, (KERN_INFO "%s: re-keying cryptpad\n", DEVNAME));
+	cipe_prnpad((unsigned char*)k, sizeof(UserKey));
+	ExpandUserKey(k, padkey);
+	padcnt=0;
+    }
+    *(int *)(buf)=padcnt;
+    cipe_prnpad(buf+sizeof(int), blockSize-sizeof(int));
+    ecb_enc((part*)buf, (part*)buf, padkey);
+}
+
+void cipe_cryptpad_iv(unsigned char *buf)
+{
+    int i=5;
+    do {
+	cipe_cryptpad(buf);
+	if (*((__u32 *)buf) & htonl(0x7FFFFFFF))
+	    break;
+    } while (i-->0);
+    if (!i)
+	printk(KERN_CRIT "cipe_cryptpad_iv failed");
+}
+#endif
+
+
+void cipe_checkskey(struct cipe *c)
+{
+    if ((++c->cntskey>MAXBLKS) || (jiffies>c->timeskey)) {
+	/* make the control process send an NK_IND */
+	cipe_fakenkey(c, NK_REQ);
+	c->timeskey=jiffies+c->tmo_keyxchg;
+	if (c->cntskey>MAXBLKS)
+	    c->cntskey-=1000;
+    }
+}
+
+void cipe_checkrkey(struct cipe *c)
+{
+    if ((c->flags&CIPF_HAVE_RKEY) &&
+	((++c->cntrkey>MAXBLKS*2) || (jiffies>c->timerkey))) {
+	/* make the control process send an NK_REQ */
+	cipe_fakenkey(c, NK_RREQ);
+	c->flags&=~CIPF_HAVE_RKEY;
+	c->timerkey=jiffies+c->tmo_keyxchg;
+	if (c->cntrkey>MAXBLKS*2)
+	    c->cntrkey-=1000;
+    }
+}
+
+void cipe_nodynkey(struct cipe *c)
+{
+    if (jiffies>c->timerkey) {
+	/* make the control process send an NK_REQ */
+	cipe_fakenkey(c, NK_RREQ);
+	c->timerkey=jiffies+c->tmo_keyxchg;
+    }
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: missing dynamic key\n",
+	     c->dev->name));
+}
+
+#if ProtocolVersion >= 3
+
+/* Encryption/decryption version 3 */
+
+void cipe_encrypt(struct cipe *c, unsigned char *buf, int *len, int typ)
+{
+    unsigned char p=7-(((*len)+4)&7);
+    /* merge key flag in IV */
+    *buf&=0x7F;
+    if (c->flags&CIPF_HAVE_SKEY)
+	*buf|=0x80;
+    /* pad */
+    cipe_prnpad(buf+(*len), p);
+    (*len)+=p+5;
+    /* set type and crc */
+    *(buf+(*len)-5)=typ|(p<<4);
+    *((unsigned long *)(buf+(*len)-4))=
+	htonl(crc32(buf+blockSize, (*len)-blockSize-4));
+
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: encrypt typ %d pad %d len %d\n",
+                        c->dev->name, typ, p, *len));
+    cbc_enc(buf, *len, c->flags&CIPF_HAVE_SKEY ? &c->skey_e : &c->key_e);
+    cipe_checkskey(c);
+}
+
+unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf, int *len)
+{
+    unsigned char p;
+
+    if (((*buf)&0x80) && !(c->flags&CIPF_HAVE_RKEY)) {
+	cipe_nodynkey(c);
+	return TW_ERROR; /* can't decrypt - no valid key */
+    }
+    cbc_dec(buf, *len, ((*buf)&0x80) ? &c->rkey_d : &c->key_d);
+    (*len)-=blockSize;
+    if (*((unsigned long *)(buf+(*len)-4)) != htonl(crc32(buf, (*len)-4))) {
+	dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt CRC error\n",
+			    c->dev->name));
+	return TW_ERROR;
+    }
+    p=*(buf+(*len)-5);
+    (*len)-=(p>>4)&7;
+    cipe_checkrkey(c);
+#define CTLBITS 0x06
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt len=%d pad=%d typ=%02X\n",
+                        c->dev->name, (*len), (p>>4)&7, p&CTLBITS));
+    return (p&CTLBITS);
+}
+
+#else
+
+/* Encryption/decryption version 1 and 2 */
+
+void cipe_encrypt(struct cipe *c, unsigned char *buf, int *len, int typ)
+{
+    unsigned short x;
+    unsigned char p;
+
+    p=8-((*len)&7);
+    cipe_prnpad(buf+(*len), p);
+    (*len)+=p;
+
+#ifdef VER_SHORT
+    x=((block_crc(buf, *len)&0xFFFE)^((p&7)<<8)^typ)|(c->haveskey);
+#else
+    x=((block_crc(buf+blockSize, (*len)-blockSize)&0xFFFE)
+       ^((p&7)<<8)^typ)|(c->haveskey);
+#endif
+#ifdef VER_BACK
+    cbc_b(buf, *len, c->haveskey ? &c->skey_e : &c->key_e, 0);
+#else
+    cbc_enc(buf, *len, c->haveskey ? &c->skey_e : &c->key_e);
+#endif
+
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: encrypt pad %d\n", c->dev->name, p));
+    buf[(*len)++]=x>>8;
+    buf[(*len)++]=x&255;
+    cipe_checkskey(c);
+}
+
+unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf, int *len)
+{
+    unsigned short x=(buf[(*len)-1])+(buf[(*len)-2]<<8);
+    unsigned char p;
+
+    if ((x&1) && !(c->haverkey)) {
+	cipe_nodynkey(c);
+	return TW_ERROR; /* can't decrypt - no valid key */
+    }
+    (*len)-=2;
+    if (*len<9
+#ifndef VER_SHORT
+	+blockSize
+#endif
+	)
+	return TW_ERROR; /* short packet */
+
+#ifdef VER_BACK
+    cbc_b(buf, *len, (x&1) ? &c->rkey_d : &c->key_d, 1);
+#else
+    cbc_dec(buf, *len, (x&1) ? &c->rkey_d : &c->key_d);
+#endif
+#ifndef VER_SHORT
+    (*len)-=blockSize;
+#endif
+
+    x^=block_crc(buf, *len);
+    p=(x>>8)&7; if (!p) p=8;
+    (*len)-=p;
+    cipe_checkrkey(c);
+
+#define CTLBITS 0xF8FE
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt pad %d typ %04X\n",
+			c->dev->name, (x>>8)&7, x&CTLBITS));
+    return (x&CTLBITS); /* delete the control bits */
+}
+
+#endif
--- linux-2.4.21/drivers/addon/cipe3/ioctl.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/ioctl.h	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,24 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   ioctl.h - prototype for the ioctl interface, user part
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: ioctl.h,v 1.3 2000/03/27 17:38:23 olaf Exp $ */
+
+#include "cipe.h"
+
+#ifdef SIOCGIFCIPPAR
+extern int ioctl_getpar(int fd, char *ifname, struct siocgifcippar *sio);
+#endif
+extern int ioctl_setpar(int fd, char *ifname, struct siocsifcippar *sio);
+extern int ioctl_setkey(int fd, char *ifname, struct siocsifcipkey *sio);
+extern int ioctl_attach(int fd, char *ifname, struct siocsifcipatt *sio);
+extern int ioctl_alloc(int fd, char *ifname, struct siocsifcipall *sio);
+extern int ioctl_unalloc(int fd, char *ifname, struct siocsifcipall *sio);
--- linux-2.4.21/drivers/addon/cipe3/module.c.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/module.c	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,89 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   module.c - kernel module interface stuff
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: module.c,v 1.5.2.1 2002/05/30 11:49:17 olaf Exp $ */
+
+#include "cipe.h"
+#include <linux/module.h>
+#include <linux/utsname.h>
+
+/* We put this all here so that none of the other source files needs
+   to include <linux/module.h>, which could lead to collisions. */
+
+#ifdef LINUX_21
+MODULE_AUTHOR("Olaf Titz <olaf at bigred.inka.de>");
+MODULE_DESCRIPTION("Encrypting IP-over-UDP tunnel");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+MODULE_PARM(cipe_maxdev,"i");
+MODULE_PARM_DESC(cipe_maxdev,"Maximum device number supported");
+#ifdef DEBUG
+MODULE_PARM(cipe_debug,"i");
+MODULE_PARM_DESC(cipe_debug,"Debugging level");
+#endif
+#endif
+
+void cipe_use_module(void)
+{
+    MOD_INC_USE_COUNT;
+}
+
+void cipe_unuse_module(void)
+{
+    MOD_DEC_USE_COUNT;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,30)
+/* older kernel not always exported this */
+
+int bad_user_access_length(void)
+{
+    panic("bad_user_access_length in " DEVNAME);
+}
+
+#endif
+
+/* HACK: sanity check on SMP/non-SMP.
+   Is this really necessary? */
+int cipe_check_kernel(void)
+{
+    int s=0;
+    const char *p=system_utsname.version;
+    while (p[0] && p[1] && p[2]) {
+	if (p[0]=='S' && p[1]=='M' && p[2]=='P') {
+	    s=1;
+	    break;
+	}
+	++p;
+    }
+    if (
+#ifdef __SMP__
+	!
+#endif
+         s) {
+	printk(KERN_ERR
+	       DEVNAME ": driver ("
+#ifndef __SMP__
+	       "not "
+#endif
+	       "SMP) "
+	       "mismatches kernel ("
+#ifdef __SMP__
+	       "not "
+#endif
+	       "SMP)\n");
+	return -EINVAL;
+    }
+    return 0;
+}
--- linux-2.4.21/drivers/addon/cipe3/options.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/options.h	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,29 @@
+/* File generated by genoptions.pl, do not edit */
+
+#define Odevice	0
+#define Odebug	1
+#define Oipaddr	2
+#define Optpaddr	3
+#define Omask	4
+#define Obcast	5
+#define Omtu	6
+#define Ometric	7
+#define Octtl	8
+#define Ome	9
+#define Opeer	10
+#define Okey	11
+#define Onokey	12
+#define Osocks	13
+#define Otokxc	14
+#define Otokey	15
+#define Oipup	16
+#define Oipdown	17
+#define Oarg	18
+#define Omaxerr	19
+#define Otokxts	20
+#define Oping	21
+#define Otoping	22
+#define Odynip	23
+#define Ohwaddr	24
+#define Oifconfig	25
+#define Ochecksum	26
--- linux-2.4.21/drivers/addon/cipe3/output.c.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/output.c	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,621 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   output.c - the sending part of the CIPE device
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: output.c,v 1.40.2.2 2002/06/28 23:38:53 olaf Exp $ */
+
+#include "cipe.h"
+
+#include <net/checksum.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <linux/if_arp.h>
+#include <linux/socket.h>
+#include <linux/version.h>
+#ifdef LINUX_24
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#endif
+
+#ifdef DEBUG
+
+#include "../lib/hexdump.c"
+
+void cipe_dump_packet(char *title, struct sk_buff *skb, int dumpskb)
+{
+    LOCK_PRINTK;
+    if (dumpskb) {
+	printk(KERN_DEBUG "SKB (%s):\n", skb->dev?skb->dev->name:"");
+	cipe_hexdump((unsigned char *)skb, sizeof(*skb));
+    }
+    printk(KERN_DEBUG
+           "%s: packet len=" FLEN " dev=%s\n",
+           title, skb->len, skb->dev?skb->dev->name:"<none>");
+    cipe_hexdump((unsigned char *)skb->data, skb->tail-skb->data);
+    UNLOCK_PRINTK;
+}
+#endif
+
+#ifdef LINUX_21
+
+/* An adapted version of Linux 2.1 net/ipv4/ipip.c output routine. */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,37)
+#define ip_ident(h,d) (h)->id=htons(ip_id_count++)
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
+#define ip_ident(h,d) ip_select_ident(h,d)
+#else
+#define ip_ident(h,d) ip_select_ident(h,d,NULL)
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,36)
+/* this is not exactly the newer kernel's routine, it just does what we need */
+struct sk_buff *skb_copy_expand(struct sk_buff *skb, int max_headroom,
+				int max_tailroom, int gfp)
+{
+    struct sk_buff *n=alloc_skb(skb->len+max_headroom+max_tailroom, gfp);
+    if (n) {
+	skb_reserve(n, max_headroom);
+	skb_put(n,skb->len);
+	memcpy(n->data,skb->data,skb->len);
+	n->priority=skb->priority;
+	n->protocol=skb->protocol;
+	n->dev=skb->dev;
+	n->dst=dst_clone(skb->dst);
+	memcpy(n->cb, skb->cb, sizeof(skb->cb));
+	n->used=skb->used;
+	n->is_clone=0;
+	atomic_set(&n->users, 1);
+	n->pkt_type=skb->pkt_type;
+	n->stamp=skb->stamp;
+	n->security=skb->security;
+#ifdef CONFIG_IP_FIREWALL
+	n->fwmark = skb->fwmark;
+#endif
+    }
+    return n;
+}
+#endif
+
+int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev)
+{
+        struct cipe *tunnel = (struct cipe*)(dev->priv);
+	struct rtable *rt = NULL;			/* Route to the other host */
+	struct NET_DEVICE *tdev;			/* Device to other host */
+	struct iphdr  *old_iph;
+	u8     	tos = 0;
+	u16	df = 0;
+	u8	ttl;
+
+	struct iphdr  *iph;			/* Our new IP header */
+        struct udphdr *udph;
+	int    	max_headroom;			/* The extra header space needed */
+	int    	max_tailroom;
+	u32    	dst = tunnel->peeraddr;
+	int    	mtu;
+        int     length = skb->len;
+
+       	dprintk(DEB_OUT, (KERN_INFO "%s: cipe_xmit len=%d\n", dev->name,
+			  length));
+        if (tunnel->magic!=CIPE_MAGIC) {
+            printk(KERN_ERR DEVNAME
+                   ": cipe_xmit called with wrong struct\n");
+            return 0;
+        }
+#ifdef DEBUG
+        if (cipe_debug&DEB_PKOU)
+            cipe_dump_packet("original", skb, 1);
+#endif
+#ifdef VER_ETH
+	/* A packet can contain anything. If sending from a bridge,
+	   the header pointers are invalid. So compute our own. */
+	old_iph = (skb->protocol==htons(ETH_P_IP))
+	          ? (struct iphdr*)(skb->data+ETH_HLEN)
+	          : NULL;
+#else
+	old_iph = skb->nh.iph; /* we get only proper IP packets */
+#endif
+	if (old_iph) {
+	    int ilen = ntohs(old_iph->tot_len)
+#ifdef VER_ETH
+		        +ETH_HLEN
+#endif
+		                 ;
+	    if (length!=ilen) {
+		printk(KERN_ERR "%s: cipe_xmit packet length problem %d/%d\n",
+		       dev->name, length, ilen);
+		goto tx_error_out;
+	    }
+	    tos = old_iph->tos;
+	    df = old_iph->frag_off&__constant_htons(IP_DF);
+	    ttl = tunnel->cttl ? tunnel->cttl : old_iph->ttl;
+	} else {
+	    ttl = tunnel->cttl ? tunnel->cttl : 64; /* XX */
+	}
+
+	if (tunnel->recursion++) {
+        	printk(KERN_ERR "%s: cipe_xmit reentrance\n", dev->name);
+		tunnel->stat.collisions++;
+		goto tx_error_out;
+	}
+#ifndef VER_ETH
+	if (skb->protocol != __constant_htons(ETH_P_IP))
+		goto tx_error_out;
+#endif
+
+#if 0
+        dprintk(DEB_OUT, (KERN_DEBUG "routing dst=%s src=%s tos=%x oif=%d\n",
+                          cipe_ntoa(0, dst), cipe_ntoa(1, tunnel->myaddr),
+                          RT_TOS(tos), tunnel->sock->bound_dev_if));
+#endif
+	if (ip_route_output(&rt, dst, tunnel->sock->rcv_saddr, RT_TOS(tos),
+                            tunnel->sock->bound_dev_if)) {
+            dprintk(DEB_OUT, (KERN_NOTICE "%s: no route\n", dev->name));
+            tunnel->stat.tx_carrier_errors++;
+            dst_link_failure(skb);
+            goto tx_error_out;
+        }
+        if (rt->rt_src!=tunnel->myaddr) {
+            printk(KERN_NOTICE "%s: changing my address: %s\n", dev->name,
+                   cipe_ntoa(rt->rt_src));
+            tunnel->myaddr=tunnel->sock->saddr=rt->rt_src;
+	}
+
+	tdev = rt->u.dst.dev;
+        dprintk(DEB_OUT, (KERN_DEBUG "route dev=%s flags=%x type=%x\n",
+                          tdev->name, rt->rt_flags, rt->rt_type));
+
+	if (tdev == dev) {
+        	printk(KERN_ERR "%s: looped route\n", dev->name);
+		tunnel->stat.collisions++;
+		goto tx_error;
+	}
+
+        mtu = rt->u.dst.pmtu - (cipehdrlen+cipefootlen);
+        if (tunnel->sockshost)
+            mtu -= sizeof(struct sockshdr);
+
+        dprintk(DEB_OUT, (KERN_DEBUG "pmtu=%d dmtu=%d size=%d\n",
+                          mtu, tdev->mtu, skb->len));
+
+	if (mtu < 68) {
+        	printk(KERN_ERR "%s: MTU too small\n", dev->name);
+		tunnel->stat.collisions++;
+		goto tx_error;
+	}
+	if (skb->dst && mtu < skb->dst->pmtu) {
+		skb->dst->pmtu = mtu;
+        	dprintk(DEB_OUT, (KERN_NOTICE "%s: adjusting PMTU\n", dev->name));
+#if 0
+                /* TEST: is this OK? */
+		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+                goto tx_error;
+#endif
+        }
+
+	if (old_iph && (old_iph->frag_off&__constant_htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) {
+        	dprintk(DEB_OUT, (KERN_NOTICE "%s: fragmentation needed\n", dev->name));
+		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+		goto tx_error;
+	}
+
+        max_headroom = ((tdev->hard_header_len+cipehdrlen+
+			 ((tunnel->sockshost) ? sizeof(struct sockshdr) : 0)
+	                )+16)&(~15);
+        max_tailroom = (tunnel->flags&CIPF_HAVE_KEY) ? cipefootlen : 0;
+	{
+	    struct sk_buff *n= skb_copy_expand(skb, max_headroom,
+                                               max_tailroom, GFP_ATOMIC);
+            if (!n) {
+                printk(KERN_INFO "%s: Out of memory, dropped packet\n",
+                       dev->name);
+                goto tx_error;
+            }
+            if (skb->sk)
+                    skb_set_owner_w(n, skb->sk);
+	    dev_kfree_skb(skb);
+            skb = n;
+        }
+	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+	dst_release(skb->dst);
+	skb->dst = &rt->u.dst;
+	skb->protocol = htons(ETH_P_IP);
+
+	if (tunnel->flags&CIPF_HAVE_KEY) {
+#ifndef VER_SHORT
+	    /* Add an IV */
+	    cipe_cryptpad_iv(skb_push(skb, blockSize));
+	    length+=blockSize;
+#endif
+            if (!tunnel->flags&CIPF_MAY_STKEY && !tunnel->flags&CIPF_HAVE_SKEY)
+                /* Attempt to encrypt data using invalid static key */
+                goto tx_error;
+	    cipe_encrypt(tunnel, skb->data, &length, TW_DATA);
+	    /* This is incorrect - the tail room gets first used and then
+	       reserved. Doesn't matter in the current (2.0.29) implementation
+	       of skb_put though. Alternative solution would ruin the nice
+	       module separation - we don't need to know the real amount
+	       of padding here. */
+	    if (length-skb->len > skb->end-skb->tail) {
+		printk(KERN_ERR "%s: tailroom problem %d %d %ld\n",
+		       dev->name, length, skb->len, skb->end-skb->tail);
+		goto tx_error;
+	    }
+	    (void) skb_put(skb, length-skb->len);
+	} else if (!tunnel->flags&CIPF_MAY_CLEAR) {
+	    goto tx_error;
+	}
+
+        if (tunnel->sockshost) {
+	    /* Install a SOCKS header */
+	    struct sockshdr *sh = (struct sockshdr *)
+		skb_push(skb, sizeof(struct sockshdr));
+	    memset(sh, 0, 4);
+	    sh->atyp=1;
+	    /* sockshost and socksport contain the real peer's address
+	       and the configured/guessed peer is really the socks relayer! */
+	    sh->dstaddr=tunnel->sockshost;
+	    sh->dstport=tunnel->socksport;
+	    length+=sizeof(struct sockshdr);
+	}
+
+        /* Install our new headers */
+        udph = skb->h.uh = (struct udphdr *) skb_push(skb, sizeof(struct udphdr));
+	skb->mac.raw = skb_push(skb, sizeof(struct iphdr));
+        iph = skb->nh.iph = (struct iphdr *) skb->mac.raw;
+
+	/*
+	 *	Push down and install the CIPE/UDP header.
+	 */
+	iph->version    =	4;
+	iph->ihl        =	sizeof(struct iphdr)>>2;
+	iph->tos        =	tos;
+	iph->tot_len    =	htons(skb->len);
+	ip_ident(iph, &rt->u.dst);
+        iph->frag_off   =	df;
+        iph->ttl        =	ttl;
+	iph->protocol   =	IPPROTO_UDP;
+	iph->saddr      =	rt->rt_src;
+	iph->daddr      =	rt->rt_dst;
+
+	ip_send_check(iph);
+
+        udph->source = tunnel->myport;
+        udph->dest   = tunnel->peerport;
+        udph->len    = htons(length+sizeof(struct udphdr));
+        /* Encrypted packets are checksummed already, so we can safely
+	   ignore the UDP checksum. Provide a means to do it nonetheless */
+	udph->check  = 0;
+	if (tunnel->flags&CIPF_DO_CSUM) {
+	    udph->check=csum_tcpudp_magic(
+		iph->saddr, iph->daddr,
+		length+sizeof(struct udphdr), IPPROTO_UDP,
+		csum_partial((char *)udph, length+sizeof(struct udphdr), 0));
+	    if (!udph->check)
+		udph->check=-1;
+	}
+
+	tunnel->stat.tx_bytes += skb->len;
+	tunnel->stat.tx_packets++;
+        dprintk(DEB_OUT, (KERN_INFO
+                          "%s: sending %d from %s:%d to %s:%d\n",
+                          dev->name, skb->len,
+                          cipe_ntoa(iph->saddr), ntohs(udph->source),
+                          cipe_ntoa(iph->daddr), ntohs(udph->dest)));
+	if (tunnel->sockshost)
+	    dprintk(DEB_OUT, (KERN_INFO "%s: via SOCKS to %s:%d\n", dev->name,
+			      cipe_ntoa(tunnel->sockshost),
+			      ntohs(tunnel->socksport)));
+#if 0
+        dprintk(DEB_OUT, (KERN_INFO "dst: (%d,%d) %s %d %d\n",
+                          skb->dst->refcnt, skb->dst->use,
+                          skb->dst->dev->name, skb->dst->pmtu,
+                          skb->dst->error));
+#endif
+#ifdef DEBUG
+        if (cipe_debug&DEB_PKOU)
+            cipe_dump_packet("sending", skb, 0);
+#endif
+        nf_conntrack_null(skb);
+#ifdef LINUX_24
+        {
+            int err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
+                              rt->u.dst.dev, ip_send);
+            if (err==NET_XMIT_SUCCESS || err==NET_XMIT_CN) {
+                tunnel->stat.tx_bytes += skb->len;
+                tunnel->stat.tx_packets++;
+            } else {
+                tunnel->stat.tx_errors++;
+                tunnel->stat.tx_aborted_errors++;
+            }
+        }
+#else
+        ip_send(skb);
+#endif
+        tunnel->recursion--;
+	return 0;
+
+ tx_error:
+        ip_rt_put(rt);
+ tx_error_out:
+	tunnel->stat.tx_errors++;
+	dev_kfree_skb(skb);
+	tunnel->recursion--;
+	return 0;
+}
+
+#else /* LINUX_21 */
+
+/* An adapted version of Linux 2.0 drivers/net/new_tunnel.c. */
+
+#ifdef SO_BINDTODEVICE
+  #define iproute(t,o,d) ip_rt_route(t,o,d)
+#else
+  #define iproute(t,o,d) ip_rt_route(t,o)
+#endif
+
+#if LINUX_VERSION_CODE < 131102  /* < 2.0.30 */
+  #include <linux/config.h>
+  #ifdef CONFIG_IP_FORWARD
+    #define ipforward(s,d,o,t) ip_forward(s,d,o,t)
+  #else
+    #error "Requires IP forwarding enabled in kernel"
+  #endif
+#else                            /* >= 2.0.30 */
+  #define ipforward(s,d,o,t) (sysctl_ip_forward ? ip_forward(s,d,o,t) : -1)
+#endif
+
+int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev)
+{
+    struct enet_statistics *stats;	/* This device's statistics */
+    struct rtable *rt;     		/* Route to the other host */
+    struct NET_DEVICE *tdev;		/* Device to other host */
+    struct iphdr  *iph;			/* Our new IP header */
+    struct udphdr *udph;
+    __u32          target;		/* The other host's IP address */
+    int      max_headroom;		/* The extra header space needed */
+    int      max_tailroom;
+    int tos, ttl, length;
+    DEVTOCIPE(dev,c,0);
+
+    if (skb == NULL || dev == NULL) {
+	dprintk(DEB_OUT, (KERN_INFO "%s: nothing to do\n", dev->name));
+	return 0;
+    }
+
+    /*
+     *	Make sure we are not busy (check lock variable)
+     */
+    stats = &(c->stat);
+    if (dev->tbusy != 0)
+    {
+	printk(KERN_WARNING "%s: device timeout (really possible?)\n",
+	       dev->name);
+	dev->tbusy=0;
+	stats->tx_errors++;
+	return(1);
+    }
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKOU)
+        cipe_dump_packet("original", skb, 0);
+#endif
+    /*
+     *  First things first.  Look up the destination address in the
+     *  routing tables
+     */
+    target = c->peeraddr;
+    if ((!target) || (!c->peerport) || (!c->myport)) {
+	/* unconfigured device */
+	printk(KERN_INFO "%s: unconfigured\n", dev->name);
+	goto error;
+    }
+    if ((rt = iproute(target, 0, skb->sk?skb->sk->bound_device:NULL)) == NULL)
+    {
+	/* No route to host */
+	printk(KERN_INFO "%s: target unreachable\n", dev->name);
+	goto error;
+    }
+    dprintk(DEB_OUT, (KERN_INFO
+		      "%s: routing to %08lX from %08lX via %08lX dev %s\n",
+		      dev->name, ntohl(rt->rt_dst), ntohl(rt->rt_src),
+		      ntohl(rt->rt_gateway), rt->rt_dev->name));
+
+    tdev = rt->rt_dev;
+    ip_rt_put(rt);
+
+    if (tdev == dev)
+    {
+	/* Tunnel to ourselves?  -- I don't think so. */
+	printk ( KERN_INFO "%s: Packet targetted at myself!\n" , dev->name);
+	goto error;
+    }
+
+    /*
+     * Okay, now see if we can stuff it in the buffer as-is. We can not.
+     */
+    max_headroom = (((tdev->hard_header_len+15)&~15)+cipehdrlen+
+		    ((c->sockshost) ? sizeof(struct sockshdr) : 0));
+    max_tailroom = (c->flags&CIPF_HAVE_KEY) ? cipefootlen : 0;
+    {
+		struct sk_buff *new_skb;
+
+		if ( !(new_skb =
+		       dev_alloc_skb(skb->len+max_headroom+max_tailroom)) )
+		{
+			printk(KERN_INFO "%s: Out of memory, dropped packet\n",
+			       dev->name);
+  			dev->tbusy = 0;
+  			stats->tx_dropped++;
+			dev_kfree_skb(skb, FREE_WRITE);
+			return 0;
+		}
+		new_skb->free = 1;
+
+		/*
+		 * Reserve space for our header and the lower device header
+		 */
+		skb_reserve(new_skb, max_headroom);
+
+		/*
+		 * Copy the old packet to the new buffer.
+		 * Note that new_skb->h.iph will be our (tunnel driver's) header
+		 * and new_skb->ip_hdr is the IP header of the old packet.
+		 */
+		new_skb->ip_hdr = (struct iphdr *) skb_put(new_skb, skb->len);
+		new_skb->mac.raw = new_skb->data;
+		new_skb->dev = skb->dev;
+		memcpy(new_skb->ip_hdr, skb->data, skb->len);
+		memset(new_skb->proto_priv, 0, sizeof(skb->proto_priv));
+
+		/* Free the old packet, we no longer need it */
+		dev_kfree_skb(skb, FREE_WRITE);
+		skb = new_skb;
+    }
+#ifdef VER_ETH
+    if (skb->mac.ethernet->h_proto==htons(ETH_P_IP)) {
+#endif
+	tos    = skb->ip_hdr->tos;
+	ttl    = skb->ip_hdr->ttl;
+#ifdef VER_ETH
+    } else {
+	tos = 0;
+	ttl = 64;
+    }
+#endif
+        length = skb->len;
+	if (c->flags&CIPF_HAVE_KEY) {
+#ifndef VER_SHORT
+	    /* Add an IV */
+	    cipe_cryptpad(skb_push(skb, blockSize));
+	    length+=blockSize;
+#endif
+            if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_SKEY)
+                /* Attempt to encrypt data using invalid static key */
+                goto error;
+	    cipe_encrypt(c, skb->data, &length, TW_DATA);
+	    /* This is incorrect - the tail room gets first used and then
+	       reserved. Doesn't matter in the current (2.0.29) implementation
+	       of skb_put though. Alternative solution would ruin the nice
+	       module separation - we don't need to know the real amount
+	       of padding here. */
+	    (void) skb_put(skb, length-skb->len);
+	} else if (!c->flags&CIPF_MAY_CLEAR) {
+	    goto error;
+	}
+
+        if (c->sockshost) {
+	    /* Install a SOCKS header */
+	    struct sockshdr *sh = (struct sockshdr *)
+		skb_push(skb, sizeof(struct sockshdr));
+	    memset(sh, 0, 4);
+	    sh->atyp=1;
+	    /* sockshost and socksport contain the real peer's address
+	       and the configured/guessed peer is really the socks relayer! */
+	    sh->dstaddr=c->sockshost;
+	    sh->dstport=c->socksport;
+	    length+=sizeof(struct sockshdr);
+	}
+
+        /* Install our new headers */
+        udph = (struct udphdr *) skb_push(skb, sizeof(struct udphdr));
+        skb->h.iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr));
+
+	/*
+	 *	Push down and install the CIPE/UDP header.
+	 */
+
+	iph 			=	skb->h.iph;
+	iph->version		= 	4;
+	iph->tos		=	tos;
+
+	/* In new_tunnel.c, we use the original packet's TTL here.
+	   Setting a new TTL behaves better to the user, and RFC2003
+	   recommends it too. But this doesn't fully protect against
+	   routing loops. So make it configurable via an argument:
+	   "cttl" gives the TTL value; if 0 use the packet's
+	   value. Default should be 64, as with the other protocols
+	   (ip_statistics.IpDefaultTTL, but this variable is not
+	   available for modules). */
+
+	iph->ttl 		=	c->cttl ? c->cttl : ttl;
+
+	iph->frag_off		=	0;
+	iph->daddr		=	target;
+	iph->saddr		=	c->myaddr; /* tdev->pa_addr; */
+	iph->protocol		=	IPPROTO_UDP;
+	iph->ihl		=	5;
+	iph->tot_len		=	htons(skb->len);
+	iph->id			=	htons(ip_id_count++);	/* Race condition here? */
+	ip_send_check(iph);
+
+        udph->source = c->myport;
+        udph->dest   = c->peerport;
+        udph->len    = htons(length+sizeof(struct udphdr));
+        /* Encrypted packets are checksummed already, so we can safely
+	   ignore the UDP checksum. Provide a means to do it nonetheless */
+	udph->check  = 0;
+	if (c->flags&CIPF_DO_CSUM) {
+	    udph->check=csum_tcpudp_magic(
+		iph->saddr, iph->daddr,
+		length+sizeof(struct udphdr), IPPROTO_UDP,
+		csum_partial((char *)udph, length+sizeof(struct udphdr), 0));
+	    if (!udph->check)
+		udph->check=-1;
+	}
+
+	skb->ip_hdr 		= skb->h.iph;
+	skb->protocol		=	htons(ETH_P_IP);
+
+	/*
+	 *	Send the packet on its way!
+	 *	Note that dev_queue_xmit() will eventually free the skb.
+	 *	If ip_forward() made a copy, it will return 1 so we can free.
+	 */
+
+	dprintk(DEB_OUT, (KERN_INFO "%s: send to %s via %s\n",
+			  dev->name, cipe_ntoa(target), tdev->name));
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKOU)
+        cipe_dump_packet("sending", skb, 0);
+#endif
+	switch (ipforward(skb, dev, IPFWD_NOTTLDEC, target)) {
+	case -1:
+	    printk(KERN_INFO "%s: forwarding failed\n", dev->name);
+	    /* fall thru */
+	case 1:
+	    dev_kfree_skb(skb, FREE_WRITE);
+	    /* Does it really need dev_ here? I think so. */
+	    break;
+	default:
+	    /* nothing to do */
+	}
+
+	/*
+	 *	Clean up:  We're done with the route and the packet
+	 */
+
+	/* Record statistics and return */
+	stats->tx_packets++;
+	dev->tbusy=0;
+	return 0;
+
+    error:
+	stats->tx_errors++;
+	dev_kfree_skb(skb, FREE_WRITE);
+	dev->tbusy=0;
+	return 0;
+}
+
+#endif /* LINUX_21 */
--- linux-2.4.21/drivers/addon/cipe3/sock.c.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/sock.c	Fri Jul 25 15:02:11 2003
@@ -0,0 +1,731 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   sock.c - socket/input interface
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: sock.c,v 1.33.2.3 2002/06/28 23:38:53 olaf Exp $ */
+
+#include "cipe.h"
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <net/sock.h>
+#include <net/ip.h>
+#include <linux/etherdevice.h>
+#ifdef LINUX_21
+#include <asm/uaccess.h>
+#else
+typedef unsigned short mm_segment_t;
+#endif
+
+#ifdef LINUX_21
+#define kfreeskb(s,t) kfree_skb(s)
+#define saddr(skb) ((skb)->nh.iph->saddr)
+#define daddr(skb) ((skb)->nh.iph->daddr)
+#else
+#define kfreeskb(s,t) kfree_skb(s,t)
+#define saddr(skb) ((skb)->saddr)
+#define daddr(skb) ((skb)->daddr)
+#endif
+
+/* Rewire generic socket operations to our device-specific ones.
+   We have new routines for close, sendmsg, recvmsg. */
+
+#ifndef LINUX_21
+#define user_data protinfo.af_packet.bound_dev
+#endif
+
+/* init struct cipe *c based on struct sock *sk */
+#define SOCKTOC(nam,sk,c,r) \
+    struct cipe *c=(struct cipe *)sk->user_data; \
+    if ((!c) || (c->magic!=CIPE_MAGIC)) { \
+	 printk(KERN_ERR "Ouch: SOCKTOC " nam "\n"); return r; } \
+    else { \
+         dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", c->dev->name)); }
+
+
+/* Close the socket */
+void cipe_sock_close(struct sock *sock, timeout_t timeout)
+{
+    SOCKTOC("sock_close",sock,c,);
+    c->sock=NULL;
+
+    /* Put back the old protocol block and let it do the close */
+    sock->prot=c->udp_prot;
+    sock->prot->close(sock, timeout);
+    if (c->dev->flags&IFF_UP) {
+	rtnl_LOCK();
+	dev_close(c->dev);
+	rtnl_UNLOCK();
+    } else {
+	cipe_close(c);
+    }
+}
+
+/* Anything we send to this socket is in fact a key exchange block.
+   Encode and encrypt it accordingly.
+*/
+int cipe_sendmsg(struct sock *sock, struct msghdr *msg, int len
+#ifndef LINUX_21
+                 , int nonblock, int flags
+#endif
+    )
+{
+    struct msghdr mymsg;
+    struct iovec myio[2];
+    struct sockaddr_in sa;
+    struct sockshdr sh;
+    int e, n=0;
+    unsigned char buf[KEYXCHGBLKMAX+blockSize];
+    SOCKTOC("cipe_sendmsg",sock,c,-ENOSYS);
+
+    if (len>KEYXCHGBLKMAX)
+	return -EMSGSIZE;
+#ifdef VER_SHORT
+    if (msg->msg_flags&MSG_OOB)
+	return -EINVAL;
+#endif
+    cipe_prnpad(buf, sizeof(buf));
+#ifdef VER_SHORT
+    memcpy_fromiovec(buf, msg->msg_iov, len);
+#else
+    memcpy_fromiovec(buf+blockSize, msg->msg_iov, len);
+    len+=blockSize;
+#endif
+    if (!(msg->msg_flags&MSG_OOB)) {
+	if (buf[0
+#ifndef VER_SHORT
+	       +blockSize
+#endif
+	                 ]>=CT_DUMMY) {
+	    if (!c->flags&CIPF_HAVE_KEY)
+		return -EINVAL;
+	    buf[KEYXCHGTSPOS-1]='\0';
+	} else {
+	    if (len<KEYXCHGBLKMIN)
+		return -EINVAL;
+	}
+    }
+    (*(__u32 *)(buf+KEYXCHGTSPOS))=htonl(CURRENT_TIME); /* timestamp */
+    if (msg->msg_flags&MSG_OOB) {
+	memset(buf, 0, blockSize);
+    } else {
+	len=KEYXCHGBLKMIN+buf[sizeof(buf)-1]; /* random */
+	cipe_encrypt(c, buf, &len, TW_NEWKEY);
+    }
+
+    sa.sin_family=AF_INET;
+    sa.sin_addr.s_addr=c->peeraddr;
+    sa.sin_port=c->peerport;
+
+    if (c->sockshost) {
+	/* Prepend a socks header. */
+	memset(&sh, 0, sizeof(sh));
+	sh.atyp=1;
+	sh.dstaddr=c->sockshost;
+	sh.dstport=c->socksport;
+	myio[n].iov_base=&sh;
+	myio[n].iov_len=sizeof(sh);
+	++n;
+    }
+    myio[n].iov_base=&buf;
+    myio[n].iov_len=len;
+    /* mymsg=*msg; */
+    mymsg.msg_name=&sa;
+    mymsg.msg_namelen=sizeof(sa);
+    mymsg.msg_iov=myio;
+    mymsg.msg_iovlen=n+1;
+    /* just to be sure */
+    mymsg.msg_control=NULL;
+    mymsg.msg_controllen=0;
+    mymsg.msg_flags=0;
+
+    /* Call the real thing. Pretend this is user space segment. */
+    {
+        mm_segment_t fs=get_fs();
+        set_fs(get_ds());
+        if (c->sockshost)
+            len+=sizeof(struct sockshdr);
+        dprintk(DEB_KXC, (KERN_INFO "%s: real sendmsg len %d text=%04x...\n",
+                          c->dev->name, len,
+                          ntohs(*((unsigned short *)(myio[n].iov_base)))));
+        e=c->udp_prot->sendmsg(sock, &mymsg, len
+#ifndef LINUX_21
+                               , nonblock, flags
+#endif
+            );
+        set_fs(fs);
+    }
+    return e;
+}
+
+/* Check if we have a new peer */
+static void checkpeer(struct cipe *c, __u32 saddr, __u16 sport)
+{
+    if (c->sockshost) {
+	if (c->sockshost==saddr && c->socksport==sport)
+	    return;
+	/* sockshost and socksport contain the real peer's address
+	   and the configured/guessed peer is really the socks relayer! */
+	c->sockshost=saddr;
+	c->socksport=sport;
+    } else {
+	if (c->peeraddr==saddr && c->peerport==sport)
+	    return;
+	c->peeraddr=saddr;
+	c->peerport=sport;
+    }
+    printk(KERN_NOTICE "%s: new peer %s:%d\n",
+	   c->dev->name, cipe_ntoa(saddr), ntohs(sport));
+}
+
+/* Decrypt a received packet. Requeue it or return kxc block. */
+/* On entry the packet starts with the original UDP header,
+   ip_hdr and h.uh are set to the IP and UDP headers. */
+struct sk_buff *cipe_decrypt_skb(struct cipe *c, struct sock *sk,
+				 struct sk_buff *skb,
+                                 int *msgflag)
+{
+    struct sk_buff *n=NULL;
+    int length;
+    __u32 rsaddr;
+    __u16 rsport;
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKIN)
+        cipe_dump_packet("received", skb, 1);
+#endif
+    length=ntohs(skb->h.uh->len)-sizeof(struct udphdr);
+#if 0 /* UDP should check this */
+    if (length!=skb->len-sizeof(struct udphdr)) {
+	dprintk(DEB_INP, (KERN_INFO "%s: bogus UDP length (%d/%d)\n",
+                          c->dev->name, length,
+                          skb->len-sizeof(struct udphdr)));
+	goto framerr;
+    }
+#endif
+    if (length<9+(c->sockshost?sizeof(struct sockshdr):0)) {
+        /* XX hardcoded IV size */
+        printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name,
+               cipe_ntoa(saddr(skb)));
+	goto framerr;
+    }
+
+    n=alloc_skb(skb->len, GFP_KERNEL);
+    if (!n) {
+	printk(KERN_WARNING "%s: cipe_decrypt_skb: out of memory\n",
+	       c->dev->name);
+	++c->stat.rx_dropped;
+	return NULL;
+    }
+#if 0 /*def LINUX_21*/
+    if (skb->sk)
+	skb_set_owner_r(n, skb->sk);
+#endif
+#ifndef LINUX_21
+    n->free=1;
+#endif
+    n->dev=c->dev;
+
+    /* Copy the datagram into new buffer, skip IP header */
+    /* We must copy here because raw sockets get only a clone of the
+       skbuff, so they would receive the plaintext */
+    dprintk(DEB_INP, (KERN_INFO DEVNAME
+                      ": sa=%s da=%s us=%d ud=%d ul=%d\n",
+                      cipe_ntoa(saddr(skb)), cipe_ntoa(daddr(skb)),
+                      ntohs(skb->h.uh->source), ntohs(skb->h.uh->dest),
+                      ntohs(skb->h.uh->len)));
+
+    /* why did this get swapped?? */
+#ifdef LINUX_21
+    rsaddr=saddr(skb);
+#else
+    rsaddr=daddr(skb);
+#endif
+    rsport=skb->h.uh->source;
+    skb_put(n,skb->len);
+    memcpy(n->data, skb->h.raw, skb->len);
+    n->h.uh=(struct udphdr *)n->data;
+
+    if (c->sockshost) {
+	/* Pull out the SOCKS header and correct the peer's address. */
+	struct sockshdr *sh;
+	sh=(struct sockshdr *)skb_pull(n, sizeof(struct udphdr));
+	dprintk(DEB_INP, (KERN_INFO "socks: fr=%d at=%d da=%s dp=%d\n",
+                          sh->frag, sh->atyp,
+                          cipe_ntoa(sh->dstaddr), ntohs(sh->dstport)));
+	if (sh->frag || (sh->atyp!=1))
+	    goto error;
+	/* Pull out UDP header */
+#ifdef LINUX_21
+        n->nh.iph=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr));
+#else
+	n->ip_hdr=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr));
+#endif
+	/***saddr(n)=sh->dstaddr;*/
+        rsaddr=sh->dstaddr;
+	rsport=n->h.uh->source=sh->dstport;
+	length-=sizeof(struct sockshdr);
+    } else {
+	/* Pull out UDP header */
+#ifdef LINUX_21
+	n->nh.iph=(struct iphdr *) skb_pull(n, sizeof(struct udphdr));
+#else
+	n->ip_hdr=(struct iphdr *) skb_pull(n, sizeof(struct udphdr));
+#endif
+	/***saddr(n)=rsaddr;*/
+	n->h.uh->source=rsport;
+    }
+
+#ifndef VER_SHORT
+    if (!(*((__u32 *)n->data) & htonl(0x7FFFFFFF))) {
+	dprintk(DEB_INP, (KERN_INFO "got unencrypted packet (iv=0) len=%d\n",
+			  length));
+	skb_pull(n, blockSize);
+	/* XX not sure about TW_CTRL handling... */
+        switch (*n->data) {
+            /* Restrict what can be received unencrypted. */
+        case CT_DUMMY: case CT_DEBUG: case CT_CONFREQ: case CT_CONF:
+            break;
+        default:
+            printk(KERN_WARNING
+                   "%s: got disallowed unencrypted control %02x\n",
+                   c->dev->name, *n->data);
+            goto error;
+        }
+#ifdef LINUX_21
+	get_fast_time(&n->stamp);
+#endif
+	/* No checkpeer() here because not authenticated! */
+	n->h.uh->check=0;
+	return n;
+    }
+#endif
+    if (c->flags&CIPF_HAVE_KEY) {
+	if (length%blockSize) {
+	    printk(KERN_INFO "%s: got bogus length=%d\n", c->dev->name,
+		   length);
+	    goto error;
+	}
+        switch (cipe_decrypt(c, n->data, &length)) {
+	case TW_DATA:
+            if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_RKEY) {
+                printk(KERN_ERR "%s: got data using invalid static key\n",
+                       c->dev->name);
+                goto error;
+            }
+	    break;
+	case TW_CTRL:
+            /* return it as a control block - out of band datagram */
+            *msgflag|=MSG_OOB;
+            /* fall thru */
+	case TW_NEWKEY:
+	    /* return it as key exchange block - proper UDP datagram */
+	    dprintk(DEB_INP, (KERN_DEBUG "TW_NEWKEY data=%p len=" FLEN
+                              " length=%d\n", n->data, n->len, length));
+#ifdef LINUX_21
+	    get_fast_time(&n->stamp);
+#endif
+	    skb_trim(n, length);
+	    checkpeer(c, rsaddr, rsport);
+#if 0
+	    n->saddr=c->myaddr;
+	    n->daddr=c->peeraddr;
+#endif
+	    n->h.uh->check=0;
+	    return n;
+	default:
+	    /* Bogus packet etc. */
+	    ++c->stat.rx_crc_errors;
+	    goto error;
+	}
+    } else if (!c->flags&CIPF_MAY_CLEAR) {
+	goto error;
+    }
+
+    dprintk(DEB_INP, (KERN_DEBUG "TW_DATA data=%p len=" FLEN "length=%d\n",
+                      n->data, n->len, length));
+    skb_trim(n, length);
+    checkpeer(c, rsaddr, rsport);
+    /* adjust pointers */
+#ifdef VER_ETH
+    n->protocol = eth_type_trans(n, c->dev);
+    /* n->pkt_type = PACKET_HOST; */
+#else
+    n->mac.raw=n->data;	/* no hw header */
+    n->protocol = htons(ETH_P_IP);
+    n->pkt_type = PACKET_HOST;
+#endif
+#ifdef LINUX_21
+    n->nh.raw=n->data;
+    memset(&(IPCB(n)->opt), 0, sizeof(IPCB(n)->opt));
+#else
+    n->h.iph=(struct iphdr *)n->data;
+    memset(n->proto_priv, 0, sizeof(struct options));
+#endif
+    if (length<cipehdrlen+(c->sockshost?sizeof(struct sockshdr):0)) {
+	printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name,
+	       cipe_ntoa(saddr(skb)));
+	goto framerr;
+    }
+
+    n->ip_summed = 0;
+    /* this prints nonsense for non-IP packets. Ignore that. */
+    dprintk(DEB_INP, (KERN_INFO "%s: real src %s dst %s len %d\n",
+                      n->dev->name, cipe_ntoa(saddr(n)),
+                      cipe_ntoa(daddr(n)), length));
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKIN)
+        cipe_dump_packet("decrypted", n, 1);
+#ifdef LINUX_23
+    dprintk(DEB_INP, (KERN_DEBUG "%s state=%ld refcnt=%d\n", n->dev->name, n->dev->state,
+		      atomic_read(&n->dev->refcnt)));
+#endif
+#endif
+
+    /* requeue */
+    netif_rx(n);
+#ifdef LINUX_21
+    c->stat.rx_bytes+=skb->len; /* count carrier-level bytes */
+#endif
+    c->stat.rx_packets++;
+    return NULL;
+
+ framerr:
+    ++c->stat.rx_frame_errors; /* slightly abuse this */
+ error:
+    ++c->stat.rx_errors;
+    if (n)
+	kfreeskb(n, FREE_READ);
+    return NULL;
+}
+
+/* Receive message. If encrypted, put it through the mill.
+   If decrypted, return it as key exchange block.
+   This is mostly from net/ipv4/udp.c, but cipe_decrypt_skb pulls the
+   UDP header.
+*/
+
+int cipe_recvmsg(struct sock *sk, struct msghdr *msg, int len,
+		 int noblock, int flags,int *addr_len)
+{
+  	int copied;
+  	struct sk_buff *skb, *skn;
+  	int er=0;
+  	struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
+	SOCKTOC("cipe_recvmsg",sk,c,-ENOSYS);
+
+	/*
+	 *	Check any passed addresses
+	 */
+
+  	if (addr_len)
+  		*addr_len=sizeof(*sin);
+
+	/*
+	 *	From here the generic datagram does a lot of the work. Come
+	 *	the finished NET3, it will do _ALL_ the work!
+	 */
+
+	do {
+	    /* CIPE: look if the packet is encrypted, repeat until
+	       a decrypted one is found */
+	    skn=NULL;
+	    skb=skb_recv_datagram(sk,flags,noblock,&er);
+	    if(skb==NULL) {
+		dprintk(DEB_KXC, (KERN_INFO "%s: skb_recv_datagram: %d\n",
+                                  c->dev->name, er));
+                return er;
+	    }
+
+	    if (!skb->h.uh->source) {
+		/* Synthetic KXC packets are marked by source port 0.
+		   Correct this - we know the truth from our structure.
+		   Perhaps it would be better to not correct it so the
+		   user level daemon can spot the difference? */
+		skb->h.uh->source=c->peerport;
+		skb_pull(skb, sizeof(struct udphdr));
+		break;
+	    }
+	    skn=cipe_decrypt_skb(c, sk, skb, &(msg->msg_flags));
+	    skb_free_datagram(sk, skb);
+	    skb=skn;
+	} while (skb==NULL);
+
+	dprintk(DEB_INP, (KERN_INFO "%s: returning " FLEN " flags %04x\n",
+			  c->dev->name, skb->len, msg->msg_flags));
+  	copied = skb->len;
+	if (copied > len)
+	{
+		copied = len;
+#ifdef LINUX_21
+		msg->msg_flags |= MSG_TRUNC;
+#endif
+	}
+	if (copied<=0) {
+	    printk(KERN_ERR "cipe_recvmsg: bogus length %d\n", copied);
+	    goto out_free;
+	}
+
+  	/*
+  	 *	FIXME : should use udp header size info value
+  	 */
+#ifdef LINUX_21
+#if 0
+	er = skb_copy_datagram_iovec(skb, skb->data-skb-h.raw,
+				     msg->msg_iov, copied);
+#else
+	er = memcpy_toiovec(msg->msg_iov, skb->data, copied);
+#endif
+	if (er<0)
+		goto out_free;
+#else
+#if 0
+        skb_copy_datagram_iovec(skb,of,msg->msg_iov,copied);
+#else
+	memcpy_toiovec(msg->msg_iov, skb->data, copied);
+#endif
+#endif
+	sk->stamp=skb->stamp;
+
+	/* Copy the address. */
+	if (sin
+#ifdef LINUX_21
+            && skb->nh.iph   /* Fake KXC has no address */
+#endif
+	) {
+		sin->sin_family = AF_INET;
+		sin->sin_port = skb->h.uh->source;
+                sin->sin_addr.s_addr = daddr(skb);
+	}
+        er=copied;
+
+ out_free:
+	if (skb==skn)
+	    /* the buffer was a copy made by decryption */
+	    kfreeskb(skb, FREE_READ);
+	else
+	    skb_free_datagram(sk, skb);
+
+  	return(er);
+}
+
+#ifdef LINUX_21
+
+#include <linux/file.h>
+
+int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm)
+{
+    struct file *file;
+    struct inode *inode;
+    struct socket *sock;
+    struct sock *sk;
+#if 0
+    struct in_device *indev;
+#endif
+    struct cipe *c0;
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    if (c->sock)
+        return -EBUSY;
+    if (!(file=fget(parm->fd)))
+        return(-EBADF);
+    inode = file->f_dentry->d_inode;
+    if (!inode || !inode->i_sock || !(sock=&inode->u.socket_i)) {
+        fput(file);
+        return(-ENOTSOCK);
+    }
+    if (sock->file != file) {
+        printk(KERN_ERR DEVNAME ": socki_lookup: socket file changed!\n");
+        sock->file = file;
+    }
+
+    fput(file);
+    if (sock->type!=SOCK_DGRAM)
+	return(-ESOCKTNOSUPPORT);
+    if (sock->ops->family!=AF_INET)
+	return(-EAFNOSUPPORT);
+
+    sk=sock->sk;
+    if (sk->state!=TCP_ESTABLISHED)
+	return(-ENOTCONN);
+    if (((c0=(struct cipe *)sk->user_data)) &&
+	(c0->magic==CIPE_MAGIC))
+	return(-EBUSY); /* socket is already attached */
+
+    cipe_use_module();
+    c->owner=current->pid;
+    c->sock=sk;
+    c->peeraddr=sk->daddr;
+    c->peerport=sk->dport;
+    c->myaddr=sk->saddr;
+    if (c->flags&CIPF_MAY_DYNIP)
+        sk->rcv_saddr=0;
+    c->myport=htons(sk->num);
+    /* Disconnect socket, we might receive from somewhere else */
+    sk->daddr=0;
+    sk->dport=0;
+
+    /* Fill an otherwise unused field in the sock struct with this info.
+       This field is conveniently named and the kernel uses it only for RPC. */
+    sk->user_data=c;
+    sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1;
+
+    /* Set up new socket operations */
+    c->udp_prot=sk->prot;
+    c->cipe_proto=*sk->prot;
+    c->cipe_proto.close=cipe_sock_close;
+    c->cipe_proto.sendmsg=cipe_sendmsg;
+    c->cipe_proto.recvmsg=cipe_recvmsg;
+    sk->prot=&c->cipe_proto;
+
+#if 0
+    /* (Try to) Set our dummy hardware address from the IP address. */
+    /* This does not work, because the IP address is set
+       _after_ the attach... */
+    if ((indev=dev->ip_ptr)) {
+	struct in_ifaddr **ifap = NULL;
+	struct in_ifaddr *ifa = NULL;
+	for (ifap=&indev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
+	    if (strcmp(dev->name, ifa->ifa_label) == 0)
+		break;
+	if (ifa) {
+	    char *x=(char *)&ifa->ifa_local;
+	    dev->dev_addr[3]=x[1]|0x80;
+	    dev->dev_addr[4]=x[2];
+	    dev->dev_addr[5]=x[3];
+	}
+    }
+#endif
+
+    return(0);
+}
+
+
+#else /* LINUX_21 */
+
+#define sreturn(x) {sti(); return((x));}
+
+int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm)
+{
+    struct file *file;
+    struct inode *inode;
+    struct socket *sock;
+    struct sock *sk;
+    int fd=parm->fd;
+    struct cipe *c0;
+    DEVTOCIPE(dev,c,-ENODEV);
+    cli();
+    if (c->sock)
+	sreturn(-EBUSY);
+
+    /* Find the socket (from net/socket.c) */
+    if (fd < 0 || fd >= NR_OPEN || !(file = current->files->fd[fd]))
+	sreturn(-EBADF);
+    inode = file->f_inode;
+    if (!inode || !inode->i_sock)
+	sreturn(-ENOTSOCK);
+    sock=&inode->u.socket_i;
+    if (sock->type!=SOCK_DGRAM)
+	sreturn(-ESOCKTNOSUPPORT);
+    if (sock->ops->family!=AF_INET)
+	sreturn(-EAFNOSUPPORT);
+    sk=(struct sock *)sock->data;
+    if (sk->state!=TCP_ESTABLISHED)
+	sreturn(-ENOTCONN);
+    if (((c0=(struct cipe *)sk->protinfo.af_packet.bound_dev)) &&
+	(c0->magic==CIPE_MAGIC))
+	sreturn(-EBUSY); /* socket is already attached */
+
+    cipe_use_module();
+    c->owner=current->pid;
+    c->sock=sk;
+    c->peeraddr=sk->daddr;
+    c->peerport=sk->dummy_th.dest;
+    c->myaddr=sk->saddr;
+    if (c->flags&CIPF_MAY_DYNIP)
+        sk->rcv_saddr=0;
+    c->myport=sk->dummy_th.source;
+    /* Disconnect socket, we might receive from somewhere else */
+    sk->daddr=0;
+    sk->dummy_th.dest=0;
+
+    /* Set up new socket operations */
+    c->udp_prot=sk->prot;
+    c->cipe_proto=*sk->prot;
+    c->cipe_proto.close=cipe_sock_close;
+    c->cipe_proto.sendmsg=cipe_sendmsg;
+    c->cipe_proto.recvmsg=cipe_recvmsg;
+    sk->prot=&c->cipe_proto;
+
+    /* Fill an otherwise unused field in the sock struct with this info.
+       Actually, this is very similar to a packet socket!
+       The ugly cast saves us one deref in the actual ops */
+    sk->protinfo.af_packet.bound_dev=(struct NET_DEVICE *)c;
+    sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1;
+
+    sti();
+    return 0;
+}
+
+#endif
+
+
+/* Build and enqueue a fake UDP packet to receive.
+   Note that these are neither encrypted nor SOCKSed.
+*/
+void cipe_fakenkey(struct cipe *c, char typ)
+{
+    int len=sizeof(struct udphdr)+KEYXCHGBLKMIN;
+    struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
+
+    if (!skb) {
+        printk(KERN_WARNING "%s: cipe_fakenkey: out of memory\n",
+               c->dev->name);
+        return; /* not much we can do */
+    }
+
+    dprintk(DEB_KXC, (KERN_INFO "%s: fake kxc block typ=%d\n",
+                      c->dev->name, typ));
+
+    skb->sk=NULL;
+    skb->dev=c->dev;
+
+    skb->h.uh=(struct udphdr *)skb->data;
+    skb->len=len;
+#ifdef LINUX_21
+    skb->nh.iph=NULL;
+#else
+    saddr(skb)=c->myaddr;
+    daddr(skb)=c->peeraddr;
+    skb->free=1; /* Discard after use */
+    skb->ip_hdr=NULL;
+#endif
+    skb->h.uh->source=0; /* mark as KXC packet */
+    skb->h.uh->dest=c->myport;
+    len-=sizeof(struct udphdr);
+    skb->h.uh->len=htons(len);
+    skb->h.uh->check=0;
+    skb->mac.raw=skb->data; /* no hardware header */
+
+    /* All those contortions for just one byte of payload data.
+       Since we generate only NK_RREQ and NK_REQ it's effectively
+       one _bit_... */
+    skb->data[sizeof(struct udphdr)]=typ;
+    (*(__u32 *)(skb->data+sizeof(struct udphdr)+KEYXCHGTSPOS))=
+        htonl(CURRENT_TIME); /* even need timestamp */
+
+    if (sock_queue_rcv_skb(c->sock, skb)<0) {
+        printk(KERN_WARNING "%s: cipe_fakenkey: enqueuing failed\n",
+               c->dev->name);
+        kfreeskb(skb, FREE_WRITE);
+    }
+}
--- linux-2.4.21/drivers/addon/cipe3/version.h.CIPE3	Fri Jul 25 15:02:11 2003
+++ linux-2.4.21/drivers/addon/cipe3/version.h	Fri Jul 25 15:07:36 2003
@@ -0,0 +1,5 @@
+#define VERSION "1.5.4"
+#define ProtocolVersion 3
+#undef Crypto_IDEA 
+#define Crypto_Blowfish 1
+#undef NO_DYNDEV 
-------------- next part --------------
--- linux-2.4.21/drivers/addon/cipe4/Makefile.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/Makefile	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,23 @@
+#   -*-Makefile-*- template for the CIPE kernel module and driver.
+#   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+#
+#   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.
+
+O_TARGET := cipdb.o
+
+obj-y := module.o device.o sock.o output.o encaps.o crc32.o bf.o
+obj-m := $(O_TARGET)
+
+ifeq ($(ARCH),i386)
+  obj-y += bf-i386.o
+endif
+
+include $(TOPDIR)/Rules.make
+
+ifeq ($(ARCH),i386)
+bf-i386.o: bf-i386.S
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+endif
--- linux-2.4.21/drivers/addon/cipe4/ciped.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/ciped.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,43 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   ciped.h - prototypes for user level routines
+
+   Copyright 1997 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: ciped.h,v 1.6 2000/12/16 17:49:06 olaf Exp $ */
+
+#include <signal.h>
+#include <netinet/in.h>
+#include "cipe.h"
+#include "options.h"
+
+/* options.c */
+struct options {
+    const char * const oname;
+    const char otyp;
+    union {
+	int ovint;
+	char *ovstr;
+	struct sockaddr_in *ovsaddr;
+    } ov;
+};
+extern struct options opts[];
+#define Tbool	0
+#define Tint	1
+#define Tstr	2
+#define Taddr	3
+#define Tuaddr	4
+#define Ttaddr	5
+#define Tsecret 6
+
+#define OI(x)      (opts[O##x].ov.ovint)
+#define OS(x)      (opts[O##x].ov.ovstr)
+#define OA(x)      (opts[O##x].ov.ovsaddr)
+#define OAaddr(x)  (OA(x)->sin_addr)
+#define OAport(x)  (OA(x)->sin_port)
--- linux-2.4.21/drivers/addon/cipe4/cipe.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/cipe.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,426 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   cipe.h - contains definitions, includes etc. common to all modules
+
+   Copyright 1996-2000 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: cipe.h,v 1.38.2.2 2002/06/28 23:38:53 olaf Exp $ */
+
+#ifndef _CIPE_H_
+#define _CIPE_H_
+
+#include "crypto.h"
+#ifdef __KERNEL__
+#include <linux/if.h>
+#else
+#include <net/if.h>
+#endif
+
+/*** The kernel/user IOCTL interface ***/
+
+/* ioctls for setup and key exchange */
+/* #define SIOCxIFCIPxxx   (SIOCDEVPRIVATE+x) */
+/* All ioctls are passed a struct ifreq <net/if.h> which contains the
+   device name in ifr_name and a pointer to the actual control struct
+   in ifr_data. */
+
+#if 0
+/* Get interface parameters. Currently unused */
+#define SIOCGIFCIPPAR   (SIOCDEVPRIVATE+0)
+struct  siocgifcippar {
+    unsigned long       magic;
+    /* SOCKS5 relayer */
+    unsigned long       sockshost;
+    unsigned short      socksport;
+    /* Timeouts (in seconds) */
+    int                 tmo_keyxchg;
+    int                 tmo_keylife;
+    /* Flags */
+    int                 flags;
+    int		        cttl;
+};
+#endif
+
+/* Set interface parameters. */
+#define SIOCSIFCIPPAR   (SIOCDEVPRIVATE+1)
+struct  siocsifcippar {
+    unsigned long       magic;
+    /* SOCKS5 relayer */
+    unsigned long       sockshost;
+    unsigned short      socksport;
+    /* Timeouts (in seconds) */
+    int                 tmo_keyxchg;
+    int                 tmo_keylife;
+    /* Flags */
+    int                 flags;
+    int		        cttl;
+};
+
+/* Set a key. */
+#define SIOCSIFCIPKEY   (SIOCDEVPRIVATE+2)
+#define KEY_STATIC      1
+#define KEY_SEND        2
+#define KEY_RECV        3
+#define KEY_INVAL       8
+#define KEY_MAXLEN      32
+struct  siocsifcipkey {
+    unsigned long       magic;
+    int                 which;
+    char                thekey[KEY_MAXLEN];
+    int                 keylen;
+};
+
+/* Attach a socket. */
+#define SIOCSIFCIPATT   (SIOCDEVPRIVATE+3)
+struct  siocsifcipatt {
+    unsigned long       magic;
+    int                 fd;
+};
+
+/* Allocate/deallocate a device. */
+#define SIOCSIFCIPALL   (SIOCDEVPRIVATE+4)
+#define SIOCSIFCIPUNA   (SIOCDEVPRIVATE+5)
+struct  siocsifcipall {
+    unsigned long       magic;
+    int                 num;
+    char                name[IFNAMSIZ];
+};
+
+/* Flag values. */
+#define CIPF_MAY_CLEAR          0x0100
+#define CIPF_MAY_STKEY          0x0200
+#define CIPF_MAY_DYNIP          0x0400
+#define CIPF_DO_CSUM		0x0800
+
+/*** Key exchange related definitions ***/
+
+/* Minimum kxc block. */
+#define KEYXCHGBLKMIN   64
+/* Maximum kxc block, padded with random bytes */
+#define KEYXCHGBLKMAX   (KEYXCHGBLKMIN+256)
+/* Position of the timestamp */
+#define KEYXCHGTSPOS    56
+/* Type words. Only 4 are possible. */
+#define TW_DATA         0
+#define TW_NEWKEY       2
+#define TW_CTRL         4
+#define TW_RSVD2        6
+/* error indication, no valid type word */
+#define TW_ERROR        1
+
+/* NEWKEY (key exchange mode 1) subtypes. */
+#define NK_RREQ         0 /* not used in protocol */
+#define NK_REQ          1 /* send me your new key */
+#define NK_IND          2 /* this is my new key   */
+#define NK_ACK          3 /* i have your new key  */
+
+/* CTRL subtypes. By now sent in a TW_NEWKEY packet. */
+#define CT_DUMMY     0x70 /* ignore */
+#define CT_DEBUG     0x71 /* log */
+#define CT_PING      0x72 /* send PONG */
+#define CT_PONG      0x73
+#define CT_KILL      0x74 /* exit */
+#define CT_CONFREQ   0x75 /* log, send CONF */
+#define CT_CONF	     0x76 /* log */
+
+/*** Kernel-module internal stuff ***/
+
+#ifdef __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/sockios.h>
+#include <linux/sched.h>
+#include <linux/if_ether.h>
+#include <linux/net.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <net/sock.h>
+#include <linux/version.h>
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define LINUX_21
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#define LINUX_23
+#endif
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)) && defined(__i386__)
+#define REGPARM /* __attribute__((regparm,3)) XX needs testing */
+#else
+#define REGPARM
+#endif
+
+#ifdef LINUX_21
+#ifndef SPIN_LOCK_UNLOCKED /* 2.2/2.4 incompat */
+#include <asm/spinlock.h>
+#endif
+#endif
+
+#if 1 /* Lock tracing */
+#define DOLOCK(s) ({ printk(KERN_DEBUG DEVNAME ": " #s " at %s:%d\n", \
+			    __FILE__, __LINE__); s; })
+#else
+#define DOLOCK(s) s
+#endif
+
+#ifdef LINUX_23
+#define tasklist_LOCK()		DOLOCK(read_lock(&tasklist_lock))
+#define tasklist_UNLOCK()	DOLOCK(read_unlock(&tasklist_lock))
+#else
+#define tasklist_LOCK()		/* nop */
+#define tasklist_UNLOCK()	/* nop */
+#endif
+
+#ifdef LINUX_21
+/* In 2.1 the ioctl operations are run under lock. Beware of deadlocks. */
+#define cipe_alloc_LOCK()       0 /* nop */
+#define cipe_alloc_UNLOCK()	  /* nop */
+#else
+extern struct semaphore cipe_alloc_sem;
+#define cipe_alloc_LOCK()       DOLOCK(down_interruptible(&cipe_alloc_sem))
+#define cipe_alloc_UNLOCK()     DOLOCK(up(&cipe_alloc_sem))
+#endif
+
+#ifdef LINUX_21
+#define FLEN "%d"
+#else
+#define FLEN "%ld"
+#endif
+
+#ifdef LINUX_23
+#define rtnl_LOCK()		DOLOCK(rtnl_lock())
+#define rtnl_UNLOCK()		DOLOCK(rtnl_unlock())
+#else
+#define rtnl_LOCK()		/* nop */
+#define rtnl_UNLOCK()		/* nop */
+#endif
+
+#ifdef LINUX_23
+#define NET_DEVICE net_device
+#define DEV_STATS  net_device_stats
+#else
+#define NET_DEVICE device
+#define DEV_STATS  enet_statistics
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127)
+#define timeout_t unsigned long
+#else
+#define timeout_t long
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99)
+#define HAVE_DEVNAME_ARRAY
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17)
+#define get_fast_time do_gettimeofday
+#endif
+
+/* The header we add to each packet */
+#ifdef VER_ETH
+#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr)+blockSize+ETH_HLEN)
+#else
+#ifdef VER_SHORT
+#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr))
+#else
+#define cipehdrlen (sizeof(struct iphdr)+sizeof(struct udphdr)+blockSize)
+#endif
+#endif
+/* ...plus a real hardware header (common case) */
+#define cipexhdrl  (cipehdrlen+((ETH_HLEN+15)&~15))
+/* max. padding at the end */
+#if ProtocolVersion >= 3
+#define cipefootlen 12 /* 7 bytes pad, 1 byte type, 4 bytes CRC */
+#else
+#define cipefootlen 10 /* 8 bytes pad, 2 bytes CRC */
+#endif
+
+/* A CIPE device's parameter block */
+
+#define CIPE_MAGIC  (htonl(0x43495045))
+struct cipe {
+    __u32               magic;
+    struct NET_DEVICE   *dev;
+     /* Set by user process */
+    __u32               peeraddr;
+    __u32               myaddr;
+    __u16               peerport;
+    __u16               myport;
+    __u32               sockshost;
+    __u16               socksport;
+    short	        cttl;
+#ifdef Crypto_IDEA
+    Key                 key_e, key_d, skey_e, rkey_d;
+#endif
+#ifdef Crypto_Blowfish
+    Key                 key, skey, rkey;
+    #define key_e       key
+    #define key_d       key
+    #define skey_e      skey
+    #define rkey_d      rkey
+#endif
+    unsigned long       tmo_keyxchg;
+    unsigned long       tmo_keylife;
+     /* Internal */
+    unsigned long       timekx;
+    unsigned long       timeskey;
+    unsigned long       timerkey;
+    int                 cntskey;
+    int                 cntrkey;
+    struct sock         *sock;
+    int                 flags;
+#ifdef LINUX_21
+    char                recursion;
+#endif
+    pid_t               owner;
+    /* Statistics */
+#ifdef LINUX_21
+    struct net_device_stats stat;
+#else
+    struct enet_statistics stat;
+#endif
+    /* Socket interface stuff */
+    struct proto        *udp_prot;
+    struct proto        cipe_proto;
+};
+
+/* Flag values (internally used) */
+#define CIPF_HAVE_KEY           0x0001
+#define CIPF_HAVE_SKEY          0x0002
+#define CIPF_HAVE_RKEY          0x0004
+#define CIPF_MASK_INT           0x00FF
+#define CIPF_MASK_EXT           0xFF00
+
+#define MAXBLKS         32767  /* max # blocks to encrypt using one key */
+
+/* Define, init and check a struct cipe * variable. */
+#define DEVTOCIPE(dev,c,err) \
+    struct cipe *c = (struct cipe*)(dev->priv); \
+    if (!c || c->magic!=CIPE_MAGIC) return err;
+
+/* Master control struct */
+struct cipe_ctrl {
+#ifndef HAVE_DEVNAME_ARRAY
+    char                name[IFNAMSIZ];
+#endif
+    struct cipe         cipe;
+    struct NET_DEVICE 	dev;
+};
+
+extern struct cipe_ctrl **cipe_ctrls;
+extern int cipe_maxdev;
+
+/* SOCKS5 encapsulation header */
+struct sockshdr {
+    char                rsv[2];
+    char                frag;
+    char                atyp;
+    __u32               dstaddr __attribute__((packed));
+    __u16               dstport __attribute__((packed));
+};
+
+#ifdef DEBUG
+extern int cipe_debug;
+
+#if 0
+/* Lock around our printks, to avoid mixing up dumps. NOT for regular use. */
+extern spinlock_t cipe_printk_lock;
+#define LOCK_PRINTK unsigned long flags; spin_lock_irqsave(&cipe_printk_lock, flags)
+#define UNLOCK_PRINTK spin_unlock_irqrestore(&cipe_printk_lock, flags)
+#else
+#define LOCK_PRINTK	/* nop */
+#define UNLOCK_PRINTK	/* nop */
+#endif
+
+#define DEB_CALL        1
+#define DEB_INP         2
+#define DEB_OUT         4
+#define DEB_CRYPT       8
+#define DEB_KXC         16
+#define DEB_PKIN        32
+#define DEB_PKOU        64
+#define DEB_CHKP	128
+
+#define dprintk(l,p)	if(cipe_debug&l){LOCK_PRINTK; printk p; UNLOCK_PRINTK;}
+
+#else
+#define dprintk(l,p)	/* nop */
+
+#endif /* DEBUG */
+
+#if defined(DEBUG) && defined(LINUX_23)
+#define __CHECKPOINT(F,L) printk(KERN_DEBUG "CHECKPOINT " F ":%d\n", L)
+#define CHECKPOINT if (cipe_debug&DEB_CHKP){\
+    LOCK_PRINTK; __CHECKPOINT(__FILE__,__LINE__); UNLOCK_PRINTK;\
+    current->state=TASK_INTERRUPTIBLE; schedule_timeout(HZ/20); }
+#else
+#define CHECKPOINT	/* nop */
+#endif
+
+static inline void nf_conntrack_null(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETFILTER
+    nf_conntrack_put(skb->nfct);
+    skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+    skb->nf_debug = 0;
+#endif
+#endif
+}
+
+/* internal routines */
+/* module.c */
+extern void cipe_use_module(void);
+extern void cipe_unuse_module(void);
+extern int cipe_check_kernel(void);
+/* device.c */
+extern void cipe_prnpad(unsigned char *buf, int len) REGPARM;
+extern void cipe_close(struct cipe *c);
+extern const char *cipe_ntoa(__u32 addr) REGPARM;
+/* sock.c */
+extern int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm)
+    REGPARM;
+extern void cipe_fakenkey(struct cipe *c, char typ) REGPARM;
+/* output.c */
+#ifdef DEBUG
+extern void cipe_dump_packet(char *title, struct sk_buff *skb, int dumpskb)
+    REGPARM;
+#endif
+extern int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev);
+/* encaps.c */
+extern void cipe_encrypt(struct cipe *c, unsigned char *buf,
+			 int *len, int typcode) REGPARM;
+extern unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf,
+				   int *len) REGPARM;
+#ifndef VER_SHORT
+extern void cipe_cryptpad(unsigned char *buf) REGPARM;
+extern void cipe_cryptpad_iv(unsigned char *buf) REGPARM;
+#endif
+
+#endif /* __KERNEL__ */
+
+#ifdef VER_CRC32
+/* crc32.c */
+extern unsigned long crc32(const unsigned char *s, unsigned int len);
+#else
+/* crc.c */
+extern unsigned short block_crc(unsigned char *d, int len);
+#endif
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+#ifndef DEVNAME
+#define DEVNAME "cip" VERNAME CRNAME
+#endif
+
+#endif /* _CIPE_H_ */
--- linux-2.4.21/drivers/addon/cipe4/config.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/config.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,54 @@
+/* config.h.  Generated automatically by configure.  */
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   Copyright 1999 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+
+/* Config-dependent defines. Always include this first. */
+/* @api means the next line is used for determining the version magic */
+
+/* Version of the CIPE package @api */
+#define VERSION "1.5.4"
+#define VERSION_MAJ 1
+
+/* Encapsulation protocol version @api */
+#define ProtocolVersion 4
+
+/* Cipher algorithm selection @api */
+/* #undef Crypto_IDEA */
+/* Cipher algorithm selection @api */
+#define Crypto_Blowfish 1
+
+/* Assembler module selection */
+/* #undef ASM_IDEA_Crypt */
+#ifdef __i386
+#define ASM_BF_Crypt 1
+#endif
+
+/* Debug code in kernel */
+#define DEBUG 1
+
+/* Use old key parser */
+/* #undef BUG_COMPATIBLE */
+
+/* Dynamic device allocation @api */
+/* #undef NO_DYNDEV */
+
+/* Syslog facility */
+#define LOGFAC LOG_DAEMON
+
+/* Memory management functions (kernel version dependent?) */
+#define HAVE_MLOCK 1
+#define HAVE_MLOCKALL 1
+
+/* End of autoconf options */
+
+/* This tells the Blowfish module to omit unneeded code */
+#define BF_DONTNEED_BE
+
--- linux-2.4.21/drivers/addon/cipe4/crc32.c.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/crc32.c	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,111 @@
+  /* ============================================================= */
+  /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or       */
+  /*  code or tables extracted from it, as desired without restriction.     */
+  /*                                                                        */
+  /*  First, the polynomial itself and its table of feedback terms.  The    */
+  /*  polynomial is                                                         */
+  /*  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0   */
+  /*                                                                        */
+  /*  Note that we take it "backwards" and put the highest-order term in    */
+  /*  the lowest-order bit.  The X^32 term is "implied"; the LSB is the     */
+  /*  X^31 term, etc.  The X^0 term (usually shown as "+1") results in      */
+  /*  the MSB being 1.                                                      */
+  /*                                                                        */
+  /*  Note that the usual hardware shift register implementation, which     */
+  /*  is what we're using (we're merely optimizing it by doing eight-bit    */
+  /*  chunks at a time) shifts bits into the lowest-order term.  In our     */
+  /*  implementation, that means shifting towards the right.  Why do we     */
+  /*  do it this way?  Because the calculated CRC must be transmitted in    */
+  /*  order from highest-order term to lowest-order term.  UARTs transmit   */
+  /*  characters in order from LSB to MSB.  By storing the CRC this way,    */
+  /*  we hand it to the UART in the order low-byte to high-byte; the UART   */
+  /*  sends each low-bit to hight-bit; and the result is transmission bit   */
+  /*  by bit from highest- to lowest-order term without requiring any bit   */
+  /*  shuffling on our part.  Reception works similarly.                    */
+  /*                                                                        */
+  /*  The feedback terms table consists of 256, 32-bit entries.  Notes:     */
+  /*                                                                        */
+  /*      The table can be generated at runtime if desired; code to do so   */
+  /*      is shown later.  It might not be obvious, but the feedback        */
+  /*      terms simply represent the results of eight shift/xor opera-      */
+  /*      tions for all combinations of data and CRC register values.       */
+  /*                                                                        */
+  /*      The values must be right-shifted by eight bits by the "updcrc"    */
+  /*      logic; the shift must be unsigned (bring in zeroes).  On some     */
+  /*      hardware you could probably optimize the shift in assembler by    */
+  /*      using byte-swap instructions.                                     */
+  /*      polynomial $edb88320                                              */
+  /*                                                                        */
+  /*  --------------------------------------------------------------------  */
+
+static unsigned long crc32_tab[] = {
+      0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+      0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+      0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+      0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+      0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+      0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+      0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+      0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+      0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+      0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+      0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+      0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+      0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+      0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+      0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+      0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+      0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+      0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+      0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+      0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+      0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+      0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+      0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+      0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+      0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+      0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+      0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+      0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+      0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+      0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+      0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+      0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+      0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+      0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+      0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+      0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+      0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+      0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+      0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+      0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+      0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+      0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+      0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+      0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+      0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+      0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+      0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+      0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+      0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+      0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+      0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+      0x2d02ef8dL
+   };
+
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+unsigned long crc32(const unsigned char *s, unsigned int len)
+{
+  unsigned int i;
+  unsigned long crc32val;
+  
+  crc32val = 0;
+  for (i = 0;  i < len;  i ++)
+    {
+      crc32val =
+	crc32_tab[(crc32val ^ s[i]) & 0xff] ^
+	  (crc32val >> 8);
+    }
+  return crc32val;
+}
--- linux-2.4.21/drivers/addon/cipe4/crypto.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/crypto.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,100 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   crypto.h - configuration of the crypto algorithm
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: crypto.h,v 1.8 2000/09/13 21:46:41 olaf Exp $ */
+
+#ifndef _CRYPTO_H_
+#define _CRYPTO_H_
+
+#include "version.h"
+
+typedef unsigned long part;
+/* the longest integer so that sizeof(part) divides blockSize.
+   Used only for optimizing block-copy and block-XOR operations. */
+
+#if     ProtocolVersion == 1
+
+#ifdef  OLDNAMES
+#define VERNAME "1"
+#else
+#define VERNAME "a"
+#endif
+#define VER_BACK                /* encryption progress backwards */
+#define VER_SHORT               /* no IV in packet */
+
+#elif   ProtocolVersion == 2
+
+#ifdef  OLDNAMES
+#define VERNAME "2"
+#else
+#define VERNAME "b"
+#endif
+
+#elif   ProtocolVersion == 3
+
+#ifdef  OLDNAMES
+#define VERNAME "3"
+#else
+#define VERNAME "c"
+#endif
+#define VER_CRC32               /* checksums are 32bit */
+
+#elif   ProtocolVersion == 4
+
+#ifdef  OLDNAMES
+#define VERNAME "4"
+#else
+#define VERNAME "d"
+#endif
+#define VER_CRC32
+#define VER_ETH
+
+#else
+#error  "Must specify correct ProtocolVersion"
+#endif
+
+
+#ifdef  Crypto_IDEA
+#define CRYPTO                  "IDEA"
+#define CRNAME			"i"
+#define CRNAMEC			'i'
+#define CRNUM			0
+#include "idea0.h"
+#define Key                     Idea_Key
+#define keySize                 Idea_keySize
+#define UserKey                 Idea_UserKey
+#define userKeySize             Idea_userKeySize
+#define ExpandUserKey           Idea_ExpandUserKey
+#define InvertKey               Idea_InvertKey
+#define blockSize               Idea_dataSize
+
+#else
+#ifdef  Crypto_Blowfish
+#define CRYPTO                  "Blowfish"
+#define CRNAME			"b"
+#define CRNAMEC			'b'
+#define CRNUM			1
+#include "bf.h"
+#define Key                     Blowfish_Key
+#define keySize                 sizeof(Blowfish_Key)
+#define UserKey                 Blowfish_UserKey
+#define userKeySize             16 /* arbitrary, but matches IDEA */
+#define ExpandUserKey(u,k)      Blowfish_ExpandUserKey(u,userKeySize,k)
+#define InvertKey(x,y)          /* noop */
+#define blockSize               sizeof(Blowfish_Data)
+
+#else
+#error  "Must specify Crypto_IDEA or Crypto_Blowfish"
+#endif
+#endif
+
+#endif
--- linux-2.4.21/drivers/addon/cipe4/encaps.c.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/encaps.c	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,313 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   encaps.c - do encryption
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: encaps.c,v 1.18 2000/09/13 21:46:41 olaf Exp $ */
+
+#include "cipe.h"
+#include <asm/string.h>
+#include <linux/socket.h>
+
+static inline void xorbuf(part *dst, part *src)
+{
+    int i;
+    for (i=0; i<blockSize/sizeof(part); ++i)
+	*dst++^=*src++;
+}
+
+#ifdef Crypto_IDEA
+/* This seems to be the only way to typecast an array.
+   Important: GCC is able to swallow the overhead when optimizing. */
+static inline void ecb_enc(part *src, part *dst, Idea_Key k)
+{
+    Idea_Data *s=(Idea_Data *)src;
+    Idea_Data *d=(Idea_Data *)dst;
+    Idea_Crypt(*s, *d, k);
+}
+#define ecb_dec(s,d,k) ecb_enc(s,d,k)
+#endif
+
+#ifdef Crypto_Blowfish
+#define ecb_enc(s,d,k) L_Blowfish_Encrypt(s,d,k)
+#define ecb_dec(s,d,k) L_Blowfish_Decrypt(s,d,k)
+#endif
+
+#ifdef VER_BACK
+
+/* Encrypt/decrypt message in CBC mode backwards.
+   Key must be set up accordingly */
+static void cbc_b(unsigned char *msg, int len, Idea_Key *key, int dec)
+{
+    int i=len/blockSize;
+    unsigned char iv[blockSize], iw[blockSize];
+    part *p=(part*)(msg+len-blockSize);
+    part *q=(part*)iv;
+    part *r=(part*)iw;
+    part *s;
+
+    memset(iv, 0, blockSize);
+    if (dec) {
+	while (i-->0) {
+	    memcpy(r, p, blockSize);
+	    ecb_dec(p, p, key);
+	    xorbuf(p, q);
+	    s=q; q=r; r=s;
+	    p-=blockSize/sizeof(part);
+	}
+    } else {
+	while (i-->0) {
+	    xorbuf(p, q);
+	    ecb_enc(p, p, key);
+	    q=p;
+	    p-=blockSize/sizeof(part);
+	}
+    }
+}
+
+#else
+
+/*
+  CBC encryption/decryption routines.
+  Note: the block to encrypt includes the IV, while decryption swallows
+  the IV. Length is always including IV.
+*/
+
+#define partinc(p) ((p)+blockSize/sizeof(part))
+
+static void cbc_enc(unsigned char *msg, int len, Key * const key)
+{
+    part *p=(part *)msg;
+    int i=len/blockSize;
+
+#if 0
+    dprintk(DEB_CRYPT, (KERN_DEBUG "cbc_enc: %08x %08x ",
+			*((__u32*)partinc(msg)), *(__u32*)key));
+#endif
+    while (--i>0) {
+	xorbuf(partinc(p), p);
+	p=partinc(p);
+	ecb_enc(p, p, *key);
+    }
+#if 0
+    dprintk(DEB_CRYPT, ("%08x\n", *((__u32*)partinc(msg))));
+#endif
+}
+
+static void cbc_dec(unsigned char *msg, int len, Key * const key)
+{
+    part *p=(part *)msg;
+    int i=len/blockSize;
+    part r[blockSize/sizeof(part)];
+
+#if 0
+    dprintk(DEB_CRYPT, (KERN_DEBUG "cbc_dec: %08x %08x ",
+			*(__u32*)msg, *(__u32*)key));
+#endif
+    while (--i>0) {
+	ecb_dec(partinc(p), r, *key);
+	xorbuf(p, r);
+	p=partinc(p);
+    }
+#if 0
+    dprintk(DEB_CRYPT, ("%08x\n", *(__u32*)msg));
+#endif
+}
+
+#endif
+
+#ifndef VER_SHORT
+/* Fill a block of length blockSize with strong random numbers.
+   Used for generating IVs. */
+void cipe_cryptpad(unsigned char *buf)
+{
+    static int padcnt=MAXBLKS;
+    static Key padkey;
+
+    if (++padcnt>MAXBLKS) {
+	/* make a new random key */
+	UserKey k;
+	dprintk(DEB_CRYPT, (KERN_INFO "%s: re-keying cryptpad\n", DEVNAME));
+	cipe_prnpad((unsigned char*)k, sizeof(UserKey));
+	ExpandUserKey(k, padkey);
+	padcnt=0;
+    }
+    *(int *)(buf)=padcnt;
+    cipe_prnpad(buf+sizeof(int), blockSize-sizeof(int));
+    ecb_enc((part*)buf, (part*)buf, padkey);
+}
+
+void cipe_cryptpad_iv(unsigned char *buf)
+{
+    int i=5;
+    do {
+	cipe_cryptpad(buf);
+	if (*((__u32 *)buf) & htonl(0x7FFFFFFF))
+	    break;
+    } while (i-->0);
+    if (!i)
+	printk(KERN_CRIT "cipe_cryptpad_iv failed");
+}
+#endif
+
+
+void cipe_checkskey(struct cipe *c)
+{
+    if ((++c->cntskey>MAXBLKS) || (jiffies>c->timeskey)) {
+	/* make the control process send an NK_IND */
+	cipe_fakenkey(c, NK_REQ);
+	c->timeskey=jiffies+c->tmo_keyxchg;
+	if (c->cntskey>MAXBLKS)
+	    c->cntskey-=1000;
+    }
+}
+
+void cipe_checkrkey(struct cipe *c)
+{
+    if ((c->flags&CIPF_HAVE_RKEY) &&
+	((++c->cntrkey>MAXBLKS*2) || (jiffies>c->timerkey))) {
+	/* make the control process send an NK_REQ */
+	cipe_fakenkey(c, NK_RREQ);
+	c->flags&=~CIPF_HAVE_RKEY;
+	c->timerkey=jiffies+c->tmo_keyxchg;
+	if (c->cntrkey>MAXBLKS*2)
+	    c->cntrkey-=1000;
+    }
+}
+
+void cipe_nodynkey(struct cipe *c)
+{
+    if (jiffies>c->timerkey) {
+	/* make the control process send an NK_REQ */
+	cipe_fakenkey(c, NK_RREQ);
+	c->timerkey=jiffies+c->tmo_keyxchg;
+    }
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: missing dynamic key\n",
+	     c->dev->name));
+}
+
+#if ProtocolVersion >= 3
+
+/* Encryption/decryption version 3 */
+
+void cipe_encrypt(struct cipe *c, unsigned char *buf, int *len, int typ)
+{
+    unsigned char p=7-(((*len)+4)&7);
+    /* merge key flag in IV */
+    *buf&=0x7F;
+    if (c->flags&CIPF_HAVE_SKEY)
+	*buf|=0x80;
+    /* pad */
+    cipe_prnpad(buf+(*len), p);
+    (*len)+=p+5;
+    /* set type and crc */
+    *(buf+(*len)-5)=typ|(p<<4);
+    *((unsigned long *)(buf+(*len)-4))=
+	htonl(crc32(buf+blockSize, (*len)-blockSize-4));
+
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: encrypt typ %d pad %d len %d\n",
+                        c->dev->name, typ, p, *len));
+    cbc_enc(buf, *len, c->flags&CIPF_HAVE_SKEY ? &c->skey_e : &c->key_e);
+    cipe_checkskey(c);
+}
+
+unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf, int *len)
+{
+    unsigned char p;
+
+    if (((*buf)&0x80) && !(c->flags&CIPF_HAVE_RKEY)) {
+	cipe_nodynkey(c);
+	return TW_ERROR; /* can't decrypt - no valid key */
+    }
+    cbc_dec(buf, *len, ((*buf)&0x80) ? &c->rkey_d : &c->key_d);
+    (*len)-=blockSize;
+    if (*((unsigned long *)(buf+(*len)-4)) != htonl(crc32(buf, (*len)-4))) {
+	dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt CRC error\n",
+			    c->dev->name));
+	return TW_ERROR;
+    }
+    p=*(buf+(*len)-5);
+    (*len)-=(p>>4)&7;
+    cipe_checkrkey(c);
+#define CTLBITS 0x06
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt len=%d pad=%d typ=%02X\n",
+                        c->dev->name, (*len), (p>>4)&7, p&CTLBITS));
+    return (p&CTLBITS);
+}
+
+#else
+
+/* Encryption/decryption version 1 and 2 */
+
+void cipe_encrypt(struct cipe *c, unsigned char *buf, int *len, int typ)
+{
+    unsigned short x;
+    unsigned char p;
+
+    p=8-((*len)&7);
+    cipe_prnpad(buf+(*len), p);
+    (*len)+=p;
+
+#ifdef VER_SHORT
+    x=((block_crc(buf, *len)&0xFFFE)^((p&7)<<8)^typ)|(c->haveskey);
+#else
+    x=((block_crc(buf+blockSize, (*len)-blockSize)&0xFFFE)
+       ^((p&7)<<8)^typ)|(c->haveskey);
+#endif
+#ifdef VER_BACK
+    cbc_b(buf, *len, c->haveskey ? &c->skey_e : &c->key_e, 0);
+#else
+    cbc_enc(buf, *len, c->haveskey ? &c->skey_e : &c->key_e);
+#endif
+
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: encrypt pad %d\n", c->dev->name, p));
+    buf[(*len)++]=x>>8;
+    buf[(*len)++]=x&255;
+    cipe_checkskey(c);
+}
+
+unsigned short cipe_decrypt(struct cipe *c, unsigned char *buf, int *len)
+{
+    unsigned short x=(buf[(*len)-1])+(buf[(*len)-2]<<8);
+    unsigned char p;
+
+    if ((x&1) && !(c->haverkey)) {
+	cipe_nodynkey(c);
+	return TW_ERROR; /* can't decrypt - no valid key */
+    }
+    (*len)-=2;
+    if (*len<9
+#ifndef VER_SHORT
+	+blockSize
+#endif
+	)
+	return TW_ERROR; /* short packet */
+
+#ifdef VER_BACK
+    cbc_b(buf, *len, (x&1) ? &c->rkey_d : &c->key_d, 1);
+#else
+    cbc_dec(buf, *len, (x&1) ? &c->rkey_d : &c->key_d);
+#endif
+#ifndef VER_SHORT
+    (*len)-=blockSize;
+#endif
+
+    x^=block_crc(buf, *len);
+    p=(x>>8)&7; if (!p) p=8;
+    (*len)-=p;
+    cipe_checkrkey(c);
+
+#define CTLBITS 0xF8FE
+    dprintk(DEB_CRYPT, (KERN_INFO "%s: decrypt pad %d typ %04X\n",
+			c->dev->name, (x>>8)&7, x&CTLBITS));
+    return (x&CTLBITS); /* delete the control bits */
+}
+
+#endif
--- linux-2.4.21/drivers/addon/cipe4/ioctl.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/ioctl.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,24 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   ioctl.h - prototype for the ioctl interface, user part
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: ioctl.h,v 1.3 2000/03/27 17:38:23 olaf Exp $ */
+
+#include "cipe.h"
+
+#ifdef SIOCGIFCIPPAR
+extern int ioctl_getpar(int fd, char *ifname, struct siocgifcippar *sio);
+#endif
+extern int ioctl_setpar(int fd, char *ifname, struct siocsifcippar *sio);
+extern int ioctl_setkey(int fd, char *ifname, struct siocsifcipkey *sio);
+extern int ioctl_attach(int fd, char *ifname, struct siocsifcipatt *sio);
+extern int ioctl_alloc(int fd, char *ifname, struct siocsifcipall *sio);
+extern int ioctl_unalloc(int fd, char *ifname, struct siocsifcipall *sio);
--- linux-2.4.21/drivers/addon/cipe4/module.c.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/module.c	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,89 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   module.c - kernel module interface stuff
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: module.c,v 1.5.2.1 2002/05/30 11:49:17 olaf Exp $ */
+
+#include "cipe.h"
+#include <linux/module.h>
+#include <linux/utsname.h>
+
+/* We put this all here so that none of the other source files needs
+   to include <linux/module.h>, which could lead to collisions. */
+
+#ifdef LINUX_21
+MODULE_AUTHOR("Olaf Titz <olaf at bigred.inka.de>");
+MODULE_DESCRIPTION("Encrypting IP-over-UDP tunnel");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+MODULE_PARM(cipe_maxdev,"i");
+MODULE_PARM_DESC(cipe_maxdev,"Maximum device number supported");
+#ifdef DEBUG
+MODULE_PARM(cipe_debug,"i");
+MODULE_PARM_DESC(cipe_debug,"Debugging level");
+#endif
+#endif
+
+void cipe_use_module(void)
+{
+    MOD_INC_USE_COUNT;
+}
+
+void cipe_unuse_module(void)
+{
+    MOD_DEC_USE_COUNT;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,30)
+/* older kernel not always exported this */
+
+int bad_user_access_length(void)
+{
+    panic("bad_user_access_length in " DEVNAME);
+}
+
+#endif
+
+/* HACK: sanity check on SMP/non-SMP.
+   Is this really necessary? */
+int cipe_check_kernel(void)
+{
+    int s=0;
+    const char *p=system_utsname.version;
+    while (p[0] && p[1] && p[2]) {
+	if (p[0]=='S' && p[1]=='M' && p[2]=='P') {
+	    s=1;
+	    break;
+	}
+	++p;
+    }
+    if (
+#ifdef __SMP__
+	!
+#endif
+         s) {
+	printk(KERN_ERR
+	       DEVNAME ": driver ("
+#ifndef __SMP__
+	       "not "
+#endif
+	       "SMP) "
+	       "mismatches kernel ("
+#ifdef __SMP__
+	       "not "
+#endif
+	       "SMP)\n");
+	return -EINVAL;
+    }
+    return 0;
+}
--- linux-2.4.21/drivers/addon/cipe4/options.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/options.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,29 @@
+/* File generated by genoptions.pl, do not edit */
+
+#define Odevice	0
+#define Odebug	1
+#define Oipaddr	2
+#define Optpaddr	3
+#define Omask	4
+#define Obcast	5
+#define Omtu	6
+#define Ometric	7
+#define Octtl	8
+#define Ome	9
+#define Opeer	10
+#define Okey	11
+#define Onokey	12
+#define Osocks	13
+#define Otokxc	14
+#define Otokey	15
+#define Oipup	16
+#define Oipdown	17
+#define Oarg	18
+#define Omaxerr	19
+#define Otokxts	20
+#define Oping	21
+#define Otoping	22
+#define Odynip	23
+#define Ohwaddr	24
+#define Oifconfig	25
+#define Ochecksum	26
--- linux-2.4.21/drivers/addon/cipe4/output.c.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/output.c	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,621 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   output.c - the sending part of the CIPE device
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: output.c,v 1.40.2.2 2002/06/28 23:38:53 olaf Exp $ */
+
+#include "cipe.h"
+
+#include <net/checksum.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <linux/if_arp.h>
+#include <linux/socket.h>
+#include <linux/version.h>
+#ifdef LINUX_24
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#endif
+
+#ifdef DEBUG
+
+#include "../lib/hexdump.c"
+
+void cipe_dump_packet(char *title, struct sk_buff *skb, int dumpskb)
+{
+    LOCK_PRINTK;
+    if (dumpskb) {
+	printk(KERN_DEBUG "SKB (%s):\n", skb->dev?skb->dev->name:"");
+	cipe_hexdump((unsigned char *)skb, sizeof(*skb));
+    }
+    printk(KERN_DEBUG
+           "%s: packet len=" FLEN " dev=%s\n",
+           title, skb->len, skb->dev?skb->dev->name:"<none>");
+    cipe_hexdump((unsigned char *)skb->data, skb->tail-skb->data);
+    UNLOCK_PRINTK;
+}
+#endif
+
+#ifdef LINUX_21
+
+/* An adapted version of Linux 2.1 net/ipv4/ipip.c output routine. */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,37)
+#define ip_ident(h,d) (h)->id=htons(ip_id_count++)
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
+#define ip_ident(h,d) ip_select_ident(h,d)
+#else
+#define ip_ident(h,d) ip_select_ident(h,d,NULL)
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,36)
+/* this is not exactly the newer kernel's routine, it just does what we need */
+struct sk_buff *skb_copy_expand(struct sk_buff *skb, int max_headroom,
+				int max_tailroom, int gfp)
+{
+    struct sk_buff *n=alloc_skb(skb->len+max_headroom+max_tailroom, gfp);
+    if (n) {
+	skb_reserve(n, max_headroom);
+	skb_put(n,skb->len);
+	memcpy(n->data,skb->data,skb->len);
+	n->priority=skb->priority;
+	n->protocol=skb->protocol;
+	n->dev=skb->dev;
+	n->dst=dst_clone(skb->dst);
+	memcpy(n->cb, skb->cb, sizeof(skb->cb));
+	n->used=skb->used;
+	n->is_clone=0;
+	atomic_set(&n->users, 1);
+	n->pkt_type=skb->pkt_type;
+	n->stamp=skb->stamp;
+	n->security=skb->security;
+#ifdef CONFIG_IP_FIREWALL
+	n->fwmark = skb->fwmark;
+#endif
+    }
+    return n;
+}
+#endif
+
+int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev)
+{
+        struct cipe *tunnel = (struct cipe*)(dev->priv);
+	struct rtable *rt = NULL;			/* Route to the other host */
+	struct NET_DEVICE *tdev;			/* Device to other host */
+	struct iphdr  *old_iph;
+	u8     	tos = 0;
+	u16	df = 0;
+	u8	ttl;
+
+	struct iphdr  *iph;			/* Our new IP header */
+        struct udphdr *udph;
+	int    	max_headroom;			/* The extra header space needed */
+	int    	max_tailroom;
+	u32    	dst = tunnel->peeraddr;
+	int    	mtu;
+        int     length = skb->len;
+
+       	dprintk(DEB_OUT, (KERN_INFO "%s: cipe_xmit len=%d\n", dev->name,
+			  length));
+        if (tunnel->magic!=CIPE_MAGIC) {
+            printk(KERN_ERR DEVNAME
+                   ": cipe_xmit called with wrong struct\n");
+            return 0;
+        }
+#ifdef DEBUG
+        if (cipe_debug&DEB_PKOU)
+            cipe_dump_packet("original", skb, 1);
+#endif
+#ifdef VER_ETH
+	/* A packet can contain anything. If sending from a bridge,
+	   the header pointers are invalid. So compute our own. */
+	old_iph = (skb->protocol==htons(ETH_P_IP))
+	          ? (struct iphdr*)(skb->data+ETH_HLEN)
+	          : NULL;
+#else
+	old_iph = skb->nh.iph; /* we get only proper IP packets */
+#endif
+	if (old_iph) {
+	    int ilen = ntohs(old_iph->tot_len)
+#ifdef VER_ETH
+		        +ETH_HLEN
+#endif
+		                 ;
+	    if (length!=ilen) {
+		printk(KERN_ERR "%s: cipe_xmit packet length problem %d/%d\n",
+		       dev->name, length, ilen);
+		goto tx_error_out;
+	    }
+	    tos = old_iph->tos;
+	    df = old_iph->frag_off&__constant_htons(IP_DF);
+	    ttl = tunnel->cttl ? tunnel->cttl : old_iph->ttl;
+	} else {
+	    ttl = tunnel->cttl ? tunnel->cttl : 64; /* XX */
+	}
+
+	if (tunnel->recursion++) {
+        	printk(KERN_ERR "%s: cipe_xmit reentrance\n", dev->name);
+		tunnel->stat.collisions++;
+		goto tx_error_out;
+	}
+#ifndef VER_ETH
+	if (skb->protocol != __constant_htons(ETH_P_IP))
+		goto tx_error_out;
+#endif
+
+#if 0
+        dprintk(DEB_OUT, (KERN_DEBUG "routing dst=%s src=%s tos=%x oif=%d\n",
+                          cipe_ntoa(0, dst), cipe_ntoa(1, tunnel->myaddr),
+                          RT_TOS(tos), tunnel->sock->bound_dev_if));
+#endif
+	if (ip_route_output(&rt, dst, tunnel->sock->rcv_saddr, RT_TOS(tos),
+                            tunnel->sock->bound_dev_if)) {
+            dprintk(DEB_OUT, (KERN_NOTICE "%s: no route\n", dev->name));
+            tunnel->stat.tx_carrier_errors++;
+            dst_link_failure(skb);
+            goto tx_error_out;
+        }
+        if (rt->rt_src!=tunnel->myaddr) {
+            printk(KERN_NOTICE "%s: changing my address: %s\n", dev->name,
+                   cipe_ntoa(rt->rt_src));
+            tunnel->myaddr=tunnel->sock->saddr=rt->rt_src;
+	}
+
+	tdev = rt->u.dst.dev;
+        dprintk(DEB_OUT, (KERN_DEBUG "route dev=%s flags=%x type=%x\n",
+                          tdev->name, rt->rt_flags, rt->rt_type));
+
+	if (tdev == dev) {
+        	printk(KERN_ERR "%s: looped route\n", dev->name);
+		tunnel->stat.collisions++;
+		goto tx_error;
+	}
+
+        mtu = rt->u.dst.pmtu - (cipehdrlen+cipefootlen);
+        if (tunnel->sockshost)
+            mtu -= sizeof(struct sockshdr);
+
+        dprintk(DEB_OUT, (KERN_DEBUG "pmtu=%d dmtu=%d size=%d\n",
+                          mtu, tdev->mtu, skb->len));
+
+	if (mtu < 68) {
+        	printk(KERN_ERR "%s: MTU too small\n", dev->name);
+		tunnel->stat.collisions++;
+		goto tx_error;
+	}
+	if (skb->dst && mtu < skb->dst->pmtu) {
+		skb->dst->pmtu = mtu;
+        	dprintk(DEB_OUT, (KERN_NOTICE "%s: adjusting PMTU\n", dev->name));
+#if 0
+                /* TEST: is this OK? */
+		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+                goto tx_error;
+#endif
+        }
+
+	if (old_iph && (old_iph->frag_off&__constant_htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) {
+        	dprintk(DEB_OUT, (KERN_NOTICE "%s: fragmentation needed\n", dev->name));
+		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+		goto tx_error;
+	}
+
+        max_headroom = ((tdev->hard_header_len+cipehdrlen+
+			 ((tunnel->sockshost) ? sizeof(struct sockshdr) : 0)
+	                )+16)&(~15);
+        max_tailroom = (tunnel->flags&CIPF_HAVE_KEY) ? cipefootlen : 0;
+	{
+	    struct sk_buff *n= skb_copy_expand(skb, max_headroom,
+                                               max_tailroom, GFP_ATOMIC);
+            if (!n) {
+                printk(KERN_INFO "%s: Out of memory, dropped packet\n",
+                       dev->name);
+                goto tx_error;
+            }
+            if (skb->sk)
+                    skb_set_owner_w(n, skb->sk);
+	    dev_kfree_skb(skb);
+            skb = n;
+        }
+	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+	dst_release(skb->dst);
+	skb->dst = &rt->u.dst;
+	skb->protocol = htons(ETH_P_IP);
+
+	if (tunnel->flags&CIPF_HAVE_KEY) {
+#ifndef VER_SHORT
+	    /* Add an IV */
+	    cipe_cryptpad_iv(skb_push(skb, blockSize));
+	    length+=blockSize;
+#endif
+            if (!tunnel->flags&CIPF_MAY_STKEY && !tunnel->flags&CIPF_HAVE_SKEY)
+                /* Attempt to encrypt data using invalid static key */
+                goto tx_error;
+	    cipe_encrypt(tunnel, skb->data, &length, TW_DATA);
+	    /* This is incorrect - the tail room gets first used and then
+	       reserved. Doesn't matter in the current (2.0.29) implementation
+	       of skb_put though. Alternative solution would ruin the nice
+	       module separation - we don't need to know the real amount
+	       of padding here. */
+	    if (length-skb->len > skb->end-skb->tail) {
+		printk(KERN_ERR "%s: tailroom problem %d %d %ld\n",
+		       dev->name, length, skb->len, skb->end-skb->tail);
+		goto tx_error;
+	    }
+	    (void) skb_put(skb, length-skb->len);
+	} else if (!tunnel->flags&CIPF_MAY_CLEAR) {
+	    goto tx_error;
+	}
+
+        if (tunnel->sockshost) {
+	    /* Install a SOCKS header */
+	    struct sockshdr *sh = (struct sockshdr *)
+		skb_push(skb, sizeof(struct sockshdr));
+	    memset(sh, 0, 4);
+	    sh->atyp=1;
+	    /* sockshost and socksport contain the real peer's address
+	       and the configured/guessed peer is really the socks relayer! */
+	    sh->dstaddr=tunnel->sockshost;
+	    sh->dstport=tunnel->socksport;
+	    length+=sizeof(struct sockshdr);
+	}
+
+        /* Install our new headers */
+        udph = skb->h.uh = (struct udphdr *) skb_push(skb, sizeof(struct udphdr));
+	skb->mac.raw = skb_push(skb, sizeof(struct iphdr));
+        iph = skb->nh.iph = (struct iphdr *) skb->mac.raw;
+
+	/*
+	 *	Push down and install the CIPE/UDP header.
+	 */
+	iph->version    =	4;
+	iph->ihl        =	sizeof(struct iphdr)>>2;
+	iph->tos        =	tos;
+	iph->tot_len    =	htons(skb->len);
+	ip_ident(iph, &rt->u.dst);
+        iph->frag_off   =	df;
+        iph->ttl        =	ttl;
+	iph->protocol   =	IPPROTO_UDP;
+	iph->saddr      =	rt->rt_src;
+	iph->daddr      =	rt->rt_dst;
+
+	ip_send_check(iph);
+
+        udph->source = tunnel->myport;
+        udph->dest   = tunnel->peerport;
+        udph->len    = htons(length+sizeof(struct udphdr));
+        /* Encrypted packets are checksummed already, so we can safely
+	   ignore the UDP checksum. Provide a means to do it nonetheless */
+	udph->check  = 0;
+	if (tunnel->flags&CIPF_DO_CSUM) {
+	    udph->check=csum_tcpudp_magic(
+		iph->saddr, iph->daddr,
+		length+sizeof(struct udphdr), IPPROTO_UDP,
+		csum_partial((char *)udph, length+sizeof(struct udphdr), 0));
+	    if (!udph->check)
+		udph->check=-1;
+	}
+
+	tunnel->stat.tx_bytes += skb->len;
+	tunnel->stat.tx_packets++;
+        dprintk(DEB_OUT, (KERN_INFO
+                          "%s: sending %d from %s:%d to %s:%d\n",
+                          dev->name, skb->len,
+                          cipe_ntoa(iph->saddr), ntohs(udph->source),
+                          cipe_ntoa(iph->daddr), ntohs(udph->dest)));
+	if (tunnel->sockshost)
+	    dprintk(DEB_OUT, (KERN_INFO "%s: via SOCKS to %s:%d\n", dev->name,
+			      cipe_ntoa(tunnel->sockshost),
+			      ntohs(tunnel->socksport)));
+#if 0
+        dprintk(DEB_OUT, (KERN_INFO "dst: (%d,%d) %s %d %d\n",
+                          skb->dst->refcnt, skb->dst->use,
+                          skb->dst->dev->name, skb->dst->pmtu,
+                          skb->dst->error));
+#endif
+#ifdef DEBUG
+        if (cipe_debug&DEB_PKOU)
+            cipe_dump_packet("sending", skb, 0);
+#endif
+        nf_conntrack_null(skb);
+#ifdef LINUX_24
+        {
+            int err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
+                              rt->u.dst.dev, ip_send);
+            if (err==NET_XMIT_SUCCESS || err==NET_XMIT_CN) {
+                tunnel->stat.tx_bytes += skb->len;
+                tunnel->stat.tx_packets++;
+            } else {
+                tunnel->stat.tx_errors++;
+                tunnel->stat.tx_aborted_errors++;
+            }
+        }
+#else
+        ip_send(skb);
+#endif
+        tunnel->recursion--;
+	return 0;
+
+ tx_error:
+        ip_rt_put(rt);
+ tx_error_out:
+	tunnel->stat.tx_errors++;
+	dev_kfree_skb(skb);
+	tunnel->recursion--;
+	return 0;
+}
+
+#else /* LINUX_21 */
+
+/* An adapted version of Linux 2.0 drivers/net/new_tunnel.c. */
+
+#ifdef SO_BINDTODEVICE
+  #define iproute(t,o,d) ip_rt_route(t,o,d)
+#else
+  #define iproute(t,o,d) ip_rt_route(t,o)
+#endif
+
+#if LINUX_VERSION_CODE < 131102  /* < 2.0.30 */
+  #include <linux/config.h>
+  #ifdef CONFIG_IP_FORWARD
+    #define ipforward(s,d,o,t) ip_forward(s,d,o,t)
+  #else
+    #error "Requires IP forwarding enabled in kernel"
+  #endif
+#else                            /* >= 2.0.30 */
+  #define ipforward(s,d,o,t) (sysctl_ip_forward ? ip_forward(s,d,o,t) : -1)
+#endif
+
+int cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev)
+{
+    struct enet_statistics *stats;	/* This device's statistics */
+    struct rtable *rt;     		/* Route to the other host */
+    struct NET_DEVICE *tdev;		/* Device to other host */
+    struct iphdr  *iph;			/* Our new IP header */
+    struct udphdr *udph;
+    __u32          target;		/* The other host's IP address */
+    int      max_headroom;		/* The extra header space needed */
+    int      max_tailroom;
+    int tos, ttl, length;
+    DEVTOCIPE(dev,c,0);
+
+    if (skb == NULL || dev == NULL) {
+	dprintk(DEB_OUT, (KERN_INFO "%s: nothing to do\n", dev->name));
+	return 0;
+    }
+
+    /*
+     *	Make sure we are not busy (check lock variable)
+     */
+    stats = &(c->stat);
+    if (dev->tbusy != 0)
+    {
+	printk(KERN_WARNING "%s: device timeout (really possible?)\n",
+	       dev->name);
+	dev->tbusy=0;
+	stats->tx_errors++;
+	return(1);
+    }
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKOU)
+        cipe_dump_packet("original", skb, 0);
+#endif
+    /*
+     *  First things first.  Look up the destination address in the
+     *  routing tables
+     */
+    target = c->peeraddr;
+    if ((!target) || (!c->peerport) || (!c->myport)) {
+	/* unconfigured device */
+	printk(KERN_INFO "%s: unconfigured\n", dev->name);
+	goto error;
+    }
+    if ((rt = iproute(target, 0, skb->sk?skb->sk->bound_device:NULL)) == NULL)
+    {
+	/* No route to host */
+	printk(KERN_INFO "%s: target unreachable\n", dev->name);
+	goto error;
+    }
+    dprintk(DEB_OUT, (KERN_INFO
+		      "%s: routing to %08lX from %08lX via %08lX dev %s\n",
+		      dev->name, ntohl(rt->rt_dst), ntohl(rt->rt_src),
+		      ntohl(rt->rt_gateway), rt->rt_dev->name));
+
+    tdev = rt->rt_dev;
+    ip_rt_put(rt);
+
+    if (tdev == dev)
+    {
+	/* Tunnel to ourselves?  -- I don't think so. */
+	printk ( KERN_INFO "%s: Packet targetted at myself!\n" , dev->name);
+	goto error;
+    }
+
+    /*
+     * Okay, now see if we can stuff it in the buffer as-is. We can not.
+     */
+    max_headroom = (((tdev->hard_header_len+15)&~15)+cipehdrlen+
+		    ((c->sockshost) ? sizeof(struct sockshdr) : 0));
+    max_tailroom = (c->flags&CIPF_HAVE_KEY) ? cipefootlen : 0;
+    {
+		struct sk_buff *new_skb;
+
+		if ( !(new_skb =
+		       dev_alloc_skb(skb->len+max_headroom+max_tailroom)) )
+		{
+			printk(KERN_INFO "%s: Out of memory, dropped packet\n",
+			       dev->name);
+  			dev->tbusy = 0;
+  			stats->tx_dropped++;
+			dev_kfree_skb(skb, FREE_WRITE);
+			return 0;
+		}
+		new_skb->free = 1;
+
+		/*
+		 * Reserve space for our header and the lower device header
+		 */
+		skb_reserve(new_skb, max_headroom);
+
+		/*
+		 * Copy the old packet to the new buffer.
+		 * Note that new_skb->h.iph will be our (tunnel driver's) header
+		 * and new_skb->ip_hdr is the IP header of the old packet.
+		 */
+		new_skb->ip_hdr = (struct iphdr *) skb_put(new_skb, skb->len);
+		new_skb->mac.raw = new_skb->data;
+		new_skb->dev = skb->dev;
+		memcpy(new_skb->ip_hdr, skb->data, skb->len);
+		memset(new_skb->proto_priv, 0, sizeof(skb->proto_priv));
+
+		/* Free the old packet, we no longer need it */
+		dev_kfree_skb(skb, FREE_WRITE);
+		skb = new_skb;
+    }
+#ifdef VER_ETH
+    if (skb->mac.ethernet->h_proto==htons(ETH_P_IP)) {
+#endif
+	tos    = skb->ip_hdr->tos;
+	ttl    = skb->ip_hdr->ttl;
+#ifdef VER_ETH
+    } else {
+	tos = 0;
+	ttl = 64;
+    }
+#endif
+        length = skb->len;
+	if (c->flags&CIPF_HAVE_KEY) {
+#ifndef VER_SHORT
+	    /* Add an IV */
+	    cipe_cryptpad(skb_push(skb, blockSize));
+	    length+=blockSize;
+#endif
+            if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_SKEY)
+                /* Attempt to encrypt data using invalid static key */
+                goto error;
+	    cipe_encrypt(c, skb->data, &length, TW_DATA);
+	    /* This is incorrect - the tail room gets first used and then
+	       reserved. Doesn't matter in the current (2.0.29) implementation
+	       of skb_put though. Alternative solution would ruin the nice
+	       module separation - we don't need to know the real amount
+	       of padding here. */
+	    (void) skb_put(skb, length-skb->len);
+	} else if (!c->flags&CIPF_MAY_CLEAR) {
+	    goto error;
+	}
+
+        if (c->sockshost) {
+	    /* Install a SOCKS header */
+	    struct sockshdr *sh = (struct sockshdr *)
+		skb_push(skb, sizeof(struct sockshdr));
+	    memset(sh, 0, 4);
+	    sh->atyp=1;
+	    /* sockshost and socksport contain the real peer's address
+	       and the configured/guessed peer is really the socks relayer! */
+	    sh->dstaddr=c->sockshost;
+	    sh->dstport=c->socksport;
+	    length+=sizeof(struct sockshdr);
+	}
+
+        /* Install our new headers */
+        udph = (struct udphdr *) skb_push(skb, sizeof(struct udphdr));
+        skb->h.iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr));
+
+	/*
+	 *	Push down and install the CIPE/UDP header.
+	 */
+
+	iph 			=	skb->h.iph;
+	iph->version		= 	4;
+	iph->tos		=	tos;
+
+	/* In new_tunnel.c, we use the original packet's TTL here.
+	   Setting a new TTL behaves better to the user, and RFC2003
+	   recommends it too. But this doesn't fully protect against
+	   routing loops. So make it configurable via an argument:
+	   "cttl" gives the TTL value; if 0 use the packet's
+	   value. Default should be 64, as with the other protocols
+	   (ip_statistics.IpDefaultTTL, but this variable is not
+	   available for modules). */
+
+	iph->ttl 		=	c->cttl ? c->cttl : ttl;
+
+	iph->frag_off		=	0;
+	iph->daddr		=	target;
+	iph->saddr		=	c->myaddr; /* tdev->pa_addr; */
+	iph->protocol		=	IPPROTO_UDP;
+	iph->ihl		=	5;
+	iph->tot_len		=	htons(skb->len);
+	iph->id			=	htons(ip_id_count++);	/* Race condition here? */
+	ip_send_check(iph);
+
+        udph->source = c->myport;
+        udph->dest   = c->peerport;
+        udph->len    = htons(length+sizeof(struct udphdr));
+        /* Encrypted packets are checksummed already, so we can safely
+	   ignore the UDP checksum. Provide a means to do it nonetheless */
+	udph->check  = 0;
+	if (c->flags&CIPF_DO_CSUM) {
+	    udph->check=csum_tcpudp_magic(
+		iph->saddr, iph->daddr,
+		length+sizeof(struct udphdr), IPPROTO_UDP,
+		csum_partial((char *)udph, length+sizeof(struct udphdr), 0));
+	    if (!udph->check)
+		udph->check=-1;
+	}
+
+	skb->ip_hdr 		= skb->h.iph;
+	skb->protocol		=	htons(ETH_P_IP);
+
+	/*
+	 *	Send the packet on its way!
+	 *	Note that dev_queue_xmit() will eventually free the skb.
+	 *	If ip_forward() made a copy, it will return 1 so we can free.
+	 */
+
+	dprintk(DEB_OUT, (KERN_INFO "%s: send to %s via %s\n",
+			  dev->name, cipe_ntoa(target), tdev->name));
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKOU)
+        cipe_dump_packet("sending", skb, 0);
+#endif
+	switch (ipforward(skb, dev, IPFWD_NOTTLDEC, target)) {
+	case -1:
+	    printk(KERN_INFO "%s: forwarding failed\n", dev->name);
+	    /* fall thru */
+	case 1:
+	    dev_kfree_skb(skb, FREE_WRITE);
+	    /* Does it really need dev_ here? I think so. */
+	    break;
+	default:
+	    /* nothing to do */
+	}
+
+	/*
+	 *	Clean up:  We're done with the route and the packet
+	 */
+
+	/* Record statistics and return */
+	stats->tx_packets++;
+	dev->tbusy=0;
+	return 0;
+
+    error:
+	stats->tx_errors++;
+	dev_kfree_skb(skb, FREE_WRITE);
+	dev->tbusy=0;
+	return 0;
+}
+
+#endif /* LINUX_21 */
--- linux-2.4.21/drivers/addon/cipe4/sock.c.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/sock.c	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,731 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   sock.c - socket/input interface
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: sock.c,v 1.33.2.3 2002/06/28 23:38:53 olaf Exp $ */
+
+#include "cipe.h"
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <net/sock.h>
+#include <net/ip.h>
+#include <linux/etherdevice.h>
+#ifdef LINUX_21
+#include <asm/uaccess.h>
+#else
+typedef unsigned short mm_segment_t;
+#endif
+
+#ifdef LINUX_21
+#define kfreeskb(s,t) kfree_skb(s)
+#define saddr(skb) ((skb)->nh.iph->saddr)
+#define daddr(skb) ((skb)->nh.iph->daddr)
+#else
+#define kfreeskb(s,t) kfree_skb(s,t)
+#define saddr(skb) ((skb)->saddr)
+#define daddr(skb) ((skb)->daddr)
+#endif
+
+/* Rewire generic socket operations to our device-specific ones.
+   We have new routines for close, sendmsg, recvmsg. */
+
+#ifndef LINUX_21
+#define user_data protinfo.af_packet.bound_dev
+#endif
+
+/* init struct cipe *c based on struct sock *sk */
+#define SOCKTOC(nam,sk,c,r) \
+    struct cipe *c=(struct cipe *)sk->user_data; \
+    if ((!c) || (c->magic!=CIPE_MAGIC)) { \
+	 printk(KERN_ERR "Ouch: SOCKTOC " nam "\n"); return r; } \
+    else { \
+         dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", c->dev->name)); }
+
+
+/* Close the socket */
+void cipe_sock_close(struct sock *sock, timeout_t timeout)
+{
+    SOCKTOC("sock_close",sock,c,);
+    c->sock=NULL;
+
+    /* Put back the old protocol block and let it do the close */
+    sock->prot=c->udp_prot;
+    sock->prot->close(sock, timeout);
+    if (c->dev->flags&IFF_UP) {
+	rtnl_LOCK();
+	dev_close(c->dev);
+	rtnl_UNLOCK();
+    } else {
+	cipe_close(c);
+    }
+}
+
+/* Anything we send to this socket is in fact a key exchange block.
+   Encode and encrypt it accordingly.
+*/
+int cipe_sendmsg(struct sock *sock, struct msghdr *msg, int len
+#ifndef LINUX_21
+                 , int nonblock, int flags
+#endif
+    )
+{
+    struct msghdr mymsg;
+    struct iovec myio[2];
+    struct sockaddr_in sa;
+    struct sockshdr sh;
+    int e, n=0;
+    unsigned char buf[KEYXCHGBLKMAX+blockSize];
+    SOCKTOC("cipe_sendmsg",sock,c,-ENOSYS);
+
+    if (len>KEYXCHGBLKMAX)
+	return -EMSGSIZE;
+#ifdef VER_SHORT
+    if (msg->msg_flags&MSG_OOB)
+	return -EINVAL;
+#endif
+    cipe_prnpad(buf, sizeof(buf));
+#ifdef VER_SHORT
+    memcpy_fromiovec(buf, msg->msg_iov, len);
+#else
+    memcpy_fromiovec(buf+blockSize, msg->msg_iov, len);
+    len+=blockSize;
+#endif
+    if (!(msg->msg_flags&MSG_OOB)) {
+	if (buf[0
+#ifndef VER_SHORT
+	       +blockSize
+#endif
+	                 ]>=CT_DUMMY) {
+	    if (!c->flags&CIPF_HAVE_KEY)
+		return -EINVAL;
+	    buf[KEYXCHGTSPOS-1]='\0';
+	} else {
+	    if (len<KEYXCHGBLKMIN)
+		return -EINVAL;
+	}
+    }
+    (*(__u32 *)(buf+KEYXCHGTSPOS))=htonl(CURRENT_TIME); /* timestamp */
+    if (msg->msg_flags&MSG_OOB) {
+	memset(buf, 0, blockSize);
+    } else {
+	len=KEYXCHGBLKMIN+buf[sizeof(buf)-1]; /* random */
+	cipe_encrypt(c, buf, &len, TW_NEWKEY);
+    }
+
+    sa.sin_family=AF_INET;
+    sa.sin_addr.s_addr=c->peeraddr;
+    sa.sin_port=c->peerport;
+
+    if (c->sockshost) {
+	/* Prepend a socks header. */
+	memset(&sh, 0, sizeof(sh));
+	sh.atyp=1;
+	sh.dstaddr=c->sockshost;
+	sh.dstport=c->socksport;
+	myio[n].iov_base=&sh;
+	myio[n].iov_len=sizeof(sh);
+	++n;
+    }
+    myio[n].iov_base=&buf;
+    myio[n].iov_len=len;
+    /* mymsg=*msg; */
+    mymsg.msg_name=&sa;
+    mymsg.msg_namelen=sizeof(sa);
+    mymsg.msg_iov=myio;
+    mymsg.msg_iovlen=n+1;
+    /* just to be sure */
+    mymsg.msg_control=NULL;
+    mymsg.msg_controllen=0;
+    mymsg.msg_flags=0;
+
+    /* Call the real thing. Pretend this is user space segment. */
+    {
+        mm_segment_t fs=get_fs();
+        set_fs(get_ds());
+        if (c->sockshost)
+            len+=sizeof(struct sockshdr);
+        dprintk(DEB_KXC, (KERN_INFO "%s: real sendmsg len %d text=%04x...\n",
+                          c->dev->name, len,
+                          ntohs(*((unsigned short *)(myio[n].iov_base)))));
+        e=c->udp_prot->sendmsg(sock, &mymsg, len
+#ifndef LINUX_21
+                               , nonblock, flags
+#endif
+            );
+        set_fs(fs);
+    }
+    return e;
+}
+
+/* Check if we have a new peer */
+static void checkpeer(struct cipe *c, __u32 saddr, __u16 sport)
+{
+    if (c->sockshost) {
+	if (c->sockshost==saddr && c->socksport==sport)
+	    return;
+	/* sockshost and socksport contain the real peer's address
+	   and the configured/guessed peer is really the socks relayer! */
+	c->sockshost=saddr;
+	c->socksport=sport;
+    } else {
+	if (c->peeraddr==saddr && c->peerport==sport)
+	    return;
+	c->peeraddr=saddr;
+	c->peerport=sport;
+    }
+    printk(KERN_NOTICE "%s: new peer %s:%d\n",
+	   c->dev->name, cipe_ntoa(saddr), ntohs(sport));
+}
+
+/* Decrypt a received packet. Requeue it or return kxc block. */
+/* On entry the packet starts with the original UDP header,
+   ip_hdr and h.uh are set to the IP and UDP headers. */
+struct sk_buff *cipe_decrypt_skb(struct cipe *c, struct sock *sk,
+				 struct sk_buff *skb,
+                                 int *msgflag)
+{
+    struct sk_buff *n=NULL;
+    int length;
+    __u32 rsaddr;
+    __u16 rsport;
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKIN)
+        cipe_dump_packet("received", skb, 1);
+#endif
+    length=ntohs(skb->h.uh->len)-sizeof(struct udphdr);
+#if 0 /* UDP should check this */
+    if (length!=skb->len-sizeof(struct udphdr)) {
+	dprintk(DEB_INP, (KERN_INFO "%s: bogus UDP length (%d/%d)\n",
+                          c->dev->name, length,
+                          skb->len-sizeof(struct udphdr)));
+	goto framerr;
+    }
+#endif
+    if (length<9+(c->sockshost?sizeof(struct sockshdr):0)) {
+        /* XX hardcoded IV size */
+        printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name,
+               cipe_ntoa(saddr(skb)));
+	goto framerr;
+    }
+
+    n=alloc_skb(skb->len, GFP_KERNEL);
+    if (!n) {
+	printk(KERN_WARNING "%s: cipe_decrypt_skb: out of memory\n",
+	       c->dev->name);
+	++c->stat.rx_dropped;
+	return NULL;
+    }
+#if 0 /*def LINUX_21*/
+    if (skb->sk)
+	skb_set_owner_r(n, skb->sk);
+#endif
+#ifndef LINUX_21
+    n->free=1;
+#endif
+    n->dev=c->dev;
+
+    /* Copy the datagram into new buffer, skip IP header */
+    /* We must copy here because raw sockets get only a clone of the
+       skbuff, so they would receive the plaintext */
+    dprintk(DEB_INP, (KERN_INFO DEVNAME
+                      ": sa=%s da=%s us=%d ud=%d ul=%d\n",
+                      cipe_ntoa(saddr(skb)), cipe_ntoa(daddr(skb)),
+                      ntohs(skb->h.uh->source), ntohs(skb->h.uh->dest),
+                      ntohs(skb->h.uh->len)));
+
+    /* why did this get swapped?? */
+#ifdef LINUX_21
+    rsaddr=saddr(skb);
+#else
+    rsaddr=daddr(skb);
+#endif
+    rsport=skb->h.uh->source;
+    skb_put(n,skb->len);
+    memcpy(n->data, skb->h.raw, skb->len);
+    n->h.uh=(struct udphdr *)n->data;
+
+    if (c->sockshost) {
+	/* Pull out the SOCKS header and correct the peer's address. */
+	struct sockshdr *sh;
+	sh=(struct sockshdr *)skb_pull(n, sizeof(struct udphdr));
+	dprintk(DEB_INP, (KERN_INFO "socks: fr=%d at=%d da=%s dp=%d\n",
+                          sh->frag, sh->atyp,
+                          cipe_ntoa(sh->dstaddr), ntohs(sh->dstport)));
+	if (sh->frag || (sh->atyp!=1))
+	    goto error;
+	/* Pull out UDP header */
+#ifdef LINUX_21
+        n->nh.iph=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr));
+#else
+	n->ip_hdr=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr));
+#endif
+	/***saddr(n)=sh->dstaddr;*/
+        rsaddr=sh->dstaddr;
+	rsport=n->h.uh->source=sh->dstport;
+	length-=sizeof(struct sockshdr);
+    } else {
+	/* Pull out UDP header */
+#ifdef LINUX_21
+	n->nh.iph=(struct iphdr *) skb_pull(n, sizeof(struct udphdr));
+#else
+	n->ip_hdr=(struct iphdr *) skb_pull(n, sizeof(struct udphdr));
+#endif
+	/***saddr(n)=rsaddr;*/
+	n->h.uh->source=rsport;
+    }
+
+#ifndef VER_SHORT
+    if (!(*((__u32 *)n->data) & htonl(0x7FFFFFFF))) {
+	dprintk(DEB_INP, (KERN_INFO "got unencrypted packet (iv=0) len=%d\n",
+			  length));
+	skb_pull(n, blockSize);
+	/* XX not sure about TW_CTRL handling... */
+        switch (*n->data) {
+            /* Restrict what can be received unencrypted. */
+        case CT_DUMMY: case CT_DEBUG: case CT_CONFREQ: case CT_CONF:
+            break;
+        default:
+            printk(KERN_WARNING
+                   "%s: got disallowed unencrypted control %02x\n",
+                   c->dev->name, *n->data);
+            goto error;
+        }
+#ifdef LINUX_21
+	get_fast_time(&n->stamp);
+#endif
+	/* No checkpeer() here because not authenticated! */
+	n->h.uh->check=0;
+	return n;
+    }
+#endif
+    if (c->flags&CIPF_HAVE_KEY) {
+	if (length%blockSize) {
+	    printk(KERN_INFO "%s: got bogus length=%d\n", c->dev->name,
+		   length);
+	    goto error;
+	}
+        switch (cipe_decrypt(c, n->data, &length)) {
+	case TW_DATA:
+            if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_RKEY) {
+                printk(KERN_ERR "%s: got data using invalid static key\n",
+                       c->dev->name);
+                goto error;
+            }
+	    break;
+	case TW_CTRL:
+            /* return it as a control block - out of band datagram */
+            *msgflag|=MSG_OOB;
+            /* fall thru */
+	case TW_NEWKEY:
+	    /* return it as key exchange block - proper UDP datagram */
+	    dprintk(DEB_INP, (KERN_DEBUG "TW_NEWKEY data=%p len=" FLEN
+                              " length=%d\n", n->data, n->len, length));
+#ifdef LINUX_21
+	    get_fast_time(&n->stamp);
+#endif
+	    skb_trim(n, length);
+	    checkpeer(c, rsaddr, rsport);
+#if 0
+	    n->saddr=c->myaddr;
+	    n->daddr=c->peeraddr;
+#endif
+	    n->h.uh->check=0;
+	    return n;
+	default:
+	    /* Bogus packet etc. */
+	    ++c->stat.rx_crc_errors;
+	    goto error;
+	}
+    } else if (!c->flags&CIPF_MAY_CLEAR) {
+	goto error;
+    }
+
+    dprintk(DEB_INP, (KERN_DEBUG "TW_DATA data=%p len=" FLEN "length=%d\n",
+                      n->data, n->len, length));
+    skb_trim(n, length);
+    checkpeer(c, rsaddr, rsport);
+    /* adjust pointers */
+#ifdef VER_ETH
+    n->protocol = eth_type_trans(n, c->dev);
+    /* n->pkt_type = PACKET_HOST; */
+#else
+    n->mac.raw=n->data;	/* no hw header */
+    n->protocol = htons(ETH_P_IP);
+    n->pkt_type = PACKET_HOST;
+#endif
+#ifdef LINUX_21
+    n->nh.raw=n->data;
+    memset(&(IPCB(n)->opt), 0, sizeof(IPCB(n)->opt));
+#else
+    n->h.iph=(struct iphdr *)n->data;
+    memset(n->proto_priv, 0, sizeof(struct options));
+#endif
+    if (length<cipehdrlen+(c->sockshost?sizeof(struct sockshdr):0)) {
+	printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name,
+	       cipe_ntoa(saddr(skb)));
+	goto framerr;
+    }
+
+    n->ip_summed = 0;
+    /* this prints nonsense for non-IP packets. Ignore that. */
+    dprintk(DEB_INP, (KERN_INFO "%s: real src %s dst %s len %d\n",
+                      n->dev->name, cipe_ntoa(saddr(n)),
+                      cipe_ntoa(daddr(n)), length));
+
+#ifdef DEBUG
+    if (cipe_debug&DEB_PKIN)
+        cipe_dump_packet("decrypted", n, 1);
+#ifdef LINUX_23
+    dprintk(DEB_INP, (KERN_DEBUG "%s state=%ld refcnt=%d\n", n->dev->name, n->dev->state,
+		      atomic_read(&n->dev->refcnt)));
+#endif
+#endif
+
+    /* requeue */
+    netif_rx(n);
+#ifdef LINUX_21
+    c->stat.rx_bytes+=skb->len; /* count carrier-level bytes */
+#endif
+    c->stat.rx_packets++;
+    return NULL;
+
+ framerr:
+    ++c->stat.rx_frame_errors; /* slightly abuse this */
+ error:
+    ++c->stat.rx_errors;
+    if (n)
+	kfreeskb(n, FREE_READ);
+    return NULL;
+}
+
+/* Receive message. If encrypted, put it through the mill.
+   If decrypted, return it as key exchange block.
+   This is mostly from net/ipv4/udp.c, but cipe_decrypt_skb pulls the
+   UDP header.
+*/
+
+int cipe_recvmsg(struct sock *sk, struct msghdr *msg, int len,
+		 int noblock, int flags,int *addr_len)
+{
+  	int copied;
+  	struct sk_buff *skb, *skn;
+  	int er=0;
+  	struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
+	SOCKTOC("cipe_recvmsg",sk,c,-ENOSYS);
+
+	/*
+	 *	Check any passed addresses
+	 */
+
+  	if (addr_len)
+  		*addr_len=sizeof(*sin);
+
+	/*
+	 *	From here the generic datagram does a lot of the work. Come
+	 *	the finished NET3, it will do _ALL_ the work!
+	 */
+
+	do {
+	    /* CIPE: look if the packet is encrypted, repeat until
+	       a decrypted one is found */
+	    skn=NULL;
+	    skb=skb_recv_datagram(sk,flags,noblock,&er);
+	    if(skb==NULL) {
+		dprintk(DEB_KXC, (KERN_INFO "%s: skb_recv_datagram: %d\n",
+                                  c->dev->name, er));
+                return er;
+	    }
+
+	    if (!skb->h.uh->source) {
+		/* Synthetic KXC packets are marked by source port 0.
+		   Correct this - we know the truth from our structure.
+		   Perhaps it would be better to not correct it so the
+		   user level daemon can spot the difference? */
+		skb->h.uh->source=c->peerport;
+		skb_pull(skb, sizeof(struct udphdr));
+		break;
+	    }
+	    skn=cipe_decrypt_skb(c, sk, skb, &(msg->msg_flags));
+	    skb_free_datagram(sk, skb);
+	    skb=skn;
+	} while (skb==NULL);
+
+	dprintk(DEB_INP, (KERN_INFO "%s: returning " FLEN " flags %04x\n",
+			  c->dev->name, skb->len, msg->msg_flags));
+  	copied = skb->len;
+	if (copied > len)
+	{
+		copied = len;
+#ifdef LINUX_21
+		msg->msg_flags |= MSG_TRUNC;
+#endif
+	}
+	if (copied<=0) {
+	    printk(KERN_ERR "cipe_recvmsg: bogus length %d\n", copied);
+	    goto out_free;
+	}
+
+  	/*
+  	 *	FIXME : should use udp header size info value
+  	 */
+#ifdef LINUX_21
+#if 0
+	er = skb_copy_datagram_iovec(skb, skb->data-skb-h.raw,
+				     msg->msg_iov, copied);
+#else
+	er = memcpy_toiovec(msg->msg_iov, skb->data, copied);
+#endif
+	if (er<0)
+		goto out_free;
+#else
+#if 0
+        skb_copy_datagram_iovec(skb,of,msg->msg_iov,copied);
+#else
+	memcpy_toiovec(msg->msg_iov, skb->data, copied);
+#endif
+#endif
+	sk->stamp=skb->stamp;
+
+	/* Copy the address. */
+	if (sin
+#ifdef LINUX_21
+            && skb->nh.iph   /* Fake KXC has no address */
+#endif
+	) {
+		sin->sin_family = AF_INET;
+		sin->sin_port = skb->h.uh->source;
+                sin->sin_addr.s_addr = daddr(skb);
+	}
+        er=copied;
+
+ out_free:
+	if (skb==skn)
+	    /* the buffer was a copy made by decryption */
+	    kfreeskb(skb, FREE_READ);
+	else
+	    skb_free_datagram(sk, skb);
+
+  	return(er);
+}
+
+#ifdef LINUX_21
+
+#include <linux/file.h>
+
+int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm)
+{
+    struct file *file;
+    struct inode *inode;
+    struct socket *sock;
+    struct sock *sk;
+#if 0
+    struct in_device *indev;
+#endif
+    struct cipe *c0;
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    if (c->sock)
+        return -EBUSY;
+    if (!(file=fget(parm->fd)))
+        return(-EBADF);
+    inode = file->f_dentry->d_inode;
+    if (!inode || !inode->i_sock || !(sock=&inode->u.socket_i)) {
+        fput(file);
+        return(-ENOTSOCK);
+    }
+    if (sock->file != file) {
+        printk(KERN_ERR DEVNAME ": socki_lookup: socket file changed!\n");
+        sock->file = file;
+    }
+
+    fput(file);
+    if (sock->type!=SOCK_DGRAM)
+	return(-ESOCKTNOSUPPORT);
+    if (sock->ops->family!=AF_INET)
+	return(-EAFNOSUPPORT);
+
+    sk=sock->sk;
+    if (sk->state!=TCP_ESTABLISHED)
+	return(-ENOTCONN);
+    if (((c0=(struct cipe *)sk->user_data)) &&
+	(c0->magic==CIPE_MAGIC))
+	return(-EBUSY); /* socket is already attached */
+
+    cipe_use_module();
+    c->owner=current->pid;
+    c->sock=sk;
+    c->peeraddr=sk->daddr;
+    c->peerport=sk->dport;
+    c->myaddr=sk->saddr;
+    if (c->flags&CIPF_MAY_DYNIP)
+        sk->rcv_saddr=0;
+    c->myport=htons(sk->num);
+    /* Disconnect socket, we might receive from somewhere else */
+    sk->daddr=0;
+    sk->dport=0;
+
+    /* Fill an otherwise unused field in the sock struct with this info.
+       This field is conveniently named and the kernel uses it only for RPC. */
+    sk->user_data=c;
+    sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1;
+
+    /* Set up new socket operations */
+    c->udp_prot=sk->prot;
+    c->cipe_proto=*sk->prot;
+    c->cipe_proto.close=cipe_sock_close;
+    c->cipe_proto.sendmsg=cipe_sendmsg;
+    c->cipe_proto.recvmsg=cipe_recvmsg;
+    sk->prot=&c->cipe_proto;
+
+#if 0
+    /* (Try to) Set our dummy hardware address from the IP address. */
+    /* This does not work, because the IP address is set
+       _after_ the attach... */
+    if ((indev=dev->ip_ptr)) {
+	struct in_ifaddr **ifap = NULL;
+	struct in_ifaddr *ifa = NULL;
+	for (ifap=&indev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
+	    if (strcmp(dev->name, ifa->ifa_label) == 0)
+		break;
+	if (ifa) {
+	    char *x=(char *)&ifa->ifa_local;
+	    dev->dev_addr[3]=x[1]|0x80;
+	    dev->dev_addr[4]=x[2];
+	    dev->dev_addr[5]=x[3];
+	}
+    }
+#endif
+
+    return(0);
+}
+
+
+#else /* LINUX_21 */
+
+#define sreturn(x) {sti(); return((x));}
+
+int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm)
+{
+    struct file *file;
+    struct inode *inode;
+    struct socket *sock;
+    struct sock *sk;
+    int fd=parm->fd;
+    struct cipe *c0;
+    DEVTOCIPE(dev,c,-ENODEV);
+    cli();
+    if (c->sock)
+	sreturn(-EBUSY);
+
+    /* Find the socket (from net/socket.c) */
+    if (fd < 0 || fd >= NR_OPEN || !(file = current->files->fd[fd]))
+	sreturn(-EBADF);
+    inode = file->f_inode;
+    if (!inode || !inode->i_sock)
+	sreturn(-ENOTSOCK);
+    sock=&inode->u.socket_i;
+    if (sock->type!=SOCK_DGRAM)
+	sreturn(-ESOCKTNOSUPPORT);
+    if (sock->ops->family!=AF_INET)
+	sreturn(-EAFNOSUPPORT);
+    sk=(struct sock *)sock->data;
+    if (sk->state!=TCP_ESTABLISHED)
+	sreturn(-ENOTCONN);
+    if (((c0=(struct cipe *)sk->protinfo.af_packet.bound_dev)) &&
+	(c0->magic==CIPE_MAGIC))
+	sreturn(-EBUSY); /* socket is already attached */
+
+    cipe_use_module();
+    c->owner=current->pid;
+    c->sock=sk;
+    c->peeraddr=sk->daddr;
+    c->peerport=sk->dummy_th.dest;
+    c->myaddr=sk->saddr;
+    if (c->flags&CIPF_MAY_DYNIP)
+        sk->rcv_saddr=0;
+    c->myport=sk->dummy_th.source;
+    /* Disconnect socket, we might receive from somewhere else */
+    sk->daddr=0;
+    sk->dummy_th.dest=0;
+
+    /* Set up new socket operations */
+    c->udp_prot=sk->prot;
+    c->cipe_proto=*sk->prot;
+    c->cipe_proto.close=cipe_sock_close;
+    c->cipe_proto.sendmsg=cipe_sendmsg;
+    c->cipe_proto.recvmsg=cipe_recvmsg;
+    sk->prot=&c->cipe_proto;
+
+    /* Fill an otherwise unused field in the sock struct with this info.
+       Actually, this is very similar to a packet socket!
+       The ugly cast saves us one deref in the actual ops */
+    sk->protinfo.af_packet.bound_dev=(struct NET_DEVICE *)c;
+    sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1;
+
+    sti();
+    return 0;
+}
+
+#endif
+
+
+/* Build and enqueue a fake UDP packet to receive.
+   Note that these are neither encrypted nor SOCKSed.
+*/
+void cipe_fakenkey(struct cipe *c, char typ)
+{
+    int len=sizeof(struct udphdr)+KEYXCHGBLKMIN;
+    struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
+
+    if (!skb) {
+        printk(KERN_WARNING "%s: cipe_fakenkey: out of memory\n",
+               c->dev->name);
+        return; /* not much we can do */
+    }
+
+    dprintk(DEB_KXC, (KERN_INFO "%s: fake kxc block typ=%d\n",
+                      c->dev->name, typ));
+
+    skb->sk=NULL;
+    skb->dev=c->dev;
+
+    skb->h.uh=(struct udphdr *)skb->data;
+    skb->len=len;
+#ifdef LINUX_21
+    skb->nh.iph=NULL;
+#else
+    saddr(skb)=c->myaddr;
+    daddr(skb)=c->peeraddr;
+    skb->free=1; /* Discard after use */
+    skb->ip_hdr=NULL;
+#endif
+    skb->h.uh->source=0; /* mark as KXC packet */
+    skb->h.uh->dest=c->myport;
+    len-=sizeof(struct udphdr);
+    skb->h.uh->len=htons(len);
+    skb->h.uh->check=0;
+    skb->mac.raw=skb->data; /* no hardware header */
+
+    /* All those contortions for just one byte of payload data.
+       Since we generate only NK_RREQ and NK_REQ it's effectively
+       one _bit_... */
+    skb->data[sizeof(struct udphdr)]=typ;
+    (*(__u32 *)(skb->data+sizeof(struct udphdr)+KEYXCHGTSPOS))=
+        htonl(CURRENT_TIME); /* even need timestamp */
+
+    if (sock_queue_rcv_skb(c->sock, skb)<0) {
+        printk(KERN_WARNING "%s: cipe_fakenkey: enqueuing failed\n",
+               c->dev->name);
+        kfreeskb(skb, FREE_WRITE);
+    }
+}
--- linux-2.4.21/drivers/addon/cipe4/version.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/version.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,5 @@
+#define VERSION "1.5.4"
+#define ProtocolVersion 3
+#define Crypto_IDEA 1
+#undef Crypto_Blowfish
+#undef NO_DYNDEV 
--- linux-2.4.21/drivers/addon/cipe4/bf.c.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/bf.c	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,552 @@
+/*
+	Bruce Schneier's Blowfish.
+	Author: Olaf Titz <olaf at bigred.inka.de>
+
+	This code is in the public domain.
+
+	$Id: bf.c,v 1.4 2000/10/26 10:11:08 olaf Exp $
+*/
+
+#include "bf.h"
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+#ifndef ASM_BF_Crypt
+
+/* The generic big/little endian routines use the following imported
+   from <asm/byteorder.h> under Linux:
+   __u32 __be32_to_cpup(__u32 *p);
+   __u32 __cpu_to_be32(__u32 x);
+   __u32 __le32_to_cpup(__u32 *p);
+   __u32 __cpu_to_le32(__u32 x);
+   These are macros. We provide replacements if necessary (non-Linux).
+   XXX the pointer types are wrong, but else a cast would be necessary.
+*/
+
+#ifdef __GNUC__
+#define INLINE static inline
+#else
+#define INLINE static
+#endif
+
+#ifndef __be32_to_cpup
+INLINE  __u32 __be32_to_cpup(unsigned char *p)
+{
+    return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
+}
+#endif
+
+#ifndef __cpu_to_be32
+INLINE __u32 __cpu_to_be32(__u32 x)
+{
+    register unsigned char *p=(unsigned char *)&x;
+    return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
+}
+#endif
+
+#ifndef __le32_to_cpup
+INLINE  __u32 __le32_to_cpup(unsigned char *p)
+{
+    return (p[3]<<24)+(p[2]<<16)+(p[1]<<8)+p[0];
+}
+#endif
+
+#ifndef __cpu_to_le32
+INLINE __u32 __cpu_to_le32(__u32 x)
+{
+    register unsigned char *p=(unsigned char *)&x;
+    return (p[3]<<24)+(p[2]<<16)+(p[1]<<8)+p[0];
+}
+#endif
+
+/* Macros to implement the round function. */
+
+/* access the P and S boxes in key array */
+#define P(n)	(key[(n)])
+#define S0(n) 	(key[(n)+18])
+#define S1(n) 	(key[(n)+274])
+#define S2(n) 	(key[(n)+530])
+#define S3(n) 	(key[(n)+786])
+/* access byte in word */
+#define B0(x)	(((x)>>24)&255)
+#define B1(x)	(((x)>>16)&255)
+#define B2(x)	(((x)>>8)&255)
+#define B3(x)	(((x))&255)
+/* one raw round sans swap. p is running ptr into P box array */
+#define F(x)	(((S0(B0(x))+S1(B1(x)))^S2(B2(x)))+S3(B3(x)))
+#define RoundP(a,b) (a)^=(*p++)^F(b)
+#define RoundN(a,b) (a)^=(*p--)^F(b)
+
+/* 16 rounds with running pointer and word swapping */
+#define RoundsP \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r); \
+    RoundP(r, l);  RoundP(l, r)
+
+#define RoundsN \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r); \
+    RoundN(r, l);  RoundN(l, r)
+
+/* Native byte order routines */
+
+void _N_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			 const Blowfish_Key key)
+{
+    register const __u32 *p=(const __u32 *)key;
+    register unsigned long
+	l=((__u32 *)dataIn)[0]^(*p++),
+	r=((__u32 *)dataIn)[1];
+    RoundsP;
+    ((__u32 *)dataOut)[0]=r^(*p);
+    ((__u32 *)dataOut)[1]=l;
+}
+
+void _N_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			 const Blowfish_Key key)
+{
+    register const __u32 *p=((const __u32 *)key)+17;
+    register unsigned long
+	l=((__u32 *)dataIn)[0]^(*p--),
+	r=((__u32 *)dataIn)[1];
+    RoundsN;
+    ((__u32 *)dataOut)[0]=r^(*p);
+    ((__u32 *)dataOut)[1]=l;
+}
+
+/* Big-endian routines (i.e. real Blowfish) */
+
+#ifndef BF_DONTNEED_BE
+#ifndef BF_NATIVE_BE
+void B_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=(const __u32 *)key;
+    register unsigned long
+	l=__be32_to_cpup(dataIn)^(*p++),
+	r=__be32_to_cpup(dataIn+4);
+    RoundsP;
+    ((__u32 *)dataOut)[0]=__cpu_to_be32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_be32(l);
+}
+
+void B_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=((const __u32 *)key)+17;
+    register unsigned long
+	l=__be32_to_cpup(dataIn)^(*p--),
+	r=__be32_to_cpup(dataIn+4);
+    RoundsN;
+    ((__u32 *)dataOut)[0]=__cpu_to_be32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_be32(l);
+}
+#endif
+#endif
+
+/* Little-endian routines */
+
+#ifndef BF_DONTNEED_LE
+#ifndef BF_NATIVE_LE
+void L_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=key;
+    register unsigned long
+	l=__le32_to_cpup(dataIn)^(*p++),
+	r=__le32_to_cpup(dataIn+4);
+    RoundsP;
+    ((__u32 *)dataOut)[0]=__cpu_to_le32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_le32(l);
+}
+
+void L_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			const Blowfish_Key key)
+{
+    register const __u32 *p=key+17;
+    register unsigned long
+	l=__le32_to_cpup(dataIn)^(*p--),
+	r=__le32_to_cpup(dataIn+4);
+    RoundsN;
+    ((__u32 *)dataOut)[0]=__cpu_to_le32(r^(*p));
+    ((__u32 *)dataOut)[1]=__cpu_to_le32(l);
+}
+#endif
+#endif
+
+/* Key setup */
+
+void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen,
+			    Blowfish_Key key)
+{
+    char d[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    int i, j;
+    __u32 u;
+
+    #define UK	(userKey[j]&255)
+    #define UKI	if (++j>=userKeyLen) j=0
+    for (i=j=0; i<18; ++i) {
+	u=UK;	     UKI;
+	u=(u<<8)+UK; UKI;
+	u=(u<<8)+UK; UKI;
+	u=(u<<8)+UK; UKI;
+	key[i]=Blowfish_Init_Key[i]^u;
+    }
+    memcpy(key+18, Blowfish_Init_Key+18, 4096);
+    for (i=0; i<1042; i+=2) {
+	_N_Blowfish_Encrypt(d, d, key);
+	key[i]=((__u32 *)d)[0];
+	key[i+1]=((__u32 *)d)[1];
+    }
+}
+
+#endif
+
+/* The initialization key. According to Schneier, this is not a magic
+   pattern but simply the first 33344 (after point) bits of "pi". */
+
+const Blowfish_Key Blowfish_Init_Key = {
+    /* The eighteen P boxes @ 1 word */
+    0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+    0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+    0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+    0x9216d5d9, 0x8979fb1b,
+    /* The four S boxes @ 256 words */
+    0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+    0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+    0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+    0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+    0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+    0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+    0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+    0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+    0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+    0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+    0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+    0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+    0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+    0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+    0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+    0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+    0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+    0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+    0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+    0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+    0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+    0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+    0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+    0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+    0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+    0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+    0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+    0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+    0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+    0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+    0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+    0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+    0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+    0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+    0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+    0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+    0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+    0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+    0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+    0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+    0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+    0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+    0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+    0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+    0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+    0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+    0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+    0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+    0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+    0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+    0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+    0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+    0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+    0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+    0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+    0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+    0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+    0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+    0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+    0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+    0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+    0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+    0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+    0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+    0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+    0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+    0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+    0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+    0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+    0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+    0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+    0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+    0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+    0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+    0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+    0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+    0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+    0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+    0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+    0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+    0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+    0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+    0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+    0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+    0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+    0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+    0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+    0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+    0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+    0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+    0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+    0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+    0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+    0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+    0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+    0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+    0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+    0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+    0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+    0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+    0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+    0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+    0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+    0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+    0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+    0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+    0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+    0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+    0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+    0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+    0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+    0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+    0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+    0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+    0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+    0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+    0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+    0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+    0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+    0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+    0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+    0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+    0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+    0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+    0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+    0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+    0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+    0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+    0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+    0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+    0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+    0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+    0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+    0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+    0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+    0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+    0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+    0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+    0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+    0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+    0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+    0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+    0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+    0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+    0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+    0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+    0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+    0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+    0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+    0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+    0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+    0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+    0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+    0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+    0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+    0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+    0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+    0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+    0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+    0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+    0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+    0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+    0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+    0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+    0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+    0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+    0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+    0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+    0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+    0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+    0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+    0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+    0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+    0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+    0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+    0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+    0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+    0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+    0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+    0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+    0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+    0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+    0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+    0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+    0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+    0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+    0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+    0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+    0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+    0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+    0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+    0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+    0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+    0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+    0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+    0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+    0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+    0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+    0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+    0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+    0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+    0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+    0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+    0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+    0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+    0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+    0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+    0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+    0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+    0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+    0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+    0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+    0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+    0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+    0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+    0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+    0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+    0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+    0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+    0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+    0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+    0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+    0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+    0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+    0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+    0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+    0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+    0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+    0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+    0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+    0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+    0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+    0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+    0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+    0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+    0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+    0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+    0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+    0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+    0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+    0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+    0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+    0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+    0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+    0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+    0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+    0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+    0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+    0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+    0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+    0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+    0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+    0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+    0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+    0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+    0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+};
+
+#if (defined(TEST) && !defined(__KERNEL__))
+
+#include <stdio.h>
+
+/* Test vectors from Schneier's reference implementation */
+
+char test1k[] = "abcdefghijklmnopqrstuvwxyz";
+char btest1p[] = { 0x42, 0x4c, 0x4f, 0x57, 0x46, 0x49, 0x53, 0x48 };
+char btest1c[] = { 0x32, 0x4e, 0xd0, 0xfe, 0xf4, 0x13, 0xa2, 0x03 };
+
+char test2k[] = "Who is John Galt?";
+char btest2p[] = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
+char btest2c[] = { 0xcc, 0x91, 0x73, 0x2b, 0x80, 0x22, 0xf6, 0x84 };
+
+/* Non-official little endian test ciphertext vectors */
+char btest1l[] = { 0x82, 0x4d, 0x92, 0x0d, 0x00, 0x4d, 0x7e, 0xe3 };
+char btest2l[] = { 0xd4, 0xf9, 0xb0, 0x06, 0xd3, 0x84, 0x92, 0x7e };
+
+typedef void (*BFTransform)(void *dataIn, void *dataOut,
+			    const Blowfish_Key key);
+
+int ftest(char *k, char *p, char *c,
+	  BFTransform Encrypt, BFTransform Decrypt)
+{
+    Blowfish_Key kk;
+    unsigned char dd[8];
+    int e=0;
+
+    Blowfish_ExpandUserKey(k, strlen(k), kk);
+    Encrypt(p, dd, kk);
+    printf("    %02x%02x%02x%02x %02x%02x%02x%02x ",
+	   dd[0], dd[1], dd[2], dd[3], dd[4], dd[5], dd[6], dd[7]);
+    if (memcmp(dd, c, 8)) {
+	printf("encrypt failed ");
+	++e;
+    }
+    Decrypt(dd, dd, kk);
+    printf("    %02x%02x%02x%02x %02x%02x%02x%02x ",
+	   dd[0], dd[1], dd[2], dd[3], dd[4], dd[5], dd[6], dd[7]);
+    if (memcmp(dd, p, 8)) {
+	printf("decrypt failed ");
+	++e;
+    }
+    printf("%s\n", e?"":"passed");
+    return e;
+}
+
+int main()
+{
+    int e=0;
+    printf("Big-endian:\n");
+    printf("  Test 1: ");
+    e+=ftest(test1k, btest1p, btest1c, B_Blowfish_Encrypt, B_Blowfish_Decrypt);
+    printf("  Test 2: ");
+    e+=ftest(test2k, btest2p, btest2c, B_Blowfish_Encrypt, B_Blowfish_Decrypt);
+    printf("Little-endian:\n");
+    printf("  Test 1: ");
+    e+=ftest(test1k, btest1p, btest1l, L_Blowfish_Encrypt, L_Blowfish_Decrypt);
+    printf("  Test 2: ");
+    e+=ftest(test2k, btest2p, btest2l, L_Blowfish_Encrypt, L_Blowfish_Decrypt);
+    return e;
+}
+
+#endif
--- linux-2.4.21/drivers/addon/cipe4/bf.h.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/bf.h	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,100 @@
+/*
+	Bruce Schneier's Blowfish.
+	Author: Olaf Titz <olaf at bigred.inka.de>
+
+	This code is in the public domain.
+
+	$Id: bf.h,v 1.4 2000/10/06 23:15:05 olaf Exp $
+*/
+
+#ifndef _BF_H_
+#define _BF_H_
+
+#include <asm/types.h>       	/* gives __u32 as an unsigned 32bit integer */
+/* PORTABILITY: under non-Linux,
+   omit this include and insert an appropriate typedef
+*/
+
+#ifdef __KERNEL__
+#include <asm/byteorder.h>
+#endif
+/* PORTABILITY: under non-Linux, omit this include.
+   Generic, endian-neutral, slower C routines will be used instead of
+   the assembler versions found in the kernel includes.
+*/
+
+/* This is ugly, but seems the easiest way to find an endianness test
+   which works both in kernel and user mode.
+   This is only an optimization - everything works even if none of the
+   tests are defined.
+*/
+#ifdef __BYTE_ORDER
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define BF_NATIVE_BE
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define BF_NATIVE_LE
+#endif
+#else
+#ifdef __BIG_ENDIAN
+#define BF_NATIVE_BE
+#endif
+#ifdef __LITTLE_ENDIAN
+#define BF_NATIVE_LE
+#endif
+#endif
+
+/* The data block processed by the encryption algorithm - 64 bits */
+typedef __u32 Blowfish_Data[2];
+/* The key as entered by the user - size may vary */
+typedef char Blowfish_UserKey[16];
+/* The expanded key for internal use - 18+4*256 words*/
+typedef __u32 Blowfish_Key[1042];
+
+/* Byteorder-dependent handling of data encryption: Blowfish is by
+   definition big-endian. However, there are broken implementations on
+   little-endian machines which treat the data as little-endian.
+   This module provides both variants.
+ */
+
+/* Native byte order. For internal use ONLY. */
+extern void _N_Blowfish_Encrypt(void *dataIn, void *dataOut,
+				const Blowfish_Key key);
+extern void _N_Blowfish_Decrypt(void *dataIn, void *dataOut,
+				const Blowfish_Key key);
+
+#ifndef BF_DONTNEED_BE
+/* Big endian. This is the "real" Blowfish. */
+#ifdef BF_NATIVE_BE
+#define B_Blowfish_Encrypt _N_Blowfish_Encrypt
+#define B_Blowfish_Decrypt _N_Blowfish_Decrypt
+#else
+extern void B_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+extern void B_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+#endif
+#endif
+
+#ifndef BF_DONTNEED_LE
+/* Little endian. To be compatible with other LE implementations. */
+#ifdef BF_NATIVE_LE
+#define L_Blowfish_Encrypt _N_Blowfish_Encrypt
+#define L_Blowfish_Decrypt _N_Blowfish_Decrypt
+#else
+extern void L_Blowfish_Encrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+extern void L_Blowfish_Decrypt(void *dataIn, void *dataOut,
+			       const Blowfish_Key key);
+#endif
+#endif
+
+/* User key expansion. This is not byteorder dependent as all common
+   implementations get it right (i.e. big-endian). */
+
+extern void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen,
+				   Blowfish_Key key);
+
+extern const Blowfish_Key Blowfish_Init_Key;
+
+#endif
--- linux-2.4.21/drivers/addon/cipe4/bf-i386.S.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/bf-i386.S	Fri Jul 25 15:12:33 2003
@@ -0,0 +1,272 @@
+/*
+	Bruce Schneier's Blowfish in i386 assembler (for linux/gcc)
+	Author: Olaf Titz <olaf at bigred.inka.de>
+
+	This code is in the public domain.
+
+	$Id: bf-i386.S,v 1.6 2000/11/16 16:45:00 olaf Exp $
+*/
+
+#ifdef ASM_BF_Crypt
+
+#ifndef __ASSEMBLY__
+#define __ASSEMBLY__
+#endif
+
+/* This header just defines ENTRY to make an appropriate global symbol */
+#include <linux/linkage.h>
+
+/* Look for CONFIG_X86_BSWAP (defined for 486 and up) */
+#include <linux/config.h>
+
+#define PosP0	   0
+#define PosP17 	  68
+#define PosS0	  72
+#define PosS1	1096
+#define PosS2	2120
+#define PosS3	3144
+#define KeyLenL 1042
+#define KeyLenB  521
+
+/* This code is optimized for speed rather than size - loops unrolled. etc. */
+
+/*
+  Endian-ness is taken care of by (a) the order of shifts in the Round
+  macro and (b) the order of shifts below under the ukx label.
+  The key tables and user data are stored and processed in the CPU
+  byte order.
+*/
+
+/* Do one round */
+#define Round(lw,rw)				\
+	movl	rw, %edx;			\
+	shrl	$24, %edx;			\
+	movl	PosS0(%edi,%edx,4), %eax;	\
+	movl	rw, %edx;			\
+	shrl	$16, %edx;			\
+	andl	$0xFF, %edx;			\
+	addl	PosS1(%edi,%edx,4), %eax;	\
+	movl	rw, %edx;			\
+	shrl	$8, %edx;			\
+	andl	$0xFF, %edx;			\
+	xorl	PosS2(%edi,%edx,4), %eax;	\
+	movl	rw, %edx;			\
+	andl	$0xFF, %edx;			\
+	addl	PosS3(%edi,%edx,4), %eax;	\
+	xorl	%eax, lw;			\
+	lodsl;					\
+	xorl	%eax, lw
+
+/* Words in %ebx, %ecx - Key in %edi - P-index in %esi - result swapped */
+blowfish:
+	lodsl
+	xorl	%eax, %ebx
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	Round(%ecx,%ebx); Round(%ebx,%ecx)
+	lodsl
+	xorl	%eax, %ecx
+	ret
+
+/* Endianness swap operation. Is there an easier way to decompose
+   %ebx into %bl and %bh within a macro? */
+#ifdef CONFIG_X86_BSWAP
+#define swab32(x,h,l) bswap x
+#else
+#define swab32(x,h,l) 		\
+	xchgb	h, l;		\
+	rorl	$16, x;		\
+	xchgb	h, l
+#endif
+
+
+/* Function prototype prologue/epilogue. Sets up registers etc.
+   This is all code common to the six encrypt/decrypt functions.
+   They have the prototype
+   extern void FUNCTION(void *dataIn, void *dataOut, const Blowfish_Key key);
+   for the following FUNCTIONs:
+   _N_Blowfish_Encrypt, _N_Blowfish_Decrypt  (native-endian)
+   B_Blowfish_Encrypt,  B_Blowfish_Decrypt   (big-endian)
+   L_Blowfish_Encrypt,  L_Blowfish_Decrypt   (little-endian)
+   Of course, in the i386 implementation, native==little-endian.
+*/
+
+/* saved regs relative to %esp */
+#define sebx	0
+#define sebp	4
+#define sesi	8
+#define sedi	12
+#define SAVE	16 /* no. of bytes the saved registers occupy */
+/* arguments relative to %esp */
+#define dataIn	SAVE+4(%esp)
+#define dataOut	SAVE+8(%esp)
+#define key	SAVE+12(%esp)
+
+#define PROLOG				\
+	/* save registers */		\
+	subl	$SAVE, %esp;		\
+	movl	%ebx, sebx(%esp);	\
+	movl	%ebp, sebp(%esp);	\
+	movl	%esi, sesi(%esp);	\
+	movl	%edi, sedi(%esp);	\
+	/* load data */			\
+	movl	dataIn, %esi;		\
+	movl	(%esi), %ebx;		\
+	movl	4(%esi), %ecx;		\
+	/* load key */			\
+	movl	key, %edi;
+
+#define EPILOG				\
+	/* store data */		\
+	movl	dataOut, %edi;		\
+	movl	%ebx, 4(%edi);		\
+	movl	%ecx, (%edi);		\
+	/* restore registers */		\
+	movl	sedi(%esp), %edi;	\
+	movl	sesi(%esp), %esi;	\
+	movl	sebp(%esp), %ebp;	\
+	movl	sebx(%esp), %ebx;	\
+	addl	$SAVE, %esp;		\
+	ret
+
+#define FORWARD				\
+	movl	%edi, %esi;		\
+	cld
+
+#define BACKWARD			\
+	leal	PosP17(%edi), %esi;	\
+	std
+
+#define SWAP				\
+	swab32(%ebx,%bh,%bl);		\
+	swab32(%ecx,%ch,%cl)
+
+/* N.B. In Linux 2.3, the D flag is assumed to be zero all the time.
+   Thus after BACKWARD an additional cld is necessary. */
+
+#ifndef BF_DONTNEED_LE
+ENTRY(L_Blowfish_Encrypt)
+#endif
+ENTRY(_N_Blowfish_Encrypt)
+	PROLOG
+	FORWARD
+	call	blowfish
+	EPILOG
+
+#ifndef BF_DONTNEED_LE
+ENTRY(L_Blowfish_Decrypt)
+#endif
+ENTRY(_N_Blowfish_Decrypt)
+	PROLOG
+	BACKWARD
+	call	blowfish
+	cld
+	EPILOG
+
+#ifndef BF_DONTNEED_BE
+ENTRY(B_Blowfish_Encrypt)
+	PROLOG
+	SWAP
+	FORWARD
+	call	blowfish
+	SWAP
+	EPILOG
+
+ENTRY(B_Blowfish_Decrypt)
+	PROLOG
+	SWAP
+	BACKWARD
+	call	blowfish
+	cld
+	SWAP
+	EPILOG
+#endif
+
+
+/* load byte from key, start over if exhausted */
+#define lodsbw(base,len)		\
+	lodsb;				\
+	decl	%ecx;			\
+	cmpl	$0, %ecx;		\
+	jg	1f;			\
+	movl	base, %esi;		\
+	movl	len, %ecx;		\
+1:
+
+/*
+   void Blowfish_ExpandUserKey(const char *userKey, int userKeyLen,
+			       Blowfish_Key key);
+*/
+
+ENTRY(Blowfish_ExpandUserKey)
+	pushl	%ebx
+	pushl	%ebp
+	pushl	%esi
+	pushl	%edi
+#define SAVE	16 /* no. of bytes the saved registers occupy */
+/* arguments relative to %esp */
+#define	userKey		SAVE+4(%esp)
+#define userKeyLen	SAVE+8(%esp)
+#define key		SAVE+12(%esp)
+#define key_push	SAVE+16(%esp) /* key with one word pushed */
+
+	/* Copy the init vector into key */
+	leal	SYMBOL_NAME(Blowfish_Init_Key), %esi
+	movl	key, %edi
+	movl	$KeyLenL, %ecx
+	cld
+	rep;	movsl
+	/* XOR the user key into the P table */
+	movl	key, %edi
+	movl	$18, %ebp
+	movl	userKey, %esi
+	movl	userKeyLen, %ecx
+ukx:
+	/* process one 32-bit word swapped */
+	lodsbw(userKey, userKeyLen)
+	shll	$8, %eax
+	lodsbw(userKey, userKeyLen)
+	shll	$8, %eax
+	lodsbw(userKey, userKeyLen)
+	shll	$8, %eax
+	lodsbw(userKey, userKeyLen)
+	xorl	%eax, (%edi)
+	addl	$4, %edi
+	decl	%ebp
+	cmpl	$0, %ebp
+	jg	ukx
+
+	/* Now do the repeated encryption process */
+	xorl	%ebx, %ebx
+	xorl	%ecx, %ecx
+	movl	$KeyLenB, %ebp
+	movl	key, %edi
+ukb:
+	pushl	%edi
+	movl	key_push, %edi
+	movl	%edi, %esi
+	call	blowfish
+	popl	%edi
+	xchgl	%ebx, %ecx
+	movl	%ebx, (%edi)
+	movl	%ecx, 4(%edi)
+	addl	$8, %edi
+	decl	%ebp
+	cmpl	$0, %ebp
+	jg	ukb
+
+	popl	%edi
+	popl	%esi
+	popl	%ebp
+	popl	%ebx
+	ret
+#undef	dataIn
+#undef	dataOut
+#undef	key
+
+#endif /* ASM_BF_Crypt */
--- linux-2.4.21/drivers/addon/cipe4/device.c.CIPE4	Fri Jul 25 15:12:33 2003
+++ linux-2.4.21/drivers/addon/cipe4/device.c	Fri Jul 25 15:13:36 2003
@@ -0,0 +1,636 @@
+/*
+   CIPE - encrypted IP over UDP tunneling
+
+   device.c - the net device driver
+
+   Copyright 1996 Olaf Titz <olaf at bigred.inka.de>
+
+   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.
+*/
+/* $Id: device.c,v 1.42 2000/11/19 23:08:34 olaf Exp $ */
+
+#include "cipe.h"
+#include "version.h"
+#include <stddef.h>
+#include <linux/if_arp.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+
+#ifdef LINUX_21
+#include <asm/uaccess.h>
+#include <linux/rtnetlink.h>
+#else
+#define register_netdevice register_netdev
+#define unregister_netdevice unregister_netdev
+#endif
+
+/*** Globals ***/
+
+static const char driver_version[]=VERSION;
+
+struct cipe_ctrl **cipe_ctrls = NULL;
+#ifdef NO_DYNDEV
+int cipe_maxdev = 4;            /* changeable via insmod */
+#else
+int cipe_maxdev = 100;          /* changeable via insmod */
+#endif
+#ifdef DEBUG
+int cipe_debug = DEB_CALL;      /* changeable via insmod */
+#endif
+
+/* clear all potentially sensitive info and stats */
+static void cipe_zero_c(struct cipe *c)
+{
+    memset(&(c->peeraddr), 0,
+           offsetof(struct cipe, udp_prot)-offsetof(struct cipe, peeraddr));
+    /* reset these to sensible values */
+    c->tmo_keyxchg = 10*HZ;
+    c->tmo_keylife = 10*60*HZ;
+}
+
+/* weak but fast PRNG, used for padding only */
+static __u32 prnseed;
+void cipe_prnpad(unsigned char *buf, int len)
+{
+    while (len>0) {
+	prnseed=prnseed*0x01001001+1;
+	if (len>=2) {
+	    *(__u16 *)buf=prnseed>>16;
+	    len-=2; buf+=2;
+	} else {
+	    *buf=(prnseed>>24)^jiffies; return;
+	}
+    }
+}
+
+#ifdef DO_LOCK_PRINTK
+spinlock_t cipe_printk_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
+/* inet_ntoa() for multiple use. */
+#ifdef __SMP__
+#define NTOABUFS	16
+#else
+#define NTOABUFS	4
+#endif
+static char ntoabuf[NTOABUFS][16];
+static int ntoaptr=0;
+#ifdef LINUX_21
+spinlock_t cipe_ntoa_lock=SPIN_LOCK_UNLOCKED;
+#endif
+
+const char *cipe_ntoa(const __u32 addr)
+{
+    const unsigned char *x=(const unsigned char *)&addr;
+    char *p;
+    int b, i;
+#ifdef LINUX_21
+    unsigned long flags;
+    spin_lock_irqsave(&cipe_ntoa_lock, flags);
+#endif
+    b=ntoaptr;
+    if (++b>=NTOABUFS)
+	b=0;
+    ntoaptr=b;
+#ifdef LINUX_21
+    spin_unlock_irqrestore(&cipe_ntoa_lock, flags);
+#endif
+    p=ntoabuf[b];
+    for (i=0; i<4; ++i) {
+        int k=x[i]/100;
+        int l=(x[i]/10)%10;
+        if (k)
+            *p++=k+'0';
+        if (k || l)
+            *p++=l+'0';
+        *p++=(x[i]%10)+'0';
+        if (i<3)
+            *p++='.';
+    }
+    *p='\0';
+    return ntoabuf[b];
+}
+
+/*** IOCTL handlers ***/
+
+#ifdef SIOCGIFCIPPAR
+static int cipe_getpar(struct NET_DEVICE *dev, struct siocgifcippar *parm)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    parm->sockshost=c->sockshost;
+    parm->socksport=c->socksport;
+    parm->tmo_keyxchg=c->tmo_keyxchg/HZ;
+    parm->tmo_keylife=c->tmo_keylife/HZ;
+    parm->flags=c->flags;
+    parm->cttl=c->cttl;
+    return 0;
+}
+#endif
+
+static int cipe_setpar(struct NET_DEVICE *dev, struct siocsifcippar *parm)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    if (parm->sockshost)
+	c->sockshost=parm->sockshost;
+    if (parm->socksport)
+	c->socksport=parm->socksport;
+    if (parm->tmo_keyxchg>10*60*HZ)
+	return -EINVAL;
+    if (parm->tmo_keyxchg)
+	c->tmo_keyxchg=parm->tmo_keyxchg*HZ;
+    if (parm->tmo_keylife>24*60*60*HZ)
+	return -EINVAL;
+    if (parm->tmo_keylife)
+	c->tmo_keylife=parm->tmo_keylife*HZ;
+    c->flags=(parm->flags&CIPF_MASK_EXT)|(c->flags&CIPF_MASK_INT);
+    c->cttl=parm->cttl;
+    dprintk(DEB_CALL, (KERN_DEBUG "%s: setpar %s:%d %ld %ld %04x %d\n",
+                       dev->name,
+                       cipe_ntoa(c->sockshost), ntohs(c->socksport),
+                       c->tmo_keyxchg, c->tmo_keylife,
+                       c->flags, c->cttl));
+    return 0;
+}
+
+static int cipe_setkey(struct NET_DEVICE *dev, struct siocsifcipkey *parm)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+
+    dprintk(DEB_KXC, (KERN_INFO "%s: setkey %d\n", dev->name, parm->which));
+    switch (parm->which) {
+    case KEY_STATIC:
+	ExpandUserKey(parm->thekey, c->key_e);
+#if 0
+	dprintk(DEB_CRYPT, (KERN_DEBUG "ExpandUserKey: %08x\n",
+			    *(__u32*)(c->key_e)));
+#endif
+	InvertKey(c->key_e, c->key_d);
+	c->flags|=CIPF_HAVE_KEY;
+	break;
+    case KEY_SEND:
+	ExpandUserKey(parm->thekey, c->skey_e);
+	c->timeskey=jiffies+c->tmo_keylife;
+	c->cntskey=0;
+	c->flags|=CIPF_HAVE_SKEY;
+	break;
+    case KEY_RECV:
+	ExpandUserKey(parm->thekey, c->rkey_d);
+	InvertKey(c->rkey_d, c->rkey_d);
+	c->timerkey=jiffies+2*c->tmo_keylife; /* allow for fuzz */
+	c->cntrkey=0;
+	c->flags|=CIPF_HAVE_RKEY;
+	break;
+    case KEY_STATIC+KEY_INVAL:
+        c->flags&=~(CIPF_HAVE_KEY|CIPF_HAVE_SKEY|CIPF_HAVE_RKEY);
+	memset(&(c->key_e), 0, sizeof(c->key_e));
+	memset(&(c->key_d), 0, sizeof(c->key_d));
+	break;
+    case KEY_SEND+KEY_INVAL:
+        c->flags&=~CIPF_HAVE_SKEY;
+	memset(&(c->skey_e), 0, sizeof(c->skey_e));
+	c->timeskey=jiffies+c->tmo_keyxchg;
+	break;
+    case KEY_RECV+KEY_INVAL:
+        c->flags&=~CIPF_HAVE_RKEY;
+	memset(&(c->rkey_d), 0, sizeof(c->rkey_d));
+	c->timerkey=jiffies+c->tmo_keyxchg;
+	break;
+    default:
+	return -EINVAL;
+    }
+    return 0;
+}
+
+static int cipe_alloc_dev(int n);
+static void cipe_unalloc_dev(int n);
+
+static int cipe_owner(struct cipe *c)
+{
+    struct task_struct *p;
+    pid_t pid=c->owner;
+    if (!pid) return 0;
+    tasklist_LOCK();
+    p=current;
+    do {
+	if (p->pid==pid) {
+	    tasklist_UNLOCK();
+	    return pid;
+	}
+	p=p->next_task;
+    } while (p!=current);
+    tasklist_UNLOCK();
+    return 0;
+}
+
+#define cipe_nowner(n) cipe_owner(&cipe_ctrls[(n)]->cipe)
+
+static int cipe_alloc(struct NET_DEVICE *dev, struct siocsifcipall *parm)
+{
+#ifdef NO_DYNDEV
+    return -ENOSYS;
+#else
+    int n=parm->num;
+    int e;
+    if (n>=cipe_maxdev)
+        return -EINVAL;
+    if ((e=cipe_alloc_LOCK()))
+        return e;
+    if (n>=0) {
+        if (cipe_ctrls[n]) {
+            if (cipe_ctrls[n]->cipe.sock || (e=cipe_nowner(n))) {
+		printk(KERN_DEBUG DEVNAME ": dev %d busy pid=%d\n", n, e);
+                e=-EBUSY;
+            } else {
+                cipe_ctrls[n]->cipe.owner=current->pid;
+	    }
+        } else {
+            e=cipe_alloc_dev(n);
+        }
+    } else {
+        e=-EMFILE;
+        for (n=0; n<cipe_maxdev; ++n) {
+            if (!cipe_ctrls[n]) {
+                e=cipe_alloc_dev(n);
+                break;
+            }
+            if (!cipe_nowner(n)) {
+                cipe_ctrls[n]->cipe.owner=current->pid;
+                e=0;
+                break;
+            }
+        }
+    }
+    if (!e) {
+        parm->num=n;
+        strncpy(parm->name, cipe_ctrls[n]->dev.name, sizeof(parm->name)-1);
+        parm->name[sizeof(parm->name)-1]='\0';
+    }
+    cipe_alloc_UNLOCK();
+    return e;
+#endif
+}
+
+static int cipe_unalloc(struct NET_DEVICE *dev, struct siocsifcipall *parm)
+{
+#ifdef NO_DYNDEV
+    return -ENOSYS;
+#else
+    int e;
+    if (parm->num<0 || parm->num>=cipe_maxdev)
+        return -EINVAL;
+    if ((e=cipe_alloc_LOCK()))
+        return e;
+    if (cipe_ctrls[parm->num]->cipe.sock) {
+        e=-EBUSY;
+    } else {
+        if (parm->num>0)
+            cipe_unalloc_dev(parm->num);
+    }
+    cipe_alloc_UNLOCK();
+    return e;
+#endif
+}
+
+
+/*** Device operation handlers ***/
+
+int cipe_dev_ioctl(struct NET_DEVICE *dev, struct ifreq *ifr, int cmd)
+{
+    int e=-EINVAL;
+
+#ifdef LINUX_21
+
+    if (!capable(CAP_NET_ADMIN))
+	return -EPERM;
+
+#define doioctl(nam,fun,str) {                                          \
+    struct str parm;                                                    \
+    dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name));          \
+    if ((e=copy_from_user((void*)&parm,(void*)ifr->ifr_data,            \
+                          sizeof(parm)))<0)                             \
+        goto out;                                                       \
+    if ((e=fun(dev, &parm))<0)                                          \
+        goto out;                                                       \
+    e=copy_to_user((void*)ifr->ifr_data, (void*)&parm, sizeof(parm));   \
+    goto out;                                                           \
+  }
+
+#else
+
+    if (!suser())
+	return -EPERM;
+
+#define doioctl(nam,fun,str) {                                              \
+    struct str parm;                                                        \
+    dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name));              \
+    if ((e=verify_area(VERIFY_READ, ifr->ifr_data, sizeof(parm)))<0)        \
+        goto out;                                                           \
+    memcpy_fromfs((void*)&parm, (void*)ifr->ifr_data, sizeof(parm));        \
+    if ((e=fun(dev, &parm))<0)                                              \
+        goto out;                                                           \
+    if ((e=verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(parm)))<0)       \
+        goto out;                                                           \
+    memcpy_tofs((void*)ifr->ifr_data, (void*)&parm, sizeof(parm));          \
+    goto out;                                                               \
+  }
+
+#endif
+
+    cipe_use_module();
+    switch (cmd) {
+#ifdef SIOCGIFCIPPAR
+    case SIOCGIFCIPPAR:
+	doioctl("getpar", cipe_getpar, siocgifcippar);
+#endif
+    case SIOCSIFCIPPAR:
+	doioctl("setpar", cipe_setpar, siocsifcippar);
+    case SIOCSIFCIPKEY:
+	doioctl("setkey", cipe_setkey, siocsifcipkey);
+    case SIOCSIFCIPATT:
+	doioctl("attach", cipe_attach, siocsifcipatt);
+    case SIOCSIFCIPALL:
+	doioctl("alloc", cipe_alloc, siocsifcipall);
+    case SIOCSIFCIPUNA:
+	doioctl("unalloc", cipe_unalloc, siocsifcipall);
+    /* default: e=-EINVAL; */
+    }
+
+ out:
+    cipe_unuse_module();
+    return e;
+
+#undef doioctl
+}
+
+int cipe_dev_open(struct NET_DEVICE *dev)
+{
+    DEVTOCIPE(dev,c,-ENODEV);
+    if (!c->sock)
+	return -ENXIO;
+    dprintk(DEB_CALL, (KERN_INFO "%s: opened\n", dev->name));
+    return 0;
+}
+
+void cipe_close(struct cipe *c)
+{
+    cipe_zero_c(c);
+    dprintk(DEB_CALL, (KERN_INFO "%s: closed\n", c->dev->name));
+    cipe_unuse_module();
+}
+
+int cipe_dev_close(struct NET_DEVICE *dev)
+{
+    struct cipe *c = (struct cipe*)(dev->priv);
+    if ((!c) || (c->magic!=CIPE_MAGIC)) {
+	printk(KERN_WARNING "%s: cipe_dev_close: no valid struct\n",
+               dev->name);
+	return 0;
+    }
+    if (c->sock) {
+	dprintk(DEB_CALL, (KERN_INFO "%s: closing\n", c->dev->name));
+	/* Tell the attached socket we're going down */
+	c->sock->shutdown=SHUTDOWN_MASK;
+	c->sock->zapped=1;
+	c->sock->err=ENXIO;
+	c->sock->error_report(c->sock);
+#ifdef LINUX_21
+	if (!cipe_owner(c)) {
+	    /* SHOULD NOT HAPPEN. Socket is probably left orphaned.
+	       This is really only an emergency path to allow closing
+	       the device after an Oops. */
+	    printk(KERN_ERR "cipe_dev_close: not owned??\n");
+	    cipe_close(c);
+	}
+#endif
+    } else {
+	cipe_close(c);
+    }
+    return 0;
+}
+
+struct DEV_STATS *cipe_get_stats(struct NET_DEVICE *dev)
+{
+    DEVTOCIPE(dev,c,NULL);
+    return &(c->stat);
+}
+
+int cipe_set_mac(struct NET_DEVICE *dev, void *p)
+{
+    struct sockaddr *addr=p;
+    memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+    return 0;
+}
+
+
+/*** Initialization and finalization stuff ***/
+
+#ifndef LINUX_21
+static inline void dev_init_buffers(struct NET_DEVICE *dev)
+{
+    int i;
+    for (i = 0; i < DEV_NUMBUFFS; i++)  {
+        skb_queue_head_init(&dev->buffs[i]);
+    }
+}
+#endif
+
+static int cipe_init_dev(struct NET_DEVICE *dev)
+{
+    struct cipe *c = (struct cipe*)(dev->priv);
+    if (!c)
+	return -ENODEV;
+
+    memset(c, 0, sizeof(struct cipe)); /* zero the device struct along */
+    c->magic       = CIPE_MAGIC;
+    c->dev         = dev;
+    cipe_zero_c(c);
+
+    /* Device parameters. */
+#ifdef VER_ETH
+    ether_setup(dev); /* sets hard_header etc. */
+#endif
+    /* Procedural */
+    dev->open                   = cipe_dev_open;
+    dev->stop                   = cipe_dev_close;
+    dev->hard_start_xmit        = cipe_xmit;
+    dev->set_mac_address	= cipe_set_mac;
+    dev->do_ioctl               = cipe_dev_ioctl;
+    dev->get_stats              = cipe_get_stats;
+
+    /* "Hardware" */
+#ifndef VER_ETH
+    dev->type		        = ARPHRD_TUNNEL;
+    dev->hard_header_len        = 0; /* we copy anyway to expand */
+    dev->tx_queue_len	        = 100; /* matches ethernet */
+#endif
+    dev->mtu		        = ETH_DATA_LEN
+                                     -sizeof(struct sockshdr)
+                                     -cipehdrlen
+                                     -cipefootlen;
+
+
+#ifdef LINUX_21
+    dev->iflink         = -1;
+#else
+    dev->family		= AF_INET;
+    dev->pa_alen	= 4;
+    dev->metric         = 1;
+#endif
+    dev_init_buffers(dev);
+
+    /* New-style flags */
+#ifndef VER_ETH
+    dev->flags		= IFF_POINTOPOINT|IFF_NOARP;
+#endif
+    return 0;
+}
+
+#ifndef LINUX_21
+struct semaphore cipe_alloc_sem=MUTEX;
+#endif
+
+static int cipe_alloc_dev(int n)
+{
+    int e=0;
+    struct cipe_ctrl *cc;
+    struct NET_DEVICE *d;
+
+    dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_alloc_dev %d\n", n));
+    if (!(cc=kmalloc(sizeof(struct cipe_ctrl), GFP_KERNEL))) {
+        cipe_ctrls[n]=NULL;
+	printk(KERN_ERR DEVNAME ": failed to allocate device %d\n", n);
+        return -ENOMEM;
+    }
+
+    memset((void *)cc, 0, sizeof(*cc));
+/* If this doesn't compile, define or undefine HAVE_DEVNAME_ARRAY
+   in cipe.h accordingly. */
+#ifdef HAVE_DEVNAME_ARRAY
+    sprintf(cc->dev.name, DEVNAME "%d", n);
+#else
+    sprintf(cc->name, DEVNAME "%d", n);
+    cc->dev.name      = cc->name;
+#endif
+    cc->dev.base_addr = n; /* dummy */
+    cc->dev.priv      = (void*)&(cc->cipe);
+    cc->dev.next      = NULL;
+    cc->dev.init      = cipe_init_dev; /* called by register_netdevice */
+
+#if 1
+    /* Generate a dummy MAC address. This code seems to be in accordance
+       to the address assignments as of RFC1700, pp.172f.
+       We use 00-00-5E-vv-nn-zz with
+       vv=1pppccc0, p=protocol, c=crypto,
+       nn=device number, zz=from MAC of first eth device.
+    */
+    cc->dev.dev_addr[2]=0x5E;
+    cc->dev.dev_addr[3]=0x80+(ProtocolVersion<<4)+(CRNUM<<1);
+    cc->dev.dev_addr[4]=n;
+    for (d=dev_base; d; d=d->next)
+	if (d->type==ARPHRD_ETHER) {
+	    cc->dev.dev_addr[5]=d->dev_addr[5];
+	    break;
+	}
+#else
+    /* MAC address will be generated from IP as with PLIP. FC-FC-ip-ip-ip-ip */
+    cc->dev.dev_addr[1]=cc->dev.dev_addr[0]=0xFC;
+#endif
+    memset(d->broadcast, 0xFF, ETH_ALEN);
+    cc->dev.addr_len=ETH_ALEN;
+
+    e=register_netdevice(&(cc->dev));
+    if (e<0) {
+	kfree(cc);
+	printk(KERN_ERR
+	       "%s: register_netdevice() failed\n", cc->dev.name);
+        cc=NULL;
+    } else {
+        cc->cipe.owner=current->pid;
+    }
+    cipe_ctrls[n]=cc;
+    return e;
+}
+
+static void cipe_unalloc_dev(int n)
+{
+    struct cipe_ctrl *cc=cipe_ctrls[n];
+    if (!cc)
+	return;
+    dprintk(DEB_CALL, (KERN_INFO DEVNAME ": cipe_unalloc_dev %d\n", n));
+    if (cc->cipe.magic!=CIPE_MAGIC) {
+        printk(KERN_WARNING DEVNAME ": Ouch: cipe_unalloc_dev() wrong struct\n");
+        return;
+    }
+    unregister_netdevice(&(cc->dev));
+    cipe_ctrls[n]=NULL;
+    kfree(cc);
+}
+
+int init_module(void)
+{
+    int e=cipe_check_kernel();
+    if (e<0)
+	return e;
+
+    /* sanity check on insmod-provided data */
+    if (cipe_maxdev<1)  cipe_maxdev=1;
+#ifdef NO_DYNDEV
+    if (cipe_maxdev>100) cipe_maxdev=100;
+#else
+    if (cipe_maxdev>10000) cipe_maxdev=10000;
+#endif
+
+#ifdef DEBUG
+    printk(KERN_INFO
+	   DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels, debug=%d\n",
+	   driver_version, cipe_maxdev, cipe_debug);
+#else
+    printk(KERN_INFO
+	   DEVNAME ": CIPE driver vers %s (c) Olaf Titz 1996-2000, %d channels\n",
+	   driver_version, cipe_maxdev);
+#endif
+
+    prnseed=(~jiffies)^CURRENT_TIME;
+    cipe_ctrls = (struct cipe_ctrl **) kmalloc(sizeof(void*)*cipe_maxdev,
+					       GFP_KERNEL);
+    if (!cipe_ctrls) {
+	printk(KERN_ERR
+	       DEVNAME ": failed to allocate master control structure\n");
+	return -ENOMEM;
+    }
+    memset(cipe_ctrls, 0, sizeof(void*)*cipe_maxdev);
+#ifdef NO_DYNDEV
+    {
+        int i;
+	rtnl_LOCK();
+        for (i=0; i<cipe_maxdev; ++i)
+            if ((e=cipe_alloc_dev(i))) {
+		rtnl_UNLOCK();
+                return e;
+	    }
+	rtnl_UNLOCK();
+        return 0;
+    }
+#else
+    rtnl_LOCK();
+    e=cipe_alloc_dev(0);
+    rtnl_UNLOCK();
+    return e;
+#endif
+}
+
+void cleanup_module(void)
+{
+    int i;
+    rtnl_LOCK();
+    for (i=0; i<cipe_maxdev; ++i)
+	cipe_unalloc_dev(i);
+    rtnl_UNLOCK();
+    kfree(cipe_ctrls);
+}
+
-------------- next part --------------
A non-text attachment was scrubbed...
Name: linux-2.4.1-compilefailure.patch
Type: text/x-patch
Size: 28007 bytes
Desc: not available
Url : http://lists.fedoraproject.org/pipermail/devel/attachments/20030725/4785382e/attachment-0004.bin 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: linux-2.4.9-addon.patch
Type: text/x-patch
Size: 3513 bytes
Desc: not available
Url : http://lists.fedoraproject.org/pipermail/devel/attachments/20030725/4785382e/attachment-0005.bin 


More information about the devel mailing list