]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/commitdiff
IPSec-Downgrade auf 2.4.8-STABLE
authorms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Thu, 7 Jun 2007 12:24:14 +0000 (12:24 +0000)
committerms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Thu, 7 Jun 2007 12:24:14 +0000 (12:24 +0000)
Outgoing-Firewall quasi fertig gemacht.
IPP2P gefixt.

git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@614 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8

18 files changed:
config/kernel/kernel.config.i586
config/kernel/kernel.config.i586.smp
config/kernel/kernel.config.i586.xen
config/outgoingfw/outgoingfw.pl
config/rootfiles/common/ipp2p
config/rootfiles/common/misc-progs
config/rootfiles/common/openswan
doc/ChangeLog
doc/packages-list.txt
lfs/ipp2p
lfs/linux
lfs/openswan
lfs/squid
make.sh
src/misc-progs/Makefile
src/misc-progs/outgoingfwctrl.c [new file with mode: 0644]
src/patches/openswan-2.4.8.kernel-2.6-klips.patch [new file with mode: 0644]
src/patches/openswan-2.4.8.kernel-2.6-natt.patch [new file with mode: 0644]

index 28451f449af84987fb2d537b6b567276978e9b5a..026514ebb9df4175e99e0cce47290dc12e1146b3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.16.50-ipfire
-# Fri Jun  1 22:33:07 2007
+# Wed Jun  6 00:04:48 2007
 #
 CONFIG_X86_32=y
 CONFIG_SEMAPHORE_SLEEPERS=y
@@ -620,6 +620,7 @@ CONFIG_KLIPS_ENC_CRYPTOAPI=y
 CONFIG_KLIPS_ENC_1DES=y
 CONFIG_KLIPS_ENC_3DES=y
 CONFIG_KLIPS_ENC_AES=y
+# CONFIG_KLIPS_ENC_NULL is not set
 CONFIG_KLIPS_IPCOMP=y
 CONFIG_KLIPS_DEBUG=y
 
index 33c2ebb341780e01dac6fc025387c7ede0d6b888..0ee763cf0021b785310d639d4959aab33ee91d77 100644 (file)
@@ -626,6 +626,7 @@ CONFIG_KLIPS_ENC_CRYPTOAPI=y
 CONFIG_KLIPS_ENC_1DES=y
 CONFIG_KLIPS_ENC_3DES=y
 CONFIG_KLIPS_ENC_AES=y
+# CONFIG_KLIPS_ENC_NULL is not set
 CONFIG_KLIPS_IPCOMP=y
 CONFIG_KLIPS_DEBUG=y
 
index 6ee74554da31611ebb3e6e55b59bf207a53ae491..57f8bfef3e10e3fa8bde241afb5db9b72a429b62 100644 (file)
@@ -504,6 +504,7 @@ CONFIG_KLIPS_ENC_CRYPTOAPI=y
 CONFIG_KLIPS_ENC_1DES=y
 CONFIG_KLIPS_ENC_3DES=y
 CONFIG_KLIPS_ENC_AES=y
+# CONFIG_KLIPS_ENC_NULL is not set
 CONFIG_KLIPS_IPCOMP=y
 CONFIG_KLIPS_DEBUG=y
 
index 5c08c3089f874fc9e7392a3a6695288efde99761..4d8ee425de8c5cfa0cb9411b983ac447ac661056 100644 (file)
@@ -6,6 +6,9 @@
 #
 # (c) The IPFire Team
 #
+# Michael Tremer - mitch@ipfire.org
+# Christian Schmidt - maniacikarus@ipfire.org
+#
 
 use strict;
 # enable only the following on debugging purpose
@@ -24,8 +27,10 @@ my @configline = ();
 my $p2pentry = "";
 my @p2ps = ();
 my @p2pline = ();
-my @protos = ();
+my @proto = ();
 my $CMD = "";
+my $P2PSTRING = "";
+
 my $DEBUG = 0;
 
 my $configfile = "/var/ipfire/outgoing/rules";
@@ -68,21 +73,10 @@ open( FILE, "< $configfile" ) or die "Unable to read $configfile";
 @configs = <FILE>;
 close FILE;
 
-# Say hello!
-print "Outgoing firewall for IPFire - $outfwsettings{'POLICY'}\n";
-if ($DEBUG) { print "Debugging mode!\n"; }
-print "\n";
-
-
-if ( $outfwsettings{'POLICY'} eq 'MODE0' ) {
-       system("/sbin/iptables --flush OUTGOINGFW >/dev/null 2>&1");
-       system("/sbin/iptables --delete-chain OUTGOINGFW >/dev/null 2>&1");
-
-       exit 0
-} elsif ( $outfwsettings{'POLICY'} eq 'MODE1' ) {
+if ( $outfwsettings{'POLICY'} eq 'MODE1' ) {
        $outfwsettings{'STATE'} = "ALLOW";
        $POLICY = "DROP";
-       $DO = "ACCEPT";
+       $DO = "RETURN";
 } elsif ( $outfwsettings{'POLICY'} eq 'MODE2' ) {
        $outfwsettings{'STATE'} = "DENY";
        $POLICY = "ACCEPT";
@@ -94,6 +88,17 @@ system("/sbin/iptables --flush OUTGOINGFW >/dev/null 2>&1");
 system("/sbin/iptables --delete-chain OUTGOINGFW >/dev/null 2>&1");
 system("/sbin/iptables -N OUTGOINGFW >/dev/null 2>&1");
 
+if ( $outfwsettings{'POLICY'} eq 'MODE0' ) {
+       exit 0
+}
+
+if ( $outfwsettings{'POLICY'} eq 'MODE1' ) {
+       $CMD = "/sbin/iptables -A OUTGOINGFW -m state --state ESTABLISHED,RELATED -j RETURN";
+       if ($DEBUG) { print "$CMD\n"; } else { system("$CMD"); }
+               $CMD = "/sbin/iptables -A OUTGOINGFW -p icmp -j RETURN";
+       if ($DEBUG) { print "$CMD\n"; } else { system("$CMD"); }
+}
+
 foreach $configentry (sort @configs)
 {
        $SOURCE = "";
@@ -122,33 +127,85 @@ foreach $configentry (sort @configs)
                }
 
                if ($configline[7]) { $DESTINATION = "$configline[7]"; } else { $DESTINATION = "0/0"; }
-
-               $CMD = "/sbin/iptables -A OUTGOINGFW -s $SOURCE -d $DESTINATION";
-
-               if ($configline[3] ne 'tcp&udp') {
-                       $PROTO = "$configline[3]";
-                       $CMD = "$CMD -p $PROTO";
+               
+               if ($configline[3] eq 'tcp') {
+                       @proto = ("tcp");
+               } elsif ($configline[3] eq 'udp') {
+                       @proto = ("udp");
+               } else {
+                       @proto = ("tcp", "udp");
+               }
+               
+               foreach $PROTO (@proto) {
+                       $CMD = "/sbin/iptables -A OUTGOINGFW -s $SOURCE -d $DESTINATION -p $PROTO";
+       
                        if ($configline[8]) {
                                $DPORT = "$configline[8]";
                                $CMD = "$CMD --dport $DPORT";
                        }
-               }
-
-               if ($DEV) {
-                       $CMD = "$CMD -i $DEV";
-               }
+                       
+                       if ($DEV) {
+                               $CMD = "$CMD -i $DEV";
+                       }
+       
+                       if ($configline[6]) {
+                               $MAC = "$configline[6]";
+                               $CMD = "$CMD -m mac --mac-source $MAC";
+                       }
+       
+                       $CMD = "$CMD -o $netsettings{'RED_DEV'}";
+                       if ($DEBUG) {
+                               print "$CMD -j $DO\n";
+                       } else {
+                               system("$CMD -j $DO");
+                       }
+                       
+                       if ($configline[9] eq "log") {
+                               if ($DEBUG) {
+                                       print "$CMD -m state --state NEW -j LOG --log-prefix 'OUTGOINGFW '\n";
+                               } else {
+                                       system("$CMD -m state --state NEW -j LOG --log-prefix 'OUTGOINGFW '");
+                               }
+                       }
+    }
+       }
+}
 
-               if ($configline[6]) {
-                       $MAC = "$configline[6]";
-                       $CMD = "$CMD -m mac --mac-source $MAC";
-               }
+### Do the P2P-Stuff here
+open( FILE, "< $p2pfile" ) or die "Unable to read $p2pfile";
+@p2ps = <FILE>;
+close FILE;
 
-               $CMD = "$CMD -o $netsettings{'RED_DEV'}";
-               if ($DEBUG) { print "$CMD -j $DO\n"; } else { system("$CMD -j $DO"); }
+$CMD = "/sbin/iptables -A OUTGOINGFW -m ipp2p";
 
-               if ($configline[9] eq "log") {
-                       if ($DEBUG) { print "$CMD -m state --state NEW -j LOG --log-prefix 'OUTGOINGFW '\n"; } else { system("$CMD -m state --state NEW -j LOG --log-prefix 'OUTGOINGFW '"); }
+foreach $p2pentry (sort @p2ps)
+{
+       @p2pline = split( /\;/, $p2pentry );
+       if ( $outfwsettings{'POLICY'} eq 'MODE2' ) {
+               $DO = "DROP";
+               if ("$p2pline[2]" eq "off") {
+                       $P2PSTRING = "$P2PSTRING --$p2pline[1]";
+               }
+       } else {
+               $DO = "RETURN";
+               if ("$p2pline[2]" eq "on") {
+                       $P2PSTRING = "$P2PSTRING --$p2pline[1]";
                }
+       }
+}
+if ($P2PSTRING) {
+       if ($DEBUG) {
+               print "$CMD $P2PSTRING -j $DO\n";
+       } else {
+               system("$CMD $P2PSTRING -j $DO");
+       }
+}
 
+if ( $outfwsettings{'POLICY'} eq 'MODE1' ) {
+       $CMD = "/sbin/iptables -A OUTGOINGFW -j DROP";
+       if ($DEBUG) {
+               print "$CMD\n";
+       } else {
+               system("$CMD");
        }
 }
index 7b005b139c250a550e0d0c8f998f886865183153..742f9eae8aa57fdaa5719e5ea3b94e0346e80eb3 100644 (file)
@@ -1,3 +1,3 @@
 #lib/modules/2.6.16/kernel/net/ipv4/netfilter/ipt_ipp2p.ko
-lib/iptables/libipt_ipp2p.o
+lib/iptables/libipt_ipp2p.so
 #lib/modules/2.6.16-smp/kernel/net/ipv4/netfilter/ipt_ipp2p.ko
index 009f2d4b5c21995503b1d692b0594a472520b4b0..6dd88ca3eba171e852b470566f363a724559322e 100644 (file)
@@ -7,11 +7,11 @@ usr/local/bin/ipsecctrl
 usr/local/bin/launch-ether-wake
 usr/local/bin/logwatch
 usr/local/bin/openvpnctrl
+usr/local/bin/outgoingfwctrl
 usr/local/bin/qosctrl
 usr/local/bin/rebuildhosts
 usr/local/bin/redctrl
 usr/local/bin/monitorTraff
-#usr/local/bin/restartapplejuice
 usr/local/bin/snortctrl
 usr/local/bin/restartssh
 usr/local/bin/restartsyslogd
index 41babb71950963fdb2311714f9c3b676f8c081d5..34ffe89ee847413d99d092bdce259a1b418639de 100644 (file)
@@ -1,9 +1,9 @@
 etc/ipsec.conf
 #etc/ipsec.d
-#etc/ipsec.d/aacerts
-#etc/ipsec.d/cacerts
-#etc/ipsec.d/certs
-#etc/ipsec.d/crls
+etc/ipsec.d/aacerts
+etc/ipsec.d/cacerts
+etc/ipsec.d/certs
+etc/ipsec.d/crls
 #etc/ipsec.d/examples
 #etc/ipsec.d/examples/l2tp-cert-orgWIN2KXP.conf
 #etc/ipsec.d/examples/l2tp-cert.conf
@@ -11,16 +11,17 @@ etc/ipsec.conf
 #etc/ipsec.d/examples/l2tp-psk.conf
 #etc/ipsec.d/examples/linux-linux.conf
 #etc/ipsec.d/examples/no_oe.conf
-#etc/ipsec.d/ocspcerts
-#etc/ipsec.d/policies
+#etc/ipsec.d/examples/sysctl.conf
+etc/ipsec.d/ocspcerts
+etc/ipsec.d/policies
 #etc/ipsec.d/policies/block
 #etc/ipsec.d/policies/clear
 #etc/ipsec.d/policies/clear-or-private
 #etc/ipsec.d/policies/private
 #etc/ipsec.d/policies/private-or-clear
-#etc/ipsec.d/private
+etc/ipsec.d/private
 etc/ipsec.secrets
-etc/rc.d/init.d/ipsec
+#etc/rc.d/init.d/ipsec.old
 #etc/rc.d/rc0.d/K76ipsec
 #etc/rc.d/rc1.d
 #etc/rc.d/rc1.d/K76ipsec
index 8c9920435d8e8749fafaa228579d32557ed33f50..21c2f4f38d62c2914c351947e16f43c7e301ec06 100644 (file)
 ------------------------------------------------------------------------
-r590 | maniacikarus | 2007-05-28 16:56:02 +0400 (Mon, 28 May 2007) | 2 lines
+r613 | maniacikarus | 2007-06-06 19:50:25 +0200 (Wed, 06 Jun 2007) | 2 lines
+
+Squid gefixt damit auch andere auth meachanismen funktionieren
+
+------------------------------------------------------------------------
+r612 | maniacikarus | 2007-06-06 19:09:21 +0200 (Wed, 06 Jun 2007) | 2 lines
+
+Viele CGIs geaendert, einige Proxy Dateien hinzugefuegt, iptables aus dem menu geschmissen
+
+------------------------------------------------------------------------
+r611 | casemaster | 2007-06-05 23:24:58 +0200 (Tue, 05 Jun 2007) | 2 lines
+
+Kleine ?\195?\132nderung beim erstellen der Auswahlzeile im Setup.
+
+------------------------------------------------------------------------
+r610 | ms | 2007-06-05 15:44:26 +0200 (Tue, 05 Jun 2007) | 2 lines
+
+Pakfire erweitert.
+
+------------------------------------------------------------------------
+r609 | ms | 2007-06-05 12:45:16 +0200 (Tue, 05 Jun 2007) | 2 lines
+
+Nur Buildfixes.
+
+------------------------------------------------------------------------
+r608 | ms | 2007-06-05 02:11:03 +0200 (Tue, 05 Jun 2007) | 4 lines
+
+Unbenutztes Nash geloescht.
+Revert der tripwire.cgi
+mISDN-Tools eingebaut und im Kernel aktualisiert.
+
+------------------------------------------------------------------------
+r607 | maniacikarus | 2007-06-04 21:37:49 +0200 (Mon, 04 Jun 2007) | 2 lines
+
+PPOE Skript sollte den kill, CGI Fixes
+
+------------------------------------------------------------------------
+r606 | ms | 2007-06-04 18:50:12 +0200 (Mon, 04 Jun 2007) | 8 lines
+
+Das kleine AJAX-Bandbreitenmeter gefixt. Zeigte zu hohe Werte aufgrund eines Berechnungsfehlers an und die XML-Schnittstelle wurde nicht korrekt angesprochen.
+Bootsplash-Bilder entfernt.
+Snort-Scripte nochmal getestet. Laedt die Updates korrekt und wird auch korrekt gestartet.
+Snortctrl geschrieben, welche noch nicht aufgerufen wird.
+Grub-Patch verschoben.
+Clamav-Update.
+CDRom-Auswurf getestet.
+
+------------------------------------------------------------------------
+r605 | ms | 2007-06-03 00:41:08 +0200 (Sun, 03 Jun 2007) | 2 lines
+
+Nochmal was neues damit der endlich die CD auswirft...
+
+------------------------------------------------------------------------
+r604 | ms | 2007-06-03 00:00:37 +0200 (Sun, 03 Jun 2007) | 3 lines
+
+RAID-Erkennung von Sven Nierlein - Danke.
+(Den altbekannten IP-Conntrack-Patch wieder eingebaut.)
+
+------------------------------------------------------------------------
+r603 | maniacikarus | 2007-06-02 19:03:20 +0200 (Sat, 02 Jun 2007) | 2 lines
+
+kleine Aenderungen in der Gui und ein paar Dateien geloescht
+
+------------------------------------------------------------------------
+r602 | ms | 2007-06-02 00:48:42 +0200 (Sat, 02 Jun 2007) | 2 lines
+
+Kernel-Config gefixt.
+
+------------------------------------------------------------------------
+r601 | ms | 2007-06-02 00:13:16 +0200 (Sat, 02 Jun 2007) | 3 lines
+
+Den Nettraffic Buildprozess bearbeitet.
+Ein neues Snort-Initscript, was noch zuende bearbeitet werden muss.
+
+------------------------------------------------------------------------
+r600 | maniacikarus | 2007-06-01 23:29:25 +0200 (Fri, 01 Jun 2007) | 2 lines
+
+Pakfire CGI ein bisl erweitert, Index CGI um die DIAL CGI erweitert -> Funktion testen, PPOE Timeout Seconds erweitert
+
+------------------------------------------------------------------------
+r599 | maniacikarus | 2007-06-01 17:29:00 +0200 (Fri, 01 Jun 2007) | 2 lines
+
+kleine fixes am nettraffic
+
+------------------------------------------------------------------------
+r598 | ms | 2007-05-31 22:30:13 +0200 (Thu, 31 May 2007) | 2 lines
+
+Busybox noch umgearbeitet... Sollte jetz die CD auswerfen...
+
+------------------------------------------------------------------------
+r597 | ms | 2007-05-31 15:55:16 +0200 (Thu, 31 May 2007) | 2 lines
+
+Grub.conf nachgeliefert.
+
+------------------------------------------------------------------------
+r596 | ms | 2007-05-31 15:54:43 +0200 (Thu, 31 May 2007) | 5 lines
+
+Die Partitionen werden nun dynamisch berechnet.
+Min. 512MB - Max. 2GB - /
+20MB - /boot
+Min. 246MB - Max. 1GB - swap
+
+------------------------------------------------------------------------
+r595 | maniacikarus | 2007-05-30 21:21:47 +0200 (Wed, 30 May 2007) | 2 lines
+
+Net-Traffic aktualisiert
+
+------------------------------------------------------------------------
+r594 | ms | 2007-05-30 21:04:59 +0200 (Wed, 30 May 2007) | 2 lines
+
+Kleiner Fix fuer das Erstellen der Ordner auf dem FTP.
+
+------------------------------------------------------------------------
+r593 | ms | 2007-05-30 21:01:59 +0200 (Wed, 30 May 2007) | 2 lines
+
+Moeglichkeit im Installer das Dateisystem auszuwaehlen...
+
+------------------------------------------------------------------------
+r592 | maniacikarus | 2007-05-29 21:35:33 +0200 (Tue, 29 May 2007) | 2 lines
+
+Die CGIs nochmal angepasst, MTU Parameter geaendert
+
+------------------------------------------------------------------------
+r591 | maniacikarus | 2007-05-29 11:53:38 +0200 (Tue, 29 May 2007) | 2 lines
+
+Build Error gefixt, config types gefixt, root partition auf 1GB
+
+------------------------------------------------------------------------
+r590 | maniacikarus | 2007-05-28 14:56:02 +0200 (Mon, 28 May 2007) | 2 lines
 
 Firewallgraphen angepasst und uebersetzt
 
 ------------------------------------------------------------------------
-r589 | maniacikarus | 2007-05-28 14:58:02 +0400 (Mon, 28 May 2007) | 2 lines
+r589 | maniacikarus | 2007-05-28 12:58:02 +0200 (Mon, 28 May 2007) | 2 lines
 
 Sprachdateien gefixt
 
 ------------------------------------------------------------------------
-r588 | maniacikarus | 2007-05-28 00:14:42 +0400 (Mon, 28 May 2007) | 2 lines
+r588 | maniacikarus | 2007-05-27 22:14:42 +0200 (Sun, 27 May 2007) | 2 lines
 
 WOL Config Types angepasst, Nettraffic und Firewall Graphs Translations, Graph Directory auf 777
 
 ------------------------------------------------------------------------
-r587 | ms | 2007-05-27 22:12:44 +0400 (Sun, 27 May 2007) | 2 lines
+r587 | ms | 2007-05-27 20:12:44 +0200 (Sun, 27 May 2007) | 2 lines
 
 Das Intermediate Functional Block Device aktiviert - Alternative zum IMQ-Device.
 
 ------------------------------------------------------------------------
-r586 | ms | 2007-05-27 15:13:06 +0400 (Sun, 27 May 2007) | 2 lines
+r586 | ms | 2007-05-27 13:13:06 +0200 (Sun, 27 May 2007) | 2 lines
 
 Nochn Fix - obs daran gelegen hat?
 
 ------------------------------------------------------------------------
-r585 | ms | 2007-05-27 14:52:36 +0400 (Sun, 27 May 2007) | 2 lines
+r585 | ms | 2007-05-27 12:52:36 +0200 (Sun, 27 May 2007) | 2 lines
 
 Freetype wird gebraucht vom rrdtool.
 
 ------------------------------------------------------------------------
-r584 | ms | 2007-05-27 00:44:12 +0400 (Sun, 27 May 2007) | 2 lines
+r584 | ms | 2007-05-26 22:44:12 +0200 (Sat, 26 May 2007) | 2 lines
 
 Ein Fix zum bauen des XEN-Kernels.
 
 ------------------------------------------------------------------------
-r583 | ms | 2007-05-26 23:04:16 +0400 (Sat, 26 May 2007) | 7 lines
+r583 | ms | 2007-05-26 21:04:16 +0200 (Sat, 26 May 2007) | 7 lines
 
 Die Abhaengigkeitspakete vom Samba erstellt.
 vsftpd hinzugefuegt... :D Vergebt mir...
@@ -44,62 +172,62 @@ Bootsplash entfernt.
 mc-Alias erstellt, sodass der auf der Textkonsole ordentlich zu bedienen ist.
 
 ------------------------------------------------------------------------
-r582 | maniacikarus | 2007-05-26 14:26:04 +0400 (Sat, 26 May 2007) | 2 lines
+r582 | maniacikarus | 2007-05-26 12:26:04 +0200 (Sat, 26 May 2007) | 2 lines
 
 nochmal eine kleine Anpassung damit die resolv.conf bei Benutzung von red auch wieder auf 127.0.0.1 steht falls man vorher mal green only hatte
 
 ------------------------------------------------------------------------
-r581 | ms | 2007-05-26 00:41:23 +0400 (Sat, 26 May 2007) | 2 lines
+r581 | ms | 2007-05-25 22:41:23 +0200 (Fri, 25 May 2007) | 2 lines
 
 Erster Xen-Kernel zum testen...
 
 ------------------------------------------------------------------------
-r580 | maniacikarus | 2007-05-25 22:32:07 +0400 (Fri, 25 May 2007) | 2 lines
+r580 | maniacikarus | 2007-05-25 20:32:07 +0200 (Fri, 25 May 2007) | 2 lines
 
 Funktionen eingebaut, damit bei green only die Gateway und DNS Einstellungen wirksam werden
 
 ------------------------------------------------------------------------
-r579 | ms | 2007-05-25 21:06:38 +0400 (Fri, 25 May 2007) | 3 lines
+r579 | ms | 2007-05-25 19:06:38 +0200 (Fri, 25 May 2007) | 3 lines
 
 Kleiner Fix fuer die pppsetup.cgi
 und noch n paar andere kleine Sachen...
 
 ------------------------------------------------------------------------
-r578 | maniacikarus | 2007-05-24 23:41:13 +0400 (Thu, 24 May 2007) | 2 lines
+r578 | maniacikarus | 2007-05-24 21:41:13 +0200 (Thu, 24 May 2007) | 2 lines
 
 CPU Graph wieder auf Ticks umgestellt und erweitert
 
 ------------------------------------------------------------------------
-r577 | casemaster | 2007-05-23 01:07:50 +0400 (Wed, 23 May 2007) | 3 lines
+r577 | casemaster | 2007-05-22 23:07:50 +0200 (Tue, 22 May 2007) | 3 lines
 
 ?\195?\132nderung am Installer/Setup.
 "Green only" darf jetzt auch DNS und Gateway setzen.
 
 ------------------------------------------------------------------------
-r576 | casemaster | 2007-05-22 23:51:25 +0400 (Tue, 22 May 2007) | 2 lines
+r576 | casemaster | 2007-05-22 21:51:25 +0200 (Tue, 22 May 2007) | 2 lines
 
 Weitere ?\195?\132nderungen am Installer/Setup vorgenommen.
 
 ------------------------------------------------------------------------
-r575 | ms | 2007-05-22 23:40:21 +0400 (Tue, 22 May 2007) | 3 lines
+r575 | ms | 2007-05-22 21:40:21 +0200 (Tue, 22 May 2007) | 3 lines
 
 Treiber fuer 1-Wire-Geraete hinzugefuegt --> Digitemp fuer "Karl S."
 Schreibt DNS-Server wenn red = static ist.
 
 ------------------------------------------------------------------------
-r574 | maniacikarus | 2007-05-22 23:14:06 +0400 (Tue, 22 May 2007) | 2 lines
+r574 | maniacikarus | 2007-05-22 21:14:06 +0200 (Tue, 22 May 2007) | 2 lines
 
 Nochmal korrigiert und fwhits auf eine Graphenart eingestellt
 
 ------------------------------------------------------------------------
-r573 | maniacikarus | 2007-05-22 23:04:48 +0400 (Tue, 22 May 2007) | 4 lines
+r573 | maniacikarus | 2007-05-22 21:04:48 +0200 (Tue, 22 May 2007) | 4 lines
 
 Graphen Hintergrundfarbe bei Standarttheme auf weiss gesetzt
 Config Types in der Nettraffic angepasst
 Erstellung der Week Month und Year Graphen nur noch bei Request
 
 ------------------------------------------------------------------------
-r572 | ms | 2007-05-22 19:43:16 +0400 (Tue, 22 May 2007) | 5 lines
+r572 | ms | 2007-05-22 17:43:16 +0200 (Tue, 22 May 2007) | 5 lines
 
 ISAPNPTOOLS entfernt, da wir kein ISA mehr unterstuetzen.
 Squid und Samba aktualisiert.
@@ -107,29 +235,29 @@ Soundtreiber im Kernel eingeschaltet.
 Time-Server funzt nun auch.
 
 ------------------------------------------------------------------------
-r571 | ms | 2007-05-22 18:02:38 +0400 (Tue, 22 May 2007) | 3 lines
+r571 | ms | 2007-05-22 16:02:38 +0200 (Tue, 22 May 2007) | 3 lines
 
 Das IPSec-Modul laesst sich nun laden.
 Einige Bugs der Alpha 2 behoben.
 
 ------------------------------------------------------------------------
-r570 | maniacikarus | 2007-05-22 00:35:30 +0400 (Tue, 22 May 2007) | 2 lines
+r570 | maniacikarus | 2007-05-21 22:35:30 +0200 (Mon, 21 May 2007) | 2 lines
 
 Qos Port und Layer7 Rules sind editierbar
 
 ------------------------------------------------------------------------
-r569 | ms | 2007-05-21 18:42:44 +0400 (Mon, 21 May 2007) | 3 lines
+r569 | ms | 2007-05-21 16:42:44 +0200 (Mon, 21 May 2007) | 3 lines
 
 Alpha2 - Aenderungen von Arne F. eingepflegt.
 ...sonst noch kleine Fixes.
 
 ------------------------------------------------------------------------
-r568 | maniacikarus | 2007-05-20 20:11:15 +0400 (Sun, 20 May 2007) | 2 lines
+r568 | maniacikarus | 2007-05-20 18:11:15 +0200 (Sun, 20 May 2007) | 2 lines
 
 nochmal 2 kleine fixes im Stack
 
 ------------------------------------------------------------------------
-r567 | maniacikarus | 2007-05-20 18:25:10 +0400 (Sun, 20 May 2007) | 5 lines
+r567 | maniacikarus | 2007-05-20 16:25:10 +0200 (Sun, 20 May 2007) | 5 lines
 
 makegraphs umgebaut, sodass nurnoch rrd daten geschrieben werden die graphen
 werden dynamisch durch die jeweiligen Seiten geladen adurch wird die Grundlast
@@ -137,287 +265,287 @@ des Systems verringert, ausserdem noch den parameter iowait eingebaut und die
 hd graphen repariert
 
 ------------------------------------------------------------------------
-r566 | ms | 2007-05-19 16:19:35 +0400 (Sat, 19 May 2007) | 2 lines
+r566 | ms | 2007-05-19 14:19:35 +0200 (Sat, 19 May 2007) | 2 lines
 
 Noch ein paar kleine Aenderungen wegen dem mkinitcpio...
 
 ------------------------------------------------------------------------
-r565 | ms | 2007-05-19 12:49:49 +0400 (Sat, 19 May 2007) | 2 lines
+r565 | ms | 2007-05-19 10:49:49 +0200 (Sat, 19 May 2007) | 2 lines
 
 2 Buildfixes
 
 ------------------------------------------------------------------------
-r564 | maniacikarus | 2007-05-19 11:26:13 +0400 (Sat, 19 May 2007) | 2 lines
+r564 | maniacikarus | 2007-05-19 09:26:13 +0200 (Sat, 19 May 2007) | 2 lines
 
 makegraphs wegen config types und besserer optik angepasst
 
 ------------------------------------------------------------------------
-r563 | maniacikarus | 2007-05-18 21:32:42 +0400 (Fri, 18 May 2007) | 2 lines
+r563 | maniacikarus | 2007-05-18 19:32:42 +0200 (Fri, 18 May 2007) | 2 lines
 
 Qos CGI vom Meister angefasst und Quellcode neu ausgewuerfelt
 
 ------------------------------------------------------------------------
-r562 | maniacikarus | 2007-05-18 20:48:08 +0400 (Fri, 18 May 2007) | 3 lines
+r562 | maniacikarus | 2007-05-18 18:48:08 +0200 (Fri, 18 May 2007) | 3 lines
 
 Config types auf ist Zustand gebogen ... hoffentlich ...
 header.pl von doppelten funktionen befreit die schon in der genereal stehen
 
 ------------------------------------------------------------------------
-r561 | ms | 2007-05-18 20:00:20 +0400 (Fri, 18 May 2007) | 3 lines
+r561 | ms | 2007-05-18 18:00:20 +0200 (Fri, 18 May 2007) | 3 lines
 
 Die IDE/SCSI/SATA/USB-Erkennung erstellt nun schoene Ramdisks :D
 Kernel ist jetzt noch modularer, da keine IDE/FS-Treiber vorhanden sind.
 
 ------------------------------------------------------------------------
-r560 | maniacikarus | 2007-05-17 20:54:15 +0400 (Thu, 17 May 2007) | 2 lines
+r560 | maniacikarus | 2007-05-17 18:54:15 +0200 (Thu, 17 May 2007) | 2 lines
 
 Quasi fast alle cgis von den fixen header farben befreit
 
 ------------------------------------------------------------------------
-r559 | maniacikarus | 2007-05-17 14:13:56 +0400 (Thu, 17 May 2007) | 3 lines
+r559 | maniacikarus | 2007-05-17 12:13:56 +0200 (Thu, 17 May 2007) | 3 lines
 
 neues Theme hinzugefuegt, geloeschtes icons wieder hinzugefuegt
 makegraphs themeable gemacht, maktegraph swap diagramm gefixt
 
 ------------------------------------------------------------------------
-r558 | maniacikarus | 2007-05-13 15:53:36 +0400 (Sun, 13 May 2007) | 2 lines
+r558 | maniacikarus | 2007-05-13 13:53:36 +0200 (Sun, 13 May 2007) | 2 lines
 
 Proxy Portrange beschraenkt Port darf nicht 444 222 81 oder 53 sein und muss zwischen 1 und 65535
 
 ------------------------------------------------------------------------
-r557 | maniacikarus | 2007-05-13 14:09:49 +0400 (Sun, 13 May 2007) | 2 lines
+r557 | maniacikarus | 2007-05-13 12:09:49 +0200 (Sun, 13 May 2007) | 2 lines
 
 kleine optische Anpassung der VPN Stati
 
 ------------------------------------------------------------------------
-r556 | casemaster | 2007-05-13 02:00:50 +0400 (Sun, 13 May 2007) | 2 lines
+r556 | casemaster | 2007-05-13 00:00:50 +0200 (Sun, 13 May 2007) | 2 lines
 
 ?\195?\132nderungen am Installer/Setup vorgenommen. ISDN wird erstmal nicht ?\195?\188ber den Installer abgefragt.
 
 ------------------------------------------------------------------------
-r555 | maniacikarus | 2007-05-13 01:36:36 +0400 (Sun, 13 May 2007) | 2 lines
+r555 | maniacikarus | 2007-05-12 23:36:36 +0200 (Sat, 12 May 2007) | 2 lines
 
 Design der Fehlermeldungen nochmal etwas angepasst
 
 ------------------------------------------------------------------------
-r554 | maniacikarus | 2007-05-12 22:55:01 +0400 (Sat, 12 May 2007) | 2 lines
+r554 | maniacikarus | 2007-05-12 20:55:01 +0200 (Sat, 12 May 2007) | 2 lines
 
 Doch glatt das Bildchen vergessen ...
 
 ------------------------------------------------------------------------
-r553 | maniacikarus | 2007-05-12 22:52:34 +0400 (Sat, 12 May 2007) | 3 lines
+r553 | maniacikarus | 2007-05-12 20:52:34 +0200 (Sat, 12 May 2007) | 3 lines
 
 Proxy.cgi von den IPCop Error Pages befreit, da nicht existent
 ausserdem gleich mal unsere eigenen Errorspages gebaut :D
 
 ------------------------------------------------------------------------
-r552 | ms | 2007-05-12 15:32:08 +0400 (Sat, 12 May 2007) | 3 lines
+r552 | ms | 2007-05-12 13:32:08 +0200 (Sat, 12 May 2007) | 3 lines
 
 Timectrl geschrieben.
 .svnignore hinzugefuegt.
 
 ------------------------------------------------------------------------
-r551 | ms | 2007-05-12 14:16:01 +0400 (Sat, 12 May 2007) | 3 lines
+r551 | ms | 2007-05-12 12:16:01 +0200 (Sat, 12 May 2007) | 3 lines
 
 Einige Dateien hatten perm:755...
 Das sollte im SVN nicht so sein ausser fuer unsere make.sh.
 
 ------------------------------------------------------------------------
-r550 | maniacikarus | 2007-05-11 22:48:57 +0400 (Fri, 11 May 2007) | 3 lines
+r550 | maniacikarus | 2007-05-11 20:48:57 +0200 (Fri, 11 May 2007) | 3 lines
 
 Die Firewallgraphen zeigen die Farben jetzt richtig
 und sind endlich auch vollstaendig themeabke
 
 ------------------------------------------------------------------------
-r549 | ms | 2007-05-11 01:36:03 +0400 (Fri, 11 May 2007) | 3 lines
+r549 | ms | 2007-05-10 23:36:03 +0200 (Thu, 10 May 2007) | 3 lines
 
 IPSec/OpenSWAN-Update
 UTF8-Patch im Kernel.
 
 ------------------------------------------------------------------------
-r548 | ms | 2007-05-09 22:10:57 +0400 (Wed, 09 May 2007) | 2 lines
+r548 | ms | 2007-05-09 20:10:57 +0200 (Wed, 09 May 2007) | 2 lines
 
 Unsere Konsole ist jetzt UTF8-Fit.
 
 ------------------------------------------------------------------------
-r547 | ms | 2007-05-09 14:27:24 +0400 (Wed, 09 May 2007) | 3 lines
+r547 | ms | 2007-05-09 12:27:24 +0200 (Wed, 09 May 2007) | 3 lines
 
 Unbenutzte Icons geloescht.
 Vorruebergehend auch das blaue Theme...
 
 ------------------------------------------------------------------------
-r546 | ms | 2007-05-09 13:53:36 +0400 (Wed, 09 May 2007) | 4 lines
+r546 | ms | 2007-05-09 11:53:36 +0200 (Wed, 09 May 2007) | 4 lines
 
 Ein Paar ganz unnoetige Scripts geloescht.
 Einen String im Installer verkuerzt.
 Einen Symlink der libnewt* vergessen.
 
 ------------------------------------------------------------------------
-r545 | ms | 2007-05-09 13:27:05 +0400 (Wed, 09 May 2007) | 4 lines
+r545 | ms | 2007-05-09 11:27:05 +0200 (Wed, 09 May 2007) | 4 lines
 
 JFFS2-Dateisystem hinzugefuegt fuer eventuelle Flash-Version der Firewall.
 Installer braucht nichtmehr die Font einzustellen.
 Oinkmasterscript war nicht in der ISO.
 
 ------------------------------------------------------------------------
-r544 | ms | 2007-05-09 01:28:00 +0400 (Wed, 09 May 2007) | 2 lines
+r544 | ms | 2007-05-08 23:28:00 +0200 (Tue, 08 May 2007) | 2 lines
 
 Noch zwei Patches geloescht.
 
 ------------------------------------------------------------------------
-r543 | ms | 2007-05-09 01:26:06 +0400 (Wed, 09 May 2007) | 2 lines
+r543 | ms | 2007-05-08 23:26:06 +0200 (Tue, 08 May 2007) | 2 lines
 
 Slang und Newt gepatcht um den Installer endlich in UTF8 zu betreiben.
 
 ------------------------------------------------------------------------
-r542 | ms | 2007-05-07 23:51:13 +0400 (Mon, 07 May 2007) | 2 lines
+r542 | ms | 2007-05-07 21:51:13 +0200 (Mon, 07 May 2007) | 2 lines
 
 Wieso sind denn Amavisd-new und Spamassassin in der ISO gelandet?
 
 ------------------------------------------------------------------------
-r541 | ms | 2007-05-07 21:29:03 +0400 (Mon, 07 May 2007) | 2 lines
+r541 | ms | 2007-05-07 19:29:03 +0200 (Mon, 07 May 2007) | 2 lines
 
 Temporaere Dateien entfernt.
 
 ------------------------------------------------------------------------
-r540 | ms | 2007-05-07 21:20:46 +0400 (Mon, 07 May 2007) | 4 lines
+r540 | ms | 2007-05-07 19:20:46 +0200 (Mon, 07 May 2007) | 4 lines
 
 Clamav-Update
 Hardwareinformationen fuer Kudzu hinzugefuegt.
 dhcpctrl-Datei erstellt.
 
 ------------------------------------------------------------------------
-r539 | ms | 2007-05-07 03:41:49 +0400 (Mon, 07 May 2007) | 2 lines
+r539 | ms | 2007-05-07 01:41:49 +0200 (Mon, 07 May 2007) | 2 lines
 
 Rootfiles noch geloescht.
 
 ------------------------------------------------------------------------
-r538 | ms | 2007-05-07 02:21:48 +0400 (Mon, 07 May 2007) | 2 lines
+r538 | ms | 2007-05-07 00:21:48 +0200 (Mon, 07 May 2007) | 2 lines
 
 Einige Builderrors aufgrund der entfernten Pakete gefunden.
 
 ------------------------------------------------------------------------
-r537 | ms | 2007-05-06 22:02:18 +0400 (Sun, 06 May 2007) | 2 lines
+r537 | ms | 2007-05-06 20:02:18 +0200 (Sun, 06 May 2007) | 2 lines
 
 Wrapper eingebaut zur Verwendung von URL-Filter und Update-Booster zur gleichen Zeit.
 
 ------------------------------------------------------------------------
-r536 | ms | 2007-05-06 21:53:16 +0400 (Sun, 06 May 2007) | 2 lines
+r536 | ms | 2007-05-06 19:53:16 +0200 (Sun, 06 May 2007) | 2 lines
 
 Pakfire Fixes.
 
 ------------------------------------------------------------------------
-r535 | ms | 2007-05-06 19:28:50 +0400 (Sun, 06 May 2007) | 2 lines
+r535 | ms | 2007-05-06 17:28:50 +0200 (Sun, 06 May 2007) | 2 lines
 
 Ueberfluessige Pakete entfernt.
 
 ------------------------------------------------------------------------
-r534 | ms | 2007-05-06 19:11:01 +0400 (Sun, 06 May 2007) | 4 lines
+r534 | ms | 2007-05-06 17:11:01 +0200 (Sun, 06 May 2007) | 4 lines
 
 Einige Fixes fuer den Paketmanager.
 ISA PnP aus Kernel entfernt.
 Defaultconf fuer Clamav.
 
 ------------------------------------------------------------------------
-r533 | maniacikarus | 2007-05-06 14:54:38 +0400 (Sun, 06 May 2007) | 2 lines
+r533 | maniacikarus | 2007-05-06 12:54:38 +0200 (Sun, 06 May 2007) | 2 lines
 
 geladene Module aus der Systemuebersicht geloescht
 
 ------------------------------------------------------------------------
-r532 | ms | 2007-05-06 03:46:42 +0400 (Sun, 06 May 2007) | 3 lines
+r532 | ms | 2007-05-06 01:46:42 +0200 (Sun, 06 May 2007) | 3 lines
 
 Meta-Dateien werden nicht verschluesselt.
 Statische IPs fuer die rote Schnittstelle funzen nun.
 
 ------------------------------------------------------------------------
-r531 | ms | 2007-05-06 00:18:27 +0400 (Sun, 06 May 2007) | 2 lines
+r531 | ms | 2007-05-05 22:18:27 +0200 (Sat, 05 May 2007) | 2 lines
 
 Pakfire Installationsfixes und AJAX-Speedmeter.
 
 ------------------------------------------------------------------------
-r530 | ms | 2007-05-05 17:53:33 +0400 (Sat, 05 May 2007) | 4 lines
+r530 | ms | 2007-05-05 15:53:33 +0200 (Sat, 05 May 2007) | 4 lines
 
 Packager finalisiert.
 Cronjobs angepasst, falls die Maschine nicht zu der Zeit (meistens nachts) lief.
 Erste Versionen der Tripwire und Samba-Pakete zum testen.
 
 ------------------------------------------------------------------------
-r529 | ms | 2007-05-05 15:13:17 +0400 (Sat, 05 May 2007) | 2 lines
+r529 | ms | 2007-05-05 13:13:17 +0200 (Sat, 05 May 2007) | 2 lines
 
 Kernelupdate auf 2.6.16.50
 
 ------------------------------------------------------------------------
-r528 | maniacikarus | 2007-05-05 00:31:15 +0400 (Sat, 05 May 2007) | 2 lines
+r528 | maniacikarus | 2007-05-04 22:31:15 +0200 (Fri, 04 May 2007) | 2 lines
 
 Viele kleine Schnheitsfehler in einigen CGIs angepasst
 
 ------------------------------------------------------------------------
-r527 | maniacikarus | 2007-05-04 23:37:59 +0400 (Fri, 04 May 2007) | 2 lines
+r527 | maniacikarus | 2007-05-04 21:37:59 +0200 (Fri, 04 May 2007) | 2 lines
 
 fixes in Samba und Korrekturen der langs
 
 ------------------------------------------------------------------------
-r526 | ms | 2007-05-04 17:41:48 +0400 (Fri, 04 May 2007) | 2 lines
+r526 | ms | 2007-05-04 15:41:48 +0200 (Fri, 04 May 2007) | 2 lines
 
 Fold hinzugefuegt.
 
 ------------------------------------------------------------------------
-r525 | ms | 2007-05-04 17:09:57 +0400 (Fri, 04 May 2007) | 2 lines
+r525 | ms | 2007-05-04 15:09:57 +0200 (Fri, 04 May 2007) | 2 lines
 
 Unser Paketmanager...
 
 ------------------------------------------------------------------------
-r524 | ms | 2007-05-04 16:25:11 +0400 (Fri, 04 May 2007) | 2 lines
+r524 | ms | 2007-05-04 14:25:11 +0200 (Fri, 04 May 2007) | 2 lines
 
 Snort Fixes.
 
 ------------------------------------------------------------------------
-r523 | linuxadmin | 2007-05-04 15:51:40 +0400 (Fri, 04 May 2007) | 2 lines
+r523 | linuxadmin | 2007-05-04 13:51:40 +0200 (Fri, 04 May 2007) | 2 lines
 
 Das Entwickler Team angepasst
 
 ------------------------------------------------------------------------
-r522 | linuxadmin | 2007-05-04 15:42:32 +0400 (Fri, 04 May 2007) | 2 lines
+r522 | linuxadmin | 2007-05-04 13:42:32 +0200 (Fri, 04 May 2007) | 2 lines
 
 Einige kleine optische Anpassungen
 
 ------------------------------------------------------------------------
-r521 | ms | 2007-05-04 03:47:46 +0400 (Fri, 04 May 2007) | 2 lines
+r521 | ms | 2007-05-04 01:47:46 +0200 (Fri, 04 May 2007) | 2 lines
 
 Test - Tripwire.
 
 ------------------------------------------------------------------------
-r520 | linuxadmin | 2007-05-04 03:39:11 +0400 (Fri, 04 May 2007) | 2 lines
+r520 | linuxadmin | 2007-05-04 01:39:11 +0200 (Fri, 04 May 2007) | 2 lines
 
 Snortsnarf hinzugefuegt.
 
 ------------------------------------------------------------------------
-r519 | maniacikarus | 2007-05-04 01:26:52 +0400 (Fri, 04 May 2007) | 2 lines
+r519 | maniacikarus | 2007-05-03 23:26:52 +0200 (Thu, 03 May 2007) | 2 lines
 
 Bugfixes in Samba und Sambactrl
 
 ------------------------------------------------------------------------
-r518 | ms | 2007-05-03 22:25:22 +0400 (Thu, 03 May 2007) | 2 lines
+r518 | ms | 2007-05-03 20:25:22 +0200 (Thu, 03 May 2007) | 2 lines
 
 Snort Oberflaeche erweitert.
 
 ------------------------------------------------------------------------
-r517 | ms | 2007-05-03 21:06:13 +0400 (Thu, 03 May 2007) | 2 lines
+r517 | ms | 2007-05-03 19:06:13 +0200 (Thu, 03 May 2007) | 2 lines
 
 Snort-Fixes
 
 ------------------------------------------------------------------------
-r516 | ms | 2007-05-03 11:49:22 +0400 (Thu, 03 May 2007) | 2 lines
+r516 | ms | 2007-05-03 09:49:22 +0200 (Thu, 03 May 2007) | 2 lines
 
 Tripwire aktualisiert.
 
 ------------------------------------------------------------------------
-r515 | casemaster | 2007-05-03 02:32:02 +0400 (Thu, 03 May 2007) | 2 lines
+r515 | casemaster | 2007-05-03 00:32:02 +0200 (Thu, 03 May 2007) | 2 lines
 
 Neue Netzwerkdialoge sind zum ersten Test verfuegbar.
 
 ------------------------------------------------------------------------
-r514 | linuxadmin | 2007-05-02 02:29:15 +0400 (Wed, 02 May 2007) | 9 lines
+r514 | linuxadmin | 2007-05-02 00:29:15 +0200 (Wed, 02 May 2007) | 9 lines
 
 Der Oinkmaster f?\195?\188r Snort ist nun erstmal unter /etc/snort/oinkmaster2.0 abgelegt
 Wenn jemand sich bei Snort registriert hat, muss dieses unter oinkmaster2.0/oink
@@ -429,18 +557,18 @@ Start und Stop ist als init Script eingerichtet.
 
 
 ------------------------------------------------------------------------
-r513 | ms | 2007-05-02 02:04:01 +0400 (Wed, 02 May 2007) | 3 lines
+r513 | ms | 2007-05-02 00:04:01 +0200 (Wed, 02 May 2007) | 3 lines
 
 Clamav-Fixes.
 Clamavctrl gebaut & Initscript geschrieben.
 
 ------------------------------------------------------------------------
-r512 | ms | 2007-05-02 00:35:00 +0400 (Wed, 02 May 2007) | 2 lines
+r512 | ms | 2007-05-01 22:35:00 +0200 (Tue, 01 May 2007) | 2 lines
 
 Noch ein fix, SMART-Status-Anzeige geht!
 
 ------------------------------------------------------------------------
-r511 | ms | 2007-05-02 00:23:13 +0400 (Wed, 02 May 2007) | 5 lines
+r511 | ms | 2007-05-01 22:23:13 +0200 (Tue, 01 May 2007) | 5 lines
 
 Paketmanagement umgeschrieben, GPG-Signatur jetzt moeglich.
 Noch im Teststadium - Clamav ist das Testpaket.
@@ -448,136 +576,136 @@ Fixes in den neuen Statusseiten und Proxysteuerung.
 Mkflash-Scripte entfernt. (Frag mich wozu die da ueberhaupt waren...)
 
 ------------------------------------------------------------------------
-r510 | ms | 2007-05-01 01:20:20 +0400 (Tue, 01 May 2007) | 2 lines
+r510 | ms | 2007-04-30 23:20:20 +0200 (Mon, 30 Apr 2007) | 2 lines
 
 Neue Proxysteuerung.
 
 ------------------------------------------------------------------------
-r509 | ms | 2007-04-30 17:25:32 +0400 (Mon, 30 Apr 2007) | 2 lines
+r509 | ms | 2007-04-30 15:25:32 +0200 (Mon, 30 Apr 2007) | 2 lines
 
 Diverse Fixes.
 
 ------------------------------------------------------------------------
-r508 | ms | 2007-04-29 09:30:18 +0400 (Sun, 29 Apr 2007) | 1 line
+r508 | ms | 2007-04-29 07:30:18 +0200 (Sun, 29 Apr 2007) | 1 line
 
 Nochmals die IPCop-Quellen geloescht
 ------------------------------------------------------------------------
-r507 | ms | 2007-04-28 18:49:02 +0400 (Sat, 28 Apr 2007) | 3 lines
+r507 | ms | 2007-04-28 16:49:02 +0200 (Sat, 28 Apr 2007) | 3 lines
 
 IPCop-Quellen entfernt, da wir sie eh nicht nutzen und uns von diesem
 Projekt distanzieren wollen.
 
 ------------------------------------------------------------------------
-r506 | ms | 2007-04-28 18:22:19 +0400 (Sat, 28 Apr 2007) | 3 lines
+r506 | ms | 2007-04-28 16:22:19 +0200 (Sat, 28 Apr 2007) | 3 lines
 
 Nagios rausgeschmissen...
 Ein paar statische Libs entfernt.
 
 ------------------------------------------------------------------------
-r505 | ms | 2007-04-28 13:01:53 +0400 (Sat, 28 Apr 2007) | 3 lines
+r505 | ms | 2007-04-28 11:01:53 +0200 (Sat, 28 Apr 2007) | 3 lines
 
 Hwinfo-Hardwareerkennung entfernt.
 Alte Paketdateien entfernt, da der Packager neu geschrieben wird.
 
 ------------------------------------------------------------------------
-r504 | ms | 2007-04-26 16:27:41 +0400 (Thu, 26 Apr 2007) | 4 lines
+r504 | ms | 2007-04-26 14:27:41 +0200 (Thu, 26 Apr 2007) | 4 lines
 
 Signierten GPG-Schluessel importiert.
 smartctrl geschrieben.
 Passwort kann nichtmehr im Webinterface geaendert werden.
 
 ------------------------------------------------------------------------
-r503 | ms | 2007-04-26 12:12:20 +0400 (Thu, 26 Apr 2007) | 2 lines
+r503 | ms | 2007-04-26 10:12:20 +0200 (Thu, 26 Apr 2007) | 2 lines
 
 Ueberarbeitung der Status-Seiten.
 
 ------------------------------------------------------------------------
-r502 | maniacikarus | 2007-04-22 12:43:35 +0400 (Sun, 22 Apr 2007) | 4 lines
+r502 | maniacikarus | 2007-04-22 10:43:35 +0200 (Sun, 22 Apr 2007) | 4 lines
 
 Samba vorbereitet fuer CUPS
 Rewrite der internen Verarbeitung mit Hashes und Sub Funktionen
 Erweiterung der ausgehenden Firewall um predefined services
 
 ------------------------------------------------------------------------
-r501 | maniacikarus | 2007-04-18 22:10:00 +0400 (Wed, 18 Apr 2007) | 3 lines
+r501 | maniacikarus | 2007-04-18 20:10:00 +0200 (Wed, 18 Apr 2007) | 3 lines
 
 Tripwire fertig fuer die BETA
 iostat auf der Statusseite eingebaut
 
 ------------------------------------------------------------------------
-r500 | ms | 2007-04-18 18:25:21 +0400 (Wed, 18 Apr 2007) | 3 lines
+r500 | ms | 2007-04-18 16:25:21 +0200 (Wed, 18 Apr 2007) | 3 lines
 
 Tripwirectrl gefixt.
 Develoption zum batch-Befehl hinzugefuegt.
 
 ------------------------------------------------------------------------
-r499 | maniacikarus | 2007-04-13 23:57:32 +0400 (Fri, 13 Apr 2007) | 2 lines
+r499 | maniacikarus | 2007-04-13 21:57:32 +0200 (Fri, 13 Apr 2007) | 2 lines
 
 Wie immer Samba und Tripwirek>
 
 ------------------------------------------------------------------------
-r498 | ms | 2007-04-13 01:55:51 +0400 (Fri, 13 Apr 2007) | 2 lines
+r498 | ms | 2007-04-12 23:55:51 +0200 (Thu, 12 Apr 2007) | 2 lines
 
 Calamaris-Proxy-Logdatei-Analyzer eingebaut.
 
 ------------------------------------------------------------------------
-r497 | maniacikarus | 2007-04-13 01:01:15 +0400 (Fri, 13 Apr 2007) | 2 lines
+r497 | maniacikarus | 2007-04-12 23:01:15 +0200 (Thu, 12 Apr 2007) | 2 lines
 
 Viele kleine ?\195?\132nderungen an Samba und Tripwire
 
 ------------------------------------------------------------------------
-r496 | ms | 2007-04-12 23:07:47 +0400 (Thu, 12 Apr 2007) | 2 lines
+r496 | ms | 2007-04-12 21:07:47 +0200 (Thu, 12 Apr 2007) | 2 lines
 
 Kleine Fixes.
 
 ------------------------------------------------------------------------
-r495 | ms | 2007-04-12 20:28:06 +0400 (Thu, 12 Apr 2007) | 3 lines
+r495 | ms | 2007-04-12 18:28:06 +0200 (Thu, 12 Apr 2007) | 3 lines
 
 Connections.cgi neu geschrieben.
 URL-Filter aktualisiert.
 
 ------------------------------------------------------------------------
-r494 | ms | 2007-04-12 18:06:59 +0400 (Thu, 12 Apr 2007) | 2 lines
+r494 | ms | 2007-04-12 16:06:59 +0200 (Thu, 12 Apr 2007) | 2 lines
 
 "Update Booster" fertiggestellt und getestet.
 
 ------------------------------------------------------------------------
-r493 | ms | 2007-04-12 03:25:47 +0400 (Thu, 12 Apr 2007) | 3 lines
+r493 | ms | 2007-04-12 01:25:47 +0200 (Thu, 12 Apr 2007) | 3 lines
 
 Noch ein Paar Komfortfunktionen.
 Zaehler wird automatisch zuruekgesetzt.
 
 ------------------------------------------------------------------------
-r492 | ms | 2007-04-12 03:04:45 +0400 (Thu, 12 Apr 2007) | 3 lines
+r492 | ms | 2007-04-12 01:04:45 +0200 (Thu, 12 Apr 2007) | 3 lines
 
 Zeitanzeige fuer PPP-Verbindungen...
 Samba-User hinzugefuegt.
 
 ------------------------------------------------------------------------
-r491 | ms | 2007-04-12 00:48:58 +0400 (Thu, 12 Apr 2007) | 4 lines
+r491 | ms | 2007-04-11 22:48:58 +0200 (Wed, 11 Apr 2007) | 4 lines
 
 Festplattenerkennung ueberarbeitet.
 Installationssystem verkleinert.
 Letzte Tripwirectrl.
 
 ------------------------------------------------------------------------
-r490 | maniacikarus | 2007-04-11 14:19:22 +0400 (Wed, 11 Apr 2007) | 2 lines
+r490 | maniacikarus | 2007-04-11 12:19:22 +0200 (Wed, 11 Apr 2007) | 2 lines
 
 MTU MRU einstellbar bei PPoE
 
 ------------------------------------------------------------------------
-r489 | ms | 2007-04-11 12:14:59 +0400 (Wed, 11 Apr 2007) | 2 lines
+r489 | ms | 2007-04-11 10:14:59 +0200 (Wed, 11 Apr 2007) | 2 lines
 
 Saemtliche unbenutzte Patches aus dem Repository geworfen.
 
 ------------------------------------------------------------------------
-r488 | ms | 2007-04-11 02:01:20 +0400 (Wed, 11 Apr 2007) | 3 lines
+r488 | ms | 2007-04-11 00:01:20 +0200 (Wed, 11 Apr 2007) | 3 lines
 
 Neuen Tux von Alex bekommen! Merci beaucoup :D
 Ein bisschen Tripwire aufgeraeumt. Leere Dateien sollten nicht ins Repository :D
 
 ------------------------------------------------------------------------
-r487 | maniacikarus | 2007-04-10 22:39:44 +0400 (Tue, 10 Apr 2007) | 5 lines
+r487 | maniacikarus | 2007-04-10 20:39:44 +0200 (Tue, 10 Apr 2007) | 5 lines
 
 Tripwire Gui integrierto>
 Tripwire Controll Datei geschrieben
@@ -585,127 +713,127 @@ Weitere Anpassungen am Sambapaket
 Tripwire Sourcen ins LFS genommen
 
 ------------------------------------------------------------------------
-r486 | ms | 2007-04-10 20:25:56 +0400 (Tue, 10 Apr 2007) | 4 lines
+r486 | ms | 2007-04-10 18:25:56 +0200 (Tue, 10 Apr 2007) | 4 lines
 
 Wir kehren zurueck zu Kudzu, da hwinfo noch mehr Aerger macht.
 sort_strings.pl erweitert damit er Umlaute automatisch kodiert.
 Tripwire und Sysstat (sar) hinzugefuegt.
 
 ------------------------------------------------------------------------
-r485 | ms | 2007-04-10 13:32:20 +0400 (Tue, 10 Apr 2007) | 4 lines
+r485 | ms | 2007-04-10 11:32:20 +0200 (Tue, 10 Apr 2007) | 4 lines
 
 Padlock-Modul aktiviert fuer VIA Epia Boards
 FAT Dateisystem fuer "Europa" angepasst
 Netzwerkerkennung durchgearbeitet
 
 ------------------------------------------------------------------------
-r484 | ms | 2007-04-05 23:25:59 +0400 (Thu, 05 Apr 2007) | 3 lines
+r484 | ms | 2007-04-05 21:25:59 +0200 (Thu, 05 Apr 2007) | 3 lines
 
 Beta der Netzwerkdialoge.
 Ueberfluessige Buildscripts noch geloescht.
 
 ------------------------------------------------------------------------
-r483 | maniacikarus | 2007-04-05 23:04:25 +0400 (Thu, 05 Apr 2007) | 3 lines
+r483 | maniacikarus | 2007-04-05 21:04:25 +0200 (Thu, 05 Apr 2007) | 3 lines
 
 In der Samba.cgi einige Icons ausgetauscht
 smbpasswd eingebunden
 
 ------------------------------------------------------------------------
-r482 | ms | 2007-04-05 00:14:15 +0400 (Thu, 05 Apr 2007) | 2 lines
+r482 | ms | 2007-04-04 22:14:15 +0200 (Wed, 04 Apr 2007) | 2 lines
 
 Das Netzwerkscript erlaubt es jetzt nur einzelne Netze neu zu starten.
 
 ------------------------------------------------------------------------
-r481 | ms | 2007-04-04 21:27:58 +0400 (Wed, 04 Apr 2007) | 2 lines
+r481 | ms | 2007-04-04 19:27:58 +0200 (Wed, 04 Apr 2007) | 2 lines
 
 General-Fuctions gefixt, da der DHCP-Client die Strings mit einigen Leerstellen davor speichert.
 
 ------------------------------------------------------------------------
-r480 | ms | 2007-04-04 16:55:38 +0400 (Wed, 04 Apr 2007) | 3 lines
+r480 | ms | 2007-04-04 14:55:38 +0200 (Wed, 04 Apr 2007) | 3 lines
 
 Netzwerkscripts erweitert.
 Sprachsdateien aktualisiert, Menue fuer Firewallloggraphen hinzugefuegt.
 
 ------------------------------------------------------------------------
-r479 | maniacikarus | 2007-04-04 00:53:31 +0400 (Wed, 04 Apr 2007) | 4 lines
+r479 | maniacikarus | 2007-04-03 22:53:31 +0200 (Tue, 03 Apr 2007) | 4 lines
 
 Samba CGI 2sprachig DE und ENG
 Anpassung an der Samba Controll Datei
 Tango Icons hinzugef?\195?\188gt
 
 ------------------------------------------------------------------------
-r478 | ms | 2007-04-03 23:55:47 +0400 (Tue, 03 Apr 2007) | 2 lines
+r478 | ms | 2007-04-03 21:55:47 +0200 (Tue, 03 Apr 2007) | 2 lines
 
 BWM-NG hinzugefuegt
 
 ------------------------------------------------------------------------
-r477 | ms | 2007-04-03 22:58:19 +0400 (Tue, 03 Apr 2007) | 2 lines
+r477 | ms | 2007-04-03 20:58:19 +0200 (Tue, 03 Apr 2007) | 2 lines
 
 Die letzten Quellcodepakete vom IPCop hinzugefuegt.
 
 ------------------------------------------------------------------------
-r476 | ms | 2007-04-03 22:52:26 +0400 (Tue, 03 Apr 2007) | 3 lines
+r476 | ms | 2007-04-03 20:52:26 +0200 (Tue, 03 Apr 2007) | 3 lines
 
 Tag von SVN295 erstellt, da das die letzte funktionierende Version mit
 Kernel 2.4 ist.
 
 ------------------------------------------------------------------------
-r475 | ms | 2007-04-03 22:41:59 +0400 (Tue, 03 Apr 2007) | 3 lines
+r475 | ms | 2007-04-03 20:41:59 +0200 (Tue, 03 Apr 2007) | 3 lines
 
 Farbiger Bash-Prompt.
 PPPoE-Script zur Einwahl.
 
 ------------------------------------------------------------------------
-r474 | maniacikarus | 2007-03-31 17:26:25 +0400 (Sat, 31 Mar 2007) | 4 lines
+r474 | maniacikarus | 2007-03-31 15:26:25 +0200 (Sat, 31 Mar 2007) | 4 lines
 
 Samba Status und Logauswertung fertiggestelllt
 ausserdem eine Menge Codefixes
 einige Icons eingef?\195?\188gt
 
 ------------------------------------------------------------------------
-r473 | ms | 2007-03-30 00:10:53 +0400 (Fri, 30 Mar 2007) | 2 lines
+r473 | ms | 2007-03-29 22:10:53 +0200 (Thu, 29 Mar 2007) | 2 lines
 
 Netzwerkbeta-Bugfixes...
 
 ------------------------------------------------------------------------
-r472 | maniacikarus | 2007-03-29 23:50:28 +0400 (Thu, 29 Mar 2007) | 3 lines
+r472 | maniacikarus | 2007-03-29 21:50:28 +0200 (Thu, 29 Mar 2007) | 3 lines
 
 Upnp fast fertig gestellt zumindest was Web
 und Ctrl Datei angeht
 
 ------------------------------------------------------------------------
-r471 | ms | 2007-03-29 22:18:27 +0400 (Thu, 29 Mar 2007) | 2 lines
+r471 | ms | 2007-03-29 20:18:27 +0200 (Thu, 29 Mar 2007) | 2 lines
 
 Neue Netzwerkerkennung-Beta
 
 ------------------------------------------------------------------------
-r470 | ms | 2007-03-28 22:59:56 +0400 (Wed, 28 Mar 2007) | 2 lines
+r470 | ms | 2007-03-28 20:59:56 +0200 (Wed, 28 Mar 2007) | 2 lines
 
 Devel Version immer bauen lassen...
 
 ------------------------------------------------------------------------
-r469 | maniacikarus | 2007-03-28 21:33:12 +0400 (Wed, 28 Mar 2007) | 3 lines
+r469 | maniacikarus | 2007-03-28 19:33:12 +0200 (Wed, 28 Mar 2007) | 3 lines
 
 kleine fixes in den firewalllogs
 neues feature in der dhcp.cgi
 
 ------------------------------------------------------------------------
-r468 | ms | 2007-03-28 19:48:45 +0400 (Wed, 28 Mar 2007) | 2 lines
+r468 | ms | 2007-03-28 17:48:45 +0200 (Wed, 28 Mar 2007) | 2 lines
 
 Mal die von Maniac geloeschten Aenderungen wieder in die status.cgi gepackt.
 
 ------------------------------------------------------------------------
-r467 | maniacikarus | 2007-03-27 22:52:07 +0400 (Tue, 27 Mar 2007) | 2 lines
+r467 | maniacikarus | 2007-03-27 20:52:07 +0200 (Tue, 27 Mar 2007) | 2 lines
 
 Korrekturen im Code, es wird langsam ....
 
 ------------------------------------------------------------------------
-r466 | ms | 2007-03-27 18:33:09 +0400 (Tue, 27 Mar 2007) | 2 lines
+r466 | ms | 2007-03-27 16:33:09 +0200 (Tue, 27 Mar 2007) | 2 lines
 
 Sambaa-Konfigurations-Fixes
 
 ------------------------------------------------------------------------
-r465 | ms | 2007-03-26 23:59:37 +0400 (Mon, 26 Mar 2007) | 5 lines
+r465 | ms | 2007-03-26 21:59:37 +0200 (Mon, 26 Mar 2007) | 5 lines
 
 Added whatmask
 Netzwerkscripts erweitert.
@@ -713,12 +841,12 @@ upnp.cgi gefixt.
 Installer schreibt die Spracheinstellungen wieder.
 
 ------------------------------------------------------------------------
-r464 | maniacikarus | 2007-03-26 23:16:19 +0400 (Mon, 26 Mar 2007) | 2 lines
+r464 | maniacikarus | 2007-03-26 21:16:19 +0200 (Mon, 26 Mar 2007) | 2 lines
 
 kleiner Zwischenfix
 
 ------------------------------------------------------------------------
-r463 | maniacikarus | 2007-03-26 22:38:15 +0400 (Mon, 26 Mar 2007) | 5 lines
+r463 | maniacikarus | 2007-03-26 20:38:15 +0200 (Mon, 26 Mar 2007) | 5 lines
 
 colours.txt ins Theme Verzeichnis geschoben,
 daher auch Anpassungen an den Firewall*.cgi
@@ -726,75 +854,75 @@ kleinere Fixes an der samba.cgi
 default Config Dateien f?\195?\188r Samba ins SVN gestellt
 
 ------------------------------------------------------------------------
-r462 | ms | 2007-03-25 23:58:37 +0400 (Sun, 25 Mar 2007) | 4 lines
+r462 | ms | 2007-03-25 21:58:37 +0200 (Sun, 25 Mar 2007) | 4 lines
 
 Erste Teile der neuen Netzwerkscripte.
 Installer-Fix.
 SCSI+SATA-Module zum Kernel hinzugefuegt
 
 ------------------------------------------------------------------------
-r461 | ms | 2007-03-25 11:47:42 +0400 (Sun, 25 Mar 2007) | 2 lines
+r461 | ms | 2007-03-25 09:47:42 +0200 (Sun, 25 Mar 2007) | 2 lines
 
 Kleiner Fix...
 
 ------------------------------------------------------------------------
-r460 | ms | 2007-03-25 10:43:08 +0400 (Sun, 25 Mar 2007) | 3 lines
+r460 | ms | 2007-03-25 08:43:08 +0200 (Sun, 25 Mar 2007) | 3 lines
 
 Domainkonfiguration neu gemacht.
 USB-Stick Images hinzugefuegt.
 
 ------------------------------------------------------------------------
-r459 | ms | 2007-03-25 08:48:58 +0400 (Sun, 25 Mar 2007) | 2 lines
+r459 | ms | 2007-03-25 06:48:58 +0200 (Sun, 25 Mar 2007) | 2 lines
 
 Obsolete Binaerdateien entfernt.
 
 ------------------------------------------------------------------------
-r458 | ms | 2007-03-25 08:40:27 +0400 (Sun, 25 Mar 2007) | 3 lines
+r458 | ms | 2007-03-25 06:40:27 +0200 (Sun, 25 Mar 2007) | 3 lines
 
 Squidupdate und QoS-Fix.
 Hostname als Ueberschrift.
 
 ------------------------------------------------------------------------
-r457 | ms | 2007-03-25 08:05:41 +0400 (Sun, 25 Mar 2007) | 4 lines
+r457 | ms | 2007-03-25 06:05:41 +0200 (Sun, 25 Mar 2007) | 4 lines
 
 Firewallhitgraphs gefixt.
 Colours.txt fehlt noch fuer unseren Style.
 ...und wieder einige Sprachfixes.
 
 ------------------------------------------------------------------------
-r456 | ms | 2007-03-25 00:23:57 +0300 (Sun, 25 Mar 2007) | 3 lines
+r456 | ms | 2007-03-24 22:23:57 +0100 (Sat, 24 Mar 2007) | 3 lines
 
 Sprachfix und FTP-Upload-Fix
 und das <br> was der Maniac haben wollte
 
 ------------------------------------------------------------------------
-r455 | maniacikarus | 2007-03-25 00:07:43 +0300 (Sun, 25 Mar 2007) | 2 lines
+r455 | maniacikarus | 2007-03-24 22:07:43 +0100 (Sat, 24 Mar 2007) | 2 lines
 
 Hallo, ich bin der Christian und das ist mein erster Commit.
 
 ------------------------------------------------------------------------
-r454 | ms | 2007-03-24 20:12:26 +0300 (Sat, 24 Mar 2007) | 2 lines
+r454 | ms | 2007-03-24 18:12:26 +0100 (Sat, 24 Mar 2007) | 2 lines
 
 Neue Sprachfunktionen und deutsch Sprachdatei aktualisiert
 
 ------------------------------------------------------------------------
-r453 | ms | 2007-03-24 16:30:47 +0300 (Sat, 24 Mar 2007) | 3 lines
+r453 | ms | 2007-03-24 14:30:47 +0100 (Sat, 24 Mar 2007) | 3 lines
 
 upnp.cgi und status.cgi von Maniac eingebaut
 IPSec aktualisiert
 
 ------------------------------------------------------------------------
-r452 | ms | 2007-03-22 23:56:22 +0300 (Thu, 22 Mar 2007) | 2 lines
+r452 | ms | 2007-03-22 21:56:22 +0100 (Thu, 22 Mar 2007) | 2 lines
 
 Neue UPNP.CGI vom Christian
 
 ------------------------------------------------------------------------
-r451 | ms | 2007-03-19 23:25:01 +0300 (Mon, 19 Mar 2007) | 2 lines
+r451 | ms | 2007-03-19 21:25:01 +0100 (Mon, 19 Mar 2007) | 2 lines
 
 Ramdisk-Arbeit nahezu beendet.
 
 ------------------------------------------------------------------------
-r450 | ms | 2007-03-19 00:34:35 +0300 (Mon, 19 Mar 2007) | 5 lines
+r450 | ms | 2007-03-18 22:34:35 +0100 (Sun, 18 Mar 2007) | 5 lines
 
 GD-Graph fuer Maniac eingebaut
 Kernel laedt ab jetzt keine Module mehr ungefragt.
@@ -802,217 +930,217 @@ Nash aktualisiert um richtige Ramdisks zu erstellen (noch unstable).
 pppsetup.cgi vom Maniac eingefuegt.
 
 ------------------------------------------------------------------------
-r449 | ms | 2007-03-18 00:14:34 +0300 (Sun, 18 Mar 2007) | 4 lines
+r449 | ms | 2007-03-17 22:14:34 +0100 (Sat, 17 Mar 2007) | 4 lines
 
 Alten PCMCIA Code aus dem Installer entfernt.
 Unattended Installation bearbeitet.
 HTTP/FTP-Installation nun moeglich.
 
 ------------------------------------------------------------------------
-r448 | ms | 2007-03-15 00:57:20 +0300 (Thu, 15 Mar 2007) | 2 lines
+r448 | ms | 2007-03-14 22:57:20 +0100 (Wed, 14 Mar 2007) | 2 lines
 
 Neue Hardwareerkennung im Installer...
 
 ------------------------------------------------------------------------
-r447 | ms | 2007-03-11 23:34:32 +0300 (Sun, 11 Mar 2007) | 2 lines
+r447 | ms | 2007-03-11 21:34:32 +0100 (Sun, 11 Mar 2007) | 2 lines
 
 Firewall-Log-Analyzer by Christian Schmidt
 
 ------------------------------------------------------------------------
-r446 | ms | 2007-03-11 23:20:29 +0300 (Sun, 11 Mar 2007) | 3 lines
+r446 | ms | 2007-03-11 21:20:29 +0100 (Sun, 11 Mar 2007) | 3 lines
 
 hwinfo in den Installer gebracht.
 (Erstmal nur in das Image...)
 
 ------------------------------------------------------------------------
-r445 | ms | 2007-03-11 23:09:05 +0300 (Sun, 11 Mar 2007) | 3 lines
+r445 | ms | 2007-03-11 21:09:05 +0100 (Sun, 11 Mar 2007) | 3 lines
 
 OpenSwan RC nach den Vorgaben von "affect" installiert.
 Zurueck zu ReiserFS, da wir mit Reiser4 noch ein paar Probleme haben und wir die Prioritaeten noch auf andere Sachen legen muessen. :'(
 
 ------------------------------------------------------------------------
-r444 | ms | 2007-03-07 22:09:28 +0300 (Wed, 07 Mar 2007) | 2 lines
+r444 | ms | 2007-03-07 20:09:28 +0100 (Wed, 07 Mar 2007) | 2 lines
 
 Tippfehler im RC Script
 
 ------------------------------------------------------------------------
-r443 | ms | 2007-03-07 21:42:02 +0300 (Wed, 07 Mar 2007) | 2 lines
+r443 | ms | 2007-03-07 19:42:02 +0100 (Wed, 07 Mar 2007) | 2 lines
 
 HWInfo wieder eingefuegt, da mit kudzu zu viele Segmentation Faults liefert.
 
 ------------------------------------------------------------------------
-r442 | ms | 2007-03-05 16:15:21 +0300 (Mon, 05 Mar 2007) | 2 lines
+r442 | ms | 2007-03-05 14:15:21 +0100 (Mon, 05 Mar 2007) | 2 lines
 
 Neuer Kudzu...
 
 ------------------------------------------------------------------------
-r441 | ms | 2007-03-05 15:56:05 +0300 (Mon, 05 Mar 2007) | 2 lines
+r441 | ms | 2007-03-05 13:56:05 +0100 (Mon, 05 Mar 2007) | 2 lines
 
 Build Fix...
 
 ------------------------------------------------------------------------
-r440 | ms | 2007-03-05 02:39:47 +0300 (Mon, 05 Mar 2007) | 2 lines
+r440 | ms | 2007-03-05 00:39:47 +0100 (Mon, 05 Mar 2007) | 2 lines
 
 IPTables Fix...
 
 ------------------------------------------------------------------------
-r439 | ms | 2007-03-04 22:07:35 +0300 (Sun, 04 Mar 2007) | 2 lines
+r439 | ms | 2007-03-04 20:07:35 +0100 (Sun, 04 Mar 2007) | 2 lines
 
 Squid Error-Seiten brauchen wir nicht in saemtlichen Sprachen
 
 ------------------------------------------------------------------------
-r438 | ms | 2007-03-04 21:35:48 +0300 (Sun, 04 Mar 2007) | 2 lines
+r438 | ms | 2007-03-04 19:35:48 +0100 (Sun, 04 Mar 2007) | 2 lines
 
 Busybox wieder einmal aufgebohrt...
 
 ------------------------------------------------------------------------
-r437 | ms | 2007-03-04 20:55:55 +0300 (Sun, 04 Mar 2007) | 2 lines
+r437 | ms | 2007-03-04 18:55:55 +0100 (Sun, 04 Mar 2007) | 2 lines
 
 IPTables Update fuer den neuen Kernel.
 
 ------------------------------------------------------------------------
-r436 | ms | 2007-03-04 19:45:10 +0300 (Sun, 04 Mar 2007) | 3 lines
+r436 | ms | 2007-03-04 17:45:10 +0100 (Sun, 04 Mar 2007) | 3 lines
 
 Reiser4 Implementation abgeschlossen...
 In memory to Nina Reiser. May she rest in peace...
 
 ------------------------------------------------------------------------
-r435 | ms | 2007-03-02 16:23:40 +0300 (Fri, 02 Mar 2007) | 2 lines
+r435 | ms | 2007-03-02 14:23:40 +0100 (Fri, 02 Mar 2007) | 2 lines
 
 Buildfixes...
 
 ------------------------------------------------------------------------
-r434 | ms | 2007-03-01 19:44:47 +0300 (Thu, 01 Mar 2007) | 3 lines
+r434 | ms | 2007-03-01 17:44:47 +0100 (Thu, 01 Mar 2007) | 3 lines
 
 Kernel Update
 Netstatusseite mit ip-Befehlen gemacht
 
 ------------------------------------------------------------------------
-r433 | ms | 2007-02-25 22:46:08 +0300 (Sun, 25 Feb 2007) | 3 lines
+r433 | ms | 2007-02-25 20:46:08 +0100 (Sun, 25 Feb 2007) | 3 lines
 
 Samba-Update von Maniac...
 Reiser4! Juhuu!
 
 ------------------------------------------------------------------------
-r432 | ms | 2007-02-25 01:10:57 +0300 (Sun, 25 Feb 2007) | 2 lines
+r432 | ms | 2007-02-24 23:10:57 +0100 (Sat, 24 Feb 2007) | 2 lines
 
 Sambactrl und samba.cgi von Maniacikarus
 
 ------------------------------------------------------------------------
-r431 | ms | 2007-02-23 16:30:56 +0300 (Fri, 23 Feb 2007) | 3 lines
+r431 | ms | 2007-02-23 14:30:56 +0100 (Fri, 23 Feb 2007) | 3 lines
 
 Also irgendwie sind da die Batch-Scripte immernoch inne Wurst... :(
 Kann das einer mal vernuenftig testen??
 
 ------------------------------------------------------------------------
-r430 | ms | 2007-02-23 00:18:59 +0300 (Fri, 23 Feb 2007) | 2 lines
+r430 | ms | 2007-02-22 22:18:59 +0100 (Thu, 22 Feb 2007) | 2 lines
 
 Fehlende CGIs in ISO gebaut
 
 ------------------------------------------------------------------------
-r429 | ms | 2007-02-23 00:15:08 +0300 (Fri, 23 Feb 2007) | 2 lines
+r429 | ms | 2007-02-22 22:15:08 +0100 (Thu, 22 Feb 2007) | 2 lines
 
 Defektes Menue gefixt
 
 ------------------------------------------------------------------------
-r428 | ms | 2007-02-22 23:15:06 +0300 (Thu, 22 Feb 2007) | 2 lines
+r428 | ms | 2007-02-22 21:15:06 +0100 (Thu, 22 Feb 2007) | 2 lines
 
 packages list aktualisiert...
 
 ------------------------------------------------------------------------
-r427 | ms | 2007-02-22 22:36:09 +0300 (Thu, 22 Feb 2007) | 2 lines
+r427 | ms | 2007-02-22 20:36:09 +0100 (Thu, 22 Feb 2007) | 2 lines
 
 Batch-Script wiederhergestellt fuer Detlefs Nightly Builds...
 
 ------------------------------------------------------------------------
-r426 | ms | 2007-02-22 21:42:58 +0300 (Thu, 22 Feb 2007) | 4 lines
+r426 | ms | 2007-02-22 19:42:58 +0100 (Thu, 22 Feb 2007) | 4 lines
 
 Hab mal alles ein wenig bereinigt, da wir die alten Sachen nichtmehr brauchen...
 connections.cgi hab ich gefixt - Die geht jetzt wieder praechtig!
 Und irgendwer (wohl mal wieder ich) hat in der lfs/iptables rumgewuetet :D Sowas aber auch... Tztz
 
 ------------------------------------------------------------------------
-r425 | ms | 2007-02-21 21:56:00 +0300 (Wed, 21 Feb 2007) | 2 lines
+r425 | ms | 2007-02-21 19:56:00 +0100 (Wed, 21 Feb 2007) | 2 lines
 
 Ein NTFS-Update fuer den Heiner :D
 
 ------------------------------------------------------------------------
-r424 | ms | 2007-02-20 23:45:54 +0300 (Tue, 20 Feb 2007) | 2 lines
+r424 | ms | 2007-02-20 21:45:54 +0100 (Tue, 20 Feb 2007) | 2 lines
 
 MiniRev: Andere Sprachen entfernt die wir eh nicht brauchen
 
 ------------------------------------------------------------------------
-r423 | ms | 2007-02-18 01:00:37 +0300 (Sun, 18 Feb 2007) | 3 lines
+r423 | ms | 2007-02-17 23:00:37 +0100 (Sat, 17 Feb 2007) | 3 lines
 
 Maniacikarus Samba.cgi eingespielt
 mISDN eingebaut
 
 ------------------------------------------------------------------------
-r422 | ms | 2007-02-16 15:55:09 +0300 (Fri, 16 Feb 2007) | 2 lines
+r422 | ms | 2007-02-16 13:55:09 +0100 (Fri, 16 Feb 2007) | 2 lines
 
 Clamav Update auf 0.90
 
 ------------------------------------------------------------------------
-r421 | ms | 2007-02-16 00:26:14 +0300 (Fri, 16 Feb 2007) | 2 lines
+r421 | ms | 2007-02-15 22:26:14 +0100 (Thu, 15 Feb 2007) | 2 lines
 
 Updatexlrator (not tested yet)
 
 ------------------------------------------------------------------------
-r420 | ms | 2007-02-15 21:17:05 +0300 (Thu, 15 Feb 2007) | 2 lines
+r420 | ms | 2007-02-15 19:17:05 +0100 (Thu, 15 Feb 2007) | 2 lines
 
 ExtraHD! Die Erweiterung um Festplatten schnell einzubinden!
 
 ------------------------------------------------------------------------
-r419 | ms | 2007-02-15 12:22:09 +0300 (Thu, 15 Feb 2007) | 3 lines
+r419 | ms | 2007-02-15 10:22:09 +0100 (Thu, 15 Feb 2007) | 3 lines
 
 NTFS-Treiber eingebaut fuer das Festplattenfeature von Silvio
 Morning Reconnect auf 5 Uhr verschoben...
 
 ------------------------------------------------------------------------
-r418 | ms | 2007-02-14 22:30:59 +0300 (Wed, 14 Feb 2007) | 4 lines
+r418 | ms | 2007-02-14 20:30:59 +0100 (Wed, 14 Feb 2007) | 4 lines
 
 Credits ueberarbeitet.
 Menue Rewrite
 Connectioncheck gefixt --> DSL/PPPoE works!
 
 ------------------------------------------------------------------------
-r417 | ms | 2007-02-13 22:49:12 +0300 (Tue, 13 Feb 2007) | 2 lines
+r417 | ms | 2007-02-13 20:49:12 +0100 (Tue, 13 Feb 2007) | 2 lines
 
 QoS-HTML Fixes
 
 ------------------------------------------------------------------------
-r416 | ms | 2007-02-13 22:31:38 +0300 (Tue, 13 Feb 2007) | 2 lines
+r416 | ms | 2007-02-13 20:31:38 +0100 (Tue, 13 Feb 2007) | 2 lines
 
 Bash promt im Fedora Core Style gemacht
 
 ------------------------------------------------------------------------
-r415 | ms | 2007-02-13 22:29:03 +0300 (Tue, 13 Feb 2007) | 2 lines
+r415 | ms | 2007-02-13 20:29:03 +0100 (Tue, 13 Feb 2007) | 2 lines
 
 Sources-ISO Fix
 
 ------------------------------------------------------------------------
-r414 | ms | 2007-02-13 21:18:11 +0300 (Tue, 13 Feb 2007) | 2 lines
+r414 | ms | 2007-02-13 19:18:11 +0100 (Tue, 13 Feb 2007) | 2 lines
 
 Unseren GPG Schluessel hinzugefuegt
 
 ------------------------------------------------------------------------
-r413 | ms | 2007-02-13 19:54:19 +0300 (Tue, 13 Feb 2007) | 2 lines
+r413 | ms | 2007-02-13 17:54:19 +0100 (Tue, 13 Feb 2007) | 2 lines
 
 MoBlock hinzugefuegt (fuer Outgoing Firewall)
 
 ------------------------------------------------------------------------
-r412 | ms | 2007-02-12 21:38:45 +0300 (Mon, 12 Feb 2007) | 2 lines
+r412 | ms | 2007-02-12 19:38:45 +0100 (Mon, 12 Feb 2007) | 2 lines
 
 Changelog-Fix
 
 ------------------------------------------------------------------------
-r411 | ms | 2007-02-12 21:37:00 +0300 (Mon, 12 Feb 2007) | 3 lines
+r411 | ms | 2007-02-12 19:37:00 +0100 (Mon, 12 Feb 2007) | 3 lines
 
 Nochmal ein kleiner Fix fuer die Devel-Version...
 Kleinere ISO.
 
 ------------------------------------------------------------------------
-r410 | ms | 2007-02-12 21:04:28 +0300 (Mon, 12 Feb 2007) | 5 lines
+r410 | ms | 2007-02-12 19:04:28 +0100 (Mon, 12 Feb 2007) | 5 lines
 
 UPNP.CGI hinzugefuegt
 SAMBA.CGI von Maniakikarus hinzugefuegt
@@ -1020,19 +1148,19 @@ Bootskripte bearbeitet
 IPFIRE-DEVEL erstellt.
 
 ------------------------------------------------------------------------
-r409 | ms | 2007-02-11 19:29:00 +0300 (Sun, 11 Feb 2007) | 3 lines
+r409 | ms | 2007-02-11 17:29:00 +0100 (Sun, 11 Feb 2007) | 3 lines
 
 PPPoE Verbindungen sollten nun aus dem Webinterface aufegbaut werden 
 k?\195?\182nnen.
 
 ------------------------------------------------------------------------
-r408 | ms | 2007-02-11 15:10:37 +0300 (Sun, 11 Feb 2007) | 3 lines
+r408 | ms | 2007-02-11 13:10:37 +0100 (Sun, 11 Feb 2007) | 3 lines
 
 IPSec update...
 Dial.cgi bearbeitet/fix...
 
 ------------------------------------------------------------------------
-r407 | ms | 2007-02-07 23:51:04 +0300 (Wed, 07 Feb 2007) | 5 lines
+r407 | ms | 2007-02-07 21:51:04 +0100 (Wed, 07 Feb 2007) | 5 lines
 
 Style ueberarbeitet.
 Graphen fuer den Speicher gefixt.
@@ -1040,263 +1168,263 @@ DNS-Server in der index.cgi gefixt.
 Sprachdatei aktualisiert.
 
 ------------------------------------------------------------------------
-r406 | ms | 2007-02-05 00:18:14 +0300 (Mon, 05 Feb 2007) | 2 lines
+r406 | ms | 2007-02-04 22:18:14 +0100 (Sun, 04 Feb 2007) | 2 lines
 
 Touch is an nem anderen Ort...
 
 ------------------------------------------------------------------------
-r405 | ms | 2007-02-04 21:03:00 +0300 (Sun, 04 Feb 2007) | 4 lines
+r405 | ms | 2007-02-04 19:03:00 +0100 (Sun, 04 Feb 2007) | 4 lines
 
 IMQ Device in den Kernel kompiliert.
 QoS Fit fuer die neue Version gemacht.
 NTPd Startscript angepasst. (Das andere dauerte einfach zu lange zum starten!)
 
 ------------------------------------------------------------------------
-r404 | ms | 2007-02-04 01:18:46 +0300 (Sun, 04 Feb 2007) | 2 lines
+r404 | ms | 2007-02-03 23:18:46 +0100 (Sat, 03 Feb 2007) | 2 lines
 
 UPnP Initscript und Chain hinzugefuegt
 
 ------------------------------------------------------------------------
-r403 | ms | 2007-02-03 23:26:00 +0300 (Sat, 03 Feb 2007) | 2 lines
+r403 | ms | 2007-02-03 21:26:00 +0100 (Sat, 03 Feb 2007) | 2 lines
 
 UPnP-Tools kompiliert und getestet -> GEIL :D
 
 ------------------------------------------------------------------------
-r402 | ms | 2007-02-02 17:50:30 +0300 (Fri, 02 Feb 2007) | 2 lines
+r402 | ms | 2007-02-02 15:50:30 +0100 (Fri, 02 Feb 2007) | 2 lines
 
 QoS-Update - Komplette grafische Ueberarbeitung
 
 ------------------------------------------------------------------------
-r401 | ms | 2007-02-02 17:22:13 +0300 (Fri, 02 Feb 2007) | 1 line
+r401 | ms | 2007-02-02 15:22:13 +0100 (Fri, 02 Feb 2007) | 1 line
 
 IPCop 1.4.13 - Quellen hinzugefuegt
 ------------------------------------------------------------------------
-r400 | ms | 2007-01-27 14:39:29 +0300 (Sat, 27 Jan 2007) | 3 lines
+r400 | ms | 2007-01-27 12:39:29 +0100 (Sat, 27 Jan 2007) | 3 lines
 
 Bash bearbeitet, da der Bootpromt nicht richtig arbeitete.
 Kleiner Fix damit man ohne prefetching bauen kann.
 
 ------------------------------------------------------------------------
-r399 | ms | 2007-01-26 15:46:40 +0300 (Fri, 26 Jan 2007) | 2 lines
+r399 | ms | 2007-01-26 13:46:40 +0100 (Fri, 26 Jan 2007) | 2 lines
 
 Nettraffic aktualisiert.
 
 ------------------------------------------------------------------------
-r398 | ms | 2007-01-25 23:49:42 +0300 (Thu, 25 Jan 2007) | 2 lines
+r398 | ms | 2007-01-25 21:49:42 +0100 (Thu, 25 Jan 2007) | 2 lines
 
 Kleines Tuning vom QoS...
 
 ------------------------------------------------------------------------
-r397 | ms | 2007-01-25 22:04:11 +0300 (Thu, 25 Jan 2007) | 2 lines
+r397 | ms | 2007-01-25 20:04:11 +0100 (Thu, 25 Jan 2007) | 2 lines
 
 Bashpromt erweitert und FTP Upload wieder funktionierend gemacht...
 
 ------------------------------------------------------------------------
-r396 | ms | 2007-01-25 18:36:43 +0300 (Thu, 25 Jan 2007) | 4 lines
+r396 | ms | 2007-01-25 16:36:43 +0100 (Thu, 25 Jan 2007) | 4 lines
 
 Installer fuer ein read-only-Dateisystem angepasst.
 mingetty entfernt, da wir agetty verwenden.
 issue veraendert
 
 ------------------------------------------------------------------------
-r395 | ms | 2007-01-24 22:13:45 +0300 (Wed, 24 Jan 2007) | 2 lines
+r395 | ms | 2007-01-24 20:13:45 +0100 (Wed, 24 Jan 2007) | 2 lines
 
 Einige (hoffentlich die letzten) Rootfiles hinzugefuegt...
 
 ------------------------------------------------------------------------
-r394 | ms | 2007-01-20 19:44:36 +0300 (Sat, 20 Jan 2007) | 2 lines
+r394 | ms | 2007-01-20 17:44:36 +0100 (Sat, 20 Jan 2007) | 2 lines
 
 Kernelconfig und Rootfile nachgeliefert...
 
 ------------------------------------------------------------------------
-r393 | ms | 2007-01-20 18:42:28 +0300 (Sat, 20 Jan 2007) | 3 lines
+r393 | ms | 2007-01-20 16:42:28 +0100 (Sat, 20 Jan 2007) | 3 lines
 
 SquashFS hinzugefuegt damit wir auf OpenVZ-Maschinen bauen koennen.
 Kein Loop-Device mehr erforderlich.
 
 ------------------------------------------------------------------------
-r392 | ms | 2007-01-18 00:17:36 +0300 (Thu, 18 Jan 2007) | 2 lines
+r392 | ms | 2007-01-17 22:17:36 +0100 (Wed, 17 Jan 2007) | 2 lines
 
 Ein bisschen die Bootscripte bearbeitet!
 
 ------------------------------------------------------------------------
-r391 | ms | 2007-01-17 23:19:01 +0300 (Wed, 17 Jan 2007) | 3 lines
+r391 | ms | 2007-01-17 21:19:01 +0100 (Wed, 17 Jan 2007) | 3 lines
 
 Builderror von IPP2P und Apache gefixt.
 Sourceforge Bild unnuetze. Da sind we ja eh nich...
 
 ------------------------------------------------------------------------
-r390 | ms | 2007-01-14 01:15:39 +0300 (Sun, 14 Jan 2007) | 3 lines
+r390 | ms | 2007-01-13 23:15:39 +0100 (Sat, 13 Jan 2007) | 3 lines
 
 Source-Links gefixt.
 Domainumzug vom Source-Code.
 
 ------------------------------------------------------------------------
-r389 | ms | 2007-01-11 00:38:07 +0300 (Thu, 11 Jan 2007) | 2 lines
+r389 | ms | 2007-01-10 22:38:07 +0100 (Wed, 10 Jan 2007) | 2 lines
 
 Der taegliche Commit am Abend :D
 
 ------------------------------------------------------------------------
-r388 | ms | 2007-01-09 03:04:31 +0300 (Tue, 09 Jan 2007) | 2 lines
+r388 | ms | 2007-01-09 01:04:31 +0100 (Tue, 09 Jan 2007) | 2 lines
 
 Alte Initscripts entfernt...
 
 ------------------------------------------------------------------------
-r387 | ms | 2007-01-09 00:41:01 +0300 (Tue, 09 Jan 2007) | 2 lines
+r387 | ms | 2007-01-08 22:41:01 +0100 (Mon, 08 Jan 2007) | 2 lines
 
 Ein Paar noch unbearbeitet Bootscripts hinzugefuegt.
 
 ------------------------------------------------------------------------
-r386 | ms | 2007-01-08 18:02:21 +0300 (Mon, 08 Jan 2007) | 3 lines
+r386 | ms | 2007-01-08 16:02:21 +0100 (Mon, 08 Jan 2007) | 3 lines
 
 DHCPCD wurde nicht gekillt :(
 Connectionscript umgearbeitet.
 
 ------------------------------------------------------------------------
-r385 | ms | 2007-01-08 01:15:06 +0300 (Mon, 08 Jan 2007) | 2 lines
+r385 | ms | 2007-01-07 23:15:06 +0100 (Sun, 07 Jan 2007) | 2 lines
 
 Tcpdump repariert.
 
 ------------------------------------------------------------------------
-r384 | ms | 2007-01-07 16:58:16 +0300 (Sun, 07 Jan 2007) | 2 lines
+r384 | ms | 2007-01-07 14:58:16 +0100 (Sun, 07 Jan 2007) | 2 lines
 
 HDDTemp nun fuer jede Platte und nicht nur die erste :D
 
 ------------------------------------------------------------------------
-r383 | ms | 2007-01-07 15:15:14 +0300 (Sun, 07 Jan 2007) | 4 lines
+r383 | ms | 2007-01-07 13:15:14 +0100 (Sun, 07 Jan 2007) | 4 lines
 
 FritzCard-Module installiert.
 OpenSwan2 fit gemacht.
 Ueberfluessige Modem-Treiber entfernt.
 
 ------------------------------------------------------------------------
-r382 | ms | 2007-01-07 03:25:35 +0300 (Sun, 07 Jan 2007) | 2 lines
+r382 | ms | 2007-01-07 01:25:35 +0100 (Sun, 07 Jan 2007) | 2 lines
 
 Von nun an kann man statische Zuordnungen mit einem Klick aus einer dynamischen Zuordnung generieren.
 
 ------------------------------------------------------------------------
-r381 | ms | 2007-01-06 15:55:49 +0300 (Sat, 06 Jan 2007) | 4 lines
+r381 | ms | 2007-01-06 13:55:49 +0100 (Sat, 06 Jan 2007) | 4 lines
 
 Bootscripte an den IPFire angepasst.
 Ramdisk bearbeitet und Diskettenimages entfernt.
 PCMCIA-Utils entfernt.
 
 ------------------------------------------------------------------------
-r380 | ms | 2007-01-05 04:46:08 +0300 (Fri, 05 Jan 2007) | 2 lines
+r380 | ms | 2007-01-05 02:46:08 +0100 (Fri, 05 Jan 2007) | 2 lines
 
 Habe ein Paar lange dagewesene Errors behoben.
 
 ------------------------------------------------------------------------
-r379 | ms | 2007-01-05 02:01:10 +0300 (Fri, 05 Jan 2007) | 2 lines
+r379 | ms | 2007-01-05 00:01:10 +0100 (Fri, 05 Jan 2007) | 2 lines
 
 Makgraphs pingt jetzt wieder den ersten Hop.
 
 ------------------------------------------------------------------------
-r378 | ms | 2007-01-05 00:30:12 +0300 (Fri, 05 Jan 2007) | 2 lines
+r378 | ms | 2007-01-04 22:30:12 +0100 (Thu, 04 Jan 2007) | 2 lines
 
 Hab ein Paar CGIs gefixt.
 
 ------------------------------------------------------------------------
-r377 | ms | 2007-01-03 02:09:46 +0300 (Wed, 03 Jan 2007) | 2 lines
+r377 | ms | 2007-01-03 00:09:46 +0100 (Wed, 03 Jan 2007) | 2 lines
 
 Ein Paar Ideen vom Benne umgesetzt.
 
 ------------------------------------------------------------------------
-r376 | ms | 2007-01-02 22:12:43 +0300 (Tue, 02 Jan 2007) | 2 lines
+r376 | ms | 2007-01-02 20:12:43 +0100 (Tue, 02 Jan 2007) | 2 lines
 
 THEME zum unattended hinzugefuegt.
 
 ------------------------------------------------------------------------
-r375 | ms | 2007-01-02 21:40:12 +0300 (Tue, 02 Jan 2007) | 4 lines
+r375 | ms | 2007-01-02 19:40:12 +0100 (Tue, 02 Jan 2007) | 4 lines
 
 Ich hab mal ein bisschen die Arbeit vom Cuebernommen :D
 Aber trotzdem geht die Routine noch kein bisschen. SegFault :(
 Ansonsten: Busyboy erweitert, PCMCIA Support begonnen zu entfernen
 
 ------------------------------------------------------------------------
-r374 | ms | 2007-01-01 19:44:44 +0300 (Mon, 01 Jan 2007) | 2 lines
+r374 | ms | 2007-01-01 17:44:44 +0100 (Mon, 01 Jan 2007) | 2 lines
 
 Kleiner PXE Fix.
 
 ------------------------------------------------------------------------
-r373 | ms | 2007-01-01 13:49:07 +0300 (Mon, 01 Jan 2007) | 3 lines
+r373 | ms | 2007-01-01 11:49:07 +0100 (Mon, 01 Jan 2007) | 3 lines
 
 Installer-Toolchain nochmals ueberarbeitet.
 Kompiliert wenigstens schonmal durch...
 
 ------------------------------------------------------------------------
-r372 | ms | 2007-01-01 00:51:45 +0300 (Mon, 01 Jan 2007) | 2 lines
+r372 | ms | 2006-12-31 22:51:45 +0100 (Sun, 31 Dec 2006) | 2 lines
 
 Neueste GnuMP3d-Version eingepflegt
 
 ------------------------------------------------------------------------
-r371 | ms | 2006-12-31 21:30:30 +0300 (Sun, 31 Dec 2006) | 4 lines
+r371 | ms | 2006-12-31 19:30:30 +0100 (Sun, 31 Dec 2006) | 4 lines
 
 * Clamav, Samba und MC Update.
 * Kleine Funktion zur Zeitanzeige 
   der Stages und des gesamten Builds gebastelt.
 
 ------------------------------------------------------------------------
-r370 | ms | 2006-12-29 19:22:29 +0300 (Fri, 29 Dec 2006) | 4 lines
+r370 | ms | 2006-12-29 17:22:29 +0100 (Fri, 29 Dec 2006) | 4 lines
 
 Asterisk aktualisiert. --> 1.4.0
 Hoffentlich gibt es endlich mal wieder nen Bristuff dafuer...
 PXE-Namen geaendert.
 
 ------------------------------------------------------------------------
-r369 | ms | 2006-12-25 23:53:27 +0300 (Mon, 25 Dec 2006) | 3 lines
+r369 | ms | 2006-12-25 21:53:27 +0100 (Mon, 25 Dec 2006) | 3 lines
 
 Ich hab mal ueber die Feiertage nen kleinen Rewrite von dem Installersystem gemacht.
 Ich hoffe somit mal das locale-Problem in den Griff zu bekommen.
 
 ------------------------------------------------------------------------
-r368 | ms | 2006-12-22 20:24:32 +0300 (Fri, 22 Dec 2006) | 4 lines
+r368 | ms | 2006-12-22 18:24:32 +0100 (Fri, 22 Dec 2006) | 4 lines
 
 Graphen gefixt.
 Bootlogo zur Iso hinzugefuegt.
 Memtest hinzugefuegt. (Kann man sicherlich mal brauchen denke ich.)
 
 ------------------------------------------------------------------------
-r367 | ms | 2006-12-22 00:56:35 +0300 (Fri, 22 Dec 2006) | 3 lines
+r367 | ms | 2006-12-21 22:56:35 +0100 (Thu, 21 Dec 2006) | 3 lines
 
 H323 Conntrack hinzugefuegt
 Bootsplash reaktiviert.
 
 ------------------------------------------------------------------------
-r366 | ms | 2006-12-21 21:38:37 +0300 (Thu, 21 Dec 2006) | 4 lines
+r366 | ms | 2006-12-21 19:38:37 +0100 (Thu, 21 Dec 2006) | 4 lines
 
 Netzwerkscript beinahe vollendet.
 Setup bearbeitet. (Geht schon ganz gut.)
 Sonstiges wie immer...
 
 ------------------------------------------------------------------------
-r365 | ms | 2006-12-19 00:40:57 +0300 (Tue, 19 Dec 2006) | 2 lines
+r365 | ms | 2006-12-18 22:40:57 +0100 (Mon, 18 Dec 2006) | 2 lines
 
 Kernel-Update und umfassende Arbeiten daran.
 
 ------------------------------------------------------------------------
-r364 | ms | 2006-12-16 19:07:45 +0300 (Sat, 16 Dec 2006) | 2 lines
+r364 | ms | 2006-12-16 17:07:45 +0100 (Sat, 16 Dec 2006) | 2 lines
 
 Themeable Webinterface mit neuem Style.
 
 ------------------------------------------------------------------------
-r363 | ms | 2006-12-13 22:56:41 +0300 (Wed, 13 Dec 2006) | 2 lines
+r363 | ms | 2006-12-13 20:56:41 +0100 (Wed, 13 Dec 2006) | 2 lines
 
 Alle htdocs nach /srv/web verschoben...
 
 ------------------------------------------------------------------------
-r362 | ms | 2006-12-13 00:20:38 +0300 (Wed, 13 Dec 2006) | 3 lines
+r362 | ms | 2006-12-12 22:20:38 +0100 (Tue, 12 Dec 2006) | 3 lines
 
 RRDTool Fix
 Bearbeitung an den Grafen noetig!
 
 ------------------------------------------------------------------------
-r361 | ms | 2006-12-13 00:18:36 +0300 (Wed, 13 Dec 2006) | 2 lines
+r361 | ms | 2006-12-12 22:18:36 +0100 (Tue, 12 Dec 2006) | 2 lines
 
 2 Buildfixes...
 
 ------------------------------------------------------------------------
-r360 | ms | 2006-12-11 23:02:07 +0300 (Mon, 11 Dec 2006) | 5 lines
+r360 | ms | 2006-12-11 21:02:07 +0100 (Mon, 11 Dec 2006) | 5 lines
 
 Patch-O-Matic in den Kernel eingebaut.
 (Einige Module fehlen noch...)
@@ -1304,119 +1432,119 @@ Unattended Installer bearbeitet.
 Firewallscript hinzugefuegt.
 
 ------------------------------------------------------------------------
-r359 | ms | 2006-12-08 19:27:26 +0300 (Fri, 08 Dec 2006) | 3 lines
+r359 | ms | 2006-12-08 17:27:26 +0100 (Fri, 08 Dec 2006) | 3 lines
 
 IPTables in Kernel aktiviert.
 Netzwork-Script Phase 1
 
 ------------------------------------------------------------------------
-r358 | ms | 2006-12-08 15:41:21 +0300 (Fri, 08 Dec 2006) | 4 lines
+r358 | ms | 2006-12-08 13:41:21 +0100 (Fri, 08 Dec 2006) | 4 lines
 
 Kernel angepasst.
 Bootprozess bearbeitet.
 Console vorlaeufig auf Deutsch eingestellt bis das Setup geht.
 
 ------------------------------------------------------------------------
-r357 | ms | 2006-12-06 00:57:32 +0300 (Wed, 06 Dec 2006) | 4 lines
+r357 | ms | 2006-12-05 22:57:32 +0100 (Tue, 05 Dec 2006) | 4 lines
 
 Starte SSH-Server beim Boot.
 Starte Cron-Server beim Boot.
 Apache bearbeitet.
 
 ------------------------------------------------------------------------
-r356 | ms | 2006-12-06 00:42:19 +0300 (Wed, 06 Dec 2006) | 2 lines
+r356 | ms | 2006-12-05 22:42:19 +0100 (Tue, 05 Dec 2006) | 2 lines
 
 Installer-Pfade gefixxt.
 
 ------------------------------------------------------------------------
-r355 | ms | 2006-12-05 17:32:03 +0300 (Tue, 05 Dec 2006) | 2 lines
+r355 | ms | 2006-12-05 15:32:03 +0100 (Tue, 05 Dec 2006) | 2 lines
 
 Einige Buildfixes
 
 ------------------------------------------------------------------------
-r354 | ms | 2006-12-03 01:38:39 +0300 (Sun, 03 Dec 2006) | 2 lines
+r354 | ms | 2006-12-02 23:38:39 +0100 (Sat, 02 Dec 2006) | 2 lines
 
 System ist mittels LFS Bootscripte startbar.
 
 ------------------------------------------------------------------------
-r353 | ms | 2006-12-01 00:30:57 +0300 (Fri, 01 Dec 2006) | 2 lines
+r353 | ms | 2006-11-30 22:30:57 +0100 (Thu, 30 Nov 2006) | 2 lines
 
 ... Viel zu tun :D
 
 ------------------------------------------------------------------------
-r352 | ms | 2006-11-29 00:27:53 +0300 (Wed, 29 Nov 2006) | 2 lines
+r352 | ms | 2006-11-28 22:27:53 +0100 (Tue, 28 Nov 2006) | 2 lines
 
 Kleiner netter neuer Versuch.
 
 ------------------------------------------------------------------------
-r351 | ms | 2006-11-28 23:05:18 +0300 (Tue, 28 Nov 2006) | 3 lines
+r351 | ms | 2006-11-28 21:05:18 +0100 (Tue, 28 Nov 2006) | 3 lines
 
 PXE Boot integriert.
 Installerarbeit fortgesetzt.
 
 ------------------------------------------------------------------------
-r350 | ms | 2006-11-27 00:34:31 +0300 (Mon, 27 Nov 2006) | 2 lines
+r350 | ms | 2006-11-26 22:34:31 +0100 (Sun, 26 Nov 2006) | 2 lines
 
 Installer lauft durch und IDE Systeme booten :D
 
 ------------------------------------------------------------------------
-r349 | ms | 2006-11-26 15:52:27 +0300 (Sun, 26 Nov 2006) | 2 lines
+r349 | ms | 2006-11-26 13:52:27 +0100 (Sun, 26 Nov 2006) | 2 lines
 
 Installer
 
 ------------------------------------------------------------------------
-r348 | ms | 2006-11-22 00:24:16 +0300 (Wed, 22 Nov 2006) | 2 lines
+r348 | ms | 2006-11-21 22:24:16 +0100 (Tue, 21 Nov 2006) | 2 lines
 
 Eine Menge Buildfixes...
 
 ------------------------------------------------------------------------
-r347 | ms | 2006-11-21 01:04:37 +0300 (Tue, 21 Nov 2006) | 2 lines
+r347 | ms | 2006-11-20 23:04:37 +0100 (Mon, 20 Nov 2006) | 2 lines
 
 Weitere Arbeit am Installer
 
 ------------------------------------------------------------------------
-r346 | ms | 2006-11-20 22:56:08 +0300 (Mon, 20 Nov 2006) | 2 lines
+r346 | ms | 2006-11-20 20:56:08 +0100 (Mon, 20 Nov 2006) | 2 lines
 
 Kudzu, ReiserFS, uClibc, gettext und Arbeit am Installer
 
 ------------------------------------------------------------------------
-r345 | ms | 2006-11-11 19:23:31 +0300 (Sat, 11 Nov 2006) | 2 lines
+r345 | ms | 2006-11-11 17:23:31 +0100 (Sat, 11 Nov 2006) | 2 lines
 
 Uptime-CGI vom gruenen Testfire kopiert.
 
 ------------------------------------------------------------------------
-r344 | ms | 2006-11-09 01:58:14 +0300 (Thu, 09 Nov 2006) | 2 lines
+r344 | ms | 2006-11-08 23:58:14 +0100 (Wed, 08 Nov 2006) | 2 lines
 
 Clamav und OpenVPN Update.
 
 ------------------------------------------------------------------------
-r343 | ms | 2006-11-09 01:30:51 +0300 (Thu, 09 Nov 2006) | 2 lines
+r343 | ms | 2006-11-08 23:30:51 +0100 (Wed, 08 Nov 2006) | 2 lines
 
 Bootvorgang des Installers weitergebracht.
 
 ------------------------------------------------------------------------
-r342 | ms | 2006-11-07 23:23:46 +0300 (Tue, 07 Nov 2006) | 2 lines
+r342 | ms | 2006-11-07 21:23:46 +0100 (Tue, 07 Nov 2006) | 2 lines
 
 Install-Initrd finalisiert..
 
 ------------------------------------------------------------------------
-r341 | ms | 2006-11-06 22:55:55 +0300 (Mon, 06 Nov 2006) | 3 lines
+r341 | ms | 2006-11-06 20:55:55 +0100 (Mon, 06 Nov 2006) | 3 lines
 
 Installmake bearbeitet. (TESTING)
 fstab gefixt.
 
 ------------------------------------------------------------------------
-r340 | ms | 2006-11-06 21:03:48 +0300 (Mon, 06 Nov 2006) | 2 lines
+r340 | ms | 2006-11-06 19:03:48 +0100 (Mon, 06 Nov 2006) | 2 lines
 
 Busybox war gegen falsche Libc gelinkt.
 
 ------------------------------------------------------------------------
-r339 | ms | 2006-11-04 02:15:47 +0300 (Sat, 04 Nov 2006) | 2 lines
+r339 | ms | 2006-11-04 00:15:47 +0100 (Sat, 04 Nov 2006) | 2 lines
 
 Mailx und Newt Fixes.
 
 ------------------------------------------------------------------------
-r338 | ms | 2006-11-03 02:59:32 +0300 (Fri, 03 Nov 2006) | 5 lines
+r338 | ms | 2006-11-03 00:59:32 +0100 (Fri, 03 Nov 2006) | 5 lines
 
 Zwischencommit...
 Typo von Meisterwinter behoben.
@@ -1424,119 +1552,119 @@ Clamav Update.
 Neuen Source-Server unter source.ipfire.eu in Betrieb genommen.
 
 ------------------------------------------------------------------------
-r337 | ms | 2006-11-02 22:00:22 +0300 (Thu, 02 Nov 2006) | 2 lines
+r337 | ms | 2006-11-02 20:00:22 +0100 (Thu, 02 Nov 2006) | 2 lines
 
 Zwischencommit... ISO wird gebaut!
 
 ------------------------------------------------------------------------
-r336 | ms | 2006-11-02 16:08:47 +0300 (Thu, 02 Nov 2006) | 2 lines
+r336 | ms | 2006-11-02 14:08:47 +0100 (Thu, 02 Nov 2006) | 2 lines
 
 Buildfixes...
 
 ------------------------------------------------------------------------
-r335 | ms | 2006-11-01 20:55:25 +0300 (Wed, 01 Nov 2006) | 2 lines
+r335 | ms | 2006-11-01 18:55:25 +0100 (Wed, 01 Nov 2006) | 2 lines
 
 Zwischencommit Rootfiles...
 
 ------------------------------------------------------------------------
-r334 | ms | 2006-11-01 19:52:39 +0300 (Wed, 01 Nov 2006) | 3 lines
+r334 | ms | 2006-11-01 17:52:39 +0100 (Wed, 01 Nov 2006) | 3 lines
 
 Zwischencommit Rootfiles...
 Der Countdown laeuft...
 
 ------------------------------------------------------------------------
-r333 | ms | 2006-10-30 23:23:28 +0300 (Mon, 30 Oct 2006) | 2 lines
+r333 | ms | 2006-10-30 21:23:28 +0100 (Mon, 30 Oct 2006) | 2 lines
 
 Zwischencommit Installer...
 
 ------------------------------------------------------------------------
-r332 | ms | 2006-10-28 02:01:34 +0400 (Sat, 28 Oct 2006) | 2 lines
+r332 | ms | 2006-10-28 00:01:34 +0200 (Sat, 28 Oct 2006) | 2 lines
 
 Zwischencommit Installer.
 
 ------------------------------------------------------------------------
-r331 | ms | 2006-10-27 19:50:54 +0400 (Fri, 27 Oct 2006) | 2 lines
+r331 | ms | 2006-10-27 17:50:54 +0200 (Fri, 27 Oct 2006) | 2 lines
 
 Busybox --> 1.2.2
 
 ------------------------------------------------------------------------
-r330 | ms | 2006-10-27 19:10:51 +0400 (Fri, 27 Oct 2006) | 2 lines
+r330 | ms | 2006-10-27 17:10:51 +0200 (Fri, 27 Oct 2006) | 2 lines
 
 Cleanup.
 
 ------------------------------------------------------------------------
-r329 | ms | 2006-10-27 19:08:59 +0400 (Fri, 27 Oct 2006) | 2 lines
+r329 | ms | 2006-10-27 17:08:59 +0200 (Fri, 27 Oct 2006) | 2 lines
 
 uClibc-0.29.8 funktioniert mit GCC 4.0.3
 
 ------------------------------------------------------------------------
-r328 | ms | 2006-10-25 22:11:37 +0400 (Wed, 25 Oct 2006) | 2 lines
+r328 | ms | 2006-10-25 20:11:37 +0200 (Wed, 25 Oct 2006) | 2 lines
 
 uClibc-Update.
 
 ------------------------------------------------------------------------
-r327 | ms | 2006-10-24 01:16:38 +0400 (Tue, 24 Oct 2006) | 3 lines
+r327 | ms | 2006-10-23 23:16:38 +0200 (Mon, 23 Oct 2006) | 3 lines
 
 uClibc haengt...
 Viele Rootfiles erstellt.
 
 ------------------------------------------------------------------------
-r326 | ms | 2006-10-20 18:32:17 +0400 (Fri, 20 Oct 2006) | 4 lines
+r326 | ms | 2006-10-20 16:32:17 +0200 (Fri, 20 Oct 2006) | 4 lines
 
 Zwischencommit fuer LFS.
 Ein Paar Rootfiles erstellt.
 ./make.sh prefetch nach ./make.sh downloadsrc umbenannt.
 
 ------------------------------------------------------------------------
-r325 | ms | 2006-10-19 22:37:19 +0400 (Thu, 19 Oct 2006) | 4 lines
+r325 | ms | 2006-10-19 20:37:19 +0200 (Thu, 19 Oct 2006) | 4 lines
 
 Zwischencommit fuer LFS.
 Die Asterisk-Leute haben mal wieder zugeschlagen...
 Da warten wir mal auf den Junghanns, oder nehmen wir was anderes?
 
 ------------------------------------------------------------------------
-r324 | ms | 2006-10-16 00:25:07 +0400 (Mon, 16 Oct 2006) | 2 lines
+r324 | ms | 2006-10-15 22:25:07 +0200 (Sun, 15 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r323 | ms | 2006-10-15 01:10:36 +0400 (Sun, 15 Oct 2006) | 2 lines
+r323 | ms | 2006-10-14 23:10:36 +0200 (Sat, 14 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS. Noch zahlreiche Errors :(
 
 ------------------------------------------------------------------------
-r322 | ms | 2006-10-14 18:17:32 +0400 (Sat, 14 Oct 2006) | 2 lines
+r322 | ms | 2006-10-14 16:17:32 +0200 (Sat, 14 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r321 | ms | 2006-10-14 16:43:29 +0400 (Sat, 14 Oct 2006) | 2 lines
+r321 | ms | 2006-10-14 14:43:29 +0200 (Sat, 14 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r320 | ms | 2006-10-13 19:35:24 +0400 (Fri, 13 Oct 2006) | 2 lines
+r320 | ms | 2006-10-13 17:35:24 +0200 (Fri, 13 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r319 | ms | 2006-10-13 17:01:14 +0400 (Fri, 13 Oct 2006) | 2 lines
+r319 | ms | 2006-10-13 15:01:14 +0200 (Fri, 13 Oct 2006) | 2 lines
 
 Kleiner Fehler in Python.
 
 ------------------------------------------------------------------------
-r318 | ms | 2006-10-13 15:51:11 +0400 (Fri, 13 Oct 2006) | 2 lines
+r318 | ms | 2006-10-13 13:51:11 +0200 (Fri, 13 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r317 | ms | 2006-10-13 00:44:44 +0400 (Fri, 13 Oct 2006) | 3 lines
+r317 | ms | 2006-10-12 22:44:44 +0200 (Thu, 12 Oct 2006) | 3 lines
 
 Zwischencommit fuer LFS.
 EXPERIMENTELLE KERNEL-KONFIGURATION.
 
 ------------------------------------------------------------------------
-r316 | ms | 2006-10-12 21:34:35 +0400 (Thu, 12 Oct 2006) | 5 lines
+r316 | ms | 2006-10-12 19:34:35 +0200 (Thu, 12 Oct 2006) | 5 lines
 
 Hinzugefuegt:
   * Net-Tools
@@ -1544,122 +1672,122 @@ Hinzugefuegt:
   * Ed
 
 ------------------------------------------------------------------------
-r315 | ms | 2006-10-12 19:57:24 +0400 (Thu, 12 Oct 2006) | 3 lines
+r315 | ms | 2006-10-12 17:57:24 +0200 (Thu, 12 Oct 2006) | 3 lines
 
 EXPERIMENTELLE Konfiguration fuer den Installer-Kernel.
 Die genaue Konfiguration wird am Entwicklertreffen festgelegt.
 
 ------------------------------------------------------------------------
-r314 | ms | 2006-10-12 19:52:06 +0400 (Thu, 12 Oct 2006) | 4 lines
+r314 | ms | 2006-10-12 17:52:06 +0200 (Thu, 12 Oct 2006) | 4 lines
 
 Neues Verfahren fuer die Rootfiles.
 Alle liegen in einer einzelnen Datei und die 3 verschiedenen Version koennen unterschiedlich zusammengestellt werden.
 USB-Stick-Images mangels Notwendigkeit entfernt.
 
 ------------------------------------------------------------------------
-r313 | ms | 2006-10-12 15:17:13 +0400 (Thu, 12 Oct 2006) | 2 lines
+r313 | ms | 2006-10-12 13:17:13 +0200 (Thu, 12 Oct 2006) | 2 lines
 
 Mehrere Tippfehler in lfs/linux beseitigt.
 
 ------------------------------------------------------------------------
-r312 | ms | 2006-10-09 17:09:55 +0400 (Mon, 09 Oct 2006) | 2 lines
+r312 | ms | 2006-10-09 15:09:55 +0200 (Mon, 09 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r311 | ms | 2006-10-09 16:16:52 +0400 (Mon, 09 Oct 2006) | 2 lines
+r311 | ms | 2006-10-09 14:16:52 +0200 (Mon, 09 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS. Bis Kernel.
 
 ------------------------------------------------------------------------
-r310 | ms | 2006-10-09 02:55:09 +0400 (Mon, 09 Oct 2006) | 2 lines
+r310 | ms | 2006-10-09 00:55:09 +0200 (Mon, 09 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r309 | ms | 2006-10-08 23:29:44 +0400 (Sun, 08 Oct 2006) | 2 lines
+r309 | ms | 2006-10-08 21:29:44 +0200 (Sun, 08 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS. Man, Sysklogd und Shadow.
 
 ------------------------------------------------------------------------
-r308 | ms | 2006-10-08 23:16:18 +0400 (Sun, 08 Oct 2006) | 2 lines
+r308 | ms | 2006-10-08 21:16:18 +0200 (Sun, 08 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS. Groff und IPRoute2.
 
 ------------------------------------------------------------------------
-r307 | ms | 2006-10-08 23:01:51 +0400 (Sun, 08 Oct 2006) | 2 lines
+r307 | ms | 2006-10-08 21:01:51 +0200 (Sun, 08 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS. Grub und Gettext.
 
 ------------------------------------------------------------------------
-r306 | ms | 2006-10-08 22:05:04 +0400 (Sun, 08 Oct 2006) | 2 lines
+r306 | ms | 2006-10-08 20:05:04 +0200 (Sun, 08 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r305 | ms | 2006-10-08 18:39:28 +0400 (Sun, 08 Oct 2006) | 2 lines
+r305 | ms | 2006-10-08 16:39:28 +0200 (Sun, 08 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS.
 
 ------------------------------------------------------------------------
-r304 | ms | 2006-10-06 13:08:18 +0400 (Fri, 06 Oct 2006) | 2 lines
+r304 | ms | 2006-10-06 11:08:18 +0200 (Fri, 06 Oct 2006) | 2 lines
 
 Zwischencommit fuer LFS. GCC und Binutils fixed.
 
 ------------------------------------------------------------------------
-r303 | ms | 2006-10-04 18:35:14 +0400 (Wed, 04 Oct 2006) | 2 lines
+r303 | ms | 2006-10-04 16:35:14 +0200 (Wed, 04 Oct 2006) | 2 lines
 
 Binutilserror behoben.
 
 ------------------------------------------------------------------------
-r302 | ms | 2006-10-03 00:48:09 +0400 (Tue, 03 Oct 2006) | 2 lines
+r302 | ms | 2006-10-02 22:48:09 +0200 (Mon, 02 Oct 2006) | 2 lines
 
 Zwischencommit LFS - Stoppt bei Stage2 - Binutils.
 
 ------------------------------------------------------------------------
-r301 | ms | 2006-10-01 23:57:04 +0400 (Sun, 01 Oct 2006) | 2 lines
+r301 | ms | 2006-10-01 21:57:04 +0200 (Sun, 01 Oct 2006) | 2 lines
 
 Zwischencommit f?\195?\188r LFS.
 
 ------------------------------------------------------------------------
-r300 | ms | 2006-10-01 19:04:23 +0400 (Sun, 01 Oct 2006) | 2 lines
+r300 | ms | 2006-10-01 17:04:23 +0200 (Sun, 01 Oct 2006) | 2 lines
 
 Naechster Schritt im LFS.
 
 ------------------------------------------------------------------------
-r299 | ms | 2006-10-01 14:51:18 +0400 (Sun, 01 Oct 2006) | 3 lines
+r299 | ms | 2006-10-01 12:51:18 +0200 (Sun, 01 Oct 2006) | 3 lines
 
 Zwischencommit beim Umzug auf LFS 6.2.
 
 
 ------------------------------------------------------------------------
-r298 | ms | 2006-10-01 02:07:28 +0400 (Sun, 01 Oct 2006) | 2 lines
+r298 | ms | 2006-10-01 00:07:28 +0200 (Sun, 01 Oct 2006) | 2 lines
 
 Make.sh gesplittet und maechtig ueberarbeitet.
 
 ------------------------------------------------------------------------
-r297 | ms | 2006-09-30 20:33:03 +0400 (Sat, 30 Sep 2006) | 4 lines
+r297 | ms | 2006-09-30 18:33:03 +0200 (Sat, 30 Sep 2006) | 4 lines
 
 Habe IPFire auf LFS 6.2 gebracht.
 Das hier ist der erste Teil.
 Nur Toolchain bisher.
 
 ------------------------------------------------------------------------
-r296 | delaco | 2006-09-29 18:42:04 +0400 (Fri, 29 Sep 2006) | 1 line
+r296 | delaco | 2006-09-29 16:42:04 +0200 (Fri, 29 Sep 2006) | 1 line
 
 Fix fuer die packages_list.txt...
 ------------------------------------------------------------------------
-r295 | delaco | 2006-09-23 21:37:59 +0400 (Sat, 23 Sep 2006) | 3 lines
+r295 | delaco | 2006-09-23 19:37:59 +0200 (Sat, 23 Sep 2006) | 3 lines
 
 Fixes fuer den Buildprozess. (applejuice, mysql)
 Quality of Service: TOS-Regeln und TOS-Matches hinzugefuegt, Graphen uebersichtlicher angeordnet.
 
 ------------------------------------------------------------------------
-r294 | delaco | 2006-09-23 03:12:12 +0400 (Sat, 23 Sep 2006) | 1 line
+r294 | delaco | 2006-09-23 01:12:12 +0200 (Sat, 23 Sep 2006) | 1 line
 
 WebCyrAdm - Dateien verschoben und nicht in Paket geaendert. Sorry.
 ------------------------------------------------------------------------
-r293 | delaco | 2006-09-23 03:05:21 +0400 (Sat, 23 Sep 2006) | 7 lines
+r293 | delaco | 2006-09-23 01:05:21 +0200 (Sat, 23 Sep 2006) | 7 lines
 
 MONSTER-REVISION!
   * Alte und ueberfluessige Pakete entfernt.
@@ -1669,15 +1797,15 @@ MONSTER-REVISION!
   * XAMPP entfernt. STILL EXPERIMENTAL
   * make.sh aufgeraeumt.
 ------------------------------------------------------------------------
-r292 | ms | 2006-09-22 01:25:43 +0400 (Fri, 22 Sep 2006) | 1 line
+r292 | ms | 2006-09-21 23:25:43 +0200 (Thu, 21 Sep 2006) | 1 line
 
 stunnel und edonkeyclc geloescht, da wir es nicht nutzen
 ------------------------------------------------------------------------
-r291 | ms | 2006-09-21 23:47:20 +0400 (Thu, 21 Sep 2006) | 1 line
+r291 | ms | 2006-09-21 21:47:20 +0200 (Thu, 21 Sep 2006) | 1 line
 
 Nicht alle Versionen von Subversion koennen den vollen Befehlsumfang :(
 ------------------------------------------------------------------------
-r290 | delaco | 2006-09-21 22:48:19 +0400 (Thu, 21 Sep 2006) | 5 lines
+r290 | delaco | 2006-09-21 20:48:19 +0200 (Thu, 21 Sep 2006) | 5 lines
 
 Make.sh:
   * svn dist ueberarbeitet.
@@ -1685,35 +1813,35 @@ Make.sh:
   * svn ad packt alle Sources in ein Archiv mit Changelog und svn_status
   * packages_list fuer Mediawiki umgemodelt.
 ------------------------------------------------------------------------
-r289 | casemaster | 2006-09-20 00:06:50 +0400 (Wed, 20 Sep 2006) | 1 line
+r289 | casemaster | 2006-09-19 22:06:50 +0200 (Tue, 19 Sep 2006) | 1 line
 
 SVN ist durcheinandergekommen bei Pfad-Anpassung Part 2 (Ende)
 ------------------------------------------------------------------------
-r288 | casemaster | 2006-09-20 00:04:44 +0400 (Wed, 20 Sep 2006) | 1 line
+r288 | casemaster | 2006-09-19 22:04:44 +0200 (Tue, 19 Sep 2006) | 1 line
 
 SVN ist durcheinandergekommen bei Pfad-Anpassung Part 1
 ------------------------------------------------------------------------
-r287 | casemaster | 2006-09-19 23:54:40 +0400 (Tue, 19 Sep 2006) | 2 lines
+r287 | casemaster | 2006-09-19 21:54:40 +0200 (Tue, 19 Sep 2006) | 2 lines
 
 Anpassung der Pfadangaben f?\195?\188r GRUB.
 ?\195?\156berfl?\195?\188ssige Dateien entfernt.
 ------------------------------------------------------------------------
-r286 | delaco | 2006-09-19 23:46:43 +0400 (Tue, 19 Sep 2006) | 3 lines
+r286 | delaco | 2006-09-19 21:46:43 +0200 (Tue, 19 Sep 2006) | 3 lines
 
 Hinzugefuegt:
   * SysLinux Patch vergessen.
   * Workaround um PHP5 zu kompilieren.
 ------------------------------------------------------------------------
-r285 | casemaster | 2006-09-19 10:53:10 +0400 (Tue, 19 Sep 2006) | 2 lines
+r285 | casemaster | 2006-09-19 08:53:10 +0200 (Tue, 19 Sep 2006) | 2 lines
 
 Update des GFXBoot-Patches f?\195?\188r GRUB aus SuSE 10.2 v8.
 Startbild aktualisiert.
 ------------------------------------------------------------------------
-r284 | ms | 2006-09-18 23:28:58 +0400 (Mon, 18 Sep 2006) | 1 line
+r284 | ms | 2006-09-18 21:28:58 +0200 (Mon, 18 Sep 2006) | 1 line
 
 Nochn Fix fuer die Passwoerter.
 ------------------------------------------------------------------------
-r283 | ms | 2006-09-18 23:05:20 +0400 (Mon, 18 Sep 2006) | 8 lines
+r283 | ms | 2006-09-18 21:05:20 +0200 (Mon, 18 Sep 2006) | 8 lines
 
 Hinzugefuegt:
   * Konfiguration fuer Apache2
@@ -1724,40 +1852,40 @@ Gefixt:
   * Fehler im Installer wegen Apache2.
 
 ------------------------------------------------------------------------
-r282 | delaco | 2006-09-18 22:23:50 +0400 (Mon, 18 Sep 2006) | 3 lines
+r282 | delaco | 2006-09-18 20:23:50 +0200 (Mon, 18 Sep 2006) | 3 lines
 
 Hinzugefuegt:
   * LibXML2 in ISO, da Abhaengigkeit von PHP5.
   * Mod_ssl.so fuer Apache2.
 ------------------------------------------------------------------------
-r281 | ms | 2006-09-17 17:10:56 +0400 (Sun, 17 Sep 2006) | 2 lines
+r281 | ms | 2006-09-17 15:10:56 +0200 (Sun, 17 Sep 2006) | 2 lines
 
 Einige Aenderungen an der make.sh.
 Das war mal noetig.
 ------------------------------------------------------------------------
-r280 | delaco | 2006-09-17 17:03:38 +0400 (Sun, 17 Sep 2006) | 3 lines
+r280 | delaco | 2006-09-17 15:03:38 +0200 (Sun, 17 Sep 2006) | 3 lines
 
 Geaendert:
   * Sauber kompilierter und strukturierter Apache2
     (Konfiguration fehlt aber noch.)
 ------------------------------------------------------------------------
-r279 | delaco | 2006-09-15 00:51:06 +0400 (Fri, 15 Sep 2006) | 2 lines
+r279 | delaco | 2006-09-14 22:51:06 +0200 (Thu, 14 Sep 2006) | 2 lines
 
 Fortschritt zur Migration auf Apache2.2
 TESTMODUS
 ------------------------------------------------------------------------
-r278 | delaco | 2006-09-14 00:20:37 +0400 (Thu, 14 Sep 2006) | 2 lines
+r278 | delaco | 2006-09-13 22:20:37 +0200 (Wed, 13 Sep 2006) | 2 lines
 
 Update:
   * OutgoingFW - Script hinzugefuegt
 ------------------------------------------------------------------------
-r277 | delaco | 2006-09-13 19:30:27 +0400 (Wed, 13 Sep 2006) | 3 lines
+r277 | delaco | 2006-09-13 17:30:27 +0200 (Wed, 13 Sep 2006) | 3 lines
 
 Fixes:
   * readline - Fehler im Patch-Pfad
   * php ist von libxml2 abhaengig
 ------------------------------------------------------------------------
-r276 | delaco | 2006-09-13 01:47:37 +0400 (Wed, 13 Sep 2006) | 10 lines
+r276 | delaco | 2006-09-12 23:47:37 +0200 (Tue, 12 Sep 2006) | 10 lines
 
 Hinzugefuegt:
   * Yasuc
@@ -1770,17 +1898,17 @@ Fixes:
   * readline
   * lfs/Config
 ------------------------------------------------------------------------
-r275 | ms | 2006-09-13 00:23:29 +0400 (Wed, 13 Sep 2006) | 3 lines
+r275 | ms | 2006-09-12 22:23:29 +0200 (Tue, 12 Sep 2006) | 3 lines
 
 Geaendert:
   * OpenSSL-Update wegen Sicherheitluecke.
   * Mache ROOTFILES passend um weniger zu aendern bei Kernelupdate.
 ------------------------------------------------------------------------
-r274 | ms | 2006-09-12 22:51:47 +0400 (Tue, 12 Sep 2006) | 1 line
+r274 | ms | 2006-09-12 20:51:47 +0200 (Tue, 12 Sep 2006) | 1 line
 
 Neues Bild fuers Bootmenue!
 ------------------------------------------------------------------------
-r273 | ms | 2006-09-12 21:56:44 +0400 (Tue, 12 Sep 2006) | 5 lines
+r273 | ms | 2006-09-12 19:56:44 +0200 (Tue, 12 Sep 2006) | 5 lines
 
 Hinzugefuegt:
   * PHP 5.1.4
@@ -1788,26 +1916,26 @@ Hinzugefuegt:
   * GNU readline 5.1
 DAS WEBINTERFACE ARBEITET MOEGLICHERWEISE NICHT!
 ------------------------------------------------------------------------
-r272 | delaco | 2006-09-12 21:51:12 +0400 (Tue, 12 Sep 2006) | 1 line
+r272 | delaco | 2006-09-12 19:51:12 +0200 (Tue, 12 Sep 2006) | 1 line
 
 MySQL Build-Fix.
 ------------------------------------------------------------------------
-r271 | ms | 2006-09-11 23:47:34 +0400 (Mon, 11 Sep 2006) | 1 line
+r271 | ms | 2006-09-11 21:47:34 +0200 (Mon, 11 Sep 2006) | 1 line
 
 Vergessen es ins BuildScript zu machen.
 ------------------------------------------------------------------------
-r270 | ms | 2006-09-11 23:37:42 +0400 (Mon, 11 Sep 2006) | 4 lines
+r270 | ms | 2006-09-11 21:37:42 +0200 (Mon, 11 Sep 2006) | 4 lines
 
 Hinzugefuegt:
   * MySQL 5.0.24a
 Geaendert:
   * Konsolentyp umgestellt fuer MC.
 ------------------------------------------------------------------------
-r269 | ms | 2006-09-11 17:46:05 +0400 (Mon, 11 Sep 2006) | 1 line
+r269 | ms | 2006-09-11 15:46:05 +0200 (Mon, 11 Sep 2006) | 1 line
 
 QoS-Improvements.
 ------------------------------------------------------------------------
-r268 | ms | 2006-09-10 23:52:20 +0400 (Sun, 10 Sep 2006) | 5 lines
+r268 | ms | 2006-09-10 21:52:20 +0200 (Sun, 10 Sep 2006) | 5 lines
 
 Geaendert:
   * Squid auf neuesten Stand gebracht.
@@ -1815,14 +1943,14 @@ Geaendert:
   * Kleines Script fuer Sprachdateiupdates.
 
 ------------------------------------------------------------------------
-r267 | ms | 2006-09-03 00:18:51 +0400 (Sun, 03 Sep 2006) | 4 lines
+r267 | ms | 2006-09-02 22:18:51 +0200 (Sat, 02 Sep 2006) | 4 lines
 
 Hinzugefuegt:
   * QoS-Graphen jetzt auch f?\195?\188r Unterklassen.
 Fix:
   * restartsquid killt jetzt auch squidGuard.
 ------------------------------------------------------------------------
-r266 | ms | 2006-09-02 16:21:49 +0400 (Sat, 02 Sep 2006) | 6 lines
+r266 | ms | 2006-09-02 14:21:49 +0200 (Sat, 02 Sep 2006) | 6 lines
 
 Geaendert:
   * redirect-Seite
@@ -1831,31 +1959,31 @@ Geaendert:
 Hinzugefuegt:
   * Samba.cgi - experimental
 ------------------------------------------------------------------------
-r265 | ms | 2006-08-30 22:56:53 +0400 (Wed, 30 Aug 2006) | 1 line
+r265 | ms | 2006-08-30 20:56:53 +0200 (Wed, 30 Aug 2006) | 1 line
 
 Direkt ein Fix fuer eben genannte Sachen...
 ------------------------------------------------------------------------
-r264 | ms | 2006-08-30 22:29:15 +0400 (Wed, 30 Aug 2006) | 3 lines
+r264 | ms | 2006-08-30 20:29:15 +0200 (Wed, 30 Aug 2006) | 3 lines
 
 Geaendert:
   * Pakete haben jetzt die Endung .ipfire
   * Kleiner Logikfehler im ConnScheduler
 ------------------------------------------------------------------------
-r263 | delaco | 2006-08-30 17:10:09 +0400 (Wed, 30 Aug 2006) | 1 line
+r263 | delaco | 2006-08-30 15:10:09 +0200 (Wed, 30 Aug 2006) | 1 line
 
 Typo in der Make.sh, die die LibMAD nicht bauen lies. Sorry :(
 ------------------------------------------------------------------------
-r262 | delaco | 2006-08-30 01:23:05 +0400 (Wed, 30 Aug 2006) | 1 line
+r262 | delaco | 2006-08-29 23:23:05 +0200 (Tue, 29 Aug 2006) | 1 line
 
 IPCop-Source 1.4.11 eingefuegt
 ------------------------------------------------------------------------
-r261 | ms | 2006-08-29 19:56:35 +0400 (Tue, 29 Aug 2006) | 3 lines
+r261 | ms | 2006-08-29 17:56:35 +0200 (Tue, 29 Aug 2006) | 3 lines
 
 Hinzugefuegt:
   * VLC und seine Libs. EXPERIMENTAL!
 
 ------------------------------------------------------------------------
-r260 | ms | 2006-08-28 21:42:07 +0400 (Mon, 28 Aug 2006) | 5 lines
+r260 | ms | 2006-08-28 19:42:07 +0200 (Mon, 28 Aug 2006) | 5 lines
 
 Hinzugefuegt:
   * Nagios 2.5 mit Plugins
@@ -1863,7 +1991,7 @@ Programmupdate:
   * GD 2.0.20 --> 2.0.33
 
 ------------------------------------------------------------------------
-r259 | ms | 2006-08-28 18:18:38 +0400 (Mon, 28 Aug 2006) | 5 lines
+r259 | ms | 2006-08-28 16:18:38 +0200 (Mon, 28 Aug 2006) | 5 lines
 
 Hinzugefuegt:
   * Load Average Graphen
@@ -1871,7 +1999,7 @@ Geaendert:
   * MC - Tasten F1 bis F5 sollten wieder gehen.
 
 ------------------------------------------------------------------------
-r258 | ms | 2006-08-26 17:20:12 +0400 (Sat, 26 Aug 2006) | 6 lines
+r258 | ms | 2006-08-26 15:20:12 +0200 (Sat, 26 Aug 2006) | 6 lines
 
 Hinzugefuegt:
   * QoS-Graphen - Erste Version!
@@ -1880,7 +2008,7 @@ Pakete:
   * Depends.txt in alle eingefuegt
   * Clamav bearbeitet
 ------------------------------------------------------------------------
-r257 | ms | 2006-08-26 12:42:48 +0400 (Sat, 26 Aug 2006) | 5 lines
+r257 | ms | 2006-08-26 10:42:48 +0200 (Sat, 26 Aug 2006) | 5 lines
 
 Update:
   * Pakfire!
@@ -1888,7 +2016,7 @@ Fixes:
   * ConnScheduler
 
 ------------------------------------------------------------------------
-r256 | ms | 2006-08-24 01:55:46 +0400 (Thu, 24 Aug 2006) | 8 lines
+r256 | ms | 2006-08-23 23:55:46 +0200 (Wed, 23 Aug 2006) | 8 lines
 
 Hinzugefuegt:
   * Copyrighthinweise der externen Addons,
@@ -1899,21 +2027,21 @@ Hinzugefuegt:
 es fuer noetig hielten, dass die Copyrighthinweise
 in jeder Datei zu finden sind.)
 ------------------------------------------------------------------------
-r255 | ms | 2006-08-23 23:19:22 +0400 (Wed, 23 Aug 2006) | 4 lines
+r255 | ms | 2006-08-23 21:19:22 +0200 (Wed, 23 Aug 2006) | 4 lines
 
 Update:
   * QoS ist funktionsfig (hoffentlich).
   * "Aktualisieren" aus Log entfernt.
   * In der header.pl aufgeraeumt.
 ------------------------------------------------------------------------
-r254 | ms | 2006-08-21 23:15:32 +0400 (Mon, 21 Aug 2006) | 4 lines
+r254 | ms | 2006-08-21 21:15:32 +0200 (Mon, 21 Aug 2006) | 4 lines
 
 Programmupdate:
   * Samba 3.0.23a --> 3.0.23b
 Ge?\195?\164ndert:
   * ConnectionScheduler kann jetzt VPNs starten/beenden.
 ------------------------------------------------------------------------
-r253 | ms | 2006-08-21 00:12:57 +0400 (Mon, 21 Aug 2006) | 5 lines
+r253 | ms | 2006-08-20 22:12:57 +0200 (Sun, 20 Aug 2006) | 5 lines
 
 Fixes:
   * libPNG12 fehlte f?\195?\188r makegraphs
@@ -1921,12 +2049,12 @@ Fixes:
 Ge?\195?\164ndert:
   * QoS leicht erweitert.
 ------------------------------------------------------------------------
-r252 | ms | 2006-08-20 00:26:47 +0400 (Sun, 20 Aug 2006) | 2 lines
+r252 | ms | 2006-08-19 22:26:47 +0200 (Sat, 19 Aug 2006) | 2 lines
 
 Geaendert:
   * LibPNG-Files-Fix
 ------------------------------------------------------------------------
-r251 | ms | 2006-08-19 22:09:18 +0400 (Sat, 19 Aug 2006) | 5 lines
+r251 | ms | 2006-08-19 20:09:18 +0200 (Sat, 19 Aug 2006) | 5 lines
 
 Programmupdate:
   * CUPS --> 1.2.2
@@ -1934,7 +2062,7 @@ Geandert:
   * Installer-Message
 
 ------------------------------------------------------------------------
-r250 | ms | 2006-08-19 15:04:41 +0400 (Sat, 19 Aug 2006) | 13 lines
+r250 | ms | 2006-08-19 13:04:41 +0200 (Sat, 19 Aug 2006) | 13 lines
 
 Quellenupdate:
   * tcpdump/glibc/wget/libpng/vlan/expect/vim
@@ -1950,25 +2078,25 @@ Hinzugefuegt:
   * IPTraf 3.0.0
 
 ------------------------------------------------------------------------
-r249 | ms | 2006-08-18 14:51:18 +0400 (Fri, 18 Aug 2006) | 3 lines
+r249 | ms | 2006-08-18 12:51:18 +0200 (Fri, 18 Aug 2006) | 3 lines
 
 Update:
   * Pakfire - umfassende ?\195?\132nderungen und Erweiterungen
 
 ------------------------------------------------------------------------
-r248 | ms | 2006-08-15 23:27:20 +0400 (Tue, 15 Aug 2006) | 3 lines
+r248 | ms | 2006-08-15 21:27:20 +0200 (Tue, 15 Aug 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Sources-CD-Upload is abw?\195?\164hlbar, da >500MB.
 
 ------------------------------------------------------------------------
-r247 | ms | 2006-08-14 23:00:12 +0400 (Mon, 14 Aug 2006) | 3 lines
+r247 | ms | 2006-08-14 21:00:12 +0200 (Mon, 14 Aug 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Kernel-ISO-Fix!
 
 ------------------------------------------------------------------------
-r246 | ms | 2006-08-14 22:50:24 +0400 (Mon, 14 Aug 2006) | 5 lines
+r246 | ms | 2006-08-14 20:50:24 +0200 (Mon, 14 Aug 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * Zaptel gefixt.
@@ -1976,7 +2104,7 @@ Hinzugef?\195?\188gt:
   * Portmap-Paket
 
 ------------------------------------------------------------------------
-r245 | ms | 2006-08-14 00:34:14 +0400 (Mon, 14 Aug 2006) | 5 lines
+r245 | ms | 2006-08-13 22:34:14 +0200 (Sun, 13 Aug 2006) | 5 lines
 
 Update:
   * KERNEL 2.4.33
@@ -1984,19 +2112,19 @@ Ge?\195?\164ndert:
   * Uploadverhalten ?\195?\188berarbeitet.
 
 ------------------------------------------------------------------------
-r244 | ms | 2006-08-12 19:16:04 +0400 (Sat, 12 Aug 2006) | 3 lines
+r244 | ms | 2006-08-12 17:16:04 +0200 (Sat, 12 Aug 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * GFXBoot - experimental
 
 ------------------------------------------------------------------------
-r243 | ms | 2006-08-12 16:40:44 +0400 (Sat, 12 Aug 2006) | 3 lines
+r243 | ms | 2006-08-12 14:40:44 +0200 (Sat, 12 Aug 2006) | 3 lines
 
 Update:
   * Asterisk und Konsorten auf neuesten Stand gebracht.
 
 ------------------------------------------------------------------------
-r242 | ms | 2006-08-09 21:15:33 +0400 (Wed, 09 Aug 2006) | 6 lines
+r242 | ms | 2006-08-09 19:15:33 +0200 (Wed, 09 Aug 2006) | 6 lines
 
 Update:
   * Clamav aktualisiert
@@ -2005,18 +2133,18 @@ Hinzugef?\195?\188gt:
   * Asterisk-Paket
 
 ------------------------------------------------------------------------
-r241 | ms | 2006-08-09 18:51:31 +0400 (Wed, 09 Aug 2006) | 2 lines
+r241 | ms | 2006-08-09 16:51:31 +0200 (Wed, 09 Aug 2006) | 2 lines
 
 OpenVPN/ZERINA-Update.
 
 ------------------------------------------------------------------------
-r240 | linuxadmin | 2006-08-09 00:53:05 +0400 (Wed, 09 Aug 2006) | 3 lines
+r240 | linuxadmin | 2006-08-08 22:53:05 +0200 (Tue, 08 Aug 2006) | 3 lines
 
 Sicherheitsabfrage ins make.sh fuer die commit Option eingebracht
 linuxadmin
 
 ------------------------------------------------------------------------
-r239 | ms | 2006-08-07 23:02:40 +0400 (Mon, 07 Aug 2006) | 7 lines
+r239 | ms | 2006-08-07 21:02:40 +0200 (Mon, 07 Aug 2006) | 7 lines
 
 Update:
   * GnuPG aktualisiert.
@@ -2026,7 +2154,7 @@ Hinzugef?\195?\188gt:
   * /home/nobody
 
 ------------------------------------------------------------------------
-r238 | ms | 2006-08-07 00:07:18 +0400 (Mon, 07 Aug 2006) | 5 lines
+r238 | ms | 2006-08-06 22:07:18 +0200 (Sun, 06 Aug 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * NEUER KERNEL 2.4.31 --> 2.4.32... EXPERIMENTAL!!!
@@ -2034,75 +2162,75 @@ Ge?\195?\164ndert:
   * Bootsplash-Patch gefixt. Unsinnige Sache entfernt.
 
 ------------------------------------------------------------------------
-r237 | delaco | 2006-08-03 14:03:21 +0400 (Thu, 03 Aug 2006) | 3 lines
+r237 | delaco | 2006-08-03 12:03:21 +0200 (Thu, 03 Aug 2006) | 3 lines
 
 Geaendert:
   * AutoScripts erweitert.
   
 ------------------------------------------------------------------------
-r236 | delaco | 2006-08-02 16:24:44 +0400 (Wed, 02 Aug 2006) | 3 lines
+r236 | delaco | 2006-08-02 14:24:44 +0200 (Wed, 02 Aug 2006) | 3 lines
 
 Geaendert:
   * connections.cgi gefixt.
   
 ------------------------------------------------------------------------
-r235 | delaco | 2006-07-31 21:54:27 +0400 (Mon, 31 Jul 2006) | 3 lines
+r235 | delaco | 2006-07-31 19:54:27 +0200 (Mon, 31 Jul 2006) | 3 lines
 
 Automatisches Build-Script
 Proxy-ACL gefixt.
 
 ------------------------------------------------------------------------
-r234 | ms | 2006-07-31 00:33:21 +0400 (Mon, 31 Jul 2006) | 3 lines
+r234 | ms | 2006-07-30 22:33:21 +0200 (Sun, 30 Jul 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Xinetd-Swat-Fix
 
 ------------------------------------------------------------------------
-r233 | ms | 2006-07-31 00:13:22 +0400 (Mon, 31 Jul 2006) | 4 lines
+r233 | ms | 2006-07-30 22:13:22 +0200 (Sun, 30 Jul 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * Ein tftp-Server f?\195?\188r space.
   * xinetd standardm?\195?\164?\195?\159ig installiert in der ISO.
 
 ------------------------------------------------------------------------
-r232 | delaco | 2006-07-27 23:41:13 +0400 (Thu, 27 Jul 2006) | 4 lines
+r232 | delaco | 2006-07-27 21:41:13 +0200 (Thu, 27 Jul 2006) | 4 lines
 
 Update:
   * Neue GeoIP-Datenbank. Dank an eXciter.
   * Einige Schritt auf dem Weg zu vollautomatisieren Build-Scripts.
   
 ------------------------------------------------------------------------
-r231 | delaco | 2006-07-26 22:08:22 +0400 (Wed, 26 Jul 2006) | 2 lines
+r231 | delaco | 2006-07-26 20:08:22 +0200 (Wed, 26 Jul 2006) | 2 lines
 
 Update:
   * Samba 3.0.23a
 ------------------------------------------------------------------------
-r230 | delaco | 2006-07-26 19:03:41 +0400 (Wed, 26 Jul 2006) | 3 lines
+r230 | delaco | 2006-07-26 17:03:41 +0200 (Wed, 26 Jul 2006) | 3 lines
 
 Gedaendert:
   * Neues Silent-Bild von CaseMaster.
 
 ------------------------------------------------------------------------
-r229 | ms | 2006-07-25 20:32:37 +0400 (Tue, 25 Jul 2006) | 3 lines
+r229 | ms | 2006-07-25 18:32:37 +0200 (Tue, 25 Jul 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Neue Routinen in der ./make.sh
 
 ------------------------------------------------------------------------
-r228 | delaco | 2006-07-24 21:28:23 +0400 (Mon, 24 Jul 2006) | 4 lines
+r228 | delaco | 2006-07-24 19:28:23 +0200 (Mon, 24 Jul 2006) | 4 lines
 
 Hinzugefuegt:
   * Mldonkey-Paket
   * Noch eine Funktion in die ./make.sh
 
 ------------------------------------------------------------------------
-r227 | ms | 2006-07-24 20:07:15 +0400 (Mon, 24 Jul 2006) | 3 lines
+r227 | ms | 2006-07-24 18:07:15 +0200 (Mon, 24 Jul 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Benutzer: mldonkey
 
 ------------------------------------------------------------------------
-r226 | ms | 2006-07-24 19:49:37 +0400 (Mon, 24 Jul 2006) | 5 lines
+r226 | ms | 2006-07-24 17:49:37 +0200 (Mon, 24 Jul 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * Mldonkey 2.7.7
@@ -2110,53 +2238,53 @@ Hinzugef?\195?\188gt:
   * Net-Config ins Webinterface.
 
 ------------------------------------------------------------------------
-r225 | delaco | 2006-07-24 19:35:54 +0400 (Mon, 24 Jul 2006) | 2 lines
+r225 | delaco | 2006-07-24 17:35:54 +0200 (Mon, 24 Jul 2006) | 2 lines
 
 Geaendert:
   * Fixes wegen des MC.
 ------------------------------------------------------------------------
-r224 | linuxadmin | 2006-07-24 02:54:18 +0400 (Mon, 24 Jul 2006) | 2 lines
+r224 | linuxadmin | 2006-07-24 00:54:18 +0200 (Mon, 24 Jul 2006) | 2 lines
 
 make.sh um die Option commit erweitert
 
 ------------------------------------------------------------------------
-r223 | linuxadmin | 2006-07-24 02:28:30 +0400 (Mon, 24 Jul 2006) | 2 lines
+r223 | linuxadmin | 2006-07-24 00:28:30 +0200 (Mon, 24 Jul 2006) | 2 lines
 
 Make.sh erweitert 
 
 ------------------------------------------------------------------------
-r222 | ms | 2006-07-24 00:41:53 +0400 (Mon, 24 Jul 2006) | 3 lines
+r222 | ms | 2006-07-23 22:41:53 +0200 (Sun, 23 Jul 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Bessere Steuerung durch ein Script nach der Idee von linuxadmin.
 
 ------------------------------------------------------------------------
-r221 | linuxadmin | 2006-07-24 00:35:40 +0400 (Mon, 24 Jul 2006) | 3 lines
+r221 | linuxadmin | 2006-07-23 22:35:40 +0200 (Sun, 23 Jul 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Bugfix #18 - Anpassung des IPSec GUIs
 
 ------------------------------------------------------------------------
-r220 | ms | 2006-07-23 21:15:05 +0400 (Sun, 23 Jul 2006) | 3 lines
+r220 | ms | 2006-07-23 19:15:05 +0200 (Sun, 23 Jul 2006) | 3 lines
 
 Update:
   * QoS-Script ist so gut wie funktionsf?\195?\164hig.
 
 ------------------------------------------------------------------------
-r219 | ms | 2006-07-23 17:44:16 +0400 (Sun, 23 Jul 2006) | 4 lines
+r219 | ms | 2006-07-23 15:44:16 +0200 (Sun, 23 Jul 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * QoS.cgi weiter ausgebaut.
   * Kein PostgreSQL mehr. - Kann man ggf. nachinstallieren.
 
 ------------------------------------------------------------------------
-r218 | ms | 2006-07-22 18:45:11 +0400 (Sat, 22 Jul 2006) | 3 lines
+r218 | ms | 2006-07-22 16:45:11 +0200 (Sat, 22 Jul 2006) | 3 lines
 
 Update:
   * Neuer Clamav.
 
 ------------------------------------------------------------------------
-r217 | ms | 2006-07-22 18:33:17 +0400 (Sat, 22 Jul 2006) | 8 lines
+r217 | ms | 2006-07-22 16:33:17 +0200 (Sat, 22 Jul 2006) | 8 lines
 
 Hinzugef?\195?\188gt:
   * Cron-Ordner.
@@ -2167,7 +2295,7 @@ Ge?\195?\164ndert:
   * Bootsplashbar wird nichtmehr im Textmodus versucht einzublenden.
 
 ------------------------------------------------------------------------
-r216 | delaco | 2006-07-21 19:10:50 +0400 (Fri, 21 Jul 2006) | 5 lines
+r216 | delaco | 2006-07-21 17:10:50 +0200 (Fri, 21 Jul 2006) | 5 lines
 
 Geaendert:
   * Kernel-Multicast entfernt.
@@ -2175,7 +2303,7 @@ Geaendert:
   * Etherwake gefixt.
   * Shutdown-Balken umgekehrt.
 ------------------------------------------------------------------------
-r215 | delaco | 2006-07-20 20:31:37 +0400 (Thu, 20 Jul 2006) | 6 lines
+r215 | delaco | 2006-07-20 18:31:37 +0200 (Thu, 20 Jul 2006) | 6 lines
 
 Geaendert:
   * Grauer Hintergrund der Hardware-Graphen geaendert.
@@ -2184,7 +2312,7 @@ Geaendert:
   * Viele Sachen gefixt...
   
 ------------------------------------------------------------------------
-r214 | delaco | 2006-07-19 18:59:29 +0400 (Wed, 19 Jul 2006) | 6 lines
+r214 | delaco | 2006-07-19 16:59:29 +0200 (Wed, 19 Jul 2006) | 6 lines
 
 Hinzugefuegt:
   * Interface fuer den Benutzer dial.
@@ -2193,7 +2321,7 @@ Geandert:
   * makegraphs gefixt.
 
 ------------------------------------------------------------------------
-r213 | delaco | 2006-07-19 15:46:26 +0400 (Wed, 19 Jul 2006) | 9 lines
+r213 | delaco | 2006-07-19 13:46:26 +0200 (Wed, 19 Jul 2006) | 9 lines
 
 Geaendert:
   * Neuer Ladebalken, in rot und gelb. Jetzt auch bein Herunterfahren.
@@ -2205,21 +2333,21 @@ Geloescht:
   * Morningreconnect-Script.
 
 ------------------------------------------------------------------------
-r212 | delaco | 2006-07-18 22:10:21 +0400 (Tue, 18 Jul 2006) | 4 lines
+r212 | delaco | 2006-07-18 20:10:21 +0200 (Tue, 18 Jul 2006) | 4 lines
 
 Hinzugefuegt:
   * Promise-Sata-300 und SataII-150-Kernel-Modul hinzugefuegt fuer SMP und einen Prozessor.
   * Morningreconnect in den ConnScheduler gelegt.
 
 ------------------------------------------------------------------------
-r211 | ms | 2006-07-17 22:18:39 +0400 (Mon, 17 Jul 2006) | 4 lines
+r211 | ms | 2006-07-17 20:18:39 +0200 (Mon, 17 Jul 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * Wake-On-Lan
   * Connection-Scheduler
 
 ------------------------------------------------------------------------
-r210 | ms | 2006-07-17 19:36:55 +0400 (Mon, 17 Jul 2006) | 10 lines
+r210 | ms | 2006-07-17 17:36:55 +0200 (Mon, 17 Jul 2006) | 10 lines
 
 Hinzugef?\195?\188gt:
   * Hddtemp war nicht in der ISO...
@@ -2232,13 +2360,13 @@ Anmerkung:
     bezeichnungen m?\195?\188ssen angepasst werden.
 
 ------------------------------------------------------------------------
-r209 | ms | 2006-07-17 13:50:24 +0400 (Mon, 17 Jul 2006) | 3 lines
+r209 | ms | 2006-07-17 11:50:24 +0200 (Mon, 17 Jul 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Kernel multicast-f?\195?\164hig.
 
 ------------------------------------------------------------------------
-r208 | ms | 2006-07-14 20:28:20 +0400 (Fri, 14 Jul 2006) | 5 lines
+r208 | ms | 2006-07-14 18:28:20 +0200 (Fri, 14 Jul 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * Errorseite von Linuxadmin.
@@ -2246,7 +2374,7 @@ Ge?\195?\164ndert:
   * Bisschen an der make.sh aufger?\195?\164umt und verbessert.
 
 ------------------------------------------------------------------------
-r207 | ms | 2006-07-14 19:53:44 +0400 (Fri, 14 Jul 2006) | 8 lines
+r207 | ms | 2006-07-14 17:53:44 +0200 (Fri, 14 Jul 2006) | 8 lines
 
 Hinzugef?\195?\188gt:
   * Unzip in die ISO gebaut.
@@ -2257,12 +2385,12 @@ Ge?\195?\164ndert:
   * QoS-Scripts aktualisiert.
 
 ------------------------------------------------------------------------
-r206 | casemaster | 2006-07-11 12:57:13 +0400 (Tue, 11 Jul 2006) | 2 lines
+r206 | casemaster | 2006-07-11 10:57:13 +0200 (Tue, 11 Jul 2006) | 2 lines
 
 fixup initrd - ?\195?\132nderung von ipcoprd.img nach ipfirerd.img
 
 ------------------------------------------------------------------------
-r205 | delaco | 2006-07-10 20:38:56 +0400 (Mon, 10 Jul 2006) | 10 lines
+r205 | delaco | 2006-07-10 18:38:56 +0200 (Mon, 10 Jul 2006) | 10 lines
 
 Hinzugefuegt:
   * p2protocols-Datei, die vergessen wurde.
@@ -2275,27 +2403,27 @@ Geaendert:
   * Im SSH den Zertifikatslogin per default ausgemacht.
 
 ------------------------------------------------------------------------
-r204 | ms | 2006-07-07 19:53:12 +0400 (Fri, 07 Jul 2006) | 3 lines
+r204 | ms | 2006-07-07 17:53:12 +0200 (Fri, 07 Jul 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * WebGUI f?\195?\188r die ausgehende Firewall.
 
 ------------------------------------------------------------------------
-r203 | ms | 2006-07-07 15:42:26 +0400 (Fri, 07 Jul 2006) | 4 lines
+r203 | ms | 2006-07-07 13:42:26 +0200 (Fri, 07 Jul 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * ?\195?\132nderungen am Installer.
   * Fix im header.pl.
 
 ------------------------------------------------------------------------
-r202 | ms | 2006-07-07 00:51:35 +0400 (Fri, 07 Jul 2006) | 4 lines
+r202 | ms | 2006-07-06 22:51:35 +0200 (Thu, 06 Jul 2006) | 4 lines
 
 Bugfixes:
   * SCSI-SMP-Kernel vergessen.
   * scsigrub.conf war fehlerhaft und nicht komplett.
 
 ------------------------------------------------------------------------
-r201 | ms | 2006-07-07 00:15:31 +0400 (Fri, 07 Jul 2006) | 8 lines
+r201 | ms | 2006-07-06 22:15:31 +0200 (Thu, 06 Jul 2006) | 8 lines
 
 Bugfixes:
   * Framebufferdevices
@@ -2306,13 +2434,13 @@ Bugfixes:
   * Installer gefixt.
 
 ------------------------------------------------------------------------
-r200 | ms | 2006-07-06 17:38:27 +0400 (Thu, 06 Jul 2006) | 3 lines
+r200 | ms | 2006-07-06 15:38:27 +0200 (Thu, 06 Jul 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Bootsplash im SVN verschoben, da nur noch einer vorhanden ist.
 
 ------------------------------------------------------------------------
-r199 | ms | 2006-07-06 17:33:16 +0400 (Thu, 06 Jul 2006) | 7 lines
+r199 | ms | 2006-07-06 15:33:16 +0200 (Thu, 06 Jul 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Nodes f?\195?\188r Framebuffer.
@@ -2322,13 +2450,13 @@ Ge?\195?\164ndert:
   * Neue Boot-Bilder.
 
 ------------------------------------------------------------------------
-r198 | ms | 2006-07-06 14:24:53 +0400 (Thu, 06 Jul 2006) | 3 lines
+r198 | ms | 2006-07-06 12:24:53 +0200 (Thu, 06 Jul 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Bootsplash-Software-Update.
 
 ------------------------------------------------------------------------
-r197 | ms | 2006-07-06 01:22:59 +0400 (Thu, 06 Jul 2006) | 6 lines
+r197 | ms | 2006-07-05 23:22:59 +0200 (Wed, 05 Jul 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * Fehlende Grafik.
@@ -2337,19 +2465,19 @@ Ge?\195?\164ndert:
   * QoS-CGI-Update.
 
 ------------------------------------------------------------------------
-r196 | casemaster | 2006-07-04 22:10:48 +0400 (Tue, 04 Jul 2006) | 2 lines
+r196 | casemaster | 2006-07-04 20:10:48 +0200 (Tue, 04 Jul 2006) | 2 lines
 
 Korrekturen
 
 ------------------------------------------------------------------------
-r195 | ms | 2006-07-04 20:00:11 +0400 (Tue, 04 Jul 2006) | 4 lines
+r195 | ms | 2006-07-04 18:00:11 +0200 (Tue, 04 Jul 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * Paar Pfade in den Bootsplash-Configs verbogen.
   * Hintergundbilder f?\195?\188r die Konsolen gesetzt. (Ich hoffe das klappt so.)
 
 ------------------------------------------------------------------------
-r194 | ms | 2006-07-04 18:44:19 +0400 (Tue, 04 Jul 2006) | 7 lines
+r194 | ms | 2006-07-04 16:44:19 +0200 (Tue, 04 Jul 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Neuer Bootsplash. - Anders organisiert.
@@ -2359,7 +2487,7 @@ Ge?\195?\164ndert:
   * Grub.conf angepasst f?\195?\188r Bootsplash (nur IDE).
 
 ------------------------------------------------------------------------
-r193 | ms | 2006-07-03 22:50:48 +0400 (Mon, 03 Jul 2006) | 5 lines
+r193 | ms | 2006-07-03 20:50:48 +0200 (Mon, 03 Jul 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * Umfassende Fixes beim URL-Filter. - Erfolgreich getestet.
@@ -2367,30 +2495,30 @@ Ge?\195?\164ndert:
   * Dateien in ISO geschoben und noch ?\195?\188berfl?\195?\188ssige gel?\195?\182scht.
 
 ------------------------------------------------------------------------
-r192 | ms | 2006-07-02 15:54:34 +0400 (Sun, 02 Jul 2006) | 4 lines
+r192 | ms | 2006-07-02 13:54:34 +0200 (Sun, 02 Jul 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * Libs und Fonts f?\195?\188r Bootsplash
   * Bootsplash-Binaries selber
 
 ------------------------------------------------------------------------
-r191 | casemaster | 2006-07-02 13:16:40 +0400 (Sun, 02 Jul 2006) | 2 lines
+r191 | casemaster | 2006-07-02 11:16:40 +0200 (Sun, 02 Jul 2006) | 2 lines
 
 Das Build wird jetzt im Browserkopf angezeigt
 
 ------------------------------------------------------------------------
-r190 | casemaster | 2006-07-02 02:15:17 +0400 (Sun, 02 Jul 2006) | 2 lines
+r190 | casemaster | 2006-07-02 00:15:17 +0200 (Sun, 02 Jul 2006) | 2 lines
 
 ?\195?\132nderung am Linux-Kernel (BootSplash)
 
 ------------------------------------------------------------------------
-r189 | casemaster | 2006-07-01 23:50:22 +0400 (Sat, 01 Jul 2006) | 3 lines
+r189 | casemaster | 2006-07-01 21:50:22 +0200 (Sat, 01 Jul 2006) | 3 lines
 
 Fehlende Datei f?\195?\188r Bootsplash nachgereicht.
 
 
 ------------------------------------------------------------------------
-r188 | ms | 2006-07-01 18:36:04 +0400 (Sat, 01 Jul 2006) | 5 lines
+r188 | ms | 2006-07-01 16:36:04 +0200 (Sat, 01 Jul 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * URL-Filter gefixt.
@@ -2398,25 +2526,25 @@ Ge?\195?\164ndert:
   * GLIB in ISO f?\195?\188r MC.
 
 ------------------------------------------------------------------------
-r187 | casemaster | 2006-07-01 15:46:39 +0400 (Sat, 01 Jul 2006) | 3 lines
+r187 | casemaster | 2006-07-01 13:46:39 +0200 (Sat, 01 Jul 2006) | 3 lines
 
 Fehlerbereinigung beim URL-Filter
 Anfang f?\195?\188r Bootsplash integriert
 
 ------------------------------------------------------------------------
-r186 | ms | 2006-06-30 18:31:17 +0400 (Fri, 30 Jun 2006) | 3 lines
+r186 | ms | 2006-06-30 16:31:17 +0200 (Fri, 30 Jun 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Leider wurden die CGIs 3x hintereinander in die Datei geschrieben. :(
 
 ------------------------------------------------------------------------
-r185 | ms | 2006-06-30 18:25:35 +0400 (Fri, 30 Jun 2006) | 3 lines
+r185 | ms | 2006-06-30 16:25:35 +0200 (Fri, 30 Jun 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * URL-Filter
 
 ------------------------------------------------------------------------
-r184 | ms | 2006-06-30 00:38:22 +0400 (Fri, 30 Jun 2006) | 8 lines
+r184 | ms | 2006-06-29 22:38:22 +0200 (Thu, 29 Jun 2006) | 8 lines
 
 Hinzugef?\195?\188gt:
   * Kernel tr?\195?\164gt den Namen ipfire.
@@ -2427,7 +2555,7 @@ Ge?\195?\164ndert:
   * GLIB ohne NLS.
 
 ------------------------------------------------------------------------
-r183 | ms | 2006-06-27 15:49:06 +0400 (Tue, 27 Jun 2006) | 6 lines
+r183 | ms | 2006-06-27 13:49:06 +0200 (Tue, 27 Jun 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * Weitere Fortschritte im QoS-GUI
@@ -2436,14 +2564,14 @@ Update:
   * Changelog aktualisiert
 
 ------------------------------------------------------------------------
-r182 | ms | 2006-06-25 01:57:29 +0400 (Sun, 25 Jun 2006) | 4 lines
+r182 | ms | 2006-06-24 23:57:29 +0200 (Sat, 24 Jun 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * Viele Schritte weiter im QoS-GUI...
   * Alten IPCop-Shaper aus den Startscripts entfernt.
 
 ------------------------------------------------------------------------
-r181 | ms | 2006-06-22 15:54:33 +0400 (Thu, 22 Jun 2006) | 5 lines
+r181 | ms | 2006-06-22 13:54:33 +0200 (Thu, 22 Jun 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * Cyrus-IMAP downgrade auf 2.2.12 mit einer Menge Patches,
@@ -2451,7 +2579,7 @@ Ge?\195?\164ndert:
   * SSH-Sch?\195?\182nheitsfehler im Webinterface behoben.
 
 ------------------------------------------------------------------------
-r180 | ms | 2006-06-20 22:31:22 +0400 (Tue, 20 Jun 2006) | 7 lines
+r180 | ms | 2006-06-20 20:31:22 +0200 (Tue, 20 Jun 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Consolenprogramme erscheinen nun in Farbe statt in S/W.
@@ -2461,7 +2589,7 @@ Ge?\195?\164ndert:
   * IMAP-Ordnerstrukturen des Cyrus-IMAPd angelegt mit richtigen Rechten.
 
 ------------------------------------------------------------------------
-r179 | ms | 2006-06-15 21:43:14 +0400 (Thu, 15 Jun 2006) | 5 lines
+r179 | ms | 2006-06-15 19:43:14 +0200 (Thu, 15 Jun 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * Postfix - PostgreSQL-Unterst?\195?\188tzung herausgenommen.
@@ -2469,13 +2597,13 @@ Ge?\195?\164ndert:
   * Konfigurationen der Mailer in die Pakete gepackt.
 
 ------------------------------------------------------------------------
-r178 | ms | 2006-06-15 01:19:05 +0400 (Thu, 15 Jun 2006) | 3 lines
+r178 | ms | 2006-06-14 23:19:05 +0200 (Wed, 14 Jun 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * In Mailserverkonfiguration fortgeschritten...
 
 ------------------------------------------------------------------------
-r177 | ms | 2006-06-14 21:35:12 +0400 (Wed, 14 Jun 2006) | 7 lines
+r177 | ms | 2006-06-14 19:35:12 +0200 (Wed, 14 Jun 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Asterisk-Konfigurationsdateien f?\195?\188rs Webinterface.
@@ -2485,7 +2613,7 @@ Ge?\195?\164ndert:
   * Postfix ohne PostgreSQL
 
 ------------------------------------------------------------------------
-r176 | ms | 2006-06-14 14:10:01 +0400 (Wed, 14 Jun 2006) | 5 lines
+r176 | ms | 2006-06-14 12:10:01 +0200 (Wed, 14 Jun 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * qos.cgi - Geht noch so gut wie nix.
@@ -2493,21 +2621,21 @@ Ge?\195?\164ndert:
   * hddshutdown funktioniert nun.
 
 ------------------------------------------------------------------------
-r175 | ms | 2006-06-14 01:05:40 +0400 (Wed, 14 Jun 2006) | 4 lines
+r175 | ms | 2006-06-13 23:05:40 +0200 (Tue, 13 Jun 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * Packager neu erstellt.
   XAMPP Paket noch nicht drin. ERRORS! :(
 
 ------------------------------------------------------------------------
-r174 | casemaster | 2006-06-13 23:46:57 +0400 (Tue, 13 Jun 2006) | 4 lines
+r174 | casemaster | 2006-06-13 21:46:57 +0200 (Tue, 13 Jun 2006) | 4 lines
 
 Installer:
 Tastatur "DE" als default
 Timezone "Europe/Berlin" als default.
 
 ------------------------------------------------------------------------
-r173 | ms | 2006-06-13 18:15:51 +0400 (Tue, 13 Jun 2006) | 8 lines
+r173 | ms | 2006-06-13 16:15:51 +0200 (Tue, 13 Jun 2006) | 8 lines
 
 Ge?\195?\164ndert:
   * (experimentelle) httpd.conf
@@ -2518,14 +2646,14 @@ Ge?\195?\164ndert:
   * fwhits-Graphs - Kleinigkeit vergessen.
 
 ------------------------------------------------------------------------
-r172 | ms | 2006-06-12 22:41:26 +0400 (Mon, 12 Jun 2006) | 4 lines
+r172 | ms | 2006-06-12 20:41:26 +0200 (Mon, 12 Jun 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * Graphs gefixt http://bugtracker.ipfire.eu/view.php?id=8
   * src/paks/*/CONFFILES gel?\195?\182scht
 
 ------------------------------------------------------------------------
-r171 | ms | 2006-06-12 19:00:19 +0400 (Mon, 12 Jun 2006) | 8 lines
+r171 | ms | 2006-06-12 17:00:19 +0200 (Mon, 12 Jun 2006) | 8 lines
 
 Hinzugef?\195?\188gt:
   * IPTables ins Webinterface - Muss der Benne nochmal dr?\195?\188berkucken!
@@ -2536,18 +2664,18 @@ Ge?\195?\164ndert:
   * Men?\195?\188 im Webinterface wieder einmal bearbeitet.
 
 ------------------------------------------------------------------------
-r170 | casemaster | 2006-06-11 02:38:23 +0400 (Sun, 11 Jun 2006) | 3 lines
+r170 | casemaster | 2006-06-11 00:38:23 +0200 (Sun, 11 Jun 2006) | 3 lines
 
 Sprachen in den Installer auf DE und EN begrenzt.
 Deutsch als default.
 Abfrage f?\195?\188r "alte Konfiguration laden" entfernt.
 ------------------------------------------------------------------------
-r169 | casemaster | 2006-06-11 01:17:42 +0400 (Sun, 11 Jun 2006) | 2 lines
+r169 | casemaster | 2006-06-10 23:17:42 +0200 (Sat, 10 Jun 2006) | 2 lines
 
 Sprachen in den Installer auf DE und EN begrenzt.
 Deutsch als default.
 ------------------------------------------------------------------------
-r168 | ms | 2006-06-10 23:21:32 +0400 (Sat, 10 Jun 2006) | 10 lines
+r168 | ms | 2006-06-10 21:21:32 +0200 (Sat, 10 Jun 2006) | 10 lines
 
 Hinzugefuegt:
   * SquidGuard - mit Patch damit es mit der DB 4.4.20 funktioniert.
@@ -2560,7 +2688,7 @@ Geaendert:
   * Karsten Rechenbachs Emailadresse in die Credits gebaut.
 
 ------------------------------------------------------------------------
-r167 | ms | 2006-06-08 17:17:52 +0400 (Thu, 08 Jun 2006) | 9 lines
+r167 | ms | 2006-06-08 15:17:52 +0200 (Thu, 08 Jun 2006) | 9 lines
 
 Hinzugef?\195?\188gt:
   * Morningreconnect - Danke an Benedikt
@@ -2572,7 +2700,7 @@ Ge?\195?\164ndert:
 
 
 ------------------------------------------------------------------------
-r166 | ms | 2006-06-08 00:31:04 +0400 (Thu, 08 Jun 2006) | 6 lines
+r166 | ms | 2006-06-07 22:31:04 +0200 (Wed, 07 Jun 2006) | 6 lines
 
 Hinzugefuegt:
   * CM zu den Credits
@@ -2581,7 +2709,7 @@ Hinzugefuegt:
   * iftop
 
 ------------------------------------------------------------------------
-r165 | ms | 2006-06-06 23:31:47 +0400 (Tue, 06 Jun 2006) | 5 lines
+r165 | ms | 2006-06-06 21:31:47 +0200 (Tue, 06 Jun 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * Bearbeitetes Startscript f?\195?\188r AJ
@@ -2589,7 +2717,7 @@ Ge?\195?\164ndert:
   * Nur noch Deutsch/Englisch f?\195?\188r das Webinterface.
 
 ------------------------------------------------------------------------
-r164 | ms | 2006-06-06 23:12:22 +0400 (Tue, 06 Jun 2006) | 10 lines
+r164 | ms | 2006-06-06 21:12:22 +0200 (Tue, 06 Jun 2006) | 10 lines
 
 Hinzugef?\195?\188gt:
   * Morningreconnect Script
@@ -2602,7 +2730,7 @@ Ge?\195?\164ndert:
   * Connectionstate vom IPCop ?\195?\188bernommen.
 
 ------------------------------------------------------------------------
-r163 | ms | 2006-06-06 16:38:52 +0400 (Tue, 06 Jun 2006) | 10 lines
+r163 | ms | 2006-06-06 14:38:52 +0200 (Tue, 06 Jun 2006) | 10 lines
 
 Hinzugef?\195?\188gt:
   * Locale-Codes - Perl-Modul f?\195?\188r die country.cgi
@@ -2615,7 +2743,7 @@ Ge?\195?\164ndert:
   * Sysconfdir von xinetd und Samba verschoben.
 
 ------------------------------------------------------------------------
-r162 | ms | 2006-06-05 21:35:00 +0400 (Mon, 05 Jun 2006) | 6 lines
+r162 | ms | 2006-06-05 19:35:00 +0200 (Mon, 05 Jun 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * HDDGraphs f?\195?\188r mehrere Festplatten
@@ -2624,13 +2752,13 @@ Ge?\195?\164ndert:
   * Sprachen auf DE und EN reduziert.
 
 ------------------------------------------------------------------------
-r161 | ms | 2006-06-05 15:51:06 +0400 (Mon, 05 Jun 2006) | 3 lines
+r161 | ms | 2006-06-05 13:51:06 +0200 (Mon, 05 Jun 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * HDDTemp wieder aktiviert. Bisher nur das Binary. CGI folgt sp?\195?\164ter.
 
 ------------------------------------------------------------------------
-r160 | ms | 2006-06-05 15:30:07 +0400 (Mon, 05 Jun 2006) | 11 lines
+r160 | ms | 2006-06-05 13:30:07 +0200 (Mon, 05 Jun 2006) | 11 lines
 
 Hinzugef?\195?\188gt:
   * Kleiner Tux im Webinterface f?\195?\188r den eXciter und den Benne :)
@@ -2644,21 +2772,21 @@ Gel?\195?\182scht:
   * Nicht ben?\195?\182tigte Reste vom IPCop entfernt.
 
 ------------------------------------------------------------------------
-r159 | ms | 2006-06-05 03:24:58 +0400 (Mon, 05 Jun 2006) | 4 lines
+r159 | ms | 2006-06-05 01:24:58 +0200 (Mon, 05 Jun 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * OpenVPN in Statusseite.
   * cftp - FTP-Client grafisch?!
 
 ------------------------------------------------------------------------
-r158 | ms | 2006-06-05 02:55:40 +0400 (Mon, 05 Jun 2006) | 4 lines
+r158 | ms | 2006-06-05 00:55:40 +0200 (Mon, 05 Jun 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * Webinterfacemen?\195?\188 vervollst?\195?\164ndigt.
   * Pfad im AdvProxy ge?\195?\164ndert.
 
 ------------------------------------------------------------------------
-r157 | ms | 2006-06-05 02:29:23 +0400 (Mon, 05 Jun 2006) | 7 lines
+r157 | ms | 2006-06-05 00:29:23 +0200 (Mon, 05 Jun 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Link Quality Graphs
@@ -2668,7 +2796,7 @@ Ge?\195?\164ndert:
   * OpenVPN in ISO gepackt.
 
 ------------------------------------------------------------------------
-r156 | ms | 2006-06-04 20:40:59 +0400 (Sun, 04 Jun 2006) | 5 lines
+r156 | ms | 2006-06-04 18:40:59 +0200 (Sun, 04 Jun 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * fcclassic (auch SMP)
@@ -2676,7 +2804,7 @@ Ge?\195?\164ndert:
   * Benedikt aus den Credits rausgenommen. Willer nich. :(
 
 ------------------------------------------------------------------------
-r155 | ms | 2006-06-04 00:16:53 +0400 (Sun, 04 Jun 2006) | 9 lines
+r155 | ms | 2006-06-03 22:16:53 +0200 (Sat, 03 Jun 2006) | 9 lines
 
 Update:
   * Squid 2.5STABLE14 eingepflegt.
@@ -2688,7 +2816,7 @@ Ge?\195?\164ndert:
   * index.cgi, v?\195?\182llig neuer Look.
 
 ------------------------------------------------------------------------
-r154 | ms | 2006-06-03 16:22:38 +0400 (Sat, 03 Jun 2006) | 5 lines
+r154 | ms | 2006-06-03 14:22:38 +0200 (Sat, 03 Jun 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * Webinterface Men?\195?\188 bearbeitet.
@@ -2696,7 +2824,7 @@ Ge?\195?\164ndert:
   * Pakfire gefixt, aber noch nicht funktionsf?\195?\164hig!
 
 ------------------------------------------------------------------------
-r153 | ms | 2006-06-02 23:03:53 +0400 (Fri, 02 Jun 2006) | 5 lines
+r153 | ms | 2006-06-02 21:03:53 +0200 (Fri, 02 Jun 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * AdvancedProxy F?\195?\164higkeiten
@@ -2704,7 +2832,7 @@ Ge?\195?\164ndert:
   * Kleiner Fehler im OpenVPN GUI verblieben und daher behoben.
 
 ------------------------------------------------------------------------
-r152 | ms | 2006-06-02 19:59:39 +0400 (Fri, 02 Jun 2006) | 5 lines
+r152 | ms | 2006-06-02 17:59:39 +0200 (Fri, 02 Jun 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * OpenVPN GUI Alpha7
@@ -2712,7 +2840,7 @@ Ge?\195?\164ndert:
   * XAMPP von 1.5.3 --> 1.5.3a
 
 ------------------------------------------------------------------------
-r151 | ms | 2006-06-02 16:48:29 +0400 (Fri, 02 Jun 2006) | 5 lines
+r151 | ms | 2006-06-02 14:48:29 +0200 (Fri, 02 Jun 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * Postfix Version 2.2.10 eingepflegt
@@ -2720,14 +2848,14 @@ Ge?\195?\164ndert:
   * JAVA-Paket erstellt
 
 ------------------------------------------------------------------------
-r150 | ms | 2006-06-01 00:46:41 +0400 (Thu, 01 Jun 2006) | 4 lines
+r150 | ms | 2006-05-31 22:46:41 +0200 (Wed, 31 May 2006) | 4 lines
 
 Quellenupdate:
   * popt
   * sane
 
 ------------------------------------------------------------------------
-r149 | ms | 2006-05-31 20:29:08 +0400 (Wed, 31 May 2006) | 6 lines
+r149 | ms | 2006-05-31 18:29:08 +0200 (Wed, 31 May 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * ./make.sh pub l?\195?\164dt die ISO auf den mirror.ipfire.org
@@ -2736,7 +2864,7 @@ Ge?\195?\164ndert:
   Zum neu bauen einfach das File l?\195?\182schen und beim n?\195?\164chsten durchlauf wird es wieder mitgebaut.
 
 ------------------------------------------------------------------------
-r148 | ms | 2006-05-31 14:09:27 +0400 (Wed, 31 May 2006) | 8 lines
+r148 | ms | 2006-05-31 12:09:27 +0200 (Wed, 31 May 2006) | 8 lines
 
 Gro?\195?\159es Update:
 Hinzugef?\195?\188gt:
@@ -2747,14 +2875,14 @@ Ge?\195?\164ndert:
   * Einige Fixes, wegen Errors im Webinterface. (Im Forum zu finden.)
 
 ------------------------------------------------------------------------
-r147 | ms | 2006-05-28 21:57:38 +0400 (Sun, 28 May 2006) | 4 lines
+r147 | ms | 2006-05-28 19:57:38 +0200 (Sun, 28 May 2006) | 4 lines
 
 BUILDFIXES:
   * ROOTFILES ?\195?\188berarbeitet. (Ne Menge vergessen.^^)
   * Packages werden nichtmehr im "build" gepackt, sondern mit dem Parameter "paks".
 
 ------------------------------------------------------------------------
-r146 | ms | 2006-05-27 14:38:03 +0400 (Sat, 27 May 2006) | 7 lines
+r146 | ms | 2006-05-27 12:38:03 +0200 (Sat, 27 May 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * XAMPP mit Python
@@ -2764,7 +2892,7 @@ Ge?\195?\164ndert:
   * Make-Packages.sh behebt jetzt doppelte Dateien in den Pak-Archiven.
 
 ------------------------------------------------------------------------
-r145 | ms | 2006-05-26 16:19:48 +0400 (Fri, 26 May 2006) | 6 lines
+r145 | ms | 2006-05-26 14:19:48 +0200 (Fri, 26 May 2006) | 6 lines
 
 Ge?\195?\164ndert:
   * IPCop -> IPFire bei den misc-progs
@@ -2773,7 +2901,7 @@ Gel?\195?\182scht:
   * Restartshaping in den Misc-Progs, weil es durch QoS ersetzt wird.
 
 ------------------------------------------------------------------------
-r144 | ms | 2006-05-26 14:51:14 +0400 (Fri, 26 May 2006) | 7 lines
+r144 | ms | 2006-05-26 12:51:14 +0200 (Fri, 26 May 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Screen
@@ -2783,31 +2911,31 @@ Ge?\195?\164ndert:
   * Lame eingepackt.
 
 ------------------------------------------------------------------------
-r143 | ms | 2006-05-26 01:49:28 +0400 (Fri, 26 May 2006) | 3 lines
+r143 | ms | 2006-05-25 23:49:28 +0200 (Thu, 25 May 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Java von SUN
 
 ------------------------------------------------------------------------
-r142 | ms | 2006-05-26 01:10:48 +0400 (Fri, 26 May 2006) | 3 lines
+r142 | ms | 2006-05-25 23:10:48 +0200 (Thu, 25 May 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Firewallhits
 
 ------------------------------------------------------------------------
-r141 | ms | 2006-05-26 00:23:12 +0400 (Fri, 26 May 2006) | 3 lines
+r141 | ms | 2006-05-25 22:23:12 +0200 (Thu, 25 May 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * HTOP - http://htop.sourceforge.net
 
 ------------------------------------------------------------------------
-r140 | ms | 2006-05-25 23:49:10 +0400 (Thu, 25 May 2006) | 3 lines
+r140 | ms | 2006-05-25 21:49:10 +0200 (Thu, 25 May 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * GeoIP
 
 ------------------------------------------------------------------------
-r139 | ms | 2006-05-25 14:52:42 +0400 (Thu, 25 May 2006) | 6 lines
+r139 | ms | 2006-05-25 12:52:42 +0200 (Thu, 25 May 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * ethereal
@@ -2816,12 +2944,12 @@ Ge?\195?\164ndert:
   * /var/ipcop --> /var/ipfire
 
 ------------------------------------------------------------------------
-r138 | ms | 2006-05-25 00:21:07 +0400 (Thu, 25 May 2006) | 2 lines
+r138 | ms | 2006-05-24 22:21:07 +0200 (Wed, 24 May 2006) | 2 lines
 
 Sourceforge-Mirror wieder ge?\195?\164ndert.
 
 ------------------------------------------------------------------------
-r137 | ms | 2006-05-24 23:47:34 +0400 (Wed, 24 May 2006) | 6 lines
+r137 | ms | 2006-05-24 21:47:34 +0200 (Wed, 24 May 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * NCFTP - Ein CLI-FTP-Client.
@@ -2830,27 +2958,27 @@ Ge?\195?\164ndert:
   * ./make.sh sync erweitert.
 
 ------------------------------------------------------------------------
-r136 | ms | 2006-05-24 22:04:26 +0400 (Wed, 24 May 2006) | 3 lines
+r136 | ms | 2006-05-24 20:04:26 +0200 (Wed, 24 May 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Amavis-Perl-Module in der ISO.
 
 ------------------------------------------------------------------------
-r135 | ms | 2006-05-24 21:42:02 +0400 (Wed, 24 May 2006) | 4 lines
+r135 | ms | 2006-05-24 19:42:02 +0200 (Wed, 24 May 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * Erste Version von CONFIRE.
   * ./make.sh sync l?\195?\164dt nun alle neuen Dateien auf den FTP-Server.
 
 ------------------------------------------------------------------------
-r134 | ms | 2006-05-24 00:15:26 +0400 (Wed, 24 May 2006) | 4 lines
+r134 | ms | 2006-05-23 22:15:26 +0200 (Tue, 23 May 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * CONFIG_ROOT in den Scripts angepasst auf /var/ipfire
   * Zwei f?\195?\188hrende "/" in den ROOTFILES entfernt.
 
 ------------------------------------------------------------------------
-r133 | ms | 2006-05-23 23:31:40 +0400 (Tue, 23 May 2006) | 6 lines
+r133 | ms | 2006-05-23 21:31:40 +0200 (Tue, 23 May 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * NMAP - Netzwerk-Scanner
@@ -2859,13 +2987,13 @@ Ge?\195?\164ndert:
   * CAPIINFO war an der falschen Stelle in der Makefile.
 
 ------------------------------------------------------------------------
-r132 | ms | 2006-05-22 16:47:00 +0400 (Mon, 22 May 2006) | 3 lines
+r132 | ms | 2006-05-22 14:47:00 +0200 (Mon, 22 May 2006) | 3 lines
 
 Zweiter Teil des dicken Quellenupdates. Diesmal: C bis D.
 Status: 49/230 fertiggestellt.
 
 ------------------------------------------------------------------------
-r131 | ms | 2006-05-22 16:14:56 +0400 (Mon, 22 May 2006) | 6 lines
+r131 | ms | 2006-05-22 14:14:56 +0200 (Mon, 22 May 2006) | 6 lines
 
 
 Wir beginnen nun ein Migration der Quellcodepakete auf einen unserer
@@ -2874,7 +3002,7 @@ A bis B einschliesslich. Ich hoffe da macht jemand anderes weiter.
 Hinzu sind die Pakete, deren Mirrors ausgefallen sind, schon umgezogen.
 
 ------------------------------------------------------------------------
-r130 | ms | 2006-05-22 14:43:28 +0400 (Mon, 22 May 2006) | 8 lines
+r130 | ms | 2006-05-22 12:43:28 +0200 (Mon, 22 May 2006) | 8 lines
 
 Hinzugef?\195?\188gt:
   * Zaptel Kernelmodule werden gleich komprimiert.
@@ -2885,7 +3013,7 @@ Gel?\195?\182scht:
   * wireless herausgenommen. (Bleibt abzuwarten, wann es in IPCop 1.4.11 ist.)
 
 ------------------------------------------------------------------------
-r129 | ms | 2006-05-22 00:54:29 +0400 (Mon, 22 May 2006) | 11 lines
+r129 | ms | 2006-05-21 22:54:29 +0200 (Sun, 21 May 2006) | 11 lines
 
 Hinzugef?\195?\188gt:
   * Nochmal ein neues Shutdown-Bild.
@@ -2899,7 +3027,7 @@ Ge?\195?\164ndert:
   * S?\195?\164mtliche /var/ipcop durch /var/ipfire ersetzt.
 
 ------------------------------------------------------------------------
-r128 | ms | 2006-05-20 15:34:29 +0400 (Sat, 20 May 2006) | 8 lines
+r128 | ms | 2006-05-20 13:34:29 +0200 (Sat, 20 May 2006) | 8 lines
 
 Hinzugef?\195?\188gt:
   * Pakfire in die ISO gepackt. (Welche nocheinmal kleiner geworden ist.)
@@ -2910,19 +3038,19 @@ Gel?\195?\182scht:
   * Ein kleines ?\195?\156berbleibsel vom IPCop entfernt.
 
 ------------------------------------------------------------------------
-r127 | ms | 2006-05-20 13:34:19 +0400 (Sat, 20 May 2006) | 3 lines
+r127 | ms | 2006-05-20 11:34:19 +0200 (Sat, 20 May 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Erste Version des Pakfire von Peter
 
 ------------------------------------------------------------------------
-r126 | ms | 2006-05-19 18:29:15 +0400 (Fri, 19 May 2006) | 3 lines
+r126 | ms | 2006-05-19 16:29:15 +0200 (Fri, 19 May 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * ?\195?\156berfl?\195?\188ssige Programme aus der ISO genommen... Postfix, Stund usw...
 
 ------------------------------------------------------------------------
-r125 | ms | 2006-05-18 21:33:39 +0400 (Thu, 18 May 2006) | 5 lines
+r125 | ms | 2006-05-18 19:33:39 +0200 (Thu, 18 May 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * Fritz!PCI Treiber (auch SMP)
@@ -2930,13 +3058,13 @@ Ge?\195?\164ndert:
   * Postfix Konfiguration gek?\195?\188rzt
 
 ------------------------------------------------------------------------
-r124 | ms | 2006-05-18 15:39:26 +0400 (Thu, 18 May 2006) | 3 lines
+r124 | ms | 2006-05-18 13:39:26 +0200 (Thu, 18 May 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Erste Postfix-Standard-Konfiguration
 
 ------------------------------------------------------------------------
-r123 | ms | 2006-05-18 15:14:03 +0400 (Thu, 18 May 2006) | 7 lines
+r123 | ms | 2006-05-18 13:14:03 +0200 (Thu, 18 May 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Amavisd-new
@@ -2946,7 +3074,7 @@ Ge?\195?\164ndert:
   * ./make.sh make bearbeitet
 
 ------------------------------------------------------------------------
-r122 | ms | 2006-05-18 13:14:22 +0400 (Thu, 18 May 2006) | 10 lines
+r122 | ms | 2006-05-18 11:14:22 +0200 (Thu, 18 May 2006) | 10 lines
 
 Hinzugef?\195?\188gt:
   * Razor - Spamkiller
@@ -2959,26 +3087,26 @@ Ge?\195?\164ndert:
   * ChangeLog-Update
 
 ------------------------------------------------------------------------
-r121 | ms | 2006-05-17 21:04:11 +0400 (Wed, 17 May 2006) | 3 lines
+r121 | ms | 2006-05-17 19:04:11 +0200 (Wed, 17 May 2006) | 3 lines
 
 Hinzugef?\195?\188gt:
   * Procmail
 
 ------------------------------------------------------------------------
-r120 | ms | 2006-05-17 16:44:06 +0400 (Wed, 17 May 2006) | 4 lines
+r120 | ms | 2006-05-17 14:44:06 +0200 (Wed, 17 May 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * CyrusIMAPd auf den neuesten Stand gebracht.
   * Saslauthd ?\195?\188berarbeitet.
 
 ------------------------------------------------------------------------
-r119 | ms | 2006-05-17 15:25:29 +0400 (Wed, 17 May 2006) | 3 lines
+r119 | ms | 2006-05-17 13:25:29 +0200 (Wed, 17 May 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * Asterisk jetzt in der Version 1.2.7.1 mit Bristuff 0.3.0-PRE-1o und Florz-Patch
 
 ------------------------------------------------------------------------
-r118 | ms | 2006-05-16 15:12:49 +0400 (Tue, 16 May 2006) | 7 lines
+r118 | ms | 2006-05-16 13:12:49 +0200 (Tue, 16 May 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * NFS
@@ -2988,13 +3116,13 @@ Ge?\195?\164ndert:
   * ./make.sh commit optimiert
 
 ------------------------------------------------------------------------
-r117 | ms | 2006-05-16 15:01:06 +0400 (Tue, 16 May 2006) | 3 lines
+r117 | ms | 2006-05-16 13:01:06 +0200 (Tue, 16 May 2006) | 3 lines
 
 Quellenupdate u.a. wegen Serverausfall bei Sourceforge.net
 Wir haben die Absicht den Sourcecode auf eigenen Servern zu hosten!
 
 ------------------------------------------------------------------------
-r116 | ms | 2006-05-16 00:28:30 +0400 (Tue, 16 May 2006) | 5 lines
+r116 | ms | 2006-05-15 22:28:30 +0200 (Mon, 15 May 2006) | 5 lines
 
 Ge?\195?\164ndert:
   * ./make.sh dist noch optimiert.
@@ -3002,7 +3130,7 @@ Ge?\195?\164ndert:
   * ChangeLog-Update hat auch nicht funktioniert.
 
 ------------------------------------------------------------------------
-r115 | ms | 2006-05-16 00:08:54 +0400 (Tue, 16 May 2006) | 7 lines
+r115 | ms | 2006-05-15 22:08:54 +0200 (Mon, 15 May 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * TCP Wrappers f?\195?\188r NFS
@@ -3012,13 +3140,13 @@ Ge?\195?\164ndert:
   * Neue Prozedur in ./make.sh commit - L?\195?\164dt alles ins SVN und aktualisiert vorher den ChangeLog.
 
 ------------------------------------------------------------------------
-r114 | ms | 2006-05-13 21:54:40 +0400 (Sat, 13 May 2006) | 3 lines
+r114 | ms | 2006-05-13 19:54:40 +0200 (Sat, 13 May 2006) | 3 lines
 
 Ge?\195?\164ndert:
   * ./make.sh dist erstellt von jetzt an einen Tarball mit den letzten Sources im SVN.
 
 ------------------------------------------------------------------------
-r113 | ms | 2006-05-13 20:59:56 +0400 (Sat, 13 May 2006) | 12 lines
+r113 | ms | 2006-05-13 18:59:56 +0200 (Sat, 13 May 2006) | 12 lines
 
 Hinzugef?\195?\188gt:
   * Clamav - Antivirus
@@ -3033,13 +3161,13 @@ Ge?\195?\164ndert:
   * Kernel schonmal angepasst f?\195?\188r NFS, noch nicht getestet!!
 
 ------------------------------------------------------------------------
-r112 | ms | 2006-05-04 14:50:41 +0400 (Thu, 04 May 2006) | 3 lines
+r112 | ms | 2006-05-04 12:50:41 +0200 (Thu, 04 May 2006) | 3 lines
 
 Haupts?\195?\164chlich Quellenupdate. Apache - Bind - hddtemp - hdparm - lame
 Ghostscript und CUPS aktiviert. Samba jetzt mit libcups-Support.
 
 ------------------------------------------------------------------------
-r111 | ms | 2006-05-04 14:48:33 +0400 (Thu, 04 May 2006) | 5 lines
+r111 | ms | 2006-05-04 12:48:33 +0200 (Thu, 04 May 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
   * Patch f?\195?\188r MPG123
@@ -3047,7 +3175,7 @@ Ge?\195?\164ndert:
   * CUPS
 
 ------------------------------------------------------------------------
-r110 | ms | 2006-05-03 00:19:59 +0400 (Wed, 03 May 2006) | 7 lines
+r110 | ms | 2006-05-02 22:19:59 +0200 (Tue, 02 May 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * mpg123 - F?\195?\188r Wartemusik im Asterisk
@@ -3057,24 +3185,24 @@ Hinzugef?\195?\188gt:
   * lame - Braucht GNUmp3d
 
 ------------------------------------------------------------------------
-r109 | ms | 2006-05-02 10:06:43 +0400 (Tue, 02 May 2006) | 4 lines
+r109 | ms | 2006-05-02 08:06:43 +0200 (Tue, 02 May 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * Samba wird jetzt ohne Dokumentation installiert
   * Gettoolchain repariert
 
 ------------------------------------------------------------------------
-r108 | ms | 2006-05-01 23:47:04 +0400 (Mon, 01 May 2006) | 2 lines
+r108 | ms | 2006-05-01 21:47:04 +0200 (Mon, 01 May 2006) | 2 lines
 
 Quellenupdate! wireless, ntp, shadow, uClibc
 
 ------------------------------------------------------------------------
-r107 | ms | 2006-05-01 23:02:50 +0400 (Mon, 01 May 2006) | 2 lines
+r107 | ms | 2006-05-01 21:02:50 +0200 (Mon, 01 May 2006) | 2 lines
 
 EmbCop-Sources gel?\195?\182scht!
 
 ------------------------------------------------------------------------
-r106 | ms | 2006-04-28 18:57:32 +0400 (Fri, 28 Apr 2006) | 7 lines
+r106 | ms | 2006-04-28 16:57:32 +0200 (Fri, 28 Apr 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * fetchmail
@@ -3084,7 +3212,7 @@ Ge?\195?\164ndert:
   * pam
 
 ------------------------------------------------------------------------
-r105 | ms | 2006-04-20 18:20:28 +0400 (Thu, 20 Apr 2006) | 7 lines
+r105 | ms | 2006-04-20 16:20:28 +0200 (Thu, 20 Apr 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Sane - Scanning
@@ -3094,19 +3222,19 @@ Ge?\195?\164ndert:
   * xinetd
 
 ------------------------------------------------------------------------
-r104 | ms | 2006-04-20 18:15:50 +0400 (Thu, 20 Apr 2006) | 2 lines
+r104 | ms | 2006-04-20 16:15:50 +0200 (Thu, 20 Apr 2006) | 2 lines
 
 Allgemeine Aufr?\195?\164umarbeiten und Optimierungen
 
 ------------------------------------------------------------------------
-r103 | ms | 2006-04-19 20:02:55 +0400 (Wed, 19 Apr 2006) | 4 lines
+r103 | ms | 2006-04-19 18:02:55 +0200 (Wed, 19 Apr 2006) | 4 lines
 
 Ge?\195?\164ndert:
   * pwlib wird bei jedem Durchgang kompiliert, auch wenn schon geschehen :(
   * Mirror-URL ge?\195?\164ndert
 
 ------------------------------------------------------------------------
-r102 | ms | 2006-04-19 17:30:44 +0400 (Wed, 19 Apr 2006) | 9 lines
+r102 | ms | 2006-04-19 15:30:44 +0200 (Wed, 19 Apr 2006) | 9 lines
 
 Ge?\195?\164ndert:
   * Asterisk mit H323
@@ -3118,7 +3246,7 @@ Fixed:
   * Men?\195?\188 im Webinterface
 
 ------------------------------------------------------------------------
-r101 | ms | 2006-04-15 03:12:47 +0400 (Sat, 15 Apr 2006) | 10 lines
+r101 | ms | 2006-04-15 01:12:47 +0200 (Sat, 15 Apr 2006) | 10 lines
 
 Hinzugef?\195?\188gt:
   * Asterisk - mit Zaptel/LibPRI/BRISTUFF/app_fax
@@ -3131,7 +3259,7 @@ Ge?\195?\164ndert:
   * postfix hat Beta-Status-1
 
 ------------------------------------------------------------------------
-r100 | ms | 2006-04-11 02:33:24 +0400 (Tue, 11 Apr 2006) | 6 lines
+r100 | ms | 2006-04-11 00:33:24 +0200 (Tue, 11 Apr 2006) | 6 lines
 
 Hinzugef?\195?\188gt:
   * Samba - Erste Test-Version
@@ -3140,26 +3268,26 @@ Ge?\195?\164ndert:
   * Linux-PAM - Libs waren falsch verlinkt
 
 ------------------------------------------------------------------------
-r99 | casemaster | 2006-04-11 01:10:53 +0400 (Tue, 11 Apr 2006) | 2 lines
+r99 | casemaster | 2006-04-10 23:10:53 +0200 (Mon, 10 Apr 2006) | 2 lines
 
 pwlib ge?\195?\164ndert.
 busybox: tar.c gr?\195?\182?\195?\159e auf 150 gesetzt.
 ------------------------------------------------------------------------
-r98 | ms | 2006-04-10 22:39:59 +0400 (Mon, 10 Apr 2006) | 4 lines
+r98 | ms | 2006-04-10 20:39:59 +0200 (Mon, 10 Apr 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * Xinetd - Super-Daemon
   * Sudo
 
 ------------------------------------------------------------------------
-r97 | ms | 2006-04-10 00:23:54 +0400 (Mon, 10 Apr 2006) | 4 lines
+r97 | ms | 2006-04-09 22:23:54 +0200 (Sun, 09 Apr 2006) | 4 lines
 
 Hinzugef?\195?\188gt:
   * OpenVPN
   * LZO
 
 ------------------------------------------------------------------------
-r96 | ms | 2006-04-09 21:55:27 +0400 (Sun, 09 Apr 2006) | 7 lines
+r96 | ms | 2006-04-09 19:55:27 +0200 (Sun, 09 Apr 2006) | 7 lines
 
 Hinzugef?\195?\188gt:
   * Midnight Commander 4.6.1 (GLIB/PKG-CONFIG)
@@ -3169,17 +3297,17 @@ Ge?\195?\164ndert:
   * make-packages - Funktionen erweitert
 
 ------------------------------------------------------------------------
-r95 | ms | 2006-04-04 21:19:54 +0400 (Tue, 04 Apr 2006) | 2 lines
+r95 | ms | 2006-04-04 19:19:54 +0200 (Tue, 04 Apr 2006) | 2 lines
 
 Kleine Fixes an den Graphs und dem Men?\195?\188!
 
 ------------------------------------------------------------------------
-r94 | casemaster | 2006-04-02 16:18:42 +0400 (Sun, 02 Apr 2006) | 2 lines
+r94 | casemaster | 2006-04-02 14:18:42 +0200 (Sun, 02 Apr 2006) | 2 lines
 
 src fuer openldap geaendert.
 ldap Unterstuetzung bei pwlib entfernt.
 ------------------------------------------------------------------------
-r93 | ms | 2006-03-28 22:54:43 +0400 (Tue, 28 Mar 2006) | 5 lines
+r93 | ms | 2006-03-28 20:54:43 +0200 (Tue, 28 Mar 2006) | 5 lines
 
 Hinzugef?\195?\188gt:
     * OpenLDAP
@@ -3187,39 +3315,39 @@ Ge?\195?\164ndert:
     * SASLAUTHD kann jetzt OpenLDAP.
 
 ------------------------------------------------------------------------
-r92 | ms | 2006-03-28 19:35:56 +0400 (Tue, 28 Mar 2006) | 2 lines
+r92 | ms | 2006-03-28 17:35:56 +0200 (Tue, 28 Mar 2006) | 2 lines
 
 Allgemeine FIXES! Das Build sollte nun durchlaufen...
 
 ------------------------------------------------------------------------
-r91 | ms | 2006-03-28 18:16:15 +0400 (Tue, 28 Mar 2006) | 1 line
+r91 | ms | 2006-03-28 16:16:15 +0200 (Tue, 28 Mar 2006) | 1 line
 
 SASL-Authd nun ohne PostgreSQL-Support.
 ------------------------------------------------------------------------
-r90 | ms | 2006-03-27 23:50:44 +0400 (Mon, 27 Mar 2006) | 1 line
+r90 | ms | 2006-03-27 21:50:44 +0200 (Mon, 27 Mar 2006) | 1 line
 
 URL von den Bridge-Utils gefixt.
 ------------------------------------------------------------------------
-r89 | casemaster | 2006-03-27 19:06:13 +0400 (Mon, 27 Mar 2006) | 1 line
+r89 | casemaster | 2006-03-27 17:06:13 +0200 (Mon, 27 Mar 2006) | 1 line
 
 Test gel?\195?\182scht.
 ------------------------------------------------------------------------
-r88 | ms | 2006-03-27 18:43:30 +0400 (Mon, 27 Mar 2006) | 3 lines
+r88 | ms | 2006-03-27 16:43:30 +0200 (Mon, 27 Mar 2006) | 3 lines
 
 Toolchain-Download mit ./make.sh gettoolchain
 Beim Netstatus werden ab jetzt nur noch aktive Verbindungen angezeigt. Erh?\195?\182ht die ?\195?\156bersichtlichkeit...
 
 ------------------------------------------------------------------------
-r87 | casemaster | 2006-03-27 18:35:38 +0400 (Mon, 27 Mar 2006) | 1 line
+r87 | casemaster | 2006-03-27 16:35:38 +0200 (Mon, 27 Mar 2006) | 1 line
 
 Test 2 Write
 ------------------------------------------------------------------------
-r86 | ms | 2006-03-27 18:02:24 +0400 (Mon, 27 Mar 2006) | 2 lines
+r86 | ms | 2006-03-27 16:02:24 +0200 (Mon, 27 Mar 2006) | 2 lines
 
 Repariert: lib-links f?\195?\188r postfix
 
 ------------------------------------------------------------------------
-r85 | ms | 2006-03-26 22:46:32 +0400 (Sun, 26 Mar 2006) | 5 lines
+r85 | ms | 2006-03-26 20:46:32 +0200 (Sun, 26 Mar 2006) | 5 lines
 
 Update Squid to 2.5STABLE13.
 Added WGET/HDDTEMP/BRIDGE-UTILS.
@@ -3227,18 +3355,18 @@ SCSI-GRUB-Konfiguration angepasst.
 
 
 ------------------------------------------------------------------------
-r84 | ms | 2006-03-25 18:06:35 +0300 (Sat, 25 Mar 2006) | 4 lines
+r84 | ms | 2006-03-25 16:06:35 +0100 (Sat, 25 Mar 2006) | 4 lines
 
 Erste Version des Paketerstellers.
 Bisher nur Postfix. :(
 
 
 ------------------------------------------------------------------------
-r83 | guest | 2006-03-24 18:47:00 +0300 (Fri, 24 Mar 2006) | 1 line
+r83 | guest | 2006-03-24 16:47:00 +0100 (Fri, 24 Mar 2006) | 1 line
 
 nomsg
 ------------------------------------------------------------------------
-r82 | ms | 2006-03-22 22:11:17 +0300 (Wed, 22 Mar 2006) | 8 lines
+r82 | ms | 2006-03-22 20:11:17 +0100 (Wed, 22 Mar 2006) | 8 lines
 
 Webinterface gefixt.
 Ohne Anmeldung kommt man im Webinterface nichtmehr auf die Index-Seite.
@@ -3249,15 +3377,15 @@ IPCop-Updates gel?\195?\182scht.
 
 
 ------------------------------------------------------------------------
-r81 | ms | 2006-03-18 14:24:42 +0300 (Sat, 18 Mar 2006) | 1 line
+r81 | ms | 2006-03-18 12:24:42 +0100 (Sat, 18 Mar 2006) | 1 line
 
 Quellenupdate
 ------------------------------------------------------------------------
-r80 | ms | 2006-03-17 03:46:51 +0300 (Fri, 17 Mar 2006) | 1 line
+r80 | ms | 2006-03-17 01:46:51 +0100 (Fri, 17 Mar 2006) | 1 line
 
 TEMP-DIR von /tmp nach /var/tmp verschoben.
 ------------------------------------------------------------------------
-r79 | ms | 2006-03-13 00:09:13 +0300 (Mon, 13 Mar 2006) | 11 lines
+r79 | ms | 2006-03-12 22:09:13 +0100 (Sun, 12 Mar 2006) | 11 lines
 
 Hinzugef?\195?\188gt:
     * Postfix 2.2.9
@@ -3271,128 +3399,128 @@ Gefixt und neu implementiert:
 leichtes aufr?\195?\164umen in der make.sh
 
 ------------------------------------------------------------------------
-r78 | ms | 2006-03-12 18:52:13 +0300 (Sun, 12 Mar 2006) | 1 line
+r78 | ms | 2006-03-12 16:52:13 +0100 (Sun, 12 Mar 2006) | 1 line
 
 New Webinterface-Style by benne
 ------------------------------------------------------------------------
-r77 | ms | 2006-03-06 17:30:36 +0300 (Mon, 06 Mar 2006) | 1 line
+r77 | ms | 2006-03-06 15:30:36 +0100 (Mon, 06 Mar 2006) | 1 line
 
 Webinterface-Bilder neu gemacht | IPAC-NG-Patches installiert | Berkeley-DB installiert
 ------------------------------------------------------------------------
-r76 | ms | 2006-03-02 23:55:58 +0300 (Thu, 02 Mar 2006) | 1 line
+r76 | ms | 2006-03-02 21:55:58 +0100 (Thu, 02 Mar 2006) | 1 line
 
 PAM-MySQL + BerkeleyDB + SASLauthd hinzugefuegt
 ------------------------------------------------------------------------
-r75 | ms | 2006-03-01 00:11:50 +0300 (Wed, 01 Mar 2006) | 1 line
+r75 | ms | 2006-02-28 22:11:50 +0100 (Tue, 28 Feb 2006) | 1 line
 
 ROOTFILES.i386 aufger?\195?\164umt
 ------------------------------------------------------------------------
-r74 | ms | 2006-03-01 00:10:58 +0300 (Wed, 01 Mar 2006) | 1 line
+r74 | ms | 2006-02-28 22:10:58 +0100 (Tue, 28 Feb 2006) | 1 line
 
 ISO verg?\195?\182?\195?\159ert und XAMPP-1.5.1 DEVEL Paket installiert
 ------------------------------------------------------------------------
-r73 | ms | 2006-02-27 23:13:17 +0300 (Mon, 27 Feb 2006) | 2 lines
+r73 | ms | 2006-02-27 21:13:17 +0100 (Mon, 27 Feb 2006) | 2 lines
 
 Quellenupdate... ipaddr busybox kernel
 
 ------------------------------------------------------------------------
-r72 | ms | 2006-02-27 20:13:57 +0300 (Mon, 27 Feb 2006) | 2 lines
+r72 | ms | 2006-02-27 18:13:57 +0100 (Mon, 27 Feb 2006) | 2 lines
 
 OpenH323 hinzugef?\195?\188gt
 
 ------------------------------------------------------------------------
-r71 | ms | 2006-02-22 23:23:30 +0300 (Wed, 22 Feb 2006) | 1 line
+r71 | ms | 2006-02-22 21:23:30 +0100 (Wed, 22 Feb 2006) | 1 line
 
 IPAC-NG ging nicht... mal sehen
 ------------------------------------------------------------------------
-r70 | ms | 2006-02-22 23:21:51 +0300 (Wed, 22 Feb 2006) | 1 line
+r70 | ms | 2006-02-22 21:21:51 +0100 (Wed, 22 Feb 2006) | 1 line
 
 ROOTFILES aktualisiert
 ------------------------------------------------------------------------
-r69 | ms | 2006-02-22 22:52:10 +0300 (Wed, 22 Feb 2006) | 1 line
+r69 | ms | 2006-02-22 20:52:10 +0100 (Wed, 22 Feb 2006) | 1 line
 
 Endlich neues Webinterface
 ------------------------------------------------------------------------
-r68 | ms | 2006-02-22 00:26:55 +0300 (Wed, 22 Feb 2006) | 2 lines
+r68 | ms | 2006-02-21 22:26:55 +0100 (Tue, 21 Feb 2006) | 2 lines
 
 SSH von vornherein aktiviert
 
 ------------------------------------------------------------------------
-r67 | ms | 2006-02-21 23:38:06 +0300 (Tue, 21 Feb 2006) | 2 lines
+r67 | ms | 2006-02-21 21:38:06 +0100 (Tue, 21 Feb 2006) | 2 lines
 
 SMP-Config angepasst.. CGIs usw. wurden im Windoof-Format gespeichert... muss noch alles korrigiert werden...
 
 ------------------------------------------------------------------------
-r66 | ms | 2006-02-21 21:55:53 +0300 (Tue, 21 Feb 2006) | 1 line
+r66 | ms | 2006-02-21 19:55:53 +0100 (Tue, 21 Feb 2006) | 1 line
 
 immernoch das alte Problem...
 ------------------------------------------------------------------------
-r65 | ms | 2006-02-21 19:55:11 +0300 (Tue, 21 Feb 2006) | 1 line
+r65 | ms | 2006-02-21 17:55:11 +0100 (Tue, 21 Feb 2006) | 1 line
 
 EmbCop-V0.1-1.4.10 in branches eingef?\195?\188gt
 ------------------------------------------------------------------------
-r64 | ms | 2006-02-21 00:23:51 +0300 (Tue, 21 Feb 2006) | 2 lines
+r64 | ms | 2006-02-20 22:23:51 +0100 (Mon, 20 Feb 2006) | 2 lines
 
 Kernel Config f?\195?\188r SMP angepasst...
 
 ------------------------------------------------------------------------
-r63 | ms | 2006-02-20 23:46:53 +0300 (Mon, 20 Feb 2006) | 2 lines
+r63 | ms | 2006-02-20 21:46:53 +0100 (Mon, 20 Feb 2006) | 2 lines
 
 Windows hat sie wieder zerschossen... :(
 
 ------------------------------------------------------------------------
-r62 | ms | 2006-02-20 23:13:28 +0300 (Mon, 20 Feb 2006) | 1 line
+r62 | ms | 2006-02-20 21:13:28 +0100 (Mon, 20 Feb 2006) | 1 line
 
 SMP wieder aktiviert (Zumindest versucht)
 ------------------------------------------------------------------------
-r61 | ms | 2006-02-20 23:01:45 +0300 (Mon, 20 Feb 2006) | 1 line
+r61 | ms | 2006-02-20 21:01:45 +0100 (Mon, 20 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r60 | ms | 2006-02-20 23:01:31 +0300 (Mon, 20 Feb 2006) | 1 line
+r60 | ms | 2006-02-20 21:01:31 +0100 (Mon, 20 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r59 | ms | 2006-02-20 22:57:20 +0300 (Mon, 20 Feb 2006) | 1 line
+r59 | ms | 2006-02-20 20:57:20 +0100 (Mon, 20 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r58 | ms | 2006-02-20 22:56:37 +0300 (Mon, 20 Feb 2006) | 1 line
+r58 | ms | 2006-02-20 20:56:37 +0100 (Mon, 20 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r57 | ms | 2006-02-20 22:55:36 +0300 (Mon, 20 Feb 2006) | 1 line
+r57 | ms | 2006-02-20 20:55:36 +0100 (Mon, 20 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r56 | ms | 2006-02-20 22:51:27 +0300 (Mon, 20 Feb 2006) | 1 line
+r56 | ms | 2006-02-20 20:51:27 +0100 (Mon, 20 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r55 | ms | 2006-02-20 22:50:08 +0300 (Mon, 20 Feb 2006) | 1 line
+r55 | ms | 2006-02-20 20:50:08 +0100 (Mon, 20 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r54 | ms | 2006-02-20 22:49:08 +0300 (Mon, 20 Feb 2006) | 2 lines
+r54 | ms | 2006-02-20 20:49:08 +0100 (Mon, 20 Feb 2006) | 2 lines
 
 Sicherheits-Update packages-list
 
 ------------------------------------------------------------------------
-r53 | ms | 2006-02-20 04:46:27 +0300 (Mon, 20 Feb 2006) | 2 lines
+r53 | ms | 2006-02-20 02:46:27 +0100 (Mon, 20 Feb 2006) | 2 lines
 
 driver.img ohne SMP
 
 ------------------------------------------------------------------------
-r52 | ms | 2006-02-20 04:39:21 +0300 (Mon, 20 Feb 2006) | 2 lines
+r52 | ms | 2006-02-20 02:39:21 +0100 (Mon, 20 Feb 2006) | 2 lines
 
 GD und gd Konflikt gel?\195?\182st...
 make.sh zerst?\195?\182rt :(
 ------------------------------------------------------------------------
-r51 | ms | 2006-02-20 04:32:51 +0300 (Mon, 20 Feb 2006) | 1 line
+r51 | ms | 2006-02-20 02:32:51 +0100 (Mon, 20 Feb 2006) | 1 line
 
 Removed file/folder gd
 ------------------------------------------------------------------------
-r50 | ms | 2006-02-20 04:10:06 +0300 (Mon, 20 Feb 2006) | 5 lines
+r50 | ms | 2006-02-20 02:10:06 +0100 (Mon, 20 Feb 2006) | 5 lines
 
 ipac-ng fix
 uClibc fix
@@ -3400,205 +3528,205 @@ pam-patch fix
 
 
 ------------------------------------------------------------------------
-r49 | ms | 2006-02-20 01:25:48 +0300 (Mon, 20 Feb 2006) | 2 lines
+r49 | ms | 2006-02-19 23:25:48 +0100 (Sun, 19 Feb 2006) | 2 lines
 
 SMP entfernt / gd hinzugef?\195?\188gt!
 
 ------------------------------------------------------------------------
-r48 | ms | 2006-02-19 20:04:08 +0300 (Sun, 19 Feb 2006) | 2 lines
+r48 | ms | 2006-02-19 18:04:08 +0100 (Sun, 19 Feb 2006) | 2 lines
 
 Quellen-Update
 
 ------------------------------------------------------------------------
-r47 | ms | 2006-02-19 17:12:52 +0300 (Sun, 19 Feb 2006) | 1 line
+r47 | ms | 2006-02-19 15:12:52 +0100 (Sun, 19 Feb 2006) | 1 line
 
 Neuer Boot-Screen f?\195?\188r GRUB
 ------------------------------------------------------------------------
-r46 | ms | 2006-02-19 16:16:13 +0300 (Sun, 19 Feb 2006) | 2 lines
+r46 | ms | 2006-02-19 14:16:13 +0100 (Sun, 19 Feb 2006) | 2 lines
 
 Installer repariert
 
 ------------------------------------------------------------------------
-r45 | ms | 2006-02-19 16:12:53 +0300 (Sun, 19 Feb 2006) | 2 lines
+r45 | ms | 2006-02-19 14:12:53 +0100 (Sun, 19 Feb 2006) | 2 lines
 
 Installer repariert
 
 ------------------------------------------------------------------------
-r44 | ms | 2006-02-19 15:19:49 +0300 (Sun, 19 Feb 2006) | 2 lines
+r44 | ms | 2006-02-19 13:19:49 +0100 (Sun, 19 Feb 2006) | 2 lines
 
 make.sh gefixt
 
 ------------------------------------------------------------------------
-r43 | ms | 2006-02-19 15:01:48 +0300 (Sun, 19 Feb 2006) | 1 line
+r43 | ms | 2006-02-19 13:01:48 +0100 (Sun, 19 Feb 2006) | 1 line
 
 IPCOP SOURCE Version 1.4.10 hinzugef?\195?\188gt
 ------------------------------------------------------------------------
-r42 | ms | 2006-02-19 14:34:16 +0300 (Sun, 19 Feb 2006) | 1 line
+r42 | ms | 2006-02-19 12:34:16 +0100 (Sun, 19 Feb 2006) | 1 line
 
 Renamed File
 ------------------------------------------------------------------------
-r41 | ms | 2006-02-19 14:25:43 +0300 (Sun, 19 Feb 2006) | 2 lines
+r41 | ms | 2006-02-19 12:25:43 +0100 (Sun, 19 Feb 2006) | 2 lines
 
 Port 445 -> 444 gewechselt und XTAccess-Regeln ausgeschaltet.
 Nach der Installation sind alle Ports geschlossen!
 ------------------------------------------------------------------------
-r40 | ms | 2006-02-19 00:39:37 +0300 (Sun, 19 Feb 2006) | 1 line
+r40 | ms | 2006-02-18 22:39:37 +0100 (Sat, 18 Feb 2006) | 1 line
 
 Ordnerstruktur 3. Teil 
 ------------------------------------------------------------------------
-r39 | ms | 2006-02-19 00:33:11 +0300 (Sun, 19 Feb 2006) | 1 line
+r39 | ms | 2006-02-18 22:33:11 +0100 (Sat, 18 Feb 2006) | 1 line
 
 Ordnerstruktur 2-ter Teil
 ------------------------------------------------------------------------
-r38 | ms | 2006-02-19 00:26:02 +0300 (Sun, 19 Feb 2006) | 1 line
+r38 | ms | 2006-02-18 22:26:02 +0100 (Sat, 18 Feb 2006) | 1 line
 
 Vern?\195?\188nftige Ordnerstruktur
 ------------------------------------------------------------------------
-r37 | ms | 2006-02-17 00:18:00 +0300 (Fri, 17 Feb 2006) | 1 line
+r37 | ms | 2006-02-16 22:18:00 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Neuer Installer eingef?\195?\188gt...
 ------------------------------------------------------------------------
-r36 | ms | 2006-02-16 22:20:41 +0300 (Thu, 16 Feb 2006) | 1 line
+r36 | ms | 2006-02-16 20:20:41 +0100 (Thu, 16 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r35 | ms | 2006-02-16 22:09:00 +0300 (Thu, 16 Feb 2006) | 1 line
+r35 | ms | 2006-02-16 20:09:00 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r34 | ms | 2006-02-16 22:07:58 +0300 (Thu, 16 Feb 2006) | 1 line
+r34 | ms | 2006-02-16 20:07:58 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Renamed remotely
 ------------------------------------------------------------------------
-r33 | admin | 2006-02-16 22:04:42 +0300 (Thu, 16 Feb 2006) | 1 line
+r33 | admin | 2006-02-16 20:04:42 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r32 | admin | 2006-02-16 22:04:37 +0300 (Thu, 16 Feb 2006) | 1 line
+r32 | admin | 2006-02-16 20:04:37 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r31 | ipfire | 2006-02-16 15:20:54 +0300 (Thu, 16 Feb 2006) | 1 line
+r31 | ipfire | 2006-02-16 13:20:54 +0100 (Thu, 16 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r30 | ipfire | 2006-02-16 15:18:34 +0300 (Thu, 16 Feb 2006) | 1 line
+r30 | ipfire | 2006-02-16 13:18:34 +0100 (Thu, 16 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r29 | ipfire | 2006-02-16 15:18:15 +0300 (Thu, 16 Feb 2006) | 1 line
+r29 | ipfire | 2006-02-16 13:18:15 +0100 (Thu, 16 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r28 | ipfire | 2006-02-16 15:09:46 +0300 (Thu, 16 Feb 2006) | 1 line
+r28 | ipfire | 2006-02-16 13:09:46 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r27 | ipfire | 2006-02-16 15:07:28 +0300 (Thu, 16 Feb 2006) | 1 line
+r27 | ipfire | 2006-02-16 13:07:28 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Removed Files
 ------------------------------------------------------------------------
-r26 | ipfire | 2006-02-16 15:06:41 +0300 (Thu, 16 Feb 2006) | 1 line
+r26 | ipfire | 2006-02-16 13:06:41 +0100 (Thu, 16 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r25 | ipfire | 2006-02-16 00:36:29 +0300 (Thu, 16 Feb 2006) | 1 line
+r25 | ipfire | 2006-02-15 22:36:29 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r24 | ipfire | 2006-02-16 00:36:15 +0300 (Thu, 16 Feb 2006) | 1 line
+r24 | ipfire | 2006-02-15 22:36:15 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r23 | ipfire | 2006-02-16 00:35:46 +0300 (Thu, 16 Feb 2006) | 1 line
+r23 | ipfire | 2006-02-15 22:35:46 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r22 | ipfire | 2006-02-16 00:33:28 +0300 (Thu, 16 Feb 2006) | 1 line
+r22 | ipfire | 2006-02-15 22:33:28 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Renamed remotely
 ------------------------------------------------------------------------
-r21 | ipfire | 2006-02-16 00:33:06 +0300 (Thu, 16 Feb 2006) | 1 line
+r21 | ipfire | 2006-02-15 22:33:06 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r20 | ipfire | 2006-02-16 00:32:33 +0300 (Thu, 16 Feb 2006) | 1 line
+r20 | ipfire | 2006-02-15 22:32:33 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r19 | ipfire | 2006-02-16 00:31:56 +0300 (Thu, 16 Feb 2006) | 1 line
+r19 | ipfire | 2006-02-15 22:31:56 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r18 | ipfire | 2006-02-16 00:31:26 +0300 (Thu, 16 Feb 2006) | 1 line
+r18 | ipfire | 2006-02-15 22:31:26 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r17 | ipfire | 2006-02-16 00:31:06 +0300 (Thu, 16 Feb 2006) | 1 line
+r17 | ipfire | 2006-02-15 22:31:06 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r16 | ipfire | 2006-02-16 00:15:54 +0300 (Thu, 16 Feb 2006) | 1 line
+r16 | ipfire | 2006-02-15 22:15:54 +0100 (Wed, 15 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r15 | ipfire | 2006-02-16 00:21:38 +0300 (Thu, 16 Feb 2006) | 1 line
+r15 | ipfire | 2006-02-15 22:21:38 +0100 (Wed, 15 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r14 | ipfire | 2006-02-16 00:07:30 +0300 (Thu, 16 Feb 2006) | 1 line
+r14 | ipfire | 2006-02-15 22:07:30 +0100 (Wed, 15 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r13 | ipfire | 2006-02-15 13:46:10 +0300 (Wed, 15 Feb 2006) | 1 line
+r13 | ipfire | 2006-02-15 11:46:10 +0100 (Wed, 15 Feb 2006) | 1 line
 
 
 ------------------------------------------------------------------------
-r12 | ipfire | 2006-02-15 13:31:15 +0300 (Wed, 15 Feb 2006) | 1 line
+r12 | ipfire | 2006-02-15 11:31:15 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Created folder remotely
 ------------------------------------------------------------------------
-r11 | ipfire | 2006-02-15 13:28:40 +0300 (Wed, 15 Feb 2006) | 1 line
+r11 | ipfire | 2006-02-15 11:28:40 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r10 | ipfire | 2006-02-15 13:27:18 +0300 (Wed, 15 Feb 2006) | 1 line
+r10 | ipfire | 2006-02-15 11:27:18 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Added a folder remotely
 ------------------------------------------------------------------------
-r9 | ipfire | 2006-02-15 13:26:47 +0300 (Wed, 15 Feb 2006) | 1 line
+r9 | ipfire | 2006-02-15 11:26:47 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Moved remotely
 ------------------------------------------------------------------------
-r8 | ipfire | 2006-02-15 13:26:18 +0300 (Wed, 15 Feb 2006) | 1 line
+r8 | ipfire | 2006-02-15 11:26:18 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Added a folder remotely
 ------------------------------------------------------------------------
-r7 | ipfire | 2006-02-15 13:25:16 +0300 (Wed, 15 Feb 2006) | 1 line
+r7 | ipfire | 2006-02-15 11:25:16 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Added a file remotely
 ------------------------------------------------------------------------
-r6 | ipfire | 2006-02-15 13:24:03 +0300 (Wed, 15 Feb 2006) | 1 line
+r6 | ipfire | 2006-02-15 11:24:03 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Added a folder remotely
 ------------------------------------------------------------------------
-r5 | ipfire | 2006-02-15 12:27:58 +0300 (Wed, 15 Feb 2006) | 1 line
+r5 | ipfire | 2006-02-15 10:27:58 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Removed file/folder
 ------------------------------------------------------------------------
-r4 | ipfire | 2006-02-15 12:27:47 +0300 (Wed, 15 Feb 2006) | 1 line
+r4 | ipfire | 2006-02-15 10:27:47 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Created folder remotely
 ------------------------------------------------------------------------
-r3 | admin | 2006-02-15 03:27:59 +0300 (Wed, 15 Feb 2006) | 1 line
+r3 | admin | 2006-02-15 01:27:59 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Ordner im Projektarchiv angelegt
 ------------------------------------------------------------------------
-r2 | admin | 2006-02-15 03:14:05 +0300 (Wed, 15 Feb 2006) | 1 line
+r2 | admin | 2006-02-15 01:14:05 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Ordner im Projektarchiv angelegt
 ------------------------------------------------------------------------
-r1 | admin | 2006-02-15 03:13:56 +0300 (Wed, 15 Feb 2006) | 1 line
+r1 | admin | 2006-02-15 01:13:56 +0100 (Wed, 15 Feb 2006) | 1 line
 
 Ordner im Projektarchiv angelegt
 ------------------------------------------------------------------------
index 4b87f4f5236c5a07938ec396061fb7f9759b0185..2e4463166f097de026507865cc36730400616f14 100644 (file)
 * openldap-2.3.20
 * openssh-4.3p2
 * openssl-0.9.8d
-* openswan-2.5.13
+* openswan-2.4.8
 * openvpn-2.0.9
 * pam_mysql-0.7RC1
 * patch-2.5.4
index e2670f7b629c5aa688208276435cf5621d47a3a4..4b09246b73ab3c3d63e0483bc612d52640541281 100644 (file)
--- a/lfs/ipp2p
+++ b/lfs/ipp2p
@@ -69,12 +69,12 @@ ifeq "$(SMP)" "1"
        cp -f $(DIR_APP)/ipt_ipp2p.ko /lib/modules/$(KVER)-ipfire-smp/kernel/net/ipv4/netfilter
 else
 ifeq "$(IPT)" "1"
-       cd $(DIR_APP) && make
-       cp -f $(DIR_APP)/libipt_ipp2p.o /lib/iptables
+       cd $(DIR_APP) && make libipt_ipp2p.so
+       cp -f $(DIR_APP)/libipt_ipp2p.so /lib/iptables
 else
        cd $(DIR_APP) && make ipt_ipp2p.ko
        cp -f $(DIR_APP)/ipt_ipp2p.ko /lib/modules/$(KVER)-ipfire/kernel/net/ipv4/netfilter
 endif
 endif
-       @rm -rf $(DIR_APP) $(DIR_SRC)/iptables-*
+       @rm -rf $(DIR_APP) $(DIR_SRC)/iptables*
        @$(POSTBUILD)
index c55f57b74919f443095cb421dc11fcea24de7f2c..ff7a4602d22f1ae511ef7da88229f9b14635ec76 100644 (file)
--- a/lfs/linux
+++ b/lfs/linux
@@ -59,7 +59,7 @@ objects =$(DL_FILE) \
        patch-o-matic-ng-20061210.tar.bz2 \
        netfilter-layer7-v2.9.tar.gz \
        patch-2.6.16-nath323-1.3.bz2 \
-       openswan-2.5.13.tar.gz
+       openswan-2.4.8.tar.gz
 
 $(DL_FILE)                                                                                             = $(URL_IPFIRE)/$(DL_FILE)
 patch-o-matic-ng-20061210.tar.bz2      = $(URL_IPFIRE)/patch-o-matic-ng-20061210.tar.bz2
@@ -68,7 +68,7 @@ netfilter-layer7-v2.9.tar.gz                  = $(URL_IPFIRE)/netfilter-layer7-v2.9.tar.gz
 patch-2.6.16-nath323-1.3.bz2                   = $(URL_IPFIRE)/patch-2.6.16-nath323-1.3.bz2
 squashfs3.2-r2.tar.gz                                                  = $(URL_IPFIRE)/squashfs3.2-r2.tar.gz
 mISDN-1_1_3.tar.gz                = $(URL_IPFIRE)/mISDN-1_1_3.tar.gz
-openswan-2.5.13.tar.gz                                         = $(URL_IPFIRE)/openswan-2.5.13.tar.gz
+openswan-2.4.8.tar.gz                                                  = $(URL_IPFIRE)/openswan-2.4.8.tar.gz
 
 $(DL_FILE)_MD5                                                                         = cc2106c6188675187d636aa518b04958
 linux-2.6.16.33.tar.bz2_MD5                            = 22f56e3a5e7524b2bbde2696152b5ad7
@@ -78,7 +78,7 @@ netfilter-layer7-v2.9.tar.gz_MD5      = ebf9043a5352ebe6dbd721989ef83dee
 patch-2.6.16-nath323-1.3.bz2_MD5       = f926409ff703a307baf54b57ab75d138
 squashfs3.2-r2.tar.gz_MD5                                      = bf360b92eba9e6d5610196ce2e02fcd1
 mISDN-1_1_3.tar.gz_MD5           = d29bcf48f16fc8a9b9f3552d111b308d
-openswan-2.5.13.tar.gz_MD5                             = b83a42ea00ee24ed34413bc122cada51
+openswan-2.4.8.tar.gz_MD5                                      = 918cc56ccf8e5d14cd2047e47450b34a
 
 install : $(TARGET)
 
@@ -121,9 +121,9 @@ endif
 
        # Openswan 2
        cd $(DIR_SRC) && rm -rf openswan-*
-       cd $(DIR_SRC) && tar xfz $(DIR_DL)/openswan-2.5.13.tar.gz
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/openswan-2.5.13.kernel-2.6-klips.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/openswan-2.5.13.kernel-2.6-natt.patch
+       cd $(DIR_SRC) && tar xfz $(DIR_DL)/openswan-2.4.8.tar.gz
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/openswan-2.4.8.kernel-2.6-klips.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/openswan-2.4.8.kernel-2.6-natt.patch
 
        cd $(DIR_SRC)/openswan-* && sed -i -e 's/INC_USRLOCAL=\/usr\/local/INC_USRLOCAL=\/usr/' Makefile.inc
 
index 0d2401ca0a0bd0e8c56f2c85ce99755f4f9989c1..b07dea2a4f09f607b5560afe40aa7ad336a8fb51 100644 (file)
@@ -26,7 +26,7 @@
 
 include Config
 
-VER        = 2.5.13
+VER        = 2.4.8
 
 THISAPP    = openswan-$(VER)
 DL_FILE    = $(THISAPP).tar.gz
@@ -42,7 +42,7 @@ objects = $(DL_FILE)
 
 $(DL_FILE) = $(DL_FROM)/$(DL_FILE)
 
-$(DL_FILE)_MD5 = b83a42ea00ee24ed34413bc122cada51
+$(DL_FILE)_MD5 = 918cc56ccf8e5d14cd2047e47450b34a
 
 install : $(TARGET)
 
index 54a96147275e237e7f59432a9ac06e9e33d57acd..178c234df8b7a89cf4aa79ce990d477987613347 100644 (file)
--- a/lfs/squid
+++ b/lfs/squid
@@ -124,12 +124,11 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
        chmod 775 /srv/web/ipfire/html/updatecache/metadata
        chmod 755 /var/log/updatexlrator
        
-  chwon squid:squid /var/log/squid
-  mkdir /usr/lib/squid/auth
-       cp -f $(DIR_SRC)/config/proxy/auth /usr/lib/squid/auth
+       chown squid:squid /var/log/squid
+       ln -sf /usr/lib/squid /usr/lib/squid/auth
        cp -f $(DIR_SRC)/config/proxy/proxy.pac /srv/web/ipfire/html/proxy.pac
        chown nobody.nobody /srv/web/ipfire/html/proxy.pac
-       ln -f /srv/web/ipfire/html/proxy.pac /srv/web/ipfire/html//wpad.dat
+       ln -sf /srv/web/ipfire/html/proxy.pac /srv/web/ipfire/html/wpad.dat
 
        @rm -rf $(DIR_APP)
        @$(POSTBUILD)
diff --git a/make.sh b/make.sh
index 6f50a485cb84523ea43d3077dbf818a47f0083d0..603bb78517be2b314f839aea0290b8c99890c273 100755 (executable)
--- a/make.sh
+++ b/make.sh
@@ -337,7 +337,7 @@ buildipfire() {
 #  ipfiremake promise-sata-300-tx      SMP=1
   ipfiremake zaptel                    SMP=1
   ipfiremake fuse                              SMP=1
-  ipfiremake linux                     XEN=1
+  #ipfiremake linux                    XEN=1
   ipfiremake linux
   ipfiremake ipp2p
   ipfiremake fcdsl
index 25b2c7c07240d1d15d5d90769dd4f316c6902e29..8cd2e22aa67287021916981d690e9de16ebeef34 100644 (file)
@@ -8,7 +8,7 @@ SUID_PROGS = setdmzholes setportfw setfilters setxtaccess \
        squidctrl restartssh ipfirereboot setaliases \
        ipsecctrl timectrl dhcpctrl snortctrl \
        monitorTraff restartapplejuice rebuildhosts \
-       restartsyslogd logwatch openvpnctrl \
+       restartsyslogd logwatch openvpnctrl outgoingfwctrl \
        restartwireless getipstat qosctrl launch-ether-wake \
        redctrl extrahdctrl sambactrl upnpctrl tripwirectrl \
        smartctrl clamavctrl
@@ -67,6 +67,9 @@ monitorTraff: monitorTraff.c setuid.o ../install+setup/libsmooth/varval.o
 clamavctrl: clamavctrl.c setuid.o ../install+setup/libsmooth/varval.o
        $(COMPILE) -I../install+setup/libsmooth/ clamavctrl.c setuid.o ../install+setup/libsmooth/varval.o -o $@
        
+outgoingfwctrl: outgoingfwctrl.c setuid.o ../install+setup/libsmooth/varval.o
+       $(COMPILE) -I../install+setup/libsmooth/ outgoingfwctrl.c setuid.o ../install+setup/libsmooth/varval.o -o $@
+       
 timectrl: timectrl.c setuid.o ../install+setup/libsmooth/varval.o
        $(COMPILE) -I../install+setup/libsmooth/ timectrl.c setuid.o ../install+setup/libsmooth/varval.o -o $@
 
diff --git a/src/misc-progs/outgoingfwctrl.c b/src/misc-progs/outgoingfwctrl.c
new file mode 100644 (file)
index 0000000..b43e106
--- /dev/null
@@ -0,0 +1,23 @@
+/* This file is part of the IPFire Firewall.
+ *
+ * This program is distributed under the terms of the GNU General Public
+ * Licence.  See the file COPYING for details.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include "setuid.h"
+
+int main(int argc, char *argv[]) {
+
+       if (!(initsetuid()))
+               exit(1);
+
+       safe_system("/var/ipfire/outgoing/bin/outgoingfw.pl");
+       return 0;
+}
diff --git a/src/patches/openswan-2.4.8.kernel-2.6-klips.patch b/src/patches/openswan-2.4.8.kernel-2.6-klips.patch
new file mode 100644 (file)
index 0000000..7f25202
--- /dev/null
@@ -0,0 +1,59382 @@
+packaging/utils/kernelpatch 2.6
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/README.openswan-2     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,112 @@
++*
++* RCSID $Id: README.openswan-2,v 1.1 2003/12/10 01:07:49 mcr Exp $
++*
++
++               ****************************************
++               * IPSEC for Linux, Release 2.xx series *
++               ****************************************
++
++
++
++1. Files
++
++The contents of linux/net/ipsec/ (see below) join the linux kernel source tree.
++as provided for higher up.
++
++The programs/ directory contains the user-level utilities which you need
++to run IPSEC.  See the top-level top/INSTALL to compile and install them.
++
++The testing/ directory contains test scripts.
++
++The doc/ directory contains -- what else -- documentation. 
++
++1.1. Kernel files
++
++The following are found in net/ipsec/:
++
++Makefile                      The Makefile
++Config.in                     The configuration script for make menuconfig
++defconfig                     Configuration defaults for first time.
++
++radij.c                               General-purpose radix-tree operations
++
++ipsec_ipcomp.c           IPCOMP encapsulate/decapsulate code.
++ipsec_ah.c       Authentication Header (AH) encapsulate/decapsulate code.
++ipsec_esp.c      Encapsulated Security Payload (ESP) encap/decap code.
++
++pfkey_v2.c                    PF_KEYv2 socket interface code.
++pfkey_v2_parser.c             PF_KEYv2 message parsing and processing code.
++
++ipsec_init.c                  Initialization code, /proc interface.
++ipsec_radij.c                 Interface with the radix tree code.
++ipsec_netlink.c                       Interface with the netlink code.
++ipsec_xform.c                 Routines and structures common to transforms.
++ipsec_tunnel.c                        The outgoing packet processing code.
++ipsec_rcv.c                   The incoming packet processing code.
++ipsec_md5c.c                  Somewhat modified RSADSI MD5 C code.
++ipsec_sha1.c                  Somewhat modified Steve Reid SHA-1 C code.
++
++sysctl_net_ipsec.c            /proc/sys/net/ipsec/* variable definitions.
++
++version.c                     symbolic link to project version.
++
++radij.h                               Headers for radij.c
++
++ipcomp.h                      Headers used by IPCOMP code.
++
++ipsec_radij.h                 Interface with the radix tree code.
++ipsec_netlink.h                       Headers used by the netlink interface.
++ipsec_encap.h                 Headers defining encapsulation structures.
++ipsec_xform.h                 Transform headers.
++ipsec_tunnel.h                        Headers used by tunneling code.
++ipsec_ipe4.h                  Headers for the IP-in-IP code.
++ipsec_ah.h                    Headers common to AH transforms.
++ipsec_md5h.h                  RSADSI MD5 headers.
++ipsec_sha1.h                  SHA-1 headers.
++ipsec_esp.h                   Headers common to ESP transfroms.
++ipsec_rcv.h                   Headers for incoming packet processing code.
++
++1.2. User-level files.
++
++The following are found in utils/:
++
++eroute.c      Create an "extended route" source code
++spi.c         Set up Security Associations source code
++spigrp.c        Link SPIs together source code.
++tncfg.c         Configure the tunneling features of the virtual interface
++              source code
++klipsdebug.c  Set/reset klips debugging features source code.
++version.c     symbolic link to project version.
++
++eroute.8      Create an "extended route" manual page
++spi.8         Set up Security Associations manual page
++spigrp.8        Link SPIs together manual page
++tncfg.8         Configure the tunneling features of the virtual interface
++              manual page
++klipsdebug.8  Set/reset klips debugging features manual page
++
++eroute.5      /proc/net/ipsec_eroute format manual page
++spi.5         /proc/net/ipsec_spi format manual page
++spigrp.5      /proc/net/ipsec_spigrp format manual page
++tncfg.5               /proc/net/ipsec_tncfg format manual page
++klipsdebug.5  /proc/net/ipsec_klipsdebug format manual page
++version.5     /proc/net/ipsec_version format manual page
++pf_key.5      /proc/net/pf_key format manual page
++
++Makefile      Utilities makefile.
++
++*.8           Manpages for the respective utils.
++
++
++1.3. Test files
++
++The test scripts are locate in testing/ and and documentation is found
++at doc/src/umltesting.html. Automated testing via "make check" is available
++provided that the User-Mode-Linux patches are available.
++
++*
++* $Log: README.openswan-2,v $
++* Revision 1.1  2003/12/10 01:07:49  mcr
++*     documentation for additions.
++*
++*
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/crypto/ciphers/aes/test_main.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,41 @@
++#include <stdio.h>
++#include <string.h>
++#include <sys/types.h>
++#include "aes_cbc.h"
++#define AES_BLOCK_SIZE        16
++#define KEY_SIZE      128     /* bits */
++#define KEY           "1234567890123456"
++#define STR           "hola guaso como estaisss ... 012"
++#define STRSZ         (sizeof(STR)-1)
++
++#define EMT_AESCBC_BLKLEN AES_BLOCK_SIZE
++#define AES_CONTEXT_T  aes_context
++#define EMT_ESPAES_KEY_SZ 16
++int pretty_print(const unsigned char *buf, int count) {
++      int i=0;
++      for (;i<count;i++) {
++              if (i%8==0) putchar(' ');
++              if (i%16==0) putchar('\n');
++              printf ("%02hhx ", buf[i]);
++      }
++      putchar('\n');
++      return i;
++}
++//#define SIZE STRSZ/2
++#define SIZE STRSZ
++int main() {
++      int ret;
++      char buf0[SIZE+1], buf1[SIZE+1];
++      char IV[AES_BLOCK_SIZE]="\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0";
++      aes_context ac; 
++      AES_set_key(&ac, KEY, KEY_SIZE);
++      //pretty_print((char *)&ac.aes_e_key, sizeof(ac.aes_e_key));
++      memset(buf0, 0, sizeof (buf0));
++      memset(buf1, 0, sizeof (buf1));
++      ret=AES_cbc_encrypt(&ac, STR, buf0, SIZE, IV, 1);
++      pretty_print(buf0, SIZE);
++      printf("size=%d ret=%d\n%s\n", SIZE, ret, buf0);
++      ret=AES_cbc_encrypt(&ac, buf0, buf1, SIZE, IV, 0);
++      printf("size=%d ret=%d\n%s\n", SIZE, ret, buf1);
++      return 0;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/crypto/ciphers/aes/test_main_mac.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,30 @@
++#include <stdio.h>
++#include <sys/types.h>
++#include <string.h>
++#include "aes.h"
++#include "aes_xcbc_mac.h"
++#define STR "Hola guasssso c|mo estais ...012"  
++void print_hash(const __u8 *hash) {
++      printf("%08x %08x %08x %08x\n", 
++                      *(__u32*)(&hash[0]), 
++                      *(__u32*)(&hash[4]), 
++                      *(__u32*)(&hash[8]), 
++                      *(__u32*)(&hash[12]));
++}
++int main(int argc, char *argv[]) {
++      aes_block key= { 0xdeadbeef, 0xceedcaca, 0xcafebabe, 0xff010204 };
++      __u8  hash[16];
++      char *str = argv[1];
++      aes_context_mac ctx;
++      if (str==NULL) {
++              fprintf(stderr, "pasame el str\n");
++              return 255;
++      }
++      AES_xcbc_mac_set_key(&ctx, (__u8 *)&key, sizeof(key));
++      AES_xcbc_mac_hash(&ctx, str, strlen(str), hash);
++      print_hash(hash);
++      str[2]='x';
++      AES_xcbc_mac_hash(&ctx, str, strlen(str), hash);
++      print_hash(hash);
++      return 0;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/crypto/aes.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,97 @@
++// I retain copyright in this code but I encourage its free use provided
++// that I don't carry any responsibility for the results. I am especially 
++// happy to see it used in free and open source software. If you do use 
++// it I would appreciate an acknowledgement of its origin in the code or
++// the product that results and I would also appreciate knowing a little
++// about the use to which it is being put. I am grateful to Frank Yellin
++// for some ideas that are used in this implementation.
++//
++// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001.
++//
++// This is an implementation of the AES encryption algorithm (Rijndael)
++// designed by Joan Daemen and Vincent Rijmen. This version is designed
++// to provide both fixed and dynamic block and key lengths and can also 
++// run with either big or little endian internal byte order (see aes.h). 
++// It inputs block and key lengths in bytes with the legal values being 
++// 16, 24 and 32.
++
++/*
++ * Modified by Jari Ruusu,  May 1 2001
++ *  - Fixed some compile warnings, code was ok but gcc warned anyway.
++ *  - Changed basic types: byte -> unsigned char, word -> u_int32_t
++ *  - Major name space cleanup: Names visible to outside now begin
++ *    with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c
++ *  - Removed C++ and DLL support as part of name space cleanup.
++ *  - Eliminated unnecessary recomputation of tables. (actual bug fix)
++ *  - Merged precomputed constant tables to aes.c file.
++ *  - Removed data alignment restrictions for portability reasons.
++ *  - Made block and key lengths accept bit count (128/192/256)
++ *    as well byte count (16/24/32).
++ *  - Removed all error checks. This change also eliminated the need
++ *    to preinitialize the context struct to zero.
++ *  - Removed some totally unused constants.
++ */
++
++#ifndef _AES_H
++#define _AES_H
++
++#if defined(__linux__) && defined(__KERNEL__)
++#  include <linux/types.h>
++#else 
++#  include <sys/types.h>
++#endif
++
++// CONFIGURATION OPTIONS (see also aes.c)
++//
++// Define AES_BLOCK_SIZE to set the cipher block size (16, 24 or 32) or
++// leave this undefined for dynamically variable block size (this will
++// result in much slower code).
++// IMPORTANT NOTE: AES_BLOCK_SIZE is in BYTES (16, 24, 32 or undefined). If
++// left undefined a slower version providing variable block length is compiled
++
++#define AES_BLOCK_SIZE  16
++
++// The number of key schedule words for different block and key lengths
++// allowing for method of computation which requires the length to be a
++// multiple of the key length
++//
++// Nk =       4   6   8
++//        -------------
++// Nb = 4 |  60  60  64
++//      6 |  96  90  96
++//      8 | 120 120 120
++
++#if !defined(AES_BLOCK_SIZE) || (AES_BLOCK_SIZE == 32)
++#define AES_KS_LENGTH   120
++#define AES_RC_LENGTH    29
++#else
++#define AES_KS_LENGTH   4 * AES_BLOCK_SIZE
++#define AES_RC_LENGTH   (9 * AES_BLOCK_SIZE) / 8 - 8
++#endif
++
++typedef struct
++{
++    u_int32_t    aes_Nkey;      // the number of words in the key input block
++    u_int32_t    aes_Nrnd;      // the number of cipher rounds
++    u_int32_t    aes_e_key[AES_KS_LENGTH];   // the encryption key schedule
++    u_int32_t    aes_d_key[AES_KS_LENGTH];   // the decryption key schedule
++#if !defined(AES_BLOCK_SIZE)
++    u_int32_t    aes_Ncol;      // the number of columns in the cipher state
++#endif
++} aes_context;
++
++// THE CIPHER INTERFACE
++
++#if !defined(AES_BLOCK_SIZE)
++extern void aes_set_blk(aes_context *, const int);
++#endif
++extern void aes_set_key(aes_context *, const unsigned char [], const int, const int);
++extern void aes_encrypt(const aes_context *, const unsigned char [], unsigned char []);
++extern void aes_decrypt(const aes_context *, const unsigned char [], unsigned char []);
++
++// The block length inputs to aes_set_block and aes_set_key are in numbers
++// of bytes or bits.  The calls to subroutines must be made in the above
++// order but multiple calls can be made without repeating earlier calls
++// if their parameters have not changed.
++
++#endif  // _AES_H
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/crypto/aes_cbc.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,4 @@
++/* Glue header */
++#include "aes.h"
++int AES_set_key(aes_context *aes_ctx, const u_int8_t * key, int keysize);
++int AES_cbc_encrypt(aes_context *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt);
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/crypto/aes_xcbc_mac.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,12 @@
++#ifndef _AES_XCBC_MAC_H
++#define _AES_XCBC_MAC_H
++
++typedef u_int32_t aes_block[4];
++typedef struct {
++      aes_context ctx_k1;
++      aes_block k2;
++      aes_block k3;
++} aes_context_mac;
++int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen);
++int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]);
++#endif /* _AES_XCBC_MAC_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/crypto/cbc_generic.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,110 @@
++#ifndef _CBC_GENERIC_H
++#define _CBC_GENERIC_H
++/*
++ * CBC macro helpers
++ *
++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ */
++
++/*
++ *    Heavily inspired in loop_AES
++ */
++#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \
++int name(ctx_type *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \
++      int ret=ilen, pos; \
++      const u_int32_t *iv_i; \
++      if ((ilen) % 16) return 0; \
++      if (encrypt) { \
++              pos=0; \
++              while(pos<ilen) { \
++                      if (pos==0) \
++                              iv_i=(const u_int32_t*) iv; \
++                      else \
++                              iv_i=(const u_int32_t*) (out-16); \
++                      *((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \
++                      *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \
++                      *((u_int32_t *)(&out[ 8])) = iv_i[2]^*((const u_int32_t *)(&in[ 8])); \
++                      *((u_int32_t *)(&out[12])) = iv_i[3]^*((const u_int32_t *)(&in[12])); \
++                      enc_func(ctx, (addr_type) out, (addr_type) out); \
++                      in+=16; \
++                      out+=16; \
++                      pos+=16; \
++              } \
++      } else { \
++              pos=ilen-16; \
++              in+=pos; \
++              out+=pos; \
++              while(pos>=0) { \
++                      dec_func(ctx, (const addr_type) in, (addr_type) out); \
++                      if (pos==0) \
++                              iv_i=(const u_int32_t*) (iv); \
++                      else \
++                              iv_i=(const u_int32_t*) (in-16); \
++                      *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \
++                      *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \
++                      *((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \
++                      *((u_int32_t *)(&out[12])) ^= iv_i[3]; \
++                      in-=16; \
++                      out-=16; \
++                      pos-=16; \
++              } \
++      } \
++      return ret; \
++} 
++#define CBC_IMPL_BLK8(name, ctx_type, addr_type,  enc_func, dec_func) \
++int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \
++      int ret=ilen, pos; \
++      const u_int32_t *iv_i; \
++      if ((ilen) % 8) return 0; \
++      if (encrypt) { \
++              pos=0; \
++              while(pos<ilen) { \
++                      if (pos==0) \
++                              iv_i=(const u_int32_t*) iv; \
++                      else \
++                              iv_i=(const u_int32_t*) (out-8); \
++                      *((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \
++                      *((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \
++                      enc_func(ctx, (addr_type)out, (addr_type)out); \
++                      in+=8; \
++                      out+=8; \
++                      pos+=8; \
++              } \
++      } else { \
++              pos=ilen-8; \
++              in+=pos; \
++              out+=pos; \
++              while(pos>=0) { \
++                      dec_func(ctx, (const addr_type)in, (addr_type)out); \
++                      if (pos==0) \
++                              iv_i=(const u_int32_t*) (iv); \
++                      else \
++                              iv_i=(const u_int32_t*) (in-8); \
++                      *((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \
++                      *((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \
++                      in-=8; \
++                      out-=8; \
++                      pos-=8; \
++              } \
++      } \
++      return ret; \
++} 
++#define CBC_DECL(name, ctx_type) \
++int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt)
++/*
++Eg.:
++CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt);
++CBC_DECL(AES_cbc_encrypt, aes_context);
++*/
++#endif /* _CBC_GENERIC_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/crypto/des.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,298 @@
++/* crypto/des/des.org */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 
++ *
++ * Always modify des.org since des.h is automatically generated from
++ * it during SSLeay configuration.
++ *
++ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
++ */
++
++#ifndef HEADER_DES_H
++#define HEADER_DES_H
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++
++/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
++ * %20 speed up (longs are 8 bytes, int's are 4). */
++/* Must be unsigned int on ia64/Itanium or DES breaks badly */
++
++#ifdef __KERNEL__
++#include <linux/types.h>
++#else
++#include <sys/types.h>
++#endif
++
++#ifndef DES_LONG
++#define DES_LONG u_int32_t
++#endif
++
++typedef unsigned char des_cblock[8];
++typedef struct { des_cblock ks; } des_key_schedule[16];
++
++#define DES_KEY_SZ    (sizeof(des_cblock))
++#define DES_SCHEDULE_SZ (sizeof(des_key_schedule))
++
++#define DES_ENCRYPT   1
++#define DES_DECRYPT   0
++
++#define DES_CBC_MODE  0
++#define DES_PCBC_MODE 1
++
++#define des_ecb2_encrypt(i,o,k1,k2,e) \
++      des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
++
++#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
++      des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
++
++#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
++      des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
++
++#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
++      des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
++
++#define C_Block des_cblock
++#define Key_schedule des_key_schedule
++#ifdef KERBEROS
++#define ENCRYPT DES_ENCRYPT
++#define DECRYPT DES_DECRYPT
++#endif
++#define KEY_SZ DES_KEY_SZ
++#define string_to_key des_string_to_key
++#define read_pw_string des_read_pw_string
++#define random_key des_random_key
++#define pcbc_encrypt des_pcbc_encrypt
++#define set_key des_set_key
++#define key_sched des_key_sched
++#define ecb_encrypt des_ecb_encrypt
++#define cbc_encrypt des_cbc_encrypt
++#define ncbc_encrypt des_ncbc_encrypt
++#define xcbc_encrypt des_xcbc_encrypt
++#define cbc_cksum des_cbc_cksum
++#define quad_cksum des_quad_cksum
++
++/* For compatibility with the MIT lib - eay 20/05/92 */
++typedef des_key_schedule bit_64;
++#define des_fixup_key_parity des_set_odd_parity
++#define des_check_key_parity check_parity
++
++extern int des_check_key;     /* defaults to false */
++extern int des_rw_mode;               /* defaults to DES_PCBC_MODE */
++
++/* The next line is used to disable full ANSI prototypes, if your
++ * compiler has problems with the prototypes, make sure this line always
++ * evaluates to true :-) */
++#if defined(MSDOS) || defined(__STDC__)
++#undef NOPROTO
++#endif
++#ifndef NOPROTO
++char *des_options(void);
++void des_ecb3_encrypt(des_cblock *input,des_cblock *output,
++      des_key_schedule ks1,des_key_schedule ks2,
++      des_key_schedule ks3, int enc);
++DES_LONG des_cbc_cksum(des_cblock *input,des_cblock *output,
++      long length,des_key_schedule schedule,des_cblock *ivec);
++void des_cbc_encrypt(des_cblock *input,des_cblock *output,long length,
++      des_key_schedule schedule,des_cblock *ivec,int enc);
++void des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length,
++      des_key_schedule schedule,des_cblock *ivec,int enc);
++void des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length,
++      des_key_schedule schedule,des_cblock *ivec,
++      des_cblock *inw,des_cblock *outw,int enc);
++void des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits,
++      long length,des_key_schedule schedule,des_cblock *ivec,int enc);
++void des_ecb_encrypt(des_cblock *input,des_cblock *output,
++      des_key_schedule ks,int enc);
++void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc);
++void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc);
++void des_encrypt3(DES_LONG *data, des_key_schedule ks1,
++      des_key_schedule ks2, des_key_schedule ks3);
++void des_decrypt3(DES_LONG *data, des_key_schedule ks1,
++      des_key_schedule ks2, des_key_schedule ks3);
++void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, 
++      long length, des_key_schedule ks1, des_key_schedule ks2, 
++      des_key_schedule ks3, des_cblock *ivec, int enc);
++void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out,
++      long length, des_key_schedule ks1, des_key_schedule ks2,
++      des_key_schedule ks3, des_cblock *ivec, int *num, int enc);
++void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out,
++      long length, des_key_schedule ks1, des_key_schedule ks2,
++      des_key_schedule ks3, des_cblock *ivec, int *num);
++
++void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white),
++      des_cblock (*out_white));
++
++int des_enc_read(int fd,char *buf,int len,des_key_schedule sched,
++      des_cblock *iv);
++int des_enc_write(int fd,char *buf,int len,des_key_schedule sched,
++      des_cblock *iv);
++char *des_fcrypt(const char *buf,const char *salt, char *ret);
++#ifdef PERL5
++char *des_crypt(const char *buf,const char *salt);
++#else
++/* some stupid compilers complain because I have declared char instead
++ * of const char */
++#ifndef __KERNEL__
++#ifdef HEADER_DES_LOCL_H
++char *crypt(const char *buf,const char *salt);
++#else /* HEADER_DES_LOCL_H */
++char *crypt(void);
++#endif /* HEADER_DES_LOCL_H */
++#endif /* __KERNEL__ */
++#endif /* PERL5 */
++void des_ofb_encrypt(unsigned char *in,unsigned char *out,
++      int numbits,long length,des_key_schedule schedule,des_cblock *ivec);
++void des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length,
++      des_key_schedule schedule,des_cblock *ivec,int enc);
++DES_LONG des_quad_cksum(des_cblock *input,des_cblock *output,
++      long length,int out_count,des_cblock *seed);
++void des_random_seed(des_cblock key);
++void des_random_key(des_cblock ret);
++int des_read_password(des_cblock *key,char *prompt,int verify);
++int des_read_2passwords(des_cblock *key1,des_cblock *key2,
++      char *prompt,int verify);
++int des_read_pw_string(char *buf,int length,char *prompt,int verify);
++void des_set_odd_parity(des_cblock *key);
++int des_is_weak_key(des_cblock *key);
++int des_set_key(des_cblock *key,des_key_schedule schedule);
++int des_key_sched(des_cblock *key,des_key_schedule schedule);
++void des_string_to_key(char *str,des_cblock *key);
++void des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2);
++void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length,
++      des_key_schedule schedule, des_cblock *ivec, int *num, int enc);
++void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length,
++      des_key_schedule schedule, des_cblock *ivec, int *num);
++int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify);
++
++/* Extra functions from Mark Murray <mark@grondar.za> */
++/* The following functions are not in the normal unix build or the
++ * SSLeay build.  When using the SSLeay build, use RAND_seed()
++ * and RAND_bytes() instead. */
++int des_new_random_key(des_cblock *key);
++void des_init_random_number_generator(des_cblock *key);
++void des_set_random_generator_seed(des_cblock *key);
++void des_set_sequence_number(des_cblock new_sequence_number);
++void des_generate_random_block(des_cblock *block);
++
++#else
++
++char *des_options();
++void des_ecb3_encrypt();
++DES_LONG des_cbc_cksum();
++void des_cbc_encrypt();
++void des_ncbc_encrypt();
++void des_xcbc_encrypt();
++void des_cfb_encrypt();
++void des_ede3_cfb64_encrypt();
++void des_ede3_ofb64_encrypt();
++void des_ecb_encrypt();
++void des_encrypt();
++void des_encrypt2();
++void des_encrypt3();
++void des_decrypt3();
++void des_ede3_cbc_encrypt();
++int des_enc_read();
++int des_enc_write();
++char *des_fcrypt();
++#ifdef PERL5
++char *des_crypt();
++#else
++char *crypt();
++#endif
++void des_ofb_encrypt();
++void des_pcbc_encrypt();
++DES_LONG des_quad_cksum();
++void des_random_seed();
++void des_random_key();
++int des_read_password();
++int des_read_2passwords();
++int des_read_pw_string();
++void des_set_odd_parity();
++int des_is_weak_key();
++int des_set_key();
++int des_key_sched();
++void des_string_to_key();
++void des_string_to_2keys();
++void des_cfb64_encrypt();
++void des_ofb64_encrypt();
++int des_read_pw();
++void des_xwhite_in2out();
++
++/* Extra functions from Mark Murray <mark@grondar.za> */
++/* The following functions are not in the normal unix build or the
++ * SSLeay build.  When using the SSLeay build, use RAND_seed()
++ * and RAND_bytes() instead. */
++#ifdef FreeBSD
++int des_new_random_key();
++void des_init_random_number_generator();
++void des_set_random_generator_seed();
++void des_set_sequence_number();
++void des_generate_random_block();
++#endif
++
++#endif
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/des/des_locl.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,515 @@
++/* crypto/des/des_locl.org */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
++ *
++ * Always modify des_locl.org since des_locl.h is automatically generated from
++ * it during SSLeay configuration.
++ *
++ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
++ */
++
++#ifndef HEADER_DES_LOCL_H
++#define HEADER_DES_LOCL_H
++
++#if defined(WIN32) || defined(WIN16)
++#ifndef MSDOS
++#define MSDOS
++#endif
++#endif
++
++#include "crypto/des.h"
++
++#ifndef DES_DEFAULT_OPTIONS
++/* the following is tweaked from a config script, that is why it is a
++ * protected undef/define */
++#ifndef DES_PTR
++#define DES_PTR
++#endif
++
++/* This helps C compiler generate the correct code for multiple functional
++ * units.  It reduces register dependancies at the expense of 2 more
++ * registers */
++#ifndef DES_RISC1
++#define DES_RISC1
++#endif
++
++#ifndef DES_RISC2
++#undef DES_RISC2
++#endif
++
++#if defined(DES_RISC1) && defined(DES_RISC2)
++YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
++#endif
++
++/* Unroll the inner loop, this sometimes helps, sometimes hinders.
++ * Very mucy CPU dependant */
++#ifndef DES_UNROLL
++#define DES_UNROLL
++#endif
++
++/* These default values were supplied by
++ * Peter Gutman <pgut001@cs.auckland.ac.nz>
++ * They are only used if nothing else has been defined */
++#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)
++/* Special defines which change the way the code is built depending on the
++   CPU and OS.  For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
++   even newer MIPS CPU's, but at the moment one size fits all for
++   optimization options.  Older Sparc's work better with only UNROLL, but
++   there's no way to tell at compile time what it is you're running on */
++ 
++#if defined( sun )            /* Newer Sparc's */
++  #define DES_PTR
++  #define DES_RISC1
++  #define DES_UNROLL
++#elif defined( __ultrix )     /* Older MIPS */
++  #define DES_PTR
++  #define DES_RISC2
++  #define DES_UNROLL
++#elif defined( __osf1__ )     /* Alpha */
++  #define DES_PTR
++  #define DES_RISC2
++#elif defined ( _AIX )                /* RS6000 */
++  /* Unknown */
++#elif defined( __hpux )               /* HP-PA */
++  /* Unknown */
++#elif defined( __aux )                /* 68K */
++  /* Unknown */
++#elif defined( __dgux )               /* 88K (but P6 in latest boxes) */
++  #define DES_UNROLL
++#elif defined( __sgi )                /* Newer MIPS */
++  #define DES_PTR
++  #define DES_RISC2
++  #define DES_UNROLL
++#elif defined( i386 )         /* x86 boxes, should be gcc */
++  #define DES_PTR
++  #define DES_RISC1
++  #define DES_UNROLL
++#endif /* Systems-specific speed defines */
++#endif
++
++#endif /* DES_DEFAULT_OPTIONS */
++
++#ifdef MSDOS          /* Visual C++ 2.1 (Windows NT/95) */
++#include <stdlib.h>
++#include <errno.h>
++#include <time.h>
++#include <io.h>
++#ifndef RAND
++#define RAND
++#endif
++#undef NOPROTO
++#endif
++
++#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS)
++#ifndef __KERNEL__
++#include <string.h>
++#else
++#include <linux/string.h>
++#endif
++#endif
++
++#ifndef RAND
++#define RAND
++#endif
++
++#ifdef linux
++#undef RAND
++#endif
++
++#ifdef MSDOS
++#define getpid() 2
++#define RAND
++#undef NOPROTO
++#endif
++
++#if defined(NOCONST)
++#define const
++#endif
++
++#ifdef __STDC__
++#undef NOPROTO
++#endif
++
++#ifdef RAND
++#define srandom(s) srand(s)
++#define random rand
++#endif
++
++#define ITERATIONS 16
++#define HALF_ITERATIONS 8
++
++/* used in des_read and des_write */
++#define MAXWRITE      (1024*16)
++#define BSIZE         (MAXWRITE+4)
++
++#define c2l(c,l)      (l =((DES_LONG)(*((c)++)))    , \
++                       l|=((DES_LONG)(*((c)++)))<< 8L, \
++                       l|=((DES_LONG)(*((c)++)))<<16L, \
++                       l|=((DES_LONG)(*((c)++)))<<24L)
++
++/* NOTE - c is not incremented as per c2l */
++#define c2ln(c,l1,l2,n)       { \
++                      c+=n; \
++                      l1=l2=0; \
++                      switch (n) { \
++                      case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \
++                      case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \
++                      case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \
++                      case 5: l2|=((DES_LONG)(*(--(c))));     \
++                      case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \
++                      case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \
++                      case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \
++                      case 1: l1|=((DES_LONG)(*(--(c))));     \
++                              } \
++                      }
++
++#define l2c(l,c)      (*((c)++)=(unsigned char)(((l)     )&0xff), \
++                       *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
++                       *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
++                       *((c)++)=(unsigned char)(((l)>>24L)&0xff))
++
++/* replacements for htonl and ntohl since I have no idea what to do
++ * when faced with machines with 8 byte longs. */
++#define HDRSIZE 4
++
++#define n2l(c,l)      (l =((DES_LONG)(*((c)++)))<<24L, \
++                       l|=((DES_LONG)(*((c)++)))<<16L, \
++                       l|=((DES_LONG)(*((c)++)))<< 8L, \
++                       l|=((DES_LONG)(*((c)++))))
++
++#define l2n(l,c)      (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
++                       *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
++                       *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
++                       *((c)++)=(unsigned char)(((l)     )&0xff))
++
++/* NOTE - c is not incremented as per l2c */
++#define l2cn(l1,l2,c,n)       { \
++                      c+=n; \
++                      switch (n) { \
++                      case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
++                      case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
++                      case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
++                      case 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \
++                      case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
++                      case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
++                      case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
++                      case 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \
++                              } \
++                      }
++
++#if defined(WIN32)
++#define       ROTATE(a,n)     (_lrotr(a,n))
++#else
++#define       ROTATE(a,n)     (((a)>>(n))+((a)<<(32-(n))))
++#endif
++
++/* Don't worry about the LOAD_DATA() stuff, that is used by
++ * fcrypt() to add it's little bit to the front */
++
++#ifdef DES_FCRYPT
++
++#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \
++      { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); }
++
++#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \
++      t=R^(R>>16L); \
++      u=t&E0; t&=E1; \
++      tmp=(u<<16); u^=R^s[S  ]; u^=tmp; \
++      tmp=(t<<16); t^=R^s[S+1]; t^=tmp
++#else
++#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g)
++#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \
++      u=R^s[S  ]; \
++      t=R^s[S+1]
++#endif
++
++/* The changes to this macro may help or hinder, depending on the
++ * compiler and the achitecture.  gcc2 always seems to do well :-).
++ * Inspired by Dana How <how@isl.stanford.edu>
++ * DO NOT use the alternative version on machines with 8 byte longs.
++ * It does not seem to work on the Alpha, even when DES_LONG is 4
++ * bytes, probably an issue of accessing non-word aligned objects :-( */
++#ifdef DES_PTR
++
++/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there
++ * is no reason to not xor all the sub items together.  This potentially
++ * saves a register since things can be xored directly into L */
++
++#if defined(DES_RISC1) || defined(DES_RISC2)
++#ifdef DES_RISC1
++#define D_ENCRYPT(LL,R,S) { \
++      unsigned int u1,u2,u3; \
++      LOAD_DATA(R,S,u,t,E0,E1,u1); \
++      u2=(int)u>>8L; \
++      u1=(int)u&0xfc; \
++      u2&=0xfc; \
++      t=ROTATE(t,4); \
++      u>>=16L; \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP      +u1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \
++      u3=(int)(u>>8L); \
++      u1=(int)u&0xfc; \
++      u3&=0xfc; \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \
++      u2=(int)t>>8L; \
++      u1=(int)t&0xfc; \
++      u2&=0xfc; \
++      t>>=16L; \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \
++      u3=(int)t>>8L; \
++      u1=(int)t&0xfc; \
++      u3&=0xfc; \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); }
++#endif
++#ifdef DES_RISC2
++#define D_ENCRYPT(LL,R,S) { \
++      unsigned int u1,u2,s1,s2; \
++      LOAD_DATA(R,S,u,t,E0,E1,u1); \
++      u2=(int)u>>8L; \
++      u1=(int)u&0xfc; \
++      u2&=0xfc; \
++      t=ROTATE(t,4); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP      +u1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \
++      s1=(int)(u>>16L); \
++      s2=(int)(u>>24L); \
++      s1&=0xfc; \
++      s2&=0xfc; \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \
++      u2=(int)t>>8L; \
++      u1=(int)t&0xfc; \
++      u2&=0xfc; \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \
++      s1=(int)(t>>16L); \
++      s2=(int)(t>>24L); \
++      s1&=0xfc; \
++      s2&=0xfc; \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \
++      LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); }
++#endif
++#else
++#define D_ENCRYPT(LL,R,S) { \
++      LOAD_DATA_tmp(R,S,u,t,E0,E1); \
++      t=ROTATE(t,4); \
++      LL^= \
++      *(DES_LONG *)((unsigned char *)des_SP      +((u     )&0xfc))^ \
++      *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \
++      *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \
++      *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \
++      *(DES_LONG *)((unsigned char *)des_SP+0x100+((t     )&0xfc))^ \
++      *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \
++      *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \
++      *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); }
++#endif
++
++#else /* original version */
++
++#if defined(DES_RISC1) || defined(DES_RISC2)
++#ifdef DES_RISC1
++#define D_ENCRYPT(LL,R,S) {\
++      unsigned int u1,u2,u3; \
++      LOAD_DATA(R,S,u,t,E0,E1,u1); \
++      u>>=2L; \
++      t=ROTATE(t,6); \
++      u2=(int)u>>8L; \
++      u1=(int)u&0x3f; \
++      u2&=0x3f; \
++      u>>=16L; \
++      LL^=des_SPtrans[0][u1]; \
++      LL^=des_SPtrans[2][u2]; \
++      u3=(int)u>>8L; \
++      u1=(int)u&0x3f; \
++      u3&=0x3f; \
++      LL^=des_SPtrans[4][u1]; \
++      LL^=des_SPtrans[6][u3]; \
++      u2=(int)t>>8L; \
++      u1=(int)t&0x3f; \
++      u2&=0x3f; \
++      t>>=16L; \
++      LL^=des_SPtrans[1][u1]; \
++      LL^=des_SPtrans[3][u2]; \
++      u3=(int)t>>8L; \
++      u1=(int)t&0x3f; \
++      u3&=0x3f; \
++      LL^=des_SPtrans[5][u1]; \
++      LL^=des_SPtrans[7][u3]; }
++#endif
++#ifdef DES_RISC2
++#define D_ENCRYPT(LL,R,S) {\
++      unsigned int u1,u2,s1,s2; \
++      LOAD_DATA(R,S,u,t,E0,E1,u1); \
++      u>>=2L; \
++      t=ROTATE(t,6); \
++      u2=(int)u>>8L; \
++      u1=(int)u&0x3f; \
++      u2&=0x3f; \
++      LL^=des_SPtrans[0][u1]; \
++      LL^=des_SPtrans[2][u2]; \
++      s1=(int)u>>16L; \
++      s2=(int)u>>24L; \
++      s1&=0x3f; \
++      s2&=0x3f; \
++      LL^=des_SPtrans[4][s1]; \
++      LL^=des_SPtrans[6][s2]; \
++      u2=(int)t>>8L; \
++      u1=(int)t&0x3f; \
++      u2&=0x3f; \
++      LL^=des_SPtrans[1][u1]; \
++      LL^=des_SPtrans[3][u2]; \
++      s1=(int)t>>16; \
++      s2=(int)t>>24L; \
++      s1&=0x3f; \
++      s2&=0x3f; \
++      LL^=des_SPtrans[5][s1]; \
++      LL^=des_SPtrans[7][s2]; }
++#endif
++
++#else
++
++#define D_ENCRYPT(LL,R,S) {\
++      LOAD_DATA_tmp(R,S,u,t,E0,E1); \
++      t=ROTATE(t,4); \
++      LL^=\
++              des_SPtrans[0][(u>> 2L)&0x3f]^ \
++              des_SPtrans[2][(u>>10L)&0x3f]^ \
++              des_SPtrans[4][(u>>18L)&0x3f]^ \
++              des_SPtrans[6][(u>>26L)&0x3f]^ \
++              des_SPtrans[1][(t>> 2L)&0x3f]^ \
++              des_SPtrans[3][(t>>10L)&0x3f]^ \
++              des_SPtrans[5][(t>>18L)&0x3f]^ \
++              des_SPtrans[7][(t>>26L)&0x3f]; }
++#endif
++#endif
++
++      /* IP and FP
++       * The problem is more of a geometric problem that random bit fiddling.
++       0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6
++       8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4
++      16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2
++      24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0
++
++      32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7
++      40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5
++      48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3
++      56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1
++
++      The output has been subject to swaps of the form
++      0 1 -> 3 1 but the odd and even bits have been put into
++      2 3    2 0
++      different words.  The main trick is to remember that
++      t=((l>>size)^r)&(mask);
++      r^=t;
++      l^=(t<<size);
++      can be used to swap and move bits between words.
++
++      So l =  0  1  2  3  r = 16 17 18 19
++              4  5  6  7      20 21 22 23
++              8  9 10 11      24 25 26 27
++             12 13 14 15      28 29 30 31
++      becomes (for size == 2 and mask == 0x3333)
++         t =   2^16  3^17 -- --   l =  0  1 16 17  r =  2  3 18 19
++               6^20  7^21 -- --        4  5 20 21       6  7 22 23
++              10^24 11^25 -- --        8  9 24 25      10 11 24 25
++              14^28 15^29 -- --       12 13 28 29      14 15 28 29
++
++      Thanks for hints from Richard Outerbridge - he told me IP&FP
++      could be done in 15 xor, 10 shifts and 5 ands.
++      When I finally started to think of the problem in 2D
++      I first got ~42 operations without xors.  When I remembered
++      how to use xors :-) I got it to its final state.
++      */
++#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
++      (b)^=(t),\
++      (a)^=((t)<<(n)))
++
++#define IP(l,r) \
++      { \
++      register DES_LONG tt; \
++      PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \
++      PERM_OP(l,r,tt,16,0x0000ffffL); \
++      PERM_OP(r,l,tt, 2,0x33333333L); \
++      PERM_OP(l,r,tt, 8,0x00ff00ffL); \
++      PERM_OP(r,l,tt, 1,0x55555555L); \
++      }
++
++#define FP(l,r) \
++      { \
++      register DES_LONG tt; \
++      PERM_OP(l,r,tt, 1,0x55555555L); \
++      PERM_OP(r,l,tt, 8,0x00ff00ffL); \
++      PERM_OP(l,r,tt, 2,0x33333333L); \
++      PERM_OP(r,l,tt,16,0x0000ffffL); \
++      PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \
++      }
++
++extern const DES_LONG des_SPtrans[8][64];
++
++#ifndef NOPROTO
++void fcrypt_body(DES_LONG *out,des_key_schedule ks,
++      DES_LONG Eswap0, DES_LONG Eswap1);
++#else
++void fcrypt_body();
++#endif
++
++#endif
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/des/des_ver.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,60 @@
++/* crypto/des/des_ver.h */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++extern char *DES_version;     /* SSLeay version string */
++extern char *libdes_version;  /* old libdes version string */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/des/podd.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,75 @@
++/* crypto/des/podd.h */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++static const unsigned char odd_parity[256]={
++  1,  1,  2,  2,  4,  4,  7,  7,  8,  8, 11, 11, 13, 13, 14, 14,
++ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
++ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
++ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
++ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
++ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
++ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
++112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
++128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
++145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
++161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
++176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
++193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
++208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
++224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
++241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254};
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/des/sk.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,204 @@
++/* crypto/des/sk.h */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++static const DES_LONG des_skb[8][64]={
++{
++/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
++0x00000000L,0x00000010L,0x20000000L,0x20000010L,
++0x00010000L,0x00010010L,0x20010000L,0x20010010L,
++0x00000800L,0x00000810L,0x20000800L,0x20000810L,
++0x00010800L,0x00010810L,0x20010800L,0x20010810L,
++0x00000020L,0x00000030L,0x20000020L,0x20000030L,
++0x00010020L,0x00010030L,0x20010020L,0x20010030L,
++0x00000820L,0x00000830L,0x20000820L,0x20000830L,
++0x00010820L,0x00010830L,0x20010820L,0x20010830L,
++0x00080000L,0x00080010L,0x20080000L,0x20080010L,
++0x00090000L,0x00090010L,0x20090000L,0x20090010L,
++0x00080800L,0x00080810L,0x20080800L,0x20080810L,
++0x00090800L,0x00090810L,0x20090800L,0x20090810L,
++0x00080020L,0x00080030L,0x20080020L,0x20080030L,
++0x00090020L,0x00090030L,0x20090020L,0x20090030L,
++0x00080820L,0x00080830L,0x20080820L,0x20080830L,
++0x00090820L,0x00090830L,0x20090820L,0x20090830L,
++},{
++/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
++0x00000000L,0x02000000L,0x00002000L,0x02002000L,
++0x00200000L,0x02200000L,0x00202000L,0x02202000L,
++0x00000004L,0x02000004L,0x00002004L,0x02002004L,
++0x00200004L,0x02200004L,0x00202004L,0x02202004L,
++0x00000400L,0x02000400L,0x00002400L,0x02002400L,
++0x00200400L,0x02200400L,0x00202400L,0x02202400L,
++0x00000404L,0x02000404L,0x00002404L,0x02002404L,
++0x00200404L,0x02200404L,0x00202404L,0x02202404L,
++0x10000000L,0x12000000L,0x10002000L,0x12002000L,
++0x10200000L,0x12200000L,0x10202000L,0x12202000L,
++0x10000004L,0x12000004L,0x10002004L,0x12002004L,
++0x10200004L,0x12200004L,0x10202004L,0x12202004L,
++0x10000400L,0x12000400L,0x10002400L,0x12002400L,
++0x10200400L,0x12200400L,0x10202400L,0x12202400L,
++0x10000404L,0x12000404L,0x10002404L,0x12002404L,
++0x10200404L,0x12200404L,0x10202404L,0x12202404L,
++},{
++/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
++0x00000000L,0x00000001L,0x00040000L,0x00040001L,
++0x01000000L,0x01000001L,0x01040000L,0x01040001L,
++0x00000002L,0x00000003L,0x00040002L,0x00040003L,
++0x01000002L,0x01000003L,0x01040002L,0x01040003L,
++0x00000200L,0x00000201L,0x00040200L,0x00040201L,
++0x01000200L,0x01000201L,0x01040200L,0x01040201L,
++0x00000202L,0x00000203L,0x00040202L,0x00040203L,
++0x01000202L,0x01000203L,0x01040202L,0x01040203L,
++0x08000000L,0x08000001L,0x08040000L,0x08040001L,
++0x09000000L,0x09000001L,0x09040000L,0x09040001L,
++0x08000002L,0x08000003L,0x08040002L,0x08040003L,
++0x09000002L,0x09000003L,0x09040002L,0x09040003L,
++0x08000200L,0x08000201L,0x08040200L,0x08040201L,
++0x09000200L,0x09000201L,0x09040200L,0x09040201L,
++0x08000202L,0x08000203L,0x08040202L,0x08040203L,
++0x09000202L,0x09000203L,0x09040202L,0x09040203L,
++},{
++/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
++0x00000000L,0x00100000L,0x00000100L,0x00100100L,
++0x00000008L,0x00100008L,0x00000108L,0x00100108L,
++0x00001000L,0x00101000L,0x00001100L,0x00101100L,
++0x00001008L,0x00101008L,0x00001108L,0x00101108L,
++0x04000000L,0x04100000L,0x04000100L,0x04100100L,
++0x04000008L,0x04100008L,0x04000108L,0x04100108L,
++0x04001000L,0x04101000L,0x04001100L,0x04101100L,
++0x04001008L,0x04101008L,0x04001108L,0x04101108L,
++0x00020000L,0x00120000L,0x00020100L,0x00120100L,
++0x00020008L,0x00120008L,0x00020108L,0x00120108L,
++0x00021000L,0x00121000L,0x00021100L,0x00121100L,
++0x00021008L,0x00121008L,0x00021108L,0x00121108L,
++0x04020000L,0x04120000L,0x04020100L,0x04120100L,
++0x04020008L,0x04120008L,0x04020108L,0x04120108L,
++0x04021000L,0x04121000L,0x04021100L,0x04121100L,
++0x04021008L,0x04121008L,0x04021108L,0x04121108L,
++},{
++/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
++0x00000000L,0x10000000L,0x00010000L,0x10010000L,
++0x00000004L,0x10000004L,0x00010004L,0x10010004L,
++0x20000000L,0x30000000L,0x20010000L,0x30010000L,
++0x20000004L,0x30000004L,0x20010004L,0x30010004L,
++0x00100000L,0x10100000L,0x00110000L,0x10110000L,
++0x00100004L,0x10100004L,0x00110004L,0x10110004L,
++0x20100000L,0x30100000L,0x20110000L,0x30110000L,
++0x20100004L,0x30100004L,0x20110004L,0x30110004L,
++0x00001000L,0x10001000L,0x00011000L,0x10011000L,
++0x00001004L,0x10001004L,0x00011004L,0x10011004L,
++0x20001000L,0x30001000L,0x20011000L,0x30011000L,
++0x20001004L,0x30001004L,0x20011004L,0x30011004L,
++0x00101000L,0x10101000L,0x00111000L,0x10111000L,
++0x00101004L,0x10101004L,0x00111004L,0x10111004L,
++0x20101000L,0x30101000L,0x20111000L,0x30111000L,
++0x20101004L,0x30101004L,0x20111004L,0x30111004L,
++},{
++/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
++0x00000000L,0x08000000L,0x00000008L,0x08000008L,
++0x00000400L,0x08000400L,0x00000408L,0x08000408L,
++0x00020000L,0x08020000L,0x00020008L,0x08020008L,
++0x00020400L,0x08020400L,0x00020408L,0x08020408L,
++0x00000001L,0x08000001L,0x00000009L,0x08000009L,
++0x00000401L,0x08000401L,0x00000409L,0x08000409L,
++0x00020001L,0x08020001L,0x00020009L,0x08020009L,
++0x00020401L,0x08020401L,0x00020409L,0x08020409L,
++0x02000000L,0x0A000000L,0x02000008L,0x0A000008L,
++0x02000400L,0x0A000400L,0x02000408L,0x0A000408L,
++0x02020000L,0x0A020000L,0x02020008L,0x0A020008L,
++0x02020400L,0x0A020400L,0x02020408L,0x0A020408L,
++0x02000001L,0x0A000001L,0x02000009L,0x0A000009L,
++0x02000401L,0x0A000401L,0x02000409L,0x0A000409L,
++0x02020001L,0x0A020001L,0x02020009L,0x0A020009L,
++0x02020401L,0x0A020401L,0x02020409L,0x0A020409L,
++},{
++/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
++0x00000000L,0x00000100L,0x00080000L,0x00080100L,
++0x01000000L,0x01000100L,0x01080000L,0x01080100L,
++0x00000010L,0x00000110L,0x00080010L,0x00080110L,
++0x01000010L,0x01000110L,0x01080010L,0x01080110L,
++0x00200000L,0x00200100L,0x00280000L,0x00280100L,
++0x01200000L,0x01200100L,0x01280000L,0x01280100L,
++0x00200010L,0x00200110L,0x00280010L,0x00280110L,
++0x01200010L,0x01200110L,0x01280010L,0x01280110L,
++0x00000200L,0x00000300L,0x00080200L,0x00080300L,
++0x01000200L,0x01000300L,0x01080200L,0x01080300L,
++0x00000210L,0x00000310L,0x00080210L,0x00080310L,
++0x01000210L,0x01000310L,0x01080210L,0x01080310L,
++0x00200200L,0x00200300L,0x00280200L,0x00280300L,
++0x01200200L,0x01200300L,0x01280200L,0x01280300L,
++0x00200210L,0x00200310L,0x00280210L,0x00280310L,
++0x01200210L,0x01200310L,0x01280210L,0x01280310L,
++},{
++/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
++0x00000000L,0x04000000L,0x00040000L,0x04040000L,
++0x00000002L,0x04000002L,0x00040002L,0x04040002L,
++0x00002000L,0x04002000L,0x00042000L,0x04042000L,
++0x00002002L,0x04002002L,0x00042002L,0x04042002L,
++0x00000020L,0x04000020L,0x00040020L,0x04040020L,
++0x00000022L,0x04000022L,0x00040022L,0x04040022L,
++0x00002020L,0x04002020L,0x00042020L,0x04042020L,
++0x00002022L,0x04002022L,0x00042022L,0x04042022L,
++0x00000800L,0x04000800L,0x00040800L,0x04040800L,
++0x00000802L,0x04000802L,0x00040802L,0x04040802L,
++0x00002800L,0x04002800L,0x00042800L,0x04042800L,
++0x00002802L,0x04002802L,0x00042802L,0x04042802L,
++0x00000820L,0x04000820L,0x00040820L,0x04040820L,
++0x00000822L,0x04000822L,0x00040822L,0x04040822L,
++0x00002820L,0x04002820L,0x00042820L,0x04042820L,
++0x00002822L,0x04002822L,0x00042822L,0x04042822L,
++}};
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/des/spr.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,204 @@
++/* crypto/des/spr.h */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++const DES_LONG des_SPtrans[8][64]={
++{
++/* nibble 0 */
++0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L,
++0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L,
++0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L,
++0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L,
++0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L,
++0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L,
++0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L,
++0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L,
++0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L,
++0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L,
++0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L,
++0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L,
++0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L,
++0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L,
++0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L,
++0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L,
++},{
++/* nibble 1 */
++0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L,
++0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L,
++0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L,
++0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L,
++0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L,
++0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L,
++0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L,
++0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L,
++0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L,
++0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L,
++0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L,
++0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L,
++0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L,
++0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L,
++0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L,
++0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L,
++},{
++/* nibble 2 */
++0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L,
++0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L,
++0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L,
++0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L,
++0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L,
++0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L,
++0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L,
++0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L,
++0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L,
++0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L,
++0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L,
++0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L,
++0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L,
++0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L,
++0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L,
++0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L,
++},{
++/* nibble 3 */
++0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L,
++0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L,
++0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L,
++0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L,
++0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L,
++0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L,
++0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L,
++0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L,
++0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L,
++0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L,
++0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L,
++0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L,
++0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L,
++0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L,
++0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L,
++0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L,
++},{
++/* nibble 4 */
++0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L,
++0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L,
++0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L,
++0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L,
++0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L,
++0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L,
++0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L,
++0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L,
++0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L,
++0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L,
++0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L,
++0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L,
++0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L,
++0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L,
++0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L,
++0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L,
++},{
++/* nibble 5 */
++0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L,
++0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L,
++0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L,
++0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L,
++0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L,
++0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L,
++0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L,
++0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L,
++0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L,
++0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L,
++0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L,
++0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L,
++0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L,
++0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L,
++0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L,
++0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L,
++},{
++/* nibble 6 */
++0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L,
++0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L,
++0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L,
++0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L,
++0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L,
++0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L,
++0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L,
++0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L,
++0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L,
++0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L,
++0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L,
++0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L,
++0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L,
++0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L,
++0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L,
++0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L,
++},{
++/* nibble 7 */
++0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L,
++0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L,
++0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L,
++0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L,
++0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L,
++0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L,
++0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L,
++0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L,
++0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L,
++0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L,
++0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L,
++0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L,
++0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L,
++0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L,
++0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L,
++0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L,
++}};
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/mast.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,33 @@
++struct mast_callbacks {
++  int (*packet_encap)(struct device *mast, void *context,
++                    struct sk_buff *skb, int flowref);
++  int (*link_inquire)(struct device *mast, void *context);
++};
++
++
++struct device *mast_init (int family,
++                        struct mast_callbacks *callbacks,
++                        unsigned int flags,
++                        unsigned int desired_unit,
++                        unsigned int max_flowref,
++                        void *context);
++
++int mast_destroy(struct device *mast);
++
++int mast_recv(struct device *mast, struct sk_buff *skb, int flowref);
++
++/* free this skb as being useless, increment failure count. */
++int mast_toast(struct device *mast, struct sk_buff *skb, int flowref);
++
++int mast_linkstat (struct device *mast, int flowref,
++                 int status);
++
++int mast_setreference (struct device *mast,
++                     int defaultSA);
++
++int mast_setneighbor (struct device *mast,
++                    struct sockaddr *source,
++                    struct sockaddr *destination,
++                    int flowref);
++
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,518 @@
++#ifndef _OPENSWAN_H
++/*
++ * header file for FreeS/WAN library functions
++ * Copyright (C) 1998, 1999, 2000  Henry Spencer.
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: openswan.h,v 1.93 2005/04/14 20:21:51 mcr Exp $
++ */
++#define       _OPENSWAN_H     /* seen it, no need to see it again */
++
++/* you'd think this should be builtin to compiler... */
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++
++
++/*
++ * We've just got to have some datatypes defined...  And annoyingly, just
++ * where we get them depends on whether we're in userland or not.
++ */
++/* things that need to come from one place or the other, depending */
++#ifdef __KERNEL__
++#include <linux/types.h>
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#define user_assert(foo)  /*nothing*/
++#else
++#include <sys/types.h>
++#include <netinet/in.h>
++#include <string.h>
++#include <ctype.h>
++#include <assert.h>
++#define user_assert(foo) assert(foo)
++#include <stdio.h>
++
++#  define uint8_t u_int8_t
++#  define uint16_t u_int16_t 
++#  define uint32_t u_int32_t 
++#  define uint64_t u_int64_t 
++
++
++#  define DEBUG_NO_STATIC static
++
++#endif
++
++#include <openswan/ipsec_param.h>
++
++
++/*
++ * Grab the kernel version to see if we have NET_21, and therefore 
++ * IPv6. Some of this is repeated from ipsec_kversions.h. Of course, 
++ * we aren't really testing if the kernel has IPv6, but rather if the
++ * the include files do.
++ */
++#include <linux/version.h>
++#ifndef KERNEL_VERSION
++#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
++#define NET_21
++#endif
++
++#ifndef IPPROTO_COMP
++#  define IPPROTO_COMP 108
++#endif /* !IPPROTO_COMP */
++
++#ifndef IPPROTO_INT
++#  define IPPROTO_INT 61
++#endif /* !IPPROTO_INT */
++
++#ifdef CONFIG_KLIPS_DEBUG
++#ifndef DEBUG_NO_STATIC
++#  define DEBUG_NO_STATIC
++#endif
++#else /* CONFIG_KLIPS_DEBUG */
++#ifndef DEBUG_NO_STATIC
++#  define DEBUG_NO_STATIC static
++#endif
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#if !defined(ESPINUDP_WITH_NON_IKE)
++#define ESPINUDP_WITH_NON_IKE   1  /* draft-ietf-ipsec-nat-t-ike-00/01 */
++#define ESPINUDP_WITH_NON_ESP   2  /* draft-ietf-ipsec-nat-t-ike-02    */
++#endif
++
++/*
++ * Basic data types for the address-handling functions.
++ * ip_address and ip_subnet are supposed to be opaque types; do not
++ * use their definitions directly, they are subject to change!
++ */
++
++/* first, some quick fakes in case we're on an old system with no IPv6 */
++#ifndef s6_addr16
++struct in6_addr {
++      union 
++      {
++              __u8            u6_addr8[16];
++              __u16           u6_addr16[8];
++              __u32           u6_addr32[4];
++      } in6_u;
++#define s6_addr                       in6_u.u6_addr8
++#define s6_addr16             in6_u.u6_addr16
++#define s6_addr32             in6_u.u6_addr32
++};
++struct sockaddr_in6 {
++      unsigned short int      sin6_family;    /* AF_INET6 */
++      __u16                   sin6_port;      /* Transport layer port # */
++      __u32                   sin6_flowinfo;  /* IPv6 flow information */
++      struct in6_addr         sin6_addr;      /* IPv6 address */
++      __u32                   sin6_scope_id;  /* scope id (new in RFC2553) */
++};
++#endif        /* !s6_addr16 */
++
++/* then the main types */
++typedef struct {
++      union {
++              struct sockaddr_in v4;
++              struct sockaddr_in6 v6;
++      } u;
++} ip_address;
++typedef struct {
++      ip_address addr;
++      int maskbits;
++} ip_subnet;
++
++/* and the SA ID stuff */
++#ifdef __KERNEL__
++typedef __u32 ipsec_spi_t;
++#else
++typedef u_int32_t ipsec_spi_t;
++#endif
++typedef struct {              /* to identify an SA, we need: */
++        ip_address dst;               /* A. destination host */
++        ipsec_spi_t spi;      /* B. 32-bit SPI, assigned by dest. host */
++#             define  SPI_PASS        256     /* magic values... */
++#             define  SPI_DROP        257     /* ...for use... */
++#             define  SPI_REJECT      258     /* ...with SA_INT */
++#             define  SPI_HOLD        259
++#             define  SPI_TRAP        260
++#             define  SPI_TRAPSUBNET  261
++      int proto;              /* C. protocol */
++#             define  SA_ESP  50      /* IPPROTO_ESP */
++#             define  SA_AH   51      /* IPPROTO_AH */
++#             define  SA_IPIP 4       /* IPPROTO_IPIP */
++#             define  SA_COMP 108     /* IPPROTO_COMP */
++#             define  SA_INT  61      /* IANA reserved for internal use */
++} ip_said;
++
++/* misc */
++typedef const char *err_t;    /* error message, or NULL for success */
++struct prng {                 /* pseudo-random-number-generator guts */
++      unsigned char sbox[256];
++      int i, j;
++      unsigned long count;
++};
++
++
++/*
++ * definitions for user space, taken from freeswan/ipsec_sa.h
++ */
++typedef uint32_t IPsecSAref_t;
++
++#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t))
++
++#define IPsecSAref2NFmark(x) ((x) << (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
++#define NFmark2IPsecSAref(x) ((x) >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
++
++#define IPSEC_SAREF_NULL (~((IPsecSAref_t)0))
++
++/* GCC magic for use in function definitions! */
++#ifdef GCC_LINT
++# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1)))
++# define NEVER_RETURNS __attribute__ ((noreturn))
++# define UNUSED __attribute__ ((unused))
++# define BLANK_FORMAT " "     /* GCC_LINT whines about empty formats */
++#else
++# define PRINTF_LIKE(n)       /* ignore */
++# define NEVER_RETURNS /* ignore */
++# define UNUSED /* ignore */
++# define BLANK_FORMAT ""
++#endif
++
++
++
++
++
++/*
++ * new IPv6-compatible functions
++ */
++
++/* text conversions */
++err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst);
++size_t ultot(unsigned long src, int format, char *buf, size_t buflen);
++#define       ULTOT_BUF       (22+1)  /* holds 64 bits in octal */
++err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst);
++err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst);
++size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen);
++/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */
++#define       ADDRTOT_BUF     (32*2 + 3 + 1 + 3 + 1 + 1)
++err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst);
++size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen);
++#define       SUBNETTOT_BUF   (ADDRTOT_BUF + 1 + 3)
++size_t subnetporttot(const ip_subnet *src, int format, char *buf, size_t buflen);
++#define       SUBNETPROTOTOT_BUF      (SUBNETTOTO_BUF + ULTOT_BUF)
++err_t ttosa(const char *src, size_t srclen, ip_said *dst);
++size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen);
++#define       SATOT_BUF       (5 + ULTOA_BUF + 1 + ADDRTOT_BUF)
++err_t ttodata(const char *src, size_t srclen, int base, char *buf,
++                                              size_t buflen, size_t *needed);
++err_t ttodatav(const char *src, size_t srclen, int base,
++             char *buf,  size_t buflen, size_t *needed,
++             char *errp, size_t errlen, unsigned int flags);
++#define       TTODATAV_BUF    40      /* ttodatav's largest non-literal message */
++#define TTODATAV_IGNORESPACE  (1<<1)  /* ignore spaces in base64 encodings*/
++#define TTODATAV_SPACECOUNTS  0       /* do not ignore spaces in base64   */
++
++size_t datatot(const char *src, size_t srclen, int format, char *buf,
++                                                              size_t buflen);
++size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst,
++                                                              size_t dstlen);
++size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m,
++                                      size_t mlen, char *dst, size_t dstlen);
++#define       KEYID_BUF       10      /* up to 9 text digits plus NUL */
++err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port,
++                                                       int *has_port_wildcard);
++
++/* initializations */
++void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst);
++err_t loopbackaddr(int af, ip_address *dst);
++err_t unspecaddr(int af, ip_address *dst);
++err_t anyaddr(int af, ip_address *dst);
++err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst);
++err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst);
++err_t addrtosubnet(const ip_address *addr, ip_subnet *dst);
++
++/* misc. conversions and related */
++err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst);
++int addrtypeof(const ip_address *src);
++int subnettypeof(const ip_subnet *src);
++size_t addrlenof(const ip_address *src);
++size_t addrbytesptr(const ip_address *src, const unsigned char **dst);
++size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen);
++int masktocount(const ip_address *src);
++void networkof(const ip_subnet *src, ip_address *dst);
++void maskof(const ip_subnet *src, ip_address *dst);
++
++/* tests */
++int sameaddr(const ip_address *a, const ip_address *b);
++int addrcmp(const ip_address *a, const ip_address *b);
++int samesubnet(const ip_subnet *a, const ip_subnet *b);
++int addrinsubnet(const ip_address *a, const ip_subnet *s);
++int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);
++int subnetishost(const ip_subnet *s);
++int samesaid(const ip_said *a, const ip_said *b);
++int sameaddrtype(const ip_address *a, const ip_address *b);
++int samesubnettype(const ip_subnet *a, const ip_subnet *b);
++int isanyaddr(const ip_address *src);
++int isunspecaddr(const ip_address *src);
++int isloopbackaddr(const ip_address *src);
++
++/* low-level grot */
++int portof(const ip_address *src);
++void setportof(int port, ip_address *dst);
++struct sockaddr *sockaddrof(ip_address *src);
++size_t sockaddrlenof(const ip_address *src);
++
++/* PRNG */
++void prng_init(struct prng *prng, const unsigned char *key, size_t keylen);
++void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen);
++unsigned long prng_count(struct prng *prng);
++void prng_final(struct prng *prng);
++
++/* odds and ends */
++const char *ipsec_version_code(void);
++const char *ipsec_version_string(void);
++const char **ipsec_copyright_notice(void);
++
++const char *dns_string_rr(int rr, char *buf, int bufsize);
++const char *dns_string_datetime(time_t seconds,
++                              char *buf,
++                              int bufsize);
++
++
++/*
++ * old functions, to be deleted eventually
++ */
++
++/* unsigned long */
++const char *                  /* NULL for success, else string literal */
++atoul(
++      const char *src,
++      size_t srclen,          /* 0 means strlen(src) */
++      int base,               /* 0 means figure it out */
++      unsigned long *resultp
++);
++size_t                                /* space needed for full conversion */
++ultoa(
++      unsigned long n,
++      int base,
++      char *dst,
++      size_t dstlen
++);
++#define       ULTOA_BUF       21      /* just large enough for largest result, */
++                              /* assuming 64-bit unsigned long! */
++
++/* Internet addresses */
++const char *                  /* NULL for success, else string literal */
++atoaddr(
++      const char *src,
++      size_t srclen,          /* 0 means strlen(src) */
++      struct in_addr *addr
++);
++size_t                                /* space needed for full conversion */
++addrtoa(
++      struct in_addr addr,
++      int format,             /* character; 0 means default */
++      char *dst,
++      size_t dstlen
++);
++#define       ADDRTOA_BUF     16      /* just large enough for largest result */
++
++/* subnets */
++const char *                  /* NULL for success, else string literal */
++atosubnet(
++      const char *src,
++      size_t srclen,          /* 0 means strlen(src) */
++      struct in_addr *addr,
++      struct in_addr *mask
++);
++size_t                                /* space needed for full conversion */
++subnettoa(
++      struct in_addr addr,
++      struct in_addr mask,
++      int format,             /* character; 0 means default */
++      char *dst,
++      size_t dstlen
++);
++#define       SUBNETTOA_BUF   32      /* large enough for worst case result */
++
++/* ranges */
++const char *                  /* NULL for success, else string literal */
++atoasr(
++      const char *src,
++      size_t srclen,          /* 0 means strlen(src) */
++      char *type,             /* 'a', 's', 'r' */
++      struct in_addr *addrs   /* two-element array */
++);
++size_t                                /* space needed for full conversion */
++rangetoa(
++      struct in_addr *addrs,  /* two-element array */
++      int format,             /* character; 0 means default */
++      char *dst,
++      size_t dstlen
++);
++#define       RANGETOA_BUF    34      /* large enough for worst case result */
++
++/* data types for SA conversion functions */
++
++/* generic data, e.g. keys */
++const char *                  /* NULL for success, else string literal */
++atobytes(
++      const char *src,
++      size_t srclen,          /* 0 means strlen(src) */
++      char *dst,
++      size_t dstlen,
++      size_t *lenp            /* NULL means don't bother telling me */
++);
++size_t                                /* 0 failure, else true size */
++bytestoa(
++      const char *src,
++      size_t srclen,
++      int format,             /* character; 0 means default */
++      char *dst,
++      size_t dstlen
++);
++
++/* old versions of generic-data functions; deprecated */
++size_t                                /* 0 failure, else true size */
++atodata(
++      const char *src,
++      size_t srclen,          /* 0 means strlen(src) */
++      char *dst,
++      size_t dstlen
++);
++size_t                                /* 0 failure, else true size */
++datatoa(
++      const char *src,
++      size_t srclen,
++      int format,             /* character; 0 means default */
++      char *dst,
++      size_t dstlen
++);
++
++/* part extraction and special addresses */
++struct in_addr
++subnetof(
++      struct in_addr addr,
++      struct in_addr mask
++);
++struct in_addr
++hostof(
++      struct in_addr addr,
++      struct in_addr mask
++);
++struct in_addr
++broadcastof(
++      struct in_addr addr,
++      struct in_addr mask
++);
++
++/* mask handling */
++int
++goodmask(
++      struct in_addr mask
++);
++int
++masktobits(
++      struct in_addr mask
++);
++struct in_addr
++bitstomask(
++      int n
++);
++
++
++
++/*
++ * general utilities
++ */
++
++#ifndef __KERNEL__
++/* option pickup from files (userland only because of use of FILE) */
++const char *optionsfrom(const char *filename, int *argcp, char ***argvp,
++                                              int optind, FILE *errorreport);
++
++/* sanitize a string */
++extern size_t sanitize_string(char *buf, size_t size);
++
++#endif
++
++
++/*
++ * ENUM of klips debugging values. Not currently used in klips.
++ * debug flag is actually 32 -bits, but only one bit is ever used,
++ * so we can actually pack it all into a single 32-bit word.
++ */
++enum klips_debug_flags {
++    KDF_VERBOSE     = 0,
++    KDF_XMIT        = 1,
++    KDF_NETLINK     = 2, /* obsolete */
++    KDF_XFORM       = 3,
++    KDF_EROUTE      = 4,
++    KDF_SPI         = 5,
++    KDF_RADIJ       = 6,
++    KDF_ESP         = 7,
++    KDF_AH          = 8, /* obsolete */
++    KDF_RCV         = 9,
++    KDF_TUNNEL      = 10,
++    KDF_PFKEY       = 11,
++    KDF_COMP        = 12
++};
++
++
++/*
++ * Debugging levels for pfkey_lib_debug
++ */
++#define PF_KEY_DEBUG_PARSE_NONE    0
++#define PF_KEY_DEBUG_PARSE_PROBLEM 1
++#define PF_KEY_DEBUG_PARSE_STRUCT  2
++#define PF_KEY_DEBUG_PARSE_FLOW    4
++#define PF_KEY_DEBUG_BUILD         8
++#define PF_KEY_DEBUG_PARSE_MAX    15
++
++extern unsigned int pfkey_lib_debug;  /* bits selecting what to report */
++
++/*
++ * pluto and lwdnsq need to know the maximum size of the commands to,
++ * and replies from lwdnsq. 
++ */
++
++#define LWDNSQ_CMDBUF_LEN      1024
++#define LWDNSQ_RESULT_LEN_MAX  4096
++
++
++/* syntax for passthrough SA */
++#ifndef PASSTHROUGHNAME
++#define       PASSTHROUGHNAME "%passthrough"
++#define       PASSTHROUGH4NAME        "%passthrough4"
++#define       PASSTHROUGH6NAME        "%passthrough6"
++#define       PASSTHROUGHIS   "tun0@0.0.0.0"
++#define       PASSTHROUGH4IS  "tun0@0.0.0.0"
++#define       PASSTHROUGH6IS  "tun0@::"
++#define       PASSTHROUGHTYPE "tun"
++#define       PASSTHROUGHSPI  0
++#define       PASSTHROUGHDST  0
++#endif
++
++
++
++#endif /* _OPENSWAN_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipcomp.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,61 @@
++/*
++ * IPCOMP zlib interface code.
++ * Copyright (C) 2000  Svenning Soerensen <svenning@post5.tele.dk>
++ * Copyright (C) 2000, 2001  Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++
++ RCSID $Id: ipcomp.h,v 1.14 2004/07/10 19:08:41 mcr Exp $
++
++ */
++
++/* SSS */
++
++#ifndef _IPCOMP_H
++#define _IPCOMP_H
++
++/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */
++#ifndef IPCOMP_PREFIX
++#define IPCOMP_PREFIX
++#endif /* IPCOMP_PREFIX */
++
++#ifndef IPPROTO_COMP
++#define IPPROTO_COMP 108
++#endif /* IPPROTO_COMP */
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int sysctl_ipsec_debug_ipcomp;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++struct ipcomphdr {                    /* IPCOMP header */
++    __u8    ipcomp_nh;                /* Next header (protocol) */
++    __u8    ipcomp_flags;     /* Reserved, must be 0 */
++    __u16   ipcomp_cpi;               /* Compression Parameter Index */
++};
++
++extern struct inet_protocol comp_protocol;
++extern int sysctl_ipsec_debug_ipcomp;
++
++#define IPCOMP_UNCOMPRESSABLE     0x000000001
++#define IPCOMP_COMPRESSIONERROR   0x000000002
++#define IPCOMP_PARMERROR          0x000000004
++#define IPCOMP_DECOMPRESSIONERROR 0x000000008
++
++#define IPCOMP_ADAPT_INITIAL_TRIES    8
++#define IPCOMP_ADAPT_INITIAL_SKIP     4
++#define IPCOMP_ADAPT_SUBSEQ_TRIES     2
++#define IPCOMP_ADAPT_SUBSEQ_SKIP      8
++
++/* Function prototypes */
++struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags);
++struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags);
++
++#endif /* _IPCOMP_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_ah.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,200 @@
++/*
++ * Authentication Header declarations
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_ah.h,v 1.26 2004/09/13 02:22:10 mcr Exp $
++ */
++
++#include "ipsec_md5h.h"
++#include "ipsec_sha1.h"
++
++#ifndef IPPROTO_AH
++#define IPPROTO_AH 51
++#endif /* IPPROTO_AH */
++
++#include "ipsec_auth.h"
++
++#ifdef __KERNEL__
++
++extern struct inet_protocol ah_protocol;
++
++struct options;
++
++struct ahhdr                          /* Generic AH header */
++{
++      __u8    ah_nh;                  /* Next header (protocol) */
++      __u8    ah_hl;                  /* AH length, in 32-bit words */
++      __u16   ah_rv;                  /* reserved, must be 0 */
++      __u32   ah_spi;                 /* Security Parameters Index */
++        __u32   ah_rpl;                 /* Replay prevention */
++      __u8    ah_data[AHHMAC_HASHLEN];/* Authentication hash */
++};
++#define AH_BASIC_LEN 8      /* basic AH header is 8 bytes, nh,hl,rv,spi
++                           * and the ah_hl, says how many bytes after that
++                           * to cover. */
++
++extern struct xform_functions ah_xform_funcs[];
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int debug_ah;
++#endif /* CONFIG_KLIPS_DEBUG */
++#endif /* __KERNEL__ */
++
++/*
++ * $Log: ipsec_ah.h,v $
++ * Revision 1.26  2004/09/13 02:22:10  mcr
++ *    #define inet_protocol if necessary.
++ *
++ * Revision 1.25  2004/09/06 18:35:41  mcr
++ *    2.6.8.1 gets rid of inet_protocol->net_protocol compatibility,
++ *    so adjust for that.
++ *
++ * Revision 1.24  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.23  2004/04/05 19:55:04  mcr
++ * Moved from linux/include/freeswan/ipsec_ah.h,v
++ *
++ * Revision 1.22  2004/04/05 19:41:05  mcr
++ *    merged alg-branch code.
++ *
++ * Revision 1.21  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.22  2003/12/11 20:14:58  mcr
++ *    refactored the xmit code, to move all encapsulation
++ *    code into protocol functions. Note that all functions
++ *    are essentially done by a single function, which is probably
++ *    wrong.
++ *    the rcv_functions structures are renamed xform_functions.
++ *
++ * Revision 1.21  2003/12/06 21:21:19  mcr
++ *    split up receive path into per-transform files, for
++ *    easier later removal.
++ *
++ * Revision 1.20.8.1  2003/12/22 15:25:52  jjo
++ *      Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.20  2003/02/06 02:21:34  rgb
++ *
++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h .
++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr".
++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code.
++ *
++ * Revision 1.19  2002/09/16 21:19:13  mcr
++ *    fixes for west-ah-icmp-01 - length of AH header must be
++ *    calculated properly, and next_header field properly copied.
++ *
++ * Revision 1.18  2002/05/14 02:37:02  rgb
++ * Change reference from _TDB to _IPSA.
++ *
++ * Revision 1.17  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_ah.h,v
++ *
++ * Revision 1.16  2002/02/20 01:27:06  rgb
++ * Ditched a pile of structs only used by the old Netlink interface.
++ *
++ * Revision 1.15  2001/12/11 02:35:57  rgb
++ * Change "struct net_device" to "struct device" for 2.2 compatibility.
++ *
++ * Revision 1.14  2001/11/26 09:23:47  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.13.2.1  2001/09/25 02:18:24  mcr
++ *    replace "struct device" with "struct netdevice"
++ *
++ * Revision 1.13  2001/06/14 19:35:08  rgb
++ * Update copyright date.
++ *
++ * Revision 1.12  2000/09/12 03:21:20  rgb
++ * Cleared out unused htonq.
++ *
++ * Revision 1.11  2000/09/08 19:12:55  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.10  2000/01/21 06:13:10  rgb
++ * Tidied up spacing.
++ * Added macros for HMAC padding magic numbers.(kravietz)
++ *
++ * Revision 1.9  1999/12/07 18:16:23  rgb
++ * Fixed comments at end of #endif lines.
++ *
++ * Revision 1.8  1999/04/11 00:28:56  henry
++ * GPL boilerplate
++ *
++ * Revision 1.7  1999/04/06 04:54:25  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.6  1999/01/26 02:06:01  rgb
++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
++ *
++ * Revision 1.5  1999/01/22 06:17:49  rgb
++ * Updated macro comments.
++ * Added context types to support algorithm switch code.
++ * 64-bit clean-up -- converting 'u long long' to __u64.
++ *
++ * Revision 1.4  1998/07/14 15:54:56  rgb
++ * Add #ifdef __KERNEL__ to protect kernel-only structures.
++ *
++ * Revision 1.3  1998/06/30 18:05:16  rgb
++ * Comment out references to htonq.
++ *
++ * Revision 1.2  1998/06/25 19:33:46  rgb
++ * Add prototype for protocol receive function.
++ * Rearrange for more logical layout.
++ *
++ * Revision 1.1  1998/06/18 21:27:43  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.4  1998/05/18 22:28:43  rgb
++ * Disable key printing facilities from /proc/net/ipsec_*.
++ *
++ * Revision 1.3  1998/04/21 21:29:07  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.2  1998/04/12 22:03:17  rgb
++ * Updated ESP-3DES-HMAC-MD5-96,
++ *    ESP-DES-HMAC-MD5-96,
++ *    AH-HMAC-MD5-96,
++ *    AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
++ *
++ * Fixed eroute references in /proc/net/ipsec*.
++ *
++ * Started to patch module unloading memory leaks in ipsec_netlink and
++ * radij tree unloading.
++ *
++ * Revision 1.1  1998/04/09 03:05:55  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * Added definitions for new AH transforms.
++ *
++ * Revision 0.3  1996/11/20 14:35:48  ji
++ * Minor Cleanup.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_alg.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,248 @@
++/*
++ * Modular extensions service and registration functions interface
++ *
++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ *
++ * ipsec_alg.h,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
++ *
++ */
++/*
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ */
++#ifndef IPSEC_ALG_H
++#define IPSEC_ALG_H
++
++/* 
++ *   gcc >= 3.2 has removed __FUNCTION__, replaced by C99 __func__
++ *   *BUT* its a compiler variable.
++ */
++#if (__GNUC__ >= 3)
++#ifndef __FUNCTION__
++#define __FUNCTION__ __func__
++#endif
++#endif
++
++/*    Version 0.8.1-0 */
++#define IPSEC_ALG_VERSION     0x00080100
++
++#include <linux/types.h>
++#include <linux/list.h>
++#include <asm/atomic.h>
++#include <pfkey.h>
++
++/*    
++ *    The following structs are used via pointers in ipsec_alg object to
++ *    avoid ipsec_alg.h coupling with freeswan headers, thus simplifying
++ *    module development
++ */
++struct ipsec_sa;
++struct esp;
++
++/**************************************
++ *
++ *    Main registration object 
++ *
++ *************************************/
++#define IPSEC_ALG_VERSION_QUAD(v)     \
++      (v>>24),((v>>16)&0xff),((v>>8)&0xff),(v&0xff)
++/*    
++ *    Main ipsec_alg objects: "OOPrograming wannabe"
++ *    Hierachy (carefully handled with _minimal_ cast'ing):
++ *
++ *      ipsec_alg+
++ *             +->ipsec_alg_enc  (ixt_alg_type=SADB_EXT_SUPPORTED_ENCRYPT)
++ *             +->ipsec_alg_auth (ixt_alg_type=SADB_EXT_SUPPORTED_AUTH)
++ */
++
++/***************************************************************
++ *
++ *    INTERFACE object: struct ipsec_alg
++ *
++ ***************************************************************/
++
++#define ixt_alg_type ixt_support.ias_exttype
++#define ixt_alg_id   ixt_support.ias_id
++
++#define IPSEC_ALG_ST_SUPP     0x01
++#define IPSEC_ALG_ST_REGISTERED 0x02
++#define IPSEC_ALG_ST_EXCL     0x04
++struct ipsec_alg {
++      unsigned ixt_version;   /* only allow this version (or 'near')*/ \
++      struct list_head ixt_list;      /* dlinked list */ \
++      struct module *ixt_module;      /* THIS_MODULE */ \
++      unsigned ixt_state;             /* state flags */ \
++      atomic_t ixt_refcnt;    /* ref. count when pointed from ipsec_sa */ \
++      char ixt_name[16];      /* descriptive short name, eg. "3des" */ \
++      void *ixt_data;         /* private for algo implementation */ \
++      uint8_t  ixt_blocksize; /* blocksize in bytes */ \
++
++      struct ipsec_alg_supported ixt_support;
++};
++/* 
++ *    Note the const in cbc_encrypt IV arg:
++ *    some ciphers like to toast passed IV (eg. 3DES): make a local IV copy
++ */
++struct ipsec_alg_enc {
++      struct ipsec_alg ixt_common;
++      unsigned ixt_e_keylen;          /* raw key length in bytes          */
++      unsigned ixt_e_ctx_size;        /* sa_p->key_e_size */
++      int (*ixt_e_set_key)(struct ipsec_alg_enc *alg, __u8 *key_e, const __u8 *key, size_t keysize);
++      __u8 *(*ixt_e_new_key)(struct ipsec_alg_enc *alg, const __u8 *key, size_t keysize);
++      void (*ixt_e_destroy_key)(struct ipsec_alg_enc *alg, __u8 *key_e);
++      int (*ixt_e_cbc_encrypt)(struct ipsec_alg_enc *alg, __u8 *key_e, __u8 *in, int ilen, const __u8 *iv, int encrypt);
++};
++struct ipsec_alg_auth {
++      struct ipsec_alg ixt_common;
++      unsigned ixt_a_keylen;          /* raw key length in bytes          */
++      unsigned ixt_a_ctx_size;        /* sa_p->key_a_size */
++      unsigned ixt_a_authlen;         /* 'natural' auth. hash len (bytes) */
++      int (*ixt_a_hmac_set_key)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *key, int keylen);
++      int (*ixt_a_hmac_hash)(struct ipsec_alg_auth *alg, __u8 *key_a, const __u8 *dat, int len, __u8 *hash, int hashlen);
++};
++/*    
++ *    These are _copies_ of SADB_EXT_SUPPORTED_{AUTH,ENCRYPT}, 
++ *    to avoid header coupling for true constants
++ *    about headers ... "cp is your friend" --Linus
++ */
++#define IPSEC_ALG_TYPE_AUTH   14
++#define IPSEC_ALG_TYPE_ENCRYPT        15
++
++/***************************************************************
++ *
++ *    INTERFACE for module loading,testing, and unloading
++ *
++ ***************************************************************/
++/*    -  registration calls   */
++int register_ipsec_alg(struct ipsec_alg *);
++int unregister_ipsec_alg(struct ipsec_alg *);
++/*    -  optional (simple test) for algos     */
++int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int testparm);
++/*    inline wrappers (usefull for type validation */
++static inline int register_ipsec_alg_enc(struct ipsec_alg_enc *ixt) {
++      return register_ipsec_alg((struct ipsec_alg*)ixt);
++}
++static inline int unregister_ipsec_alg_enc(struct ipsec_alg_enc *ixt) {
++      return unregister_ipsec_alg((struct ipsec_alg*)ixt);
++}
++static inline int register_ipsec_alg_auth(struct ipsec_alg_auth *ixt) {
++      return register_ipsec_alg((struct ipsec_alg*)ixt);
++}
++static inline int unregister_ipsec_alg_auth(struct ipsec_alg_auth *ixt) {
++      return unregister_ipsec_alg((struct ipsec_alg*)ixt);
++}
++
++/*****************************************************************
++ *
++ *    INTERFACE for ENC services: key creation, encrypt function
++ *
++ *****************************************************************/
++
++#define IPSEC_ALG_ENCRYPT 1
++#define IPSEC_ALG_DECRYPT 0
++
++/*    encryption key context creation function */
++int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p);
++/* 
++ *    ipsec_alg_esp_encrypt(): encrypt ilen bytes in idat returns
++ *    0 or ERR<0
++ */
++int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 *idat, int ilen, const __u8 *iv, int action);
++
++/***************************************************************
++ *
++ *    INTERFACE for AUTH services: key creation, hash functions
++ *
++ ***************************************************************/
++int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p);
++int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) ;
++#define ipsec_alg_sa_esp_update(c,k,l) ipsec_alg_sa_esp_hash(c,k,l,NULL,0)
++
++/* only called from ipsec_init.c */
++int ipsec_alg_init(void);
++
++/* algo module glue for static algos */
++void ipsec_alg_static_init(void);
++typedef int (*ipsec_alg_init_func_t) (void);
++
++/**********************************************
++ *
++ *    INTERFACE for ipsec_sa init and wipe
++ *
++ **********************************************/
++
++/* returns true if ipsec_sa has ipsec_alg obj attached */
++/* 
++ * Initializes ipsec_sa's ipsec_alg object, using already loaded
++ * proto, authalg, encalg.; links ipsec_alg objects (enc, auth)
++ */
++int ipsec_alg_sa_init(struct ipsec_sa *sa_p);
++/* 
++ * Destroys ipsec_sa's ipsec_alg object
++ * unlinking ipsec_alg objects
++ */
++int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p);
++
++#define IPSEC_ALG_MODULE_INIT_MOD( func_name )        \
++      static int func_name(void);             \
++      module_init(func_name);                 \
++      static int __init func_name(void)
++#define IPSEC_ALG_MODULE_EXIT_MOD( func_name )        \
++      static void func_name(void);            \
++      module_exit(func_name);                 \
++      static void __exit func_name(void)
++
++#define IPSEC_ALG_MODULE_INIT_STATIC( func_name )     \
++      extern int func_name(void);             \
++      int func_name(void)
++#define IPSEC_ALG_MODULE_EXIT_STATIC( func_name )     \
++      extern void func_name(void);            \
++      void func_name(void)
++
++/**********************************************
++ *
++ *    2.2 backport for some 2.4 useful module stuff
++ *
++ **********************************************/
++#ifdef MODULE
++#ifndef THIS_MODULE
++#define THIS_MODULE          (&__this_module)
++#endif
++#ifndef module_init
++typedef int (*__init_module_func_t)(void);
++typedef void (*__cleanup_module_func_t)(void);
++
++#define module_init(x) \
++        int init_module(void) __attribute__((alias(#x))); \
++        static inline __init_module_func_t __init_module_inline(void) \
++        { return x; }
++#define module_exit(x) \
++        void cleanup_module(void) __attribute__((alias(#x))); \
++        static inline __cleanup_module_func_t __cleanup_module_inline(void) \
++        { return x; }
++#endif
++#define IPSEC_ALG_MODULE_INIT( func_name )    IPSEC_ALG_MODULE_INIT_MOD( func_name )  
++#define IPSEC_ALG_MODULE_EXIT( func_name )    IPSEC_ALG_MODULE_EXIT_MOD( func_name )
++
++#else /* not MODULE */
++#ifndef THIS_MODULE
++#define THIS_MODULE          NULL
++#endif
++/*    
++ *    I only want module_init() magic 
++ *    when algo.c file *is THE MODULE*, in all other
++ *    cases, initialization is called explicitely from ipsec_alg_init()
++ */
++#define IPSEC_ALG_MODULE_INIT( func_name )      IPSEC_ALG_MODULE_INIT_STATIC(func_name)
++#define IPSEC_ALG_MODULE_EXIT( func_name )    IPSEC_ALG_MODULE_EXIT_STATIC(func_name)
++#endif
++
++#endif /* IPSEC_ALG_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_alg_3des.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,12 @@
++struct TripleDES_context {
++  des_key_schedule s1;
++  des_key_schedule s2;
++  des_key_schedule s3;
++};
++typedef struct TripleDES_context TripleDES_context;
++
++#define ESP_3DES_KEY_SZ       3*(sizeof(des_cblock))
++#define ESP_3DES_CBC_BLK_LEN    8
++
++
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_auth.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,100 @@
++/*
++ * Authentication Header declarations
++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_auth.h,v 1.3 2004/04/06 02:49:08 mcr Exp $
++ */
++
++#include "ipsec_md5h.h"
++#include "ipsec_sha1.h"
++
++#ifndef IPSEC_AUTH_H
++#define IPSEC_AUTH_H
++
++#define AH_FLENGTH            12              /* size of fixed part */
++#define AHMD5_KMAX            64              /* MD5 max 512 bits key */
++#define AHMD5_AMAX            12              /* MD5 96 bits of authenticator */
++
++#define AHMD596_KLEN          16              /* MD5 128 bits key */
++#define AHSHA196_KLEN         20              /* SHA1 160 bits key */
++
++#define AHMD596_ALEN          16              /* MD5 128 bits authentication length */
++#define AHSHA196_ALEN         20              /* SHA1 160 bits authentication length */
++
++#define AHMD596_BLKLEN        64              /* MD5 block length */
++#define AHSHA196_BLKLEN       64              /* SHA1 block length */
++#define AHSHA2_256_BLKLEN     64              /* SHA2-256 block length */
++#define AHSHA2_384_BLKLEN     128             /* SHA2-384 block length (?) */
++#define AHSHA2_512_BLKLEN     128             /* SHA2-512 block length */
++
++#define AH_BLKLEN_MAX                 128             /* keep up to date! */
++
++
++#define AH_AMAX               AHSHA196_ALEN   /* keep up to date! */
++#define AHHMAC_HASHLEN        12              /* authenticator length of 96bits */
++#define AHHMAC_RPLLEN         4               /* 32 bit replay counter */
++
++#define DB_AH_PKTRX           0x0001
++#define DB_AH_PKTRX2          0x0002
++#define DB_AH_DMP             0x0004
++#define DB_AH_IPSA            0x0010
++#define DB_AH_XF              0x0020
++#define DB_AH_INAU            0x0040
++#define DB_AH_REPLAY          0x0100
++
++#ifdef __KERNEL__
++
++/* General HMAC algorithm is described in RFC 2104 */
++
++#define               HMAC_IPAD       0x36
++#define               HMAC_OPAD       0x5C
++
++struct md5_ctx {
++      MD5_CTX ictx;           /* context after H(K XOR ipad) */
++      MD5_CTX octx;           /* context after H(K XOR opad) */
++};
++
++struct sha1_ctx {
++      SHA1_CTX ictx;          /* context after H(K XOR ipad) */
++      SHA1_CTX octx;          /* context after H(K XOR opad) */
++};
++
++struct auth_alg {
++      void (*init)(void *ctx);
++      void (*update)(void *ctx, unsigned char *bytes, __u32 len);
++      void (*final)(unsigned char *hash, void *ctx);
++      int hashlen;
++};
++
++struct options;
++
++#endif /* __KERNEL__ */
++#endif /* IPSEC_AUTH_H */
++
++/*
++ * $Log: ipsec_auth.h,v $
++ * Revision 1.3  2004/04/06 02:49:08  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.2  2004/04/05 19:55:04  mcr
++ * Moved from linux/include/freeswan/ipsec_auth.h,v
++ *
++ * Revision 1.1  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.1  2003/12/06 21:21:19  mcr
++ *    split up receive path into per-transform files, for
++ *    easier later removal.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_encap.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,149 @@
++/*
++ * declarations relevant to encapsulation-like operations
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_encap.h,v 1.19 2004/04/05 19:55:04 mcr Exp $
++ */
++
++#ifndef _IPSEC_ENCAP_H_
++
++#define SENT_IP4      16      /* data is two struct in_addr + proto + ports*/
++                      /* (2 * sizeof(struct in_addr)) */
++                      /* sizeof(struct sockaddr_encap)
++                         - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */
++
++struct sockaddr_encap
++{
++      __u8    sen_len;                /* length */
++      __u8    sen_family;             /* AF_ENCAP */
++      __u16   sen_type;               /* see SENT_* */
++      union
++      {
++              struct                  /* SENT_IP4 */
++              {
++                      struct in_addr Src;
++                      struct in_addr Dst;
++                      __u8 Proto;
++                      __u16 Sport;
++                      __u16 Dport;
++              } Sip4;
++      } Sen;
++};
++
++#define sen_ip_src    Sen.Sip4.Src
++#define sen_ip_dst    Sen.Sip4.Dst
++#define sen_proto       Sen.Sip4.Proto
++#define sen_sport       Sen.Sip4.Sport
++#define sen_dport       Sen.Sip4.Dport
++
++#ifndef AF_ENCAP
++#define AF_ENCAP 26
++#endif /* AF_ENCAP */
++
++#define _IPSEC_ENCAP_H_
++#endif /* _IPSEC_ENCAP_H_ */
++
++/*
++ * $Log: ipsec_encap.h,v $
++ * Revision 1.19  2004/04/05 19:55:04  mcr
++ * Moved from linux/include/freeswan/ipsec_encap.h,v
++ *
++ * Revision 1.18  2003/10/31 02:27:05  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.17.30.1  2003/09/21 13:59:38  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.17  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_encap.h,v
++ *
++ * Revision 1.16  2001/11/26 09:23:47  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.15.2.1  2001/09/25 02:18:54  mcr
++ *    struct eroute moved to ipsec_eroute.h
++ *
++ * Revision 1.15  2001/09/14 16:58:36  rgb
++ * Added support for storing the first and last packets through a HOLD.
++ *
++ * Revision 1.14  2001/09/08 21:13:31  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.13  2001/06/14 19:35:08  rgb
++ * Update copyright date.
++ *
++ * Revision 1.12  2001/05/27 06:12:10  rgb
++ * Added structures for pid, packet count and last access time to eroute.
++ * Added packet count to beginning of /proc/net/ipsec_eroute.
++ *
++ * Revision 1.11  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.10  2000/03/22 16:15:36  rgb
++ * Fixed renaming of dev_get (MB).
++ *
++ * Revision 1.9  2000/01/21 06:13:26  rgb
++ * Added a macro for AF_ENCAP
++ *
++ * Revision 1.8  1999/12/31 14:56:55  rgb
++ * MB fix for 2.3 dev-use-count.
++ *
++ * Revision 1.7  1999/11/18 04:09:18  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ *
++ * Revision 1.6  1999/09/24 00:34:13  rgb
++ * Add Marc Boucher's support for 2.3.xx+.
++ *
++ * Revision 1.5  1999/04/11 00:28:57  henry
++ * GPL boilerplate
++ *
++ * Revision 1.4  1999/04/06 04:54:25  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.3  1998/10/19 14:44:28  rgb
++ * Added inclusion of freeswan.h.
++ * sa_id structure implemented and used: now includes protocol.
++ *
++ * Revision 1.2  1998/07/14 18:19:33  rgb
++ * Added #ifdef __KERNEL__ directives to restrict scope of header.
++ *
++ * Revision 1.1  1998/06/18 21:27:44  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.2  1998/04/21 21:29:10  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.1  1998/04/09 03:05:58  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * Minor cosmetic changes.
++ *
++ * Revision 0.3  1996/11/20 14:35:48  ji
++ * Minor Cleanup.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_eroute.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,112 @@
++/*
++ * @(#) declarations of eroute structures
++ *
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
++ * Copyright (C) 2001                    Michael Richardson <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_eroute.h,v 1.5 2004/04/05 19:55:05 mcr Exp $
++ *
++ * derived from ipsec_encap.h 1.15 on 2001/9/18 by mcr.
++ *
++ */
++
++#ifndef _IPSEC_EROUTE_H_
++
++#include "radij.h"
++#include "ipsec_encap.h"
++#include "ipsec_radij.h"
++
++/*
++ * The "type" is really part of the address as far as the routing
++ * system is concerned. By using only one bit in the type field
++ * for each type, we sort-of make sure that different types of
++ * encapsulation addresses won't be matched against the wrong type.
++ */
++
++/*
++ * An entry in the radix tree 
++ */
++
++struct rjtentry
++{
++      struct  radij_node rd_nodes[2]; /* tree glue, and other values */
++#define       rd_key(r)       ((struct sockaddr_encap *)((r)->rd_nodes->rj_key))
++#define       rd_mask(r)      ((struct sockaddr_encap *)((r)->rd_nodes->rj_mask))
++      short   rd_flags;
++      short   rd_count;
++};
++
++struct ident
++{
++      __u16   type;   /* identity type */
++      __u64   id;     /* identity id */
++      __u8    len;    /* identity len */
++      caddr_t data;   /* identity data */
++};
++
++/*
++ * An encapsulation route consists of a pointer to a 
++ * radix tree entry and a SAID (a destination_address/SPI/protocol triple).
++ */
++
++struct eroute
++{
++      struct rjtentry er_rjt;
++      ip_said er_said;
++      uint32_t er_pid;
++      uint32_t er_count;
++      uint64_t er_lasttime;
++      struct sockaddr_encap er_eaddr; /* MCR get rid of _encap, it is silly*/
++      struct sockaddr_encap er_emask;
++        struct ident er_ident_s;
++        struct ident er_ident_d;
++      struct sk_buff* er_first;
++      struct sk_buff* er_last;
++};
++
++#define er_dst er_said.dst
++#define er_spi er_said.spi
++
++#define _IPSEC_EROUTE_H_
++#endif /* _IPSEC_EROUTE_H_ */
++
++/*
++ * $Log: ipsec_eroute.h,v $
++ * Revision 1.5  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_eroute.h,v
++ *
++ * Revision 1.4  2003/10/31 02:27:05  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.3.30.2  2003/10/29 01:10:19  mcr
++ *    elimited "struct sa_id"
++ *
++ * Revision 1.3.30.1  2003/09/21 13:59:38  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.3  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_eroute.h,v
++ *
++ * Revision 1.2  2001/11/26 09:16:13  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:18:54  mcr
++ *    struct eroute moved to ipsec_eroute.h
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_errs.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,53 @@
++/*
++ * @(#) definition of ipsec_errs structure
++ *
++ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
++ *                 and Michael Richardson  <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_errs.h,v 1.4 2004/04/05 19:55:05 mcr Exp $
++ *
++ */
++
++/* 
++ * This file describes the errors/statistics that FreeSWAN collects.
++ *
++ */
++
++struct ipsec_errs {
++      __u32           ips_alg_errs;          /* number of algorithm errors */
++      __u32           ips_auth_errs;         /* # of authentication errors */
++      __u32           ips_encsize_errs;      /* # of encryption size errors*/
++      __u32           ips_encpad_errs;       /* # of encryption pad  errors*/
++      __u32           ips_replaywin_errs;    /* # of pkt sequence errors */
++};
++
++/*
++ * $Log: ipsec_errs.h,v $
++ * Revision 1.4  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_errs.h,v
++ *
++ * Revision 1.3  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_errs.h,v
++ *
++ * Revision 1.2  2001/11/26 09:16:13  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:25:57  mcr
++ *    lifetime structure created and common functions created.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_esp.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,157 @@
++/*
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_esp.h,v 1.28 2004/09/13 02:22:10 mcr Exp $
++ */
++
++#include "openswan/ipsec_md5h.h"
++#include "openswan/ipsec_sha1.h"
++
++#include "crypto/des.h"
++
++#ifndef IPPROTO_ESP
++#define IPPROTO_ESP 50
++#endif /* IPPROTO_ESP */
++
++#define ESP_HEADER_LEN                8       /* 64 bits header (spi+rpl)*/
++
++#define EMT_ESPDESCBC_ULEN    20      /* coming from user mode */
++#define EMT_ESPDES_KMAX               64      /* 512 bit secret key enough? */
++#define EMT_ESPDES_KEY_SZ     8       /* 56 bit secret key with parity = 64 bits */
++#define EMT_ESP3DES_KEY_SZ    24      /* 168 bit secret key with parity = 192 bits */
++#define EMT_ESPDES_IV_SZ      8       /* IV size */
++#define ESP_DESCBC_BLKLEN       8       /* DES-CBC block size */
++
++#define ESP_IV_MAXSZ          16      /* This is _critical_ */
++#define ESP_IV_MAXSZ_INT      (ESP_IV_MAXSZ/sizeof(int))
++
++#define DB_ES_PKTRX   0x0001
++#define DB_ES_PKTRX2  0x0002
++#define DB_ES_IPSA    0x0010
++#define DB_ES_XF      0x0020
++#define DB_ES_IPAD    0x0040
++#define DB_ES_INAU    0x0080
++#define DB_ES_OINFO   0x0100
++#define DB_ES_OINFO2  0x0200
++#define DB_ES_OH      0x0400
++#define DB_ES_REPLAY  0x0800
++
++#ifdef __KERNEL__
++struct des_eks {
++      des_key_schedule ks;
++};
++
++extern struct inet_protocol esp_protocol;
++
++struct options;
++
++struct esphdr
++{
++      __u32   esp_spi;                /* Security Parameters Index */
++        __u32   esp_rpl;                /* Replay counter */
++      __u8    esp_iv[8];              /* iv */
++};
++
++extern struct xform_functions esp_xform_funcs[];
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int debug_esp;
++#endif /* CONFIG_KLIPS_DEBUG */
++#endif /* __KERNEL__ */
++
++/*
++ * $Log: ipsec_esp.h,v $
++ * Revision 1.28  2004/09/13 02:22:10  mcr
++ *    #define inet_protocol if necessary.
++ *
++ * Revision 1.27  2004/09/06 18:35:41  mcr
++ *    2.6.8.1 gets rid of inet_protocol->net_protocol compatibility,
++ *    so adjust for that.
++ *
++ * Revision 1.26  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.25  2004/04/06 02:49:08  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.24  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_esp.h,v
++ *
++ * Revision 1.23  2004/04/05 19:41:05  mcr
++ *    merged alg-branch code.
++ *
++ * Revision 1.22  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.23  2003/12/11 20:14:58  mcr
++ *    refactored the xmit code, to move all encapsulation
++ *    code into protocol functions. Note that all functions
++ *    are essentially done by a single function, which is probably
++ *    wrong.
++ *    the rcv_functions structures are renamed xform_functions.
++ *
++ * Revision 1.22  2003/12/06 21:21:19  mcr
++ *    split up receive path into per-transform files, for
++ *    easier later removal.
++ *
++ * Revision 1.21.8.1  2003/12/22 15:25:52  jjo
++ *      Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.21  2003/02/06 02:21:34  rgb
++ *
++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h .
++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr".
++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code.
++ *
++ * Revision 1.20  2002/05/14 02:37:02  rgb
++ * Change reference from _TDB to _IPSA.
++ *
++ * Revision 1.19  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.18  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_esp.h,v
++ *
++ * Revision 1.17  2002/02/20 01:27:07  rgb
++ * Ditched a pile of structs only used by the old Netlink interface.
++ *
++ * Revision 1.16  2001/12/11 02:35:57  rgb
++ * Change "struct net_device" to "struct device" for 2.2 compatibility.
++ *
++ * Revision 1.15  2001/11/26 09:23:48  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.14.2.3  2001/10/23 04:16:42  mcr
++ *    get definition of des_key_schedule from des.h
++ *
++ * Revision 1.14.2.2  2001/10/22 20:33:13  mcr
++ *    use "des_key_schedule" structure instead of cooking our own.
++ *
++ * Revision 1.14.2.1  2001/09/25 02:18:25  mcr
++ *    replace "struct device" with "struct netdevice"
++ *
++ * Revision 1.14  2001/06/14 19:35:08  rgb
++ * Update copyright date.
++ *
++ * Revision 1.13  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.12  2000/08/01 14:51:50  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.11  2000/01/10 16:36:20  rgb
++ * Ditch last of EME option flags, including initiator.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_ipcomp.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,94 @@
++/*
++ * IP compression header declations
++ *
++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_ipcomp.h,v 1.4 2004/07/10 19:08:41 mcr Exp $
++ */
++
++#ifndef IPSEC_IPCOMP_H
++#define IPSEC_IPCOMP_H
++
++#include "openswan/ipsec_auth.h"
++
++/* Prefix all global deflate symbols with "ipcomp_" to avoid collisions with ppp_deflate & ext2comp */
++#ifndef IPCOMP_PREFIX
++#define IPCOMP_PREFIX
++#endif /* IPCOMP_PREFIX */
++
++#ifndef IPPROTO_COMP
++#define IPPROTO_COMP 108
++#endif /* IPPROTO_COMP */
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int sysctl_ipsec_debug_ipcomp;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++struct ipcomphdr {                    /* IPCOMP header */
++    __u8    ipcomp_nh;                /* Next header (protocol) */
++    __u8    ipcomp_flags;     /* Reserved, must be 0 */
++    __u16   ipcomp_cpi;               /* Compression Parameter Index */
++};
++
++extern struct inet_protocol comp_protocol;
++extern int sysctl_ipsec_debug_ipcomp;
++
++#define IPCOMP_UNCOMPRESSABLE     0x000000001
++#define IPCOMP_COMPRESSIONERROR   0x000000002
++#define IPCOMP_PARMERROR          0x000000004
++#define IPCOMP_DECOMPRESSIONERROR 0x000000008
++
++#define IPCOMP_ADAPT_INITIAL_TRIES    8
++#define IPCOMP_ADAPT_INITIAL_SKIP     4
++#define IPCOMP_ADAPT_SUBSEQ_TRIES     2
++#define IPCOMP_ADAPT_SUBSEQ_SKIP      8
++
++/* Function prototypes */
++struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags);
++struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags);
++
++extern struct xform_functions ipcomp_xform_funcs[];
++
++#endif /* IPSEC_IPCOMP_H */
++
++/*
++ * $Log: ipsec_ipcomp.h,v $
++ * Revision 1.4  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.3  2004/04/06 02:49:08  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.2  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_ipcomp.h,v
++ *
++ * Revision 1.1  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.2  2003/12/11 20:14:58  mcr
++ *    refactored the xmit code, to move all encapsulation
++ *    code into protocol functions. Note that all functions
++ *    are essentially done by a single function, which is probably
++ *    wrong.
++ *    the rcv_functions structures are renamed xform_functions.
++ *
++ * Revision 1.1  2003/12/06 21:21:19  mcr
++ *    split up receive path into per-transform files, for
++ *    easier later removal.
++ *
++ *
++ *
++ */
++
++
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_ipe4.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,68 @@
++/*
++ * IP-in-IP Header declarations
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_ipe4.h,v 1.6 2004/04/05 19:55:05 mcr Exp $
++ */
++
++/* The packet header is an IP header! */
++
++struct ipe4_xdata                     /* transform table data */
++{
++      struct in_addr  i4_src;
++      struct in_addr  i4_dst;
++};
++
++#define EMT_IPE4_ULEN 8       /* coming from user mode */
++ 
++
++/*
++ * $Log: ipsec_ipe4.h,v $
++ * Revision 1.6  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_ipe4.h,v
++ *
++ * Revision 1.5  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_ipe4.h,v
++ *
++ * Revision 1.4  2001/06/14 19:35:08  rgb
++ * Update copyright date.
++ *
++ * Revision 1.3  1999/04/11 00:28:57  henry
++ * GPL boilerplate
++ *
++ * Revision 1.2  1999/04/06 04:54:25  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.1  1998/06/18 21:27:47  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.1  1998/04/09 03:06:07  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:48:53  ji
++ * Release update only.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_ipip.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_ipip.h,v 1.2 2004/04/05 19:55:05 mcr Exp $
++ */
++
++#ifndef _IPSEC_IPIP_H_
++
++#ifndef IPPROTO_IPIP
++#define IPPROTO_IPIP 4
++#endif /* IPPROTO_ESP */
++
++extern struct xform_functions ipip_xform_funcs[];
++
++#define _IPSEC_IPIP_H_
++
++#endif /* _IPSEC_IPIP_H_ */
++
++/*
++ * $Log: ipsec_ipip.h,v $
++ * Revision 1.2  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_ipip.h,v
++ *
++ * Revision 1.1  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.1  2003/12/11 20:14:58  mcr
++ *    refactored the xmit code, to move all encapsulation
++ *    code into protocol functions. Note that all functions
++ *    are essentially done by a single function, which is probably
++ *    wrong.
++ *    the rcv_functions structures are renamed xform_functions.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_kern24.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,61 @@
++/*
++ * @(#) routines to makes kernel 2.4 compatible with 2.6 usage.
++ *
++ * Copyright (C) 2004 Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_kern24.h,v 1.4 2005/05/20 03:19:18 mcr Exp $
++ */
++
++#ifndef _IPSEC_KERN24_H
++
++#ifndef NET_26
++#define sk_receive_queue  receive_queue
++#define sk_destruct       destruct
++#define sk_reuse          reuse
++#define sk_zapped         zapped
++#define sk_family         family
++#define sk_protocol       protocol
++#define sk_protinfo       protinfo
++#define sk_sleep          sleep
++#define sk_state_change   state_change
++#define sk_shutdown       shutdown
++#define sk_err            err
++#define sk_stamp          stamp
++#define sk_socket         socket
++#define sk_sndbuf         sndbuf
++#define sock_flag(sk, flag)  sk->dead
++#define sk_for_each(sk, node, plist) for(sk=*plist; sk!=NULL; sk = sk->next)
++#endif
++
++/* deal with 2.4 vs 2.6 issues with module counts */
++
++/* in 2.6, all refcounts are maintained *outside* of the
++ * module to deal with race conditions.
++ */
++
++#ifdef NET_26
++#define KLIPS_INC_USE /* nothing */
++#define KLIPS_DEC_USE /* nothing */
++
++#else
++#define KLIPS_INC_USE MOD_INC_USE_COUNT
++#define KLIPS_DEC_USE MOD_DEC_USE_COUNT
++#endif
++
++extern int printk_ratelimit(void);
++
++
++#define _IPSEC_KERN24_H 1
++
++#endif /* _IPSEC_KERN24_H */
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_kversion.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,352 @@
++#ifndef _OPENSWAN_KVERSIONS_H
++/*
++ * header file for FreeS/WAN library functions
++ * Copyright (C) 1998, 1999, 2000  Henry Spencer.
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: ipsec_kversion.h,v 1.15.2.11 2007/02/20 03:53:16 paul Exp $
++ */
++#define       _OPENSWAN_KVERSIONS_H   /* seen it, no need to see it again */
++
++/*
++ * this file contains a series of atomic defines that depend upon
++ * kernel version numbers. The kernel versions are arranged
++ * in version-order number (which is often not chronological)
++ * and each clause enables or disables a feature.
++ */
++
++/*
++ * First, assorted kernel-version-dependent trickery.
++ */
++#include <linux/version.h>
++#ifndef KERNEL_VERSION
++#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
++#define HEADER_CACHE_BIND_21
++#error "KLIPS is no longer supported on Linux 2.0. Sorry"
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
++#define SPINLOCK
++#define PROC_FS_21
++#define NETLINK_SOCK
++#define NET_21
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,19)
++#define net_device_stats enet_statistics
++#endif                                                                         
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
++#define SPINLOCK_23
++#define NETDEV_23
++#  ifndef CONFIG_IP_ALIAS
++#  define CONFIG_IP_ALIAS
++#  endif
++#include <linux/socket.h>
++#include <linux/skbuff.h>
++#include <linux/netlink.h>
++#  ifdef NETLINK_XFRM
++#  define NETDEV_25
++#  endif
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,25)
++#define PROC_FS_2325
++#undef  PROC_FS_21
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)
++#define PROC_NO_DUMMY
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,35)
++#define SKB_COPY_EXPAND
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,37)
++#define IP_SELECT_IDENT
++#endif
++
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,50)) && defined(CONFIG_NETFILTER)
++#define SKB_RESET_NFCT
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,2)
++#define IP_SELECT_IDENT_NEW
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
++#define IPH_is_SKB_PULLED
++#define SKB_COW_NEW
++#define PROTO_HANDLER_SINGLE_PARM
++#define IP_FRAGMENT_LINEARIZE 1
++#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */
++#  ifdef REDHAT_BOGOSITY
++#  define IP_SELECT_IDENT_NEW
++#  define IPH_is_SKB_PULLED
++#  define SKB_COW_NEW
++#  define PROTO_HANDLER_SINGLE_PARM
++#  endif /* REDHAT_BOGOSITY */
++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) */
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
++#define MALLOC_SLAB
++#define LINUX_KERNEL_HAS_SNPRINTF
++#endif                                                                         
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#define HAVE_NETDEV_PRINTK 1
++#define NET_26
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
++#define NEED_INET_PROTOCOL
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
++#define HAVE_SOCK_ZAPPED
++#define NET_26_12_SKALLOC
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
++#define HAVE_SOCK_SECURITY
++/* skb->nf_debug disappared completely in 2.6.13 */
++#define HAVE_SKB_NF_DEBUG
++#endif
++
++#define SYSCTL_IPSEC_DEFAULT_TTL sysctl_ip_default_ttl                      
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
++/* skb->stamp changed to skb->tstamp in 2.6.14 */
++#define HAVE_TSTAMP
++#define HAVE_INET_SK_SPORT
++#undef  SYSCTL_IPSEC_DEFAULT_TTL
++#define SYSCTL_IPSEC_DEFAULT_TTL IPSEC_DEFAULT_TTL
++#else
++#define HAVE_SKB_LIST
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
++#define HAVE_NEW_SKB_LINEARIZE
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++/* skb->nfmark changed to skb->mark in 2.6.20 */
++#define nfmark mark
++#endif
++
++#ifdef NET_21
++#  include <linux/in6.h>
++#else
++     /* old kernel in.h has some IPv6 stuff, but not quite enough */
++#  define     s6_addr16       s6_addr
++#  define     AF_INET6        10
++#  define uint8_t __u8
++#  define uint16_t __u16 
++#  define uint32_t __u32 
++#  define uint64_t __u64 
++#endif
++
++#ifdef NET_21
++# define ipsec_kfree_skb(a) kfree_skb(a)
++#else /* NET_21 */
++# define ipsec_kfree_skb(a) kfree_skb(a, FREE_WRITE)
++#endif /* NET_21 */
++
++#ifdef NETDEV_23
++#if 0
++#ifndef NETDEV_25
++#define device net_device
++#endif
++#endif
++# define ipsec_dev_get dev_get_by_name
++# define __ipsec_dev_get __dev_get_by_name
++# define ipsec_dev_put(x) dev_put(x)
++# define __ipsec_dev_put(x) __dev_put(x)
++# define ipsec_dev_hold(x) dev_hold(x)
++#else /* NETDEV_23 */
++# define ipsec_dev_get dev_get
++# define __ipsec_dev_put(x) 
++# define ipsec_dev_put(x)
++# define ipsec_dev_hold(x) 
++#endif /* NETDEV_23 */
++
++#ifndef SPINLOCK
++#  include <linux/bios32.h>
++     /* simulate spin locks and read/write locks */
++     typedef struct {
++       volatile char lock;
++     } spinlock_t;
++
++     typedef struct {
++       volatile unsigned int lock;
++     } rwlock_t;                                                                     
++
++#  define spin_lock_init(x) { (x)->lock = 0;}
++#  define rw_lock_init(x) { (x)->lock = 0; }
++
++#  define spin_lock(x) { while ((x)->lock) barrier(); (x)->lock=1;}
++#  define spin_lock_irq(x) { cli(); spin_lock(x);}
++#  define spin_lock_irqsave(x,flags) { save_flags(flags); spin_lock_irq(x);}
++
++#  define spin_unlock(x) { (x)->lock=0;}
++#  define spin_unlock_irq(x) { spin_unlock(x); sti();}
++#  define spin_unlock_irqrestore(x,flags) { spin_unlock(x); restore_flags(flags);}
++
++#  define read_lock(x) spin_lock(x)
++#  define read_lock_irq(x) spin_lock_irq(x)
++#  define read_lock_irqsave(x,flags) spin_lock_irqsave(x,flags)
++
++#  define read_unlock(x) spin_unlock(x)
++#  define read_unlock_irq(x) spin_unlock_irq(x)
++#  define read_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags)
++
++#  define write_lock(x) spin_lock(x)
++#  define write_lock_irq(x) spin_lock_irq(x)
++#  define write_lock_irqsave(x,flags) spin_lock_irqsave(x,flags)
++
++#  define write_unlock(x) spin_unlock(x)
++#  define write_unlock_irq(x) spin_unlock_irq(x)
++#  define write_unlock_irqrestore(x,flags) spin_unlock_irqrestore(x,flags)
++#endif /* !SPINLOCK */
++
++#ifndef SPINLOCK_23
++#  define spin_lock_bh(x)  spin_lock_irq(x)
++#  define spin_unlock_bh(x)  spin_unlock_irq(x)
++
++#  define read_lock_bh(x)  read_lock_irq(x)
++#  define read_unlock_bh(x)  read_unlock_irq(x)
++
++#  define write_lock_bh(x)  write_lock_irq(x)
++#  define write_unlock_bh(x)  write_unlock_irq(x)
++#endif /* !SPINLOCK_23 */
++
++#ifndef HAVE_NETDEV_PRINTK
++#define netdev_printk(sevlevel, netdev, msglevel, format, arg...) \
++      printk(sevlevel "%s: " format , netdev->name , ## arg)
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) 
++#include "openswan/ipsec_kern24.h"
++#else
++#error "kernels before 2.4 are not supported at this time"
++#endif
++#endif
++
++
++#endif /* _OPENSWAN_KVERSIONS_H */
++
++/*
++ * $Log: ipsec_kversion.h,v $
++ * Revision 1.15.2.11  2007/02/20 03:53:16  paul
++ * Added comment, made layout consistent with other checks.
++ *
++ * Revision 1.15.2.10  2007/02/16 19:08:12  paul
++ * Fix for compiling on 2.6.20 (nfmark is now called mark in sk_buff)
++ *
++ * Revision 1.15.2.9  2006/07/29 05:00:40  paul
++ * Added HAVE_NEW_SKB_LINEARIZE for 2.6.18+ kernels where skb_linearize
++ * only takes 1 argument.
++ *
++ * Revision 1.15.2.8  2006/05/01 14:31:52  mcr
++ * FREESWAN->OPENSWAN in #ifdef.
++ *
++ * Revision 1.15.2.7  2006/01/11 02:02:59  mcr
++ * updated patches and DEFAULT_TTL code to work
++ *
++ * Revision 1.15.2.6  2006/01/03 19:25:02  ken
++ * Remove duplicated #ifdef for TTL fix - bad patch
++ *
++ * Revision 1.15.2.5  2006/01/03 18:06:33  ken
++ * Fix for missing sysctl default ttl
++ *
++ * Revision 1.15.2.4  2005/11/27 21:40:14  paul
++ * Pull down TTL fixes from head. this fixes "Unknown symbol sysctl_ip_default_ttl"
++ * in for klips as module.
++ *
++ * Revision 1.15.2.3  2005/11/22 04:11:52  ken
++ * Backport fixes for 2.6.14 kernels from HEAD
++ *
++ * Revision 1.15.2.2  2005/09/01 01:57:19  paul
++ * michael's fixes for 2.6.13 from head
++ *
++ * Revision 1.15.2.1  2005/08/27 23:13:48  paul
++ * Fix for:
++ * 7 weeks ago:       [NET]: Remove unused security member in sk_buff
++ * changeset 4280:    328ea53f5fee
++ * parent 4279:       beb0afb0e3f8
++ * author:    Thomas Graf <tgraf@suug.ch>
++ * date:      Tue Jul 5 21:12:44 2005
++ * files:     include/linux/skbuff.h include/linux/tc_ematch/tc_em_meta.h net/core/skbuff.c net/ipv4/ip_output.c net/ipv6/ip6_output.c net/sched/em_meta.c
++ *
++ * This should fix compilation on 2.6.13(rc) kernels
++ *
++ * Revision 1.15  2005/07/19 20:02:15  mcr
++ *    sk_alloc() interface change.
++ *
++ * Revision 1.14  2005/07/08 16:20:05  mcr
++ *    fix for 2.6.12 disapperance of sk_zapped field -> sock_flags.
++ *
++ * Revision 1.13  2005/05/20 03:19:18  mcr
++ *    modifications for use on 2.4.30 kernel, with backported
++ *    printk_ratelimit(). all warnings removed.
++ *
++ * Revision 1.12  2005/04/13 22:46:21  mcr
++ *    note that KLIPS does not work on Linux 2.0.
++ *
++ * Revision 1.11  2004/09/13 02:22:26  mcr
++ *    #define inet_protocol if necessary.
++ *
++ * Revision 1.10  2004/08/03 18:17:15  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.9  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_kversion.h,v
++ *
++ * Revision 1.8  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.7  2003/07/31 22:48:08  mcr
++ *    derive NET25-ness from presence of NETLINK_XFRM macro.
++ *
++ * Revision 1.6  2003/06/24 20:22:32  mcr
++ *    added new global: ipsecdevices[] so that we can keep track of
++ *    the ipsecX devices. They will be referenced with dev_hold(),
++ *    so 2.2 may need this as well.
++ *
++ * Revision 1.5  2003/04/03 17:38:09  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ *
++ * Revision 1.4  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_kversion.h,v
++ *
++ * Revision 1.3  2002/04/12 03:21:17  mcr
++ *    three parameter version of ip_select_ident appears first
++ *    in 2.4.2 (RH7.1) not 2.4.4.
++ *
++ * Revision 1.2  2002/03/08 21:35:22  rgb
++ * Defined LINUX_KERNEL_HAS_SNPRINTF to shut up compiler warnings after
++ * 2.4.9.  (Andreas Piesk).
++ *
++ * Revision 1.1  2002/01/29 02:11:42  mcr
++ *    removal of kversions.h - sources that needed it now use ipsec_param.h.
++ *    updating of IPv6 structures to match latest in6.h version.
++ *    removed dead code from freeswan.h that also duplicated kversions.h
++ *    code.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_life.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,112 @@
++/*
++ * Definitions relevant to IPSEC lifetimes
++ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
++ *                 and Michael Richardson  <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_life.h,v 1.4 2004/04/05 19:55:05 mcr Exp $
++ *
++ * This file derived from ipsec_xform.h on 2001/9/18 by mcr.
++ *
++ */
++
++/* 
++ * This file describes the book keeping fields for the 
++ *   IPsec Security Association Structure. ("ipsec_sa")
++ *
++ * This structure is never allocated directly by kernel code,
++ * (it is always a static/auto or is part of a structure)
++ * so it does not have a reference count.
++ *
++ */
++
++#ifndef _IPSEC_LIFE_H_
++
++/*
++ *  _count is total count.
++ *  _hard is hard limit (kill SA after this number)
++ *  _soft is soft limit (try to renew SA after this number)
++ *  _last is used in some special cases.
++ *
++ */
++
++struct ipsec_lifetime64
++{
++      __u64           ipl_count;
++      __u64           ipl_soft;
++      __u64           ipl_hard;
++      __u64           ipl_last;  
++};
++
++struct ipsec_lifetimes
++{
++      /* number of bytes processed */
++      struct ipsec_lifetime64 ipl_bytes;
++
++      /* number of packets processed */
++      struct ipsec_lifetime64 ipl_packets;
++
++      /* time since SA was added */
++      struct ipsec_lifetime64 ipl_addtime;
++
++      /* time since SA was first used */
++      struct ipsec_lifetime64 ipl_usetime;
++
++      /* from rfc2367:  
++         *         For CURRENT, the number of different connections,
++         *         endpoints, or flows that the association has been
++         *          allocated towards. For HARD and SOFT, the number of
++         *          these the association may be allocated towards
++         *          before it expires. The concept of a connection,
++         *          flow, or endpoint is system specific.
++       *
++       * mcr(2001-9-18) it is unclear what purpose these serve for FreeSWAN.
++       *          They are maintained for PF_KEY compatibility. 
++       */
++      struct ipsec_lifetime64 ipl_allocations;
++};
++
++enum ipsec_life_alive {
++      ipsec_life_harddied = -1,
++      ipsec_life_softdied = 0,
++      ipsec_life_okay     = 1
++};
++
++enum ipsec_life_type {
++      ipsec_life_timebased = 1,
++      ipsec_life_countbased= 0
++};
++
++#define _IPSEC_LIFE_H_
++#endif /* _IPSEC_LIFE_H_ */
++
++
++/*
++ * $Log: ipsec_life.h,v $
++ * Revision 1.4  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_life.h,v
++ *
++ * Revision 1.3  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_life.h,v
++ *
++ * Revision 1.2  2001/11/26 09:16:14  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:25:58  mcr
++ *    lifetime structure created and common functions created.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_md5h.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,143 @@
++/*
++ * RCSID $Id: ipsec_md5h.h,v 1.10 2004/09/08 17:21:35 ken Exp $
++ */
++
++/*
++ * The rest of this file is Copyright RSA DSI. See the following comments
++ * for the full Copyright notice.
++ */
++
++#ifndef _IPSEC_MD5H_H_
++#define _IPSEC_MD5H_H_
++
++/* GLOBAL.H - RSAREF types and constants
++ */
++
++/* PROTOTYPES should be set to one if and only if the compiler supports
++     function argument prototyping.
++   The following makes PROTOTYPES default to 0 if it has not already
++     been defined with C compiler flags.
++ */
++#ifndef PROTOTYPES
++#define PROTOTYPES 1
++#endif /* !PROTOTYPES */
++
++/* POINTER defines a generic pointer type */
++typedef __u8 *POINTER;
++
++/* UINT2 defines a two byte word */
++typedef __u16 UINT2;
++
++/* UINT4 defines a four byte word */
++typedef __u32 UINT4;
++
++/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
++   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
++     returns an empty list.
++ */
++
++#if PROTOTYPES
++#define PROTO_LIST(list) list
++#else /* PROTOTYPES */
++#define PROTO_LIST(list) ()
++#endif /* PROTOTYPES */
++
++
++/* MD5.H - header file for MD5C.C
++ */
++
++/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
++rights reserved.
++
++License to copy and use this software is granted provided that it
++is identified as the "RSA Data Security, Inc. MD5 Message-Digest
++Algorithm" in all material mentioning or referencing this software
++or this function.
++
++License is also granted to make and use derivative works provided
++that such works are identified as "derived from the RSA Data
++Security, Inc. MD5 Message-Digest Algorithm" in all material
++mentioning or referencing the derived work.
++
++RSA Data Security, Inc. makes no representations concerning either
++the merchantability of this software or the suitability of this
++software for any particular purpose. It is provided "as is"
++without express or implied warranty of any kind.
++
++These notices must be retained in any copies of any part of this
++documentation and/or software.
++ */
++
++/* MD5 context. */
++typedef struct {
++  UINT4 state[4];                                   /* state (ABCD) */
++  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
++  unsigned char buffer[64];                         /* input buffer */
++} MD5_CTX;
++
++void osMD5Init PROTO_LIST ((void *));
++void osMD5Update PROTO_LIST
++  ((void *, unsigned char *, __u32));
++void osMD5Final PROTO_LIST ((unsigned char [16], void *));
++ 
++#endif /* _IPSEC_MD5H_H_ */
++
++/*
++ * $Log: ipsec_md5h.h,v $
++ * Revision 1.10  2004/09/08 17:21:35  ken
++ * Rename MD5* -> osMD5 functions to prevent clashes with other symbols exported by kernel modules (CIFS in 2.6 initiated this)
++ *
++ * Revision 1.9  2004/04/05 19:55:05  mcr
++ * Moved from linux/include/freeswan/ipsec_md5h.h,v
++ *
++ * Revision 1.8  2002/09/10 01:45:09  mcr
++ *    changed type of MD5_CTX and SHA1_CTX to void * so that
++ *    the function prototypes would match, and could be placed
++ *    into a pointer to a function.
++ *
++ * Revision 1.7  2002/04/24 07:36:46  mcr
++ * Moved from ./klips/net/ipsec/ipsec_md5h.h,v
++ *
++ * Revision 1.6  1999/12/13 13:59:13  rgb
++ * Quick fix to argument size to Update bugs.
++ *
++ * Revision 1.5  1999/12/07 18:16:23  rgb
++ * Fixed comments at end of #endif lines.
++ *
++ * Revision 1.4  1999/04/06 04:54:26  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.3  1999/01/22 06:19:58  rgb
++ * 64-bit clean-up.
++ *
++ * Revision 1.2  1998/11/30 13:22:54  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.1  1998/06/18 21:27:48  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.2  1998/04/23 20:54:03  rgb
++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
++ * verified.
++ *
++ * Revision 1.1  1998/04/09 03:04:21  henry
++ * sources moved up from linux/net/ipsec
++ * these two include files modified not to include others except in kernel
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:48:53  ji
++ * Release update only.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_param.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,387 @@
++/*
++ * @(#) Openswan tunable paramaters
++ *
++ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
++ *                 and Michael Richardson  <mcr@freeswan.org>
++ * Copyright (C) 2004  Michael Richardson  <mcr@xelerance.com>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_param.h,v 1.29.6.3 2006/05/01 14:32:31 mcr Exp $
++ *
++ */
++
++/* 
++ * This file provides a set of #define's which may be tuned by various
++ * people/configurations. It keeps all compile-time tunables in one place.
++ *
++ * This file should be included before all other IPsec kernel-only files.
++ *
++ */
++
++#ifndef _IPSEC_PARAM_H_
++
++#ifdef __KERNEL__
++#include "ipsec_kversion.h"
++
++/* Set number of ipsecX virtual devices here. */
++/* This must be < exp(field width of IPSEC_DEV_FORMAT) */
++/* It must also be reasonable so as not to overload the memory and CPU */
++/* constraints of the host. */
++#define IPSEC_NUM_IF  4
++/* The field width must be < IF_NAM_SIZ - strlen("ipsec") - 1. */
++/* With "ipsec" being 5 characters, that means 10 is the max field width */
++/* but machine memory and CPU constraints are not likely to tollerate */
++/* more than 3 digits.  The default is one digit. */
++/* Update: userland scripts get upset if they can't find "ipsec0", so */
++/* for now, no "0"-padding should be used (which would have been helpful */
++/* to make text-searches work */
++#define IPSEC_DEV_FORMAT "ipsec%d"
++/* For, say, 500 virtual ipsec devices, I would recommend: */
++/* #define IPSEC_NUM_IF       500 */
++/* #define IPSEC_DEV_FORMAT "ipsec%03d" */
++/* Note that the "interfaces=" line in /etc/ipsec.conf would be, um, challenging. */
++
++/* use dynamic ipsecX device allocation */
++#ifndef CONFIG_KLIPS_DYNDEV
++#define CONFIG_KLIPS_DYNDEV 1
++#endif /* CONFIG_KLIPS_DYNDEV */
++
++
++#ifdef CONFIG_KLIPS_BIGGATE
++# define SADB_HASHMOD   8069
++#else /* CONFIG_KLIPS_BIGGATE */
++# define SADB_HASHMOD 257
++#endif /* CONFIG_KLIPS_BIGGATE */
++#endif /* __KERNEL__ */
++
++/*
++ * This is for the SA reference table. This number is related to the
++ * maximum number of SAs that KLIPS can concurrently deal with, plus enough
++ * space for keeping expired SAs around.
++ *
++ * TABLE_MAX_WIDTH is the number of bits that we will use.
++ * MAIN_TABLE_WIDTH is the number of bits used for the primary index table.
++ *
++ */
++#ifndef IPSEC_SA_REF_TABLE_IDX_WIDTH
++# define IPSEC_SA_REF_TABLE_IDX_WIDTH 16
++#endif
++
++#ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 
++# define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4 
++#endif
++
++#ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES 
++# define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256
++#endif
++
++#ifndef IPSEC_SA_REF_CODE 
++# define IPSEC_SA_REF_CODE 1 
++#endif
++
++#ifdef __KERNEL__
++/* This is defined for 2.4, but not 2.2.... */
++#ifndef ARPHRD_VOID
++# define ARPHRD_VOID 0xFFFF
++#endif
++
++/* always turn on IPIP mode */
++#ifndef CONFIG_KLIPS_IPIP 
++#define CONFIG_KLIPS_IPIP 1
++#endif
++
++/*
++ * Worry about PROC_FS stuff
++ */
++#if defined(PROC_FS_2325)
++/* kernel 2.4 */
++# define IPSEC_PROC_LAST_ARG ,int *eof,void *data
++# define IPSEC_PROCFS_DEBUG_NO_STATIC
++# define IPSEC_PROC_SUBDIRS
++#else
++/* kernel <2.4 */
++# define IPSEC_PROCFS_DEBUG_NO_STATIC DEBUG_NO_STATIC
++
++# ifndef PROC_NO_DUMMY
++#  define IPSEC_PROC_LAST_ARG , int dummy
++# else
++#  define IPSEC_PROC_LAST_ARG
++# endif /* !PROC_NO_DUMMY */
++#endif /* PROC_FS_2325 */
++
++#if !defined(LINUX_KERNEL_HAS_SNPRINTF)
++/* GNU CPP specific! */
++# define snprintf(buf, len, fmt...) sprintf(buf, ##fmt)
++#endif /* !LINUX_KERNEL_HAS_SNPRINTF */
++
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#ifndef KLIPS_FIXES_DES_PARITY
++# define KLIPS_FIXES_DES_PARITY 1
++#endif /* !KLIPS_FIXES_DES_PARITY */
++
++/* we don't really want to print these unless there are really big problems */
++#ifndef KLIPS_DIVULGE_CYPHER_KEY
++# define KLIPS_DIVULGE_CYPHER_KEY 0
++#endif /* !KLIPS_DIVULGE_CYPHER_KEY */
++
++#ifndef KLIPS_DIVULGE_HMAC_KEY
++# define KLIPS_DIVULGE_HMAC_KEY 0
++#endif /* !KLIPS_DIVULGE_HMAC_KEY */
++
++#ifndef IPSEC_DISALLOW_IPOPTIONS
++# define IPSEC_DISALLOW_IPOPTIONS 1
++#endif /* !KLIPS_DIVULGE_HMAC_KEY */
++
++/* extra toggles for regression testing */
++#ifdef CONFIG_KLIPS_REGRESS
++
++/* 
++ * should pfkey_acquire() become 100% lossy?
++ *
++ */
++extern int sysctl_ipsec_regress_pfkey_lossage;
++#ifndef KLIPS_PFKEY_ACQUIRE_LOSSAGE
++# ifdef CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE
++#  define KLIPS_PFKEY_ACQUIRE_LOSSAGE 100
++# endif /* CONFIG_KLIPS_PFKEY_ACQUIRE_LOSSAGE */
++#else
++#define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0
++#endif /* KLIPS_PFKEY_ACQUIRE_LOSSAGE */
++
++#else /* CONFIG_KLIPS_REGRESS */
++#define KLIPS_PFKEY_ACQUIRE_LOSSAGE 0
++
++#endif /* CONFIG_KLIPS_REGRESS */
++
++
++/*
++ * debugging routines.
++ */
++#define KLIPS_ERROR(flag, format, args...) if(printk_ratelimit() || flag) printk(KERN_ERR "KLIPS " format, ## args)
++#ifdef CONFIG_KLIPS_DEBUG
++extern void ipsec_print_ip(struct iphdr *ip);
++
++      #define KLIPS_PRINT(flag, format, args...) \
++              ((flag) ? printk(KERN_INFO format , ## args) : 0)
++      #define KLIPS_PRINTMORE(flag, format, args...) \
++              ((flag) ? printk(format , ## args) : 0)
++      #define KLIPS_IP_PRINT(flag, ip) \
++              ((flag) ? ipsec_print_ip(ip) : 0)
++#else /* CONFIG_KLIPS_DEBUG */
++      #define KLIPS_PRINT(flag, format, args...) do ; while(0)
++      #define KLIPS_PRINTMORE(flag, format, args...) do ; while(0)
++      #define KLIPS_IP_PRINT(flag, ip) do ; while(0)
++#endif /* CONFIG_KLIPS_DEBUG */
++
++
++/* 
++ * Stupid kernel API differences in APIs. Not only do some
++ * kernels not have ip_select_ident, but some have differing APIs,
++ * and SuSE has one with one parameter, but no way of checking to
++ * see what is really what.
++ */
++
++#ifdef SUSE_LINUX_2_4_19_IS_STUPID
++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph)
++#else
++
++/* simplest case, nothing */
++#if !defined(IP_SELECT_IDENT)
++#define KLIPS_IP_SELECT_IDENT(iph, skb)  do { iph->id = htons(ip_id_count++); } while(0)
++#endif
++
++/* kernels > 2.3.37-ish */
++#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW)
++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst)
++#endif
++
++/* kernels > 2.4.2 */
++#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW)
++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL)
++#endif
++
++#endif /* SUSE_LINUX_2_4_19_IS_STUPID */
++
++/*
++ * make klips fail test:east-espiv-01.
++ * exploit is at testing/attacks/espiv
++ *
++ */
++#define KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK 0
++
++
++/* IP_FRAGMENT_LINEARIZE is set in freeswan.h if Kernel > 2.4.4 */
++#ifndef IP_FRAGMENT_LINEARIZE
++# define IP_FRAGMENT_LINEARIZE 0
++#endif /* IP_FRAGMENT_LINEARIZE */
++#endif /* __KERNEL__ */
++
++#ifdef NEED_INET_PROTOCOL
++#define inet_protocol net_protocol
++#endif
++
++#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && CONFIG_IPSEC_NAT_TRAVERSAL
++#define NAT_TRAVERSAL 1
++#else
++/* let people either #undef, or #define = 0 it */
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++#undef CONFIG_IPSEC_NAT_TRAVERSAL
++#endif
++#endif
++
++#ifndef IPSEC_DEFAULT_TTL
++#define IPSEC_DEFAULT_TTL 64
++#endif
++
++#define _IPSEC_PARAM_H_
++#endif /* _IPSEC_PARAM_H_ */
++
++/*
++ * $Log: ipsec_param.h,v $
++ * Revision 1.29.6.3  2006/05/01 14:32:31  mcr
++ * added KLIPS_ERROR and make sure that things work without CONFIG_KLIPS_REGRESS.
++ *
++ * Revision 1.29.6.2  2005/11/27 21:40:14  paul
++ * Pull down TTL fixes from head. this fixes "Unknown symbol sysctl_ip_default_ttl"
++ * in for klips as module.
++ *
++ * Revision 1.29.6.1  2005/08/12 16:24:18  ken
++ * Pull in NAT-T compile logic from HEAD
++ *
++ * Revision 1.29  2005/01/26 00:50:35  mcr
++ *    adjustment of confusion of CONFIG_IPSEC_NAT vs CONFIG_KLIPS_NAT,
++ *    and make sure that NAT_TRAVERSAL is set as well to match
++ *    userspace compiles of code.
++ *
++ * Revision 1.28  2004/09/13 15:50:15  mcr
++ *    spell NEED_INET properly, not NET_INET.
++ *
++ * Revision 1.27  2004/09/13 02:21:45  mcr
++ *    always turn on IPIP mode.
++ *    #define inet_protocol if necessary.
++ *
++ * Revision 1.26  2004/08/17 03:25:43  mcr
++ *    freeswan->openswan.
++ *
++ * Revision 1.25  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.24  2004/04/05 19:55:06  mcr
++ * Moved from linux/include/freeswan/ipsec_param.h,v
++ *
++ * Revision 1.23  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.22  2003/10/31 02:27:05  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.21.4.1  2003/10/29 01:10:19  mcr
++ *    elimited "struct sa_id"
++ *
++ * Revision 1.21  2003/04/03 17:38:18  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ * Change indentation for readability.
++ *
++ * Revision 1.20  2003/03/14 08:09:26  rgb
++ * Fixed up CONFIG_IPSEC_DYNDEV definitions.
++ *
++ * Revision 1.19  2003/01/30 02:31:43  rgb
++ *
++ * Rename SAref table macro names for clarity.
++ *
++ * Revision 1.18  2002/09/30 19:06:26  rgb
++ *    Reduce default table to 16 bits width.
++ *
++ * Revision 1.17  2002/09/20 15:40:29  rgb
++ * Define switch to activate new SAref code.
++ * Prefix macros with "IPSEC_".
++ * Rework saref freelist.
++ * Restrict some bits to kernel context for use to klips utils.
++ *
++ * Revision 1.16  2002/09/20 05:00:31  rgb
++ * Define switch to divulge hmac keys for debugging.
++ * Added IPOPTIONS switch.
++ *
++ * Revision 1.15  2002/09/19 02:34:24  mcr
++ *    define IPSEC_PROC_SUBDIRS if we are 2.4, and use that in ipsec_proc.c
++ *    to decide if we are to create /proc/net/ipsec/.
++ *
++ * Revision 1.14  2002/08/30 01:20:54  mcr
++ *    reorganized 2.0/2.2/2.4 procfs support macro so match
++ *    2.4 values/typedefs.
++ *
++ * Revision 1.13  2002/07/28 22:03:28  mcr
++ *    added some documentation to SA_REF_*
++ *    turned on fix for ESPIV attack, now that we have the attack code.
++ *
++ * Revision 1.12  2002/07/26 08:48:31  rgb
++ * Added SA ref table code.
++ *
++ * Revision 1.11  2002/07/23 02:57:45  rgb
++ * Define ARPHRD_VOID for < 2.4 kernels.
++ *
++ * Revision 1.10  2002/05/27 21:37:28  rgb
++ * Set the defaults sanely for those adventurous enough to try more than 1
++ * digit of ipsec devices.
++ *
++ * Revision 1.9  2002/05/27 18:56:07  rgb
++ * Convert to dynamic ipsec device allocation.
++ *
++ * Revision 1.8  2002/04/24 07:36:47  mcr
++ * Moved from ./klips/net/ipsec/ipsec_param.h,v
++ *
++ * Revision 1.7  2002/04/20 00:12:25  rgb
++ * Added esp IV CBC attack fix, disabled.
++ *
++ * Revision 1.6  2002/01/29 02:11:42  mcr
++ *    removal of kversions.h - sources that needed it now use ipsec_param.h.
++ *    updating of IPv6 structures to match latest in6.h version.
++ *    removed dead code from freeswan.h that also duplicated kversions.h
++ *    code.
++ *
++ * Revision 1.5  2002/01/28 19:22:01  mcr
++ *    by default, turn off LINEARIZE option
++ *    (let kversions.h turn it on)
++ *
++ * Revision 1.4  2002/01/20 20:19:36  mcr
++ *    renamed option to IP_FRAGMENT_LINEARIZE.
++ *
++ * Revision 1.3  2002/01/12 02:57:25  mcr
++ *    first regression test causes acquire messages to be lost
++ *    100% of the time. This is to help testing of pluto.
++ *
++ * Revision 1.2  2001/11/26 09:16:14  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.3  2001/10/23 04:40:16  mcr
++ *    added #define for DIVULGING session keys in debug output.
++ *
++ * Revision 1.1.2.2  2001/10/22 20:53:25  mcr
++ *    added a define to control forcing of DES parity.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:20:19  mcr
++ *    many common kernel configuration questions centralized.
++ *    more things remain that should be moved from freeswan.h.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_policy.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,217 @@
++#ifndef _IPSEC_POLICY_H
++/*
++ * policy interface file between pluto and applications
++ * Copyright (C) 2003              Michael Richardson <mcr@freeswan.org>
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: ipsec_policy.h,v 1.7.6.1 2005/07/26 01:53:07 ken Exp $
++ */
++#define       _IPSEC_POLICY_H         /* seen it, no need to see it again */
++
++
++/*
++ * this file defines an interface between an application (or rather an
++ * application library) and a key/policy daemon. It provides for inquiries
++ * as to the current state of a connected socket, as well as for general
++ * questions.
++ *
++ * In general, the interface is defined as a series of functional interfaces,
++ * and the policy messages should be internal. However, because this is in
++ * fact an ABI between pieces of the system that may get compiled and revised
++ * seperately, this ABI must be public and revision controlled.
++ *
++ * It is expected that the daemon will always support previous versions.
++ */
++
++#define IPSEC_POLICY_MSG_REVISION (unsigned)200305061
++
++enum ipsec_policy_command {
++  IPSEC_CMD_QUERY_FD       = 1,
++  IPSEC_CMD_QUERY_HOSTPAIR = 2,
++  IPSEC_CMD_QUERY_DSTONLY  = 3,
++};
++
++struct ipsec_policy_msg_head {
++  u_int32_t ipm_version;
++  u_int32_t ipm_msg_len;  
++  u_int32_t ipm_msg_type;
++  u_int32_t ipm_msg_seq;
++};
++
++enum ipsec_privacy_quality {
++  IPSEC_PRIVACY_NONE     = 0,
++  IPSEC_PRIVACY_INTEGRAL = 4,   /* not private at all. AH-like */
++  IPSEC_PRIVACY_UNKNOWN  = 8,   /* something is claimed, but details unavail */
++  IPSEC_PRIVACY_ROT13    = 12,  /* trivially breakable, i.e. 1DES */
++  IPSEC_PRIVACY_GAK      = 16,  /* known eavesdroppers */
++  IPSEC_PRIVACY_PRIVATE  = 32,  /* secure for at least a decade */
++  IPSEC_PRIVACY_STRONG   = 64,  /* ridiculously secure */
++  IPSEC_PRIVACY_TORTOISE = 192, /* even stronger, but very slow */
++  IPSEC_PRIVACY_OTP      = 224, /* some kind of *true* one time pad */
++};
++
++enum ipsec_bandwidth_quality {
++  IPSEC_QOS_UNKNOWN = 0,       /* unknown bandwidth */
++  IPSEC_QOS_INTERACTIVE = 16,  /* reasonably moderate jitter, moderate fast.
++                                Good enough for telnet/ssh. */
++  IPSEC_QOS_VOIP        = 32,  /* faster crypto, predicable jitter */
++  IPSEC_QOS_FTP         = 64,  /* higher throughput crypto, perhaps hardware
++                                offloaded, but latency/jitter may be bad */
++  IPSEC_QOS_WIRESPEED   = 128, /* expect to be able to fill your pipe */
++};
++
++/* moved from programs/pluto/constants.h */
++/* IPsec AH transform values
++ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.3
++ * and in http://www.iana.org/assignments/isakmp-registry
++ */
++enum ipsec_authentication_algo {
++  AH_MD5=2,
++  AH_SHA=3,
++  AH_DES=4,
++  AH_SHA2_256=5,
++  AH_SHA2_384=6,
++  AH_SHA2_512=7
++};
++
++/* IPsec ESP transform values
++ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.4
++ * and from http://www.iana.org/assignments/isakmp-registry
++ */
++
++enum ipsec_cipher_algo {
++  ESP_reserved=0,
++  ESP_DES_IV64=1,
++  ESP_DES=2,
++  ESP_3DES=3,
++  ESP_RC5=4,
++  ESP_IDEA=5,
++  ESP_CAST=6,
++  ESP_BLOWFISH=7,
++  ESP_3IDEA=8,
++  ESP_DES_IV32=9,
++  ESP_RC4=10,
++  ESP_NULL=11,
++  ESP_AES=12,         /* 128 bit AES */
++};
++
++/* IPCOMP transform values
++ * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.4.5
++ */
++
++enum ipsec_comp_algo {
++  IPCOMP_OUI=               1,
++  IPCOMP_DEFLATE=           2,
++  IPCOMP_LZS=               3,
++  IPCOMP_V42BIS=            4
++};
++
++/* Identification type values
++ * RFC 2407 The Internet IP security Domain of Interpretation for ISAKMP 4.6.2.1 
++ */
++
++enum ipsec_id_type {
++  ID_IMPOSSIBLE=             (-2),    /* private to Pluto */
++  ID_MYID=                   (-1),    /* private to Pluto */
++  ID_NONE=                     0,     /* private to Pluto */
++  ID_IPV4_ADDR=                1,
++  ID_FQDN=                     2,
++  ID_USER_FQDN=                3,
++  ID_IPV4_ADDR_SUBNET=         4,
++  ID_IPV6_ADDR=                5,
++  ID_IPV6_ADDR_SUBNET=         6,
++  ID_IPV4_ADDR_RANGE=          7,
++  ID_IPV6_ADDR_RANGE=          8,
++  ID_DER_ASN1_DN=              9,
++  ID_DER_ASN1_GN=              10,
++  ID_KEY_ID=                   11
++};
++
++/* Certificate type values
++ * RFC 2408 ISAKMP, chapter 3.9
++ */
++enum ipsec_cert_type {
++  CERT_NONE=                  0,  /* none, or guess from file contents */
++  CERT_PKCS7_WRAPPED_X509=    1,  /* self-signed certificate from disk */
++  CERT_PGP=                   2,
++  CERT_DNS_SIGNED_KEY=                3,  /* KEY RR from DNS */
++  CERT_X509_SIGNATURE=                4,
++  CERT_X509_KEY_EXCHANGE=     5,
++  CERT_KERBEROS_TOKENS=               6,
++  CERT_CRL=                   7,
++  CERT_ARL=                   8,
++  CERT_SPKI=                  9,
++  CERT_X509_ATTRIBUTE=                10,
++  CERT_RAW_RSA=                 11, /* raw RSA from config file */ 
++};
++
++/* a SIG record in ASCII */
++struct ipsec_dns_sig {
++  char fqdn[256];
++  char dns_sig[768];     /* empty string if not signed */
++};
++
++struct ipsec_raw_key {
++  char id_name[256];
++  char fs_keyid[8];
++};
++
++struct ipsec_identity {
++  enum ipsec_id_type     ii_type;
++  enum ipsec_cert_type   ii_format;
++  union {
++    struct ipsec_dns_sig ipsec_dns_signed;
++    /* some thing for PGP */
++    /* some thing for PKIX */
++    struct ipsec_raw_key ipsec_raw_key;
++  } ii_credential;
++};
++
++#define IPSEC_MAX_CREDENTIALS 32
++
++struct ipsec_policy_cmd_query {
++  struct ipsec_policy_msg_head head;
++
++  /* Query section */
++  ip_address query_local;     /* us   */
++  ip_address query_remote;    /* them */
++  u_int8_t proto;             /* TCP, ICMP, etc. */
++  u_short src_port, dst_port;
++
++  /* Answer section */
++  enum ipsec_privacy_quality     strength;
++  enum ipsec_bandwidth_quality   bandwidth;
++  enum ipsec_authentication_algo auth_detail;  
++  enum ipsec_cipher_algo         esp_detail;
++  enum ipsec_comp_algo           comp_detail;
++
++  int                            credential_count;
++
++  struct ipsec_identity credentials[IPSEC_MAX_CREDENTIALS];
++};
++
++#define IPSEC_POLICY_SOCKET "/var/run/pluto/pluto.info"
++
++/* prototypes */
++extern err_t ipsec_policy_lookup(int fd, struct ipsec_policy_cmd_query *result);
++extern err_t ipsec_policy_init(void);
++extern err_t ipsec_policy_final(void);
++extern err_t ipsec_policy_readmsg(int policysock,
++                                unsigned char *buf, size_t buflen);
++extern err_t ipsec_policy_sendrecv(unsigned char *buf, size_t buflen);
++extern err_t ipsec_policy_cgilookup(struct ipsec_policy_cmd_query *result);
++
++
++extern const char *ipsec_policy_version_code(void);
++extern const char *ipsec_policy_version_string(void);
++
++#endif /* _IPSEC_POLICY_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_proto.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,199 @@
++/*
++ * @(#) prototypes for FreeSWAN functions 
++ *
++ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
++ *                 and Michael Richardson  <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_proto.h,v 1.14 2005/04/29 04:50:03 mcr Exp $
++ *
++ */
++
++#ifndef _IPSEC_PROTO_H_
++
++#include "ipsec_param.h"
++
++/* 
++ * This file is a kernel only file that declares prototypes for
++ * all intra-module function calls and global data structures.
++ *
++ * Include this file last.
++ *
++ */
++
++/* forward references */
++enum ipsec_direction;
++enum ipsec_life_type;
++struct ipsec_lifetime64;
++struct ident;
++struct sockaddr_encap;
++struct ipsec_sa;
++
++/* ipsec_init.c */
++extern struct prng ipsec_prng;
++
++/* ipsec_sa.c */
++extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];
++extern spinlock_t       tdb_lock;
++extern int ipsec_sadb_init(void);
++extern int ipsec_sadb_cleanup(__u8);
++
++extern struct ipsec_sa *ipsec_sa_alloc(int*error); 
++
++
++extern struct ipsec_sa *ipsec_sa_getbyid(ip_said *);
++extern int ipsec_sa_put(struct ipsec_sa *);
++extern /* void */ int ipsec_sa_del(struct ipsec_sa *);
++extern /* void */ int ipsec_sa_delchain(struct ipsec_sa *);
++extern /* void */ int ipsec_sa_add(struct ipsec_sa *);
++
++extern int ipsec_sa_init(struct ipsec_sa *ipsp);
++extern int ipsec_sa_wipe(struct ipsec_sa *ipsp);
++
++/* debug declarations */
++
++/* ipsec_proc.c */
++extern int  ipsec_proc_init(void);
++extern void ipsec_proc_cleanup(void);
++
++/* ipsec_rcv.c */
++extern int ipsec_rcv(struct sk_buff *skb);
++extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type);
++
++/* ipsec_xmit.c */
++struct ipsec_xmit_state;
++extern enum ipsec_xmit_value ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs);
++extern enum ipsec_xmit_value ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs);
++extern void ipsec_print_ip(struct iphdr *ip);
++
++
++
++/* ipsec_radij.c */
++extern int ipsec_makeroute(struct sockaddr_encap *ea,
++                         struct sockaddr_encap *em,
++                         ip_said said,
++                         uint32_t pid,
++                         struct sk_buff *skb,
++                         struct ident *ident_s,
++                         struct ident *ident_d);
++
++extern int ipsec_breakroute(struct sockaddr_encap *ea,
++                          struct sockaddr_encap *em,
++                          struct sk_buff **first,
++                          struct sk_buff **last);
++
++int ipsec_radijinit(void);
++int ipsec_cleareroutes(void);
++int ipsec_radijcleanup(void);
++
++/* ipsec_life.c */
++extern enum ipsec_life_alive ipsec_lifetime_check(struct ipsec_lifetime64 *il64,
++                                                const char *lifename,
++                                                const char *saname,
++                                                enum ipsec_life_type ilt,
++                                                enum ipsec_direction idir,
++                                                struct ipsec_sa *ips);
++
++
++extern int ipsec_lifetime_format(char *buffer,
++                               int   buflen,
++                               char *lifename,
++                               enum ipsec_life_type timebaselife,
++                               struct ipsec_lifetime64 *lifetime);
++
++extern void ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime,
++                                     __u64 newvalue);
++
++extern void ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime,
++                                     __u64 newvalue);
++
++/* ipsec_snprintf.c */
++extern int ipsec_snprintf(char * buf, ssize_t size, const char *fmt, ...);
++extern void ipsec_dmp_block(char *s, caddr_t bb, int len);
++
++
++/* ipsec_alg.c */
++extern int ipsec_alg_init(void);
++
++
++#ifdef CONFIG_KLIPS_DEBUG
++
++extern int debug_xform;
++extern int debug_eroute;
++extern int debug_spi;
++extern int debug_netlink;
++
++#endif /* CONFIG_KLIPS_DEBUG */
++
++
++
++
++#define _IPSEC_PROTO_H
++#endif /* _IPSEC_PROTO_H_ */
++
++/*
++ * $Log: ipsec_proto.h,v $
++ * Revision 1.14  2005/04/29 04:50:03  mcr
++ *    prototypes for xmit and alg code.
++ *
++ * Revision 1.13  2005/04/17 03:46:07  mcr
++ *    added prototypes for ipsec_rcv() routines.
++ *
++ * Revision 1.12  2005/04/14 20:28:37  mcr
++ *    added additional prototypes.
++ *
++ * Revision 1.11  2005/04/14 01:16:28  mcr
++ *    add prototypes for snprintf.
++ *
++ * Revision 1.10  2005/04/13 22:47:28  mcr
++ *    make sure that forward references are available.
++ *
++ * Revision 1.9  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.8  2004/04/05 19:55:06  mcr
++ * Moved from linux/include/freeswan/ipsec_proto.h,v
++ *
++ * Revision 1.7  2003/10/31 02:27:05  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.6.30.1  2003/10/29 01:10:19  mcr
++ *    elimited "struct sa_id"
++ *
++ * Revision 1.6  2002/05/23 07:13:48  rgb
++ * Added ipsec_sa_put() for releasing an ipsec_sa refcount.
++ *
++ * Revision 1.5  2002/05/14 02:36:40  rgb
++ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion
++ * with "put" usage in the kernel.
++ *
++ * Revision 1.4  2002/04/24 07:36:47  mcr
++ * Moved from ./klips/net/ipsec/ipsec_proto.h,v
++ *
++ * Revision 1.3  2002/04/20 00:12:25  rgb
++ * Added esp IV CBC attack fix, disabled.
++ *
++ * Revision 1.2  2001/11/26 09:16:15  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:21:01  mcr
++ *    ipsec_proto.h created to keep prototypes rather than deal with
++ *    cyclic dependancies of structures and prototypes in .h files.
++ *
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_radij.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,179 @@
++/*
++ * @(#) Definitions relevant to the IPSEC <> radij tree interfacing
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_radij.h,v 1.22 2004/07/10 19:08:41 mcr Exp $
++ */
++
++#ifndef _IPSEC_RADIJ_H
++
++#include <openswan.h>
++
++int ipsec_walk(char *);
++
++int ipsec_rj_walker_procprint(struct radij_node *, void *);
++int ipsec_rj_walker_delete(struct radij_node *, void *);
++
++/* This structure is used to pass information between
++ * ipsec_eroute_get_info and ipsec_rj_walker_procprint
++ * (through rj_walktree) and between calls of ipsec_rj_walker_procprint.
++ */
++struct wsbuf
++{
++       /* from caller of ipsec_eroute_get_info: */
++       char *const buffer;     /* start of buffer provided */
++       const int length;       /* length of buffer provided */
++       const off_t offset;     /* file position of first character of interest */
++       /* accumulated by ipsec_rj_walker_procprint: */
++       int len;        /* number of character filled into buffer */
++       off_t begin;    /* file position contained in buffer[0] (<=offset) */
++};
++
++extern struct radij_node_head *rnh;
++extern spinlock_t eroute_lock;
++
++struct eroute * ipsec_findroute(struct sockaddr_encap *);
++
++#define O1(x) (int)(((x)>>24)&0xff)
++#define O2(x) (int)(((x)>>16)&0xff)
++#define O3(x) (int)(((x)>>8)&0xff)
++#define O4(x) (int)(((x))&0xff)
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int debug_radij;
++void rj_dumptrees(void);
++
++#define DB_RJ_DUMPTREES       0x0001
++#define DB_RJ_FINDROUTE 0x0002
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#define _IPSEC_RADIJ_H
++#endif
++
++/*
++ * $Log: ipsec_radij.h,v $
++ * Revision 1.22  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.21  2004/04/29 11:06:42  ken
++ * Last bits from 2.06 procfs updates
++ *
++ * Revision 1.20  2004/04/06 02:49:08  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.19  2004/04/05 19:55:06  mcr
++ * Moved from linux/include/freeswan/ipsec_radij.h,v
++ *
++ * Revision 1.18  2002/04/24 07:36:47  mcr
++ * Moved from ./klips/net/ipsec/ipsec_radij.h,v
++ *
++ * Revision 1.17  2001/11/26 09:23:49  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.16.2.1  2001/09/25 02:21:17  mcr
++ *    ipsec_proto.h created to keep prototypes rather than deal with
++ *    cyclic dependancies of structures and prototypes in .h files.
++ *
++ * Revision 1.16  2001/09/15 16:24:04  rgb
++ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
++ *
++ * Revision 1.15  2001/09/14 16:58:37  rgb
++ * Added support for storing the first and last packets through a HOLD.
++ *
++ * Revision 1.14  2001/09/08 21:13:32  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.13  2001/06/14 19:35:09  rgb
++ * Update copyright date.
++ *
++ * Revision 1.12  2001/05/27 06:12:11  rgb
++ * Added structures for pid, packet count and last access time to eroute.
++ * Added packet count to beginning of /proc/net/ipsec_eroute.
++ *
++ * Revision 1.11  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.10  1999/11/17 15:53:39  rgb
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ *
++ * Revision 1.9  1999/10/01 00:01:23  rgb
++ * Added eroute structure locking.
++ *
++ * Revision 1.8  1999/04/11 00:28:59  henry
++ * GPL boilerplate
++ *
++ * Revision 1.7  1999/04/06 04:54:26  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.6  1999/01/22 06:23:26  rgb
++ * Cruft clean-out.
++ *
++ * Revision 1.5  1998/10/25 02:42:08  rgb
++ * Change return type on ipsec_breakroute and ipsec_makeroute and add an
++ * argument to be able to transmit more infomation about errors.
++ *
++ * Revision 1.4  1998/10/19 14:44:29  rgb
++ * Added inclusion of freeswan.h.
++ * sa_id structure implemented and used: now includes protocol.
++ *
++ * Revision 1.3  1998/07/28 00:03:31  rgb
++ * Comment out temporary inet_nto4u() kluge.
++ *
++ * Revision 1.2  1998/07/14 18:22:00  rgb
++ * Add function to clear the eroute table.
++ *
++ * Revision 1.1  1998/06/18 21:27:49  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.5  1998/05/25 20:30:38  rgb
++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
++ *
++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
++ * add ipsec_rj_walker_delete.
++ *
++ * Revision 1.4  1998/05/21 13:02:56  rgb
++ * Imported definitions from ipsec_radij.c and radij.c to support /proc 3k
++ * limit fix.
++ *
++ * Revision 1.3  1998/04/21 21:29:09  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.2  1998/04/14 17:30:39  rgb
++ * Fix up compiling errors for radij tree memory reclamation.
++ *
++ * Revision 1.1  1998/04/09 03:06:10  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:39:04  ji
++ * Minor cleanups.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_rcv.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,199 @@
++/*
++ * 
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_rcv.h,v 1.28.2.2 2006/10/06 21:39:26 paul Exp $
++ */
++
++#ifndef IPSEC_RCV_H
++#define IPSEC_RCV_H
++
++#include "openswan/ipsec_auth.h"
++
++#define DB_RX_PKTRX   0x0001
++#define DB_RX_PKTRX2  0x0002
++#define DB_RX_DMP     0x0004
++#define DB_RX_IPSA    0x0010
++#define DB_RX_XF      0x0020
++#define DB_RX_IPAD    0x0040
++#define DB_RX_INAU    0x0080
++#define DB_RX_OINFO   0x0100
++#define DB_RX_OINFO2  0x0200
++#define DB_RX_OH      0x0400
++#define DB_RX_REPLAY  0x0800
++
++#ifdef __KERNEL__
++/* struct options; */
++
++#define __NO_VERSION__
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>     /* for CONFIG_IP_FORWARD */
++#endif
++#ifdef CONFIG_MODULES
++#include <linux/module.h>
++#endif
++#include <linux/version.h>
++#include <openswan.h>
++
++#define IPSEC_BIRTH_TEMPLATE_MAXLEN 256
++
++struct ipsec_birth_reply {
++  int            packet_template_len;
++  unsigned char  packet_template[IPSEC_BIRTH_TEMPLATE_MAXLEN];
++};
++
++extern struct ipsec_birth_reply ipsec_ipv4_birth_packet;
++extern struct ipsec_birth_reply ipsec_ipv6_birth_packet;
++
++enum ipsec_rcv_value {
++      IPSEC_RCV_LASTPROTO=1,
++      IPSEC_RCV_OK=0,
++      IPSEC_RCV_BADPROTO=-1,
++      IPSEC_RCV_BADLEN=-2,
++      IPSEC_RCV_ESP_BADALG=-3,
++      IPSEC_RCV_3DES_BADBLOCKING=-4,
++      IPSEC_RCV_ESP_DECAPFAIL=-5,
++      IPSEC_RCV_DECAPFAIL=-6,
++      IPSEC_RCV_SAIDNOTFOUND=-7,
++      IPSEC_RCV_IPCOMPALONE=-8,
++      IPSEC_RCV_IPCOMPFAILED=-10,
++      IPSEC_RCV_SAIDNOTLIVE=-11,
++      IPSEC_RCV_FAILEDINBOUND=-12,
++      IPSEC_RCV_LIFETIMEFAILED=-13,
++      IPSEC_RCV_BADAUTH=-14,
++      IPSEC_RCV_REPLAYFAILED=-15,
++      IPSEC_RCV_AUTHFAILED=-16,
++      IPSEC_RCV_REPLAYROLLED=-17,
++      IPSEC_RCV_BAD_DECRYPT=-18
++};
++
++struct ipsec_rcv_state {
++      struct sk_buff *skb;
++      struct net_device_stats *stats;
++      struct iphdr    *ipp;          /* the IP header */
++      struct ipsec_sa *ipsp;         /* current SA being processed */
++      int len;                       /* length of packet */
++      int ilen;                      /* length of inner payload (-authlen) */
++      int authlen;                   /* how big is the auth data at end */
++      int hard_header_len;           /* layer 2 size */
++      int iphlen;                    /* how big is IP header */
++      struct auth_alg *authfuncs;
++      ip_said said;
++      char   sa[SATOT_BUF];
++      size_t sa_len;
++      __u8 next_header;
++      __u8 hash[AH_AMAX];
++      char ipsaddr_txt[ADDRTOA_BUF];
++      char ipdaddr_txt[ADDRTOA_BUF];
++      __u8 *octx;
++      __u8 *ictx;
++      int ictx_len;
++      int octx_len;
++      union {
++              struct {
++                      struct esphdr *espp;
++              } espstuff;
++              struct {
++                      struct ahhdr *ahp;
++              } ahstuff;
++              struct {
++                      struct ipcomphdr *compp;
++              } ipcompstuff;
++      } protostuff;
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      __u8            natt_type;
++      __u16           natt_sport;
++      __u16           natt_dport;
++      int             natt_len; 
++#endif  
++};
++
++extern int
++#ifdef PROTO_HANDLER_SINGLE_PARM
++ipsec_rcv(struct sk_buff *skb);
++#else /* PROTO_HANDLER_SINGLE_PARM */
++ipsec_rcv(struct sk_buff *skb,
++        unsigned short xlen);
++#endif /* PROTO_HANDLER_SINGLE_PARM */
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int debug_rcv;
++#define ipsec_rcv_dmp(_x,_y, _z) if (debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z)
++#else
++#define ipsec_rcv_dmp(_x,_y, _z) do {} while(0)
++#endif /* CONFIG_KLIPS_DEBUG */
++
++extern int sysctl_ipsec_inbound_policy_check;
++#endif /* __KERNEL__ */
++
++extern int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type);
++
++
++#endif /* IPSEC_RCV_H */
++
++/*
++ * $Log: ipsec_rcv.h,v $
++ * Revision 1.28.2.2  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.28.2.1  2006/07/10 15:52:20  paul
++ * Fix for bug #642 by Bart Trojanowski
++ *
++ * Revision 1.28  2005/05/11 00:59:45  mcr
++ *    do not call debug routines if !defined KLIPS_DEBUG.
++ *
++ * Revision 1.27  2005/04/29 04:59:46  mcr
++ *    use ipsec_dmp_block.
++ *
++ * Revision 1.26  2005/04/13 22:48:35  mcr
++ *    added comments, and removed some log.
++ *    removed Linux 2.0 support.
++ *
++ * Revision 1.25  2005/04/08 18:25:37  mcr
++ *    prototype klips26 encap receive function
++ *
++ * Revision 1.24  2004/08/20 21:45:37  mcr
++ *    CONFIG_KLIPS_NAT_TRAVERSAL is not used in an attempt to
++ *    be 26sec compatible. But, some defines where changed.
++ *
++ * Revision 1.23  2004/08/03 18:17:40  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.22  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.21  2004/04/06 02:49:08  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.20  2004/04/05 19:55:06  mcr
++ * Moved from linux/include/freeswan/ipsec_rcv.h,v
++ *
++ * Revision 1.19  2003/12/15 18:13:09  mcr
++ *    when compiling with NAT traversal, don't assume that the
++ *    kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP
++ *    is set.
++ *
++ * history elided 2005-04-12.
++ *
++ * Local Variables:
++ * c-basic-offset:8
++ * c-style:linux
++ * End:
++ *
++ */
++
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_sa.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,355 @@
++/*
++ * @(#) Definitions of IPsec Security Association (ipsec_sa)
++ *
++ * Copyright (C) 2001, 2002, 2003
++ *                      Richard Guy Briggs  <rgb@freeswan.org>
++ *                  and Michael Richardson  <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_sa.h,v 1.23 2005/05/11 01:18:59 mcr Exp $
++ *
++ * This file derived from ipsec_xform.h on 2001/9/18 by mcr.
++ *
++ */
++
++/* 
++ * This file describes the IPsec Security Association Structure.
++ *
++ * This structure keeps track of a single transform that may be done
++ * to a set of packets. It can describe applying the transform or
++ * apply the reverse. (e.g. compression vs expansion). However, it
++ * only describes one at a time. To describe both, two structures would
++ * be used, but since the sides of the transform are performed 
++ * on different machines typically it is usual to have only one side
++ * of each association.
++ * 
++ */
++
++#ifndef _IPSEC_SA_H_
++
++#ifdef __KERNEL__
++#include "openswan/ipsec_stats.h"
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_eroute.h"
++#endif /* __KERNEL__ */
++#include "openswan/ipsec_param.h"
++
++#include "pfkeyv2.h"
++
++
++/* SAs are held in a table.
++ * Entries in this table are referenced by IPsecSAref_t values.
++ * IPsecSAref_t values are conceptually subscripts.  Because
++ * we want to allocate the table piece-meal, the subscripting
++ * is implemented with two levels, a bit like paged virtual memory.
++ * This representation mechanism is known as an Iliffe Vector.
++ *
++ * The Main table (AKA the refTable) consists of 2^IPSEC_SA_REF_MAINTABLE_IDX_WIDTH
++ * pointers to subtables.
++ * Each subtable has 2^IPSEC_SA_REF_SUBTABLE_IDX_WIDTH entries, each of which
++ * is a pointer to an SA.
++ *
++ * An IPsecSAref_t contains either an exceptional value (signified by the
++ * high-order bit being on) or a reference to a table entry.  A table entry
++ * reference has the subtable subscript in the low-order
++ * IPSEC_SA_REF_SUBTABLE_IDX_WIDTH bits and the Main table subscript
++ * in the next lowest IPSEC_SA_REF_MAINTABLE_IDX_WIDTH bits.
++ *
++ * The Maintable entry for an IPsecSAref_t x, a pointer to its subtable, is
++ * IPsecSAref2table(x).  It is of type struct IPsecSArefSubTable *.
++ *
++ * The pointer to the SA for x is IPsecSAref2SA(x).  It is of type
++ * struct ipsec_sa*.  The macro definition clearly shows the two-level
++ * access needed to find the SA pointer.
++ *
++ * The Maintable is allocated when IPsec is initialized.
++ * Each subtable is allocated when needed, but the first is allocated
++ * when IPsec is initialized.
++ *
++ * IPsecSAref_t is designed to be smaller than an NFmark so that
++ * they can be stored in NFmarks and still leave a few bits for other
++ * purposes.  The spare bits are in the low order of the NFmark
++ * but in the high order of the IPsecSAref_t, so conversion is required.
++ * We pick the upper bits of NFmark on the theory that they are less likely to
++ * interfere with more pedestrian uses of nfmark.
++ */
++
++
++typedef unsigned short int IPsecRefTableUnusedCount;
++
++#define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)
++
++#ifdef __KERNEL__
++#if ((IPSEC_SA_REF_TABLE_IDX_WIDTH - (1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) < 0)
++#error "IPSEC_SA_REF_TABLE_IDX_WIDTH("IPSEC_SA_REF_TABLE_IDX_WIDTH") MUST be < 1 + IPSEC_SA_REF_MAINTABLE_IDX_WIDTH("IPSEC_SA_REF_MAINTABLE_IDX_WIDTH")"
++#endif
++
++#define IPSEC_SA_REF_SUBTABLE_IDX_WIDTH (IPSEC_SA_REF_TABLE_IDX_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)
++
++#define IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)
++#define IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)
++
++#ifdef CONFIG_NETFILTER
++#define IPSEC_SA_REF_HOST_FIELD(x) ((struct sk_buff*)(x))->nfmark
++#define IPSEC_SA_REF_HOST_FIELD_TYPE typeof(IPSEC_SA_REF_HOST_FIELD(NULL))
++#else /* CONFIG_NETFILTER */
++/* just make it work for now, it doesn't matter, since there is no nfmark */
++#define IPSEC_SA_REF_HOST_FIELD_TYPE unsigned long
++#endif /* CONFIG_NETFILTER */
++#define IPSEC_SA_REF_HOST_FIELD_WIDTH (8 * sizeof(IPSEC_SA_REF_HOST_FIELD_TYPE))
++#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t))
++
++#define IPSEC_SA_REF_MASK        (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
++#define IPSEC_SA_REF_TABLE_MASK ((IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_MAINTABLE_IDX_WIDTH)) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)
++#define IPSEC_SA_REF_ENTRY_MASK  (IPSEC_SAREF_NULL >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_SUBTABLE_IDX_WIDTH))
++
++#define IPsecSAref2table(x) (((x) & IPSEC_SA_REF_TABLE_MASK) >> IPSEC_SA_REF_SUBTABLE_IDX_WIDTH)
++#define IPsecSAref2entry(x) ((x) & IPSEC_SA_REF_ENTRY_MASK)
++#define IPsecSArefBuild(x,y) (((x) << IPSEC_SA_REF_SUBTABLE_IDX_WIDTH) + (y))
++
++#define IPsecSAref2SA(x) (ipsec_sadb.refTable[IPsecSAref2table(x)]->entry[IPsecSAref2entry(x)])
++#define IPsecSA2SAref(x) ((x)->ips_ref)
++
++#define EMT_INBOUND   0x01    /* SA direction, 1=inbound */
++
++/* 'struct ipsec_sa' should be 64bit aligned when allocated. */
++struct ipsec_sa                               
++{
++      IPsecSAref_t    ips_ref;                /* reference table entry number */
++      atomic_t        ips_refcount;           /* reference count for this struct */
++      struct ipsec_sa *ips_hnext;             /* next in hash chain */
++      struct ipsec_sa *ips_inext;             /* pointer to next xform */
++      struct ipsec_sa *ips_onext;             /* pointer to prev xform */
++
++      struct ifnet    *ips_rcvif;             /* related rcv encap interface */
++
++      ip_said         ips_said;               /* SA ID */
++
++      __u32           ips_seq;                /* seq num of msg that initiated this SA */
++      __u32           ips_pid;                /* PID of process that initiated this SA */
++      __u8            ips_authalg;            /* auth algorithm for this SA */
++      __u8            ips_encalg;             /* enc algorithm for this SA */
++
++      struct ipsec_stats ips_errs;
++
++      __u8            ips_replaywin;          /* replay window size */
++      enum sadb_sastate ips_state;            /* state of SA */
++      __u32           ips_replaywin_lastseq;  /* last pkt sequence num */
++      __u64           ips_replaywin_bitmap;   /* bitmap of received pkts */
++      __u32           ips_replaywin_maxdiff;  /* max pkt sequence difference */
++
++      __u32           ips_flags;              /* generic xform flags */
++
++
++      struct ipsec_lifetimes ips_life;        /* lifetime records */
++
++      /* selector information */
++        __u8            ips_transport_protocol; /* protocol for this SA, if ports are involved */
++      struct sockaddr*ips_addr_s;             /* src sockaddr */
++      struct sockaddr*ips_addr_d;             /* dst sockaddr */
++      struct sockaddr*ips_addr_p;             /* proxy sockaddr */
++      __u16           ips_addr_s_size;
++      __u16           ips_addr_d_size;
++      __u16           ips_addr_p_size;
++      ip_address      ips_flow_s;
++      ip_address      ips_flow_d;
++      ip_address      ips_mask_s;
++      ip_address      ips_mask_d;
++
++      __u16           ips_key_bits_a;         /* size of authkey in bits */
++      __u16           ips_auth_bits;          /* size of authenticator in bits */
++      __u16           ips_key_bits_e;         /* size of enckey in bits */
++      __u16           ips_iv_bits;            /* size of IV in bits */
++      __u8            ips_iv_size;
++      __u16           ips_key_a_size;
++      __u16           ips_key_e_size;
++
++      caddr_t         ips_key_a;              /* authentication key */
++      caddr_t         ips_key_e;              /* encryption key */
++      caddr_t         ips_iv;                 /* Initialisation Vector */
++
++      struct ident    ips_ident_s;            /* identity src */
++      struct ident    ips_ident_d;            /* identity dst */
++
++        /* these are included even if CONFIG_KLIPS_IPCOMP is off */
++      __u16           ips_comp_adapt_tries;   /* ipcomp self-adaption tries */
++      __u16           ips_comp_adapt_skip;    /* ipcomp self-adaption to-skip */
++      __u64           ips_comp_ratio_cbytes;  /* compressed bytes */
++      __u64           ips_comp_ratio_dbytes;  /* decompressed (or uncompressed) bytes */
++
++        /* these are included even if CONFIG_IPSEC_NAT_TRAVERSAL is off */
++      __u8            ips_natt_type;
++      __u8            ips_natt_reserved[3];
++      __u16           ips_natt_sport;
++      __u16           ips_natt_dport;
++
++      struct sockaddr *ips_natt_oa;
++      __u16           ips_natt_oa_size;
++      __u16           ips_natt_reserved2;
++
++#if 0
++      __u32           ips_sens_dpd;
++      __u8            ips_sens_sens_level;
++      __u8            ips_sens_sens_len;
++      __u64*          ips_sens_sens_bitmap;
++      __u8            ips_sens_integ_level;
++      __u8            ips_sens_integ_len;
++      __u64*          ips_sens_integ_bitmap;
++#endif
++      struct ipsec_alg_enc *ips_alg_enc;
++      struct ipsec_alg_auth *ips_alg_auth;
++      IPsecSAref_t    ips_ref_rel;
++};
++
++struct IPsecSArefSubTable
++{
++      struct ipsec_sa* entry[IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES];
++};
++
++struct ipsec_sadb {
++      struct IPsecSArefSubTable* refTable[IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES];
++      IPsecSAref_t refFreeList[IPSEC_SA_REF_FREELIST_NUM_ENTRIES];
++      int refFreeListHead;
++      int refFreeListTail;
++      IPsecSAref_t refFreeListCont;
++      IPsecSAref_t said_hash[SADB_HASHMOD];
++      spinlock_t sadb_lock;
++};
++
++extern struct ipsec_sadb ipsec_sadb;
++
++extern int ipsec_SAref_recycle(void);
++extern int ipsec_SArefSubTable_alloc(unsigned table);
++extern int ipsec_saref_freelist_init(void);
++extern int ipsec_sadb_init(void);
++extern struct ipsec_sa *ipsec_sa_alloc(int*error); /* pass in error var by pointer */
++extern IPsecSAref_t ipsec_SAref_alloc(int*erorr); /* pass in error var by pointer */
++extern int ipsec_sa_free(struct ipsec_sa* ips);
++extern int ipsec_sa_put(struct ipsec_sa *ips);
++extern int ipsec_sa_add(struct ipsec_sa *ips);
++extern int ipsec_sa_del(struct ipsec_sa *ips);
++extern int ipsec_sa_delchain(struct ipsec_sa *ips);
++extern int ipsec_sadb_cleanup(__u8 proto);
++extern int ipsec_sadb_free(void);
++extern int ipsec_sa_wipe(struct ipsec_sa *ips);
++#endif /* __KERNEL__ */
++
++enum ipsec_direction {
++      ipsec_incoming = 1,
++      ipsec_outgoing = 2
++};
++
++#define _IPSEC_SA_H_
++#endif /* _IPSEC_SA_H_ */
++
++/*
++ * $Log: ipsec_sa.h,v $
++ * Revision 1.23  2005/05/11 01:18:59  mcr
++ *    do not change structure based upon options, to avoid
++ *    too many #ifdef.
++ *
++ * Revision 1.22  2005/04/14 01:17:09  mcr
++ *    change sadb_state to an enum.
++ *
++ * Revision 1.21  2004/08/20 21:45:37  mcr
++ *    CONFIG_KLIPS_NAT_TRAVERSAL is not used in an attempt to
++ *    be 26sec compatible. But, some defines where changed.
++ *
++ * Revision 1.20  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.19  2004/04/05 19:55:06  mcr
++ * Moved from linux/include/freeswan/ipsec_sa.h,v
++ *
++ * Revision 1.18  2004/04/05 19:41:05  mcr
++ *    merged alg-branch code.
++ *
++ * Revision 1.17.2.1  2003/12/22 15:25:52  jjo
++ * . Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.17  2003/12/10 01:20:06  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.16  2003/10/31 02:27:05  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.15.4.1  2003/10/29 01:10:19  mcr
++ *    elimited "struct sa_id"
++ *
++ * Revision 1.15  2003/05/11 00:53:09  mcr
++ *    IPsecSAref_t and macros were moved to freeswan.h.
++ *
++ * Revision 1.14  2003/02/12 19:31:55  rgb
++ * Fixed bug in "file seen" machinery.
++ * Updated copyright year.
++ *
++ * Revision 1.13  2003/01/30 02:31:52  rgb
++ *
++ * Re-wrote comments describing SAref system for accuracy.
++ * Rename SAref table macro names for clarity.
++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
++ * Transmit error code through to caller from callee for better diagnosis of problems.
++ * Enclose all macro arguments in parens to avoid any possible obscrure bugs.
++ *
++ * Revision 1.12  2002/10/07 18:31:19  rgb
++ * Change comment to reflect the flexible nature of the main and sub-table widths.
++ * Added a counter for the number of unused entries in each subtable.
++ * Further break up host field type macro to host field.
++ * Move field width sanity checks to ipsec_sa.c
++ * Define a mask for an entire saref.
++ *
++ * Revision 1.11  2002/09/20 15:40:33  rgb
++ * Re-write most of the SAref macros and types to eliminate any pointer references to Entrys.
++ * Fixed SAref/nfmark macros.
++ * Rework saref freeslist.
++ * Place all ipsec sadb globals into one struct.
++ * Restrict some bits to kernel context for use to klips utils.
++ *
++ * Revision 1.10  2002/09/20 05:00:34  rgb
++ * Update copyright date.
++ *
++ * Revision 1.9  2002/09/17 17:19:29  mcr
++ *    make it compile even if there is no netfilter - we lost
++ *    functionality, but it works, especially on 2.2.
++ *
++ * Revision 1.8  2002/07/28 22:59:53  mcr
++ *    clarified/expanded one comment.
++ *
++ * Revision 1.7  2002/07/26 08:48:31  rgb
++ * Added SA ref table code.
++ *
++ * Revision 1.6  2002/05/31 17:27:48  rgb
++ * Comment fix.
++ *
++ * Revision 1.5  2002/05/27 18:55:03  rgb
++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT.
++ *
++ * Revision 1.4  2002/05/23 07:13:36  rgb
++ * Convert "usecount" to "refcount" to remove ambiguity.
++ *
++ * Revision 1.3  2002/04/24 07:36:47  mcr
++ * Moved from ./klips/net/ipsec/ipsec_sa.h,v
++ *
++ * Revision 1.2  2001/11/26 09:16:15  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:24:58  mcr
++ *    struct tdb -> struct ipsec_sa.
++ *    sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
++ *    ipsec_xform.c removed. header file still contains useful things.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_sha1.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,79 @@
++/*
++ * RCSID $Id: ipsec_sha1.h,v 1.8 2004/04/05 19:55:07 mcr Exp $
++ */
++
++/*
++ * Here is the original comment from the distribution:
++
++SHA-1 in C
++By Steve Reid <steve@edmweb.com>
++100% Public Domain
++
++ * Adapted for use by the IPSEC code by John Ioannidis
++ */
++
++
++#ifndef _IPSEC_SHA1_H_
++#define _IPSEC_SHA1_H_
++
++typedef struct
++{
++      __u32   state[5];
++      __u32   count[2];
++      __u8    buffer[64];
++} SHA1_CTX;
++
++void SHA1Transform(__u32 state[5], __u8 buffer[64]);
++void SHA1Init(void *context);
++void SHA1Update(void *context, unsigned char *data, __u32 len);
++void SHA1Final(unsigned char digest[20], void *context);
++
++ 
++#endif /* _IPSEC_SHA1_H_ */
++
++/*
++ * $Log: ipsec_sha1.h,v $
++ * Revision 1.8  2004/04/05 19:55:07  mcr
++ * Moved from linux/include/freeswan/ipsec_sha1.h,v
++ *
++ * Revision 1.7  2002/09/10 01:45:09  mcr
++ *    changed type of MD5_CTX and SHA1_CTX to void * so that
++ *    the function prototypes would match, and could be placed
++ *    into a pointer to a function.
++ *
++ * Revision 1.6  2002/04/24 07:36:47  mcr
++ * Moved from ./klips/net/ipsec/ipsec_sha1.h,v
++ *
++ * Revision 1.5  1999/12/13 13:59:13  rgb
++ * Quick fix to argument size to Update bugs.
++ *
++ * Revision 1.4  1999/12/07 18:16:23  rgb
++ * Fixed comments at end of #endif lines.
++ *
++ * Revision 1.3  1999/04/06 04:54:27  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.2  1998/11/30 13:22:54  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.1  1998/06/18 21:27:50  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.2  1998/04/23 20:54:05  rgb
++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
++ * verified.
++ *
++ * Revision 1.1  1998/04/09 03:04:21  henry
++ * sources moved up from linux/net/ipsec
++ * these two include files modified not to include others except in kernel
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * New transform
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_stats.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,76 @@
++/*
++ * @(#) definition of ipsec_stats structure
++ *
++ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
++ *                 and Michael Richardson  <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_stats.h,v 1.7 2005/04/14 01:17:45 mcr Exp $
++ *
++ */
++
++/* 
++ * This file describes the errors/statistics that FreeSWAN collects.
++ */
++
++#ifndef _IPSEC_STATS_H_
++
++struct ipsec_stats {
++      __u32           ips_alg_errs;          /* number of algorithm errors */
++      __u32           ips_auth_errs;         /* # of authentication errors */
++      __u32           ips_encsize_errs;      /* # of encryption size errors*/
++      __u32           ips_encpad_errs;       /* # of encryption pad  errors*/
++      __u32           ips_replaywin_errs;    /* # of pkt sequence errors */
++};
++
++#define _IPSEC_STATS_H_
++#endif /* _IPSEC_STATS_H_ */
++
++/*
++ * $Log: ipsec_stats.h,v $
++ * Revision 1.7  2005/04/14 01:17:45  mcr
++ *    add prototypes for snprintf.
++ *
++ * Revision 1.6  2004/04/05 19:55:07  mcr
++ * Moved from linux/include/freeswan/ipsec_stats.h,v
++ *
++ * Revision 1.5  2004/04/05 19:41:05  mcr
++ *    merged alg-branch code.
++ *
++ * Revision 1.4  2004/03/28 20:27:19  paul
++ * Included tested and confirmed fixes mcr made and dhr verified for
++ * snprint statements. Changed one other snprintf to use ipsec_snprintf
++ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with
++ * dhr. (thanks dhr!)
++ *
++ * Revision 1.4  2004/03/24 01:58:31  mcr
++ *     sprintf->snprintf for formatting into proc buffer.
++ *
++ * Revision 1.3.34.1  2004/04/05 04:30:46  mcr
++ *    patches for alg-branch to compile/work with 2.x openswan
++ *
++ * Revision 1.3  2002/04/24 07:36:47  mcr
++ * Moved from ./klips/net/ipsec/ipsec_stats.h,v
++ *
++ * Revision 1.2  2001/11/26 09:16:16  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:27:00  mcr
++ *    statistics moved to seperate structure.
++ *
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_tunnel.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,280 @@
++/*
++ * IPSEC tunneling code
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_tunnel.h,v 1.33 2005/06/04 16:06:05 mcr Exp $
++ */
++
++
++#ifdef NET_21
++# define DEV_QUEUE_XMIT(skb, device, pri) {\
++      skb->dev = device; \
++      neigh_compat_output(skb); \
++      /* skb->dst->output(skb); */ \
++ }
++# define ICMP_SEND(skb_in, type, code, info, dev) \
++      icmp_send(skb_in, type, code, htonl(info))
++# define IP_SEND(skb, dev) \
++      ip_send(skb);
++#else /* NET_21 */
++# define DEV_QUEUE_XMIT(skb, device, pri) {\
++      dev_queue_xmit(skb, device, pri); \
++ }
++# define ICMP_SEND(skb_in, type, code, info, dev) \
++      icmp_send(skb_in, type, code, info, dev)
++# define IP_SEND(skb, dev) \
++      if(ntohs(iph->tot_len) > physmtu) { \
++              ip_fragment(NULL, skb, dev, 0); \
++              ipsec_kfree_skb(skb); \
++      } else { \
++              dev_queue_xmit(skb, dev, SOPRI_NORMAL); \
++      }
++#endif /* NET_21 */
++
++
++/*
++ * Heavily based on drivers/net/new_tunnel.c.  Lots
++ * of ideas also taken from the 2.1.x version of drivers/net/shaper.c
++ */
++
++struct ipsectunnelconf
++{
++      __u32   cf_cmd;
++      union
++      {
++              char    cfu_name[12];
++      } cf_u;
++#define cf_name cf_u.cfu_name
++};
++
++#define IPSEC_SET_DEV (SIOCDEVPRIVATE)
++#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1)
++#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2)
++
++#ifdef __KERNEL__
++#include <linux/version.h>
++#ifndef KERNEL_VERSION
++#  define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
++#endif
++struct ipsecpriv
++{
++      struct sk_buff_head sendq;
++      struct net_device *dev;
++      struct wait_queue *wait_queue;
++      char locked;
++      int  (*hard_start_xmit) (struct sk_buff *skb,
++              struct net_device *dev);
++      int  (*hard_header) (struct sk_buff *skb,
++              struct net_device *dev,
++              unsigned short type,
++              void *daddr,
++              void *saddr,
++              unsigned len);
++#ifdef NET_21
++      int  (*rebuild_header)(struct sk_buff *skb);
++#else /* NET_21 */
++      int  (*rebuild_header)(void *buff, struct net_device *dev,
++                      unsigned long raddr, struct sk_buff *skb);
++#endif /* NET_21 */
++      int  (*set_mac_address)(struct net_device *dev, void *addr);
++#ifndef NET_21
++      void (*header_cache_bind)(struct hh_cache **hhp, struct net_device *dev,
++                               unsigned short htype, __u32 daddr);
++#endif /* !NET_21 */
++      void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char *  haddr);
++      struct net_device_stats *(*get_stats)(struct net_device *dev);
++      struct net_device_stats mystats;
++      int mtu;        /* What is the desired MTU? */
++};
++
++extern char ipsec_tunnel_c_version[];
++
++extern struct net_device *ipsecdevices[IPSEC_NUM_IF];
++
++int ipsec_tunnel_init_devices(void);
++
++/* void */ int ipsec_tunnel_cleanup_devices(void);
++
++extern /* void */ int ipsec_init(void);
++
++extern int ipsec_tunnel_start_xmit(struct sk_buff *skb, struct net_device *dev);
++extern struct net_device *ipsec_get_device(int inst);
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int debug_tunnel;
++extern int sysctl_ipsec_debug_verbose;
++#endif /* CONFIG_KLIPS_DEBUG */
++#endif /* __KERNEL__ */
++
++#ifdef CONFIG_KLIPS_DEBUG
++#define DB_TN_INIT    0x0001
++#define DB_TN_PROCFS  0x0002
++#define DB_TN_XMIT    0x0010
++#define DB_TN_OHDR    0x0020
++#define DB_TN_CROUT   0x0040
++#define DB_TN_OXFS    0x0080
++#define DB_TN_REVEC   0x0100
++#define DB_TN_ENCAP     0x0200
++#endif /* CONFIG_KLIPS_DEBUG */
++
++/*
++ * $Log: ipsec_tunnel.h,v $
++ * Revision 1.33  2005/06/04 16:06:05  mcr
++ *    better patch for nat-t rcv-device code.
++ *
++ * Revision 1.32  2005/05/21 03:18:35  mcr
++ *    added additional debug flag tunnelling.
++ *
++ * Revision 1.31  2004/08/03 18:18:02  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.30  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.29  2004/04/05 19:55:07  mcr
++ * Moved from linux/include/freeswan/ipsec_tunnel.h,v
++ *
++ * Revision 1.28  2003/06/24 20:22:32  mcr
++ *    added new global: ipsecdevices[] so that we can keep track of
++ *    the ipsecX devices. They will be referenced with dev_hold(),
++ *    so 2.2 may need this as well.
++ *
++ * Revision 1.27  2003/04/03 17:38:09  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ *
++ * Revision 1.26  2003/02/12 19:32:20  rgb
++ * Updated copyright year.
++ *
++ * Revision 1.25  2002/05/27 18:56:07  rgb
++ * Convert to dynamic ipsec device allocation.
++ *
++ * Revision 1.24  2002/04/24 07:36:48  mcr
++ * Moved from ./klips/net/ipsec/ipsec_tunnel.h,v
++ *
++ * Revision 1.23  2001/11/06 19:50:44  rgb
++ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for
++ * use also by pfkey_v2_parser.c
++ *
++ * Revision 1.22  2001/09/15 16:24:05  rgb
++ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
++ *
++ * Revision 1.21  2001/06/14 19:35:10  rgb
++ * Update copyright date.
++ *
++ * Revision 1.20  2000/09/15 11:37:02  rgb
++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++ * IPCOMP zlib deflate code.
++ *
++ * Revision 1.19  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.18  2000/07/28 13:50:54  rgb
++ * Changed enet_statistics to net_device_stats and added back compatibility
++ * for pre-2.1.19.
++ *
++ * Revision 1.17  1999/11/19 01:12:15  rgb
++ * Purge unneeded proc_info prototypes, now that static linking uses
++ * dynamic proc_info registration.
++ *
++ * Revision 1.16  1999/11/18 18:51:00  rgb
++ * Changed all device registrations for static linking to
++ * dynamic to reduce the number and size of patches.
++ *
++ * Revision 1.15  1999/11/18 04:14:21  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
++ * Added Marc Boucher's 2.3.25 proc patches.
++ *
++ * Revision 1.14  1999/05/25 02:50:10  rgb
++ * Fix kernel version macros for 2.0.x static linking.
++ *
++ * Revision 1.13  1999/05/25 02:41:06  rgb
++ * Add ipsec_klipsdebug support for static linking.
++ *
++ * Revision 1.12  1999/05/05 22:02:32  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.11  1999/04/29 15:19:50  rgb
++ * Add return values to init and cleanup functions.
++ *
++ * Revision 1.10  1999/04/16 16:02:39  rgb
++ * Bump up macro to 4 ipsec I/Fs.
++ *
++ * Revision 1.9  1999/04/15 15:37:25  rgb
++ * Forward check changes from POST1_00 branch.
++ *
++ * Revision 1.5.2.1  1999/04/02 04:26:14  rgb
++ * Backcheck from HEAD, pre1.0.
++ *
++ * Revision 1.8  1999/04/11 00:29:01  henry
++ * GPL boilerplate
++ *
++ * Revision 1.7  1999/04/06 04:54:28  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.6  1999/03/31 05:44:48  rgb
++ * Keep PMTU reduction private.
++ *
++ * Revision 1.5  1999/02/10 22:31:20  rgb
++ * Change rebuild_header member to reflect generality of link layer.
++ *
++ * Revision 1.4  1998/12/01 13:22:04  rgb
++ * Added support for debug printing of version info.
++ *
++ * Revision 1.3  1998/07/29 20:42:46  rgb
++ * Add a macro for clearing all tunnel devices.
++ * Rearrange structures and declarations for sharing with userspace.
++ *
++ * Revision 1.2  1998/06/25 20:01:45  rgb
++ * Make prototypes available for ipsec_init and ipsec proc_dir_entries
++ * for static linking.
++ *
++ * Revision 1.1  1998/06/18 21:27:50  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.3  1998/05/18 21:51:50  rgb
++ * Added macros for num of I/F's and a procfs debug switch.
++ *
++ * Revision 1.2  1998/04/21 21:29:09  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.1  1998/04/09 03:06:13  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:05  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.5  1997/06/03 04:24:48  ji
++ * Added transport mode.
++ * Changed the way routing is done.
++ * Lots of bug fixes.
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:39:04  ji
++ * Minor cleanups.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_xform.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,257 @@
++/*
++ * Definitions relevant to IPSEC transformations
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * COpyright (C) 2003  Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_xform.h,v 1.41 2004/07/10 19:08:41 mcr Exp $
++ */
++
++#ifndef _IPSEC_XFORM_H_
++
++#include <openswan.h>
++
++#define XF_NONE                       0       /* No transform set */
++#define XF_IP4                        1       /* IPv4 inside IPv4 */
++#define XF_AHMD5              2       /* AH MD5 */
++#define XF_AHSHA              3       /* AH SHA */
++#define XF_ESP3DES            5       /* ESP DES3-CBC */
++#define XF_AHHMACMD5          6       /* AH-HMAC-MD5 with opt replay prot */
++#define XF_AHHMACSHA1         7       /* AH-HMAC-SHA1 with opt replay prot */
++#define XF_ESP3DESMD5         9       /* triple DES, HMAC-MD-5, 128-bits of authentication */
++#define       XF_ESP3DESMD596         10      /* triple DES, HMAC-MD-5, 96-bits of authentication */
++#define       XF_ESPNULLMD596         12      /* NULL, HMAC-MD-5 with 96-bits of authentication */
++#define       XF_ESPNULLSHA196        13      /* NULL, HMAC-SHA-1 with 96-bits of authentication */
++#define       XF_ESP3DESSHA196        14      /* triple DES, HMAC-SHA-1, 96-bits of authentication */
++#define XF_IP6                        15      /* IPv6 inside IPv6 */
++#define XF_COMPDEFLATE                16      /* IPCOMP deflate */
++
++#define XF_CLR                        126     /* Clear SA table */
++#define XF_DEL                        127     /* Delete SA */
++
++/* IPsec AH transform values
++ * RFC 2407
++ * draft-ietf-ipsec-doi-tc-mib-02.txt
++ */
++
++#define AH_NONE                       0
++#define AH_MD5                        2
++#define AH_SHA                        3
++/* draft-ietf-ipsec-ciph-aes-cbc-03.txt */
++#define AH_SHA2_256           5
++#define AH_SHA2_384           6
++#define AH_SHA2_512           7
++#define AH_RIPEMD             8
++#define AH_MAX                        15
++
++/* IPsec ESP transform values */
++
++#define ESP_NONE              0
++#define ESP_DES                       2
++#define ESP_3DES              3
++#define ESP_RC5                       4
++#define ESP_IDEA              5
++#define ESP_CAST              6
++#define ESP_BLOWFISH          7
++#define ESP_3IDEA             8
++#define ESP_RC4                       10
++#define ESP_NULL              11
++#define ESP_AES                       12
++
++/* as draft-ietf-ipsec-ciph-aes-cbc-02.txt */
++#define ESP_MARS              249
++#define       ESP_RC6                 250
++#define ESP_SERPENT           252
++#define ESP_TWOFISH           253
++                       
++/* IPCOMP transform values */
++
++#define IPCOMP_NONE           0
++#define IPCOMP_OUI            1
++#define IPCOMP_DEFLAT         2
++#define IPCOMP_LZS            3
++#define IPCOMP_V42BIS         4
++
++#define XFT_AUTH              0x0001
++#define XFT_CONF              0x0100
++
++/* available if CONFIG_KLIPS_DEBUG is defined */
++#define DB_XF_INIT            0x0001
++
++#define PROTO2TXT(x) \
++      (x) == IPPROTO_AH ? "AH" : \
++      (x) == IPPROTO_ESP ? "ESP" : \
++      (x) == IPPROTO_IPIP ? "IPIP" : \
++      (x) == IPPROTO_COMP ? "COMP" : \
++      "UNKNOWN_proto"
++static inline const char *enc_name_id (unsigned id) {
++      static char buf[16];
++      snprintf(buf, sizeof(buf), "_ID%d", id);
++      return buf;
++}
++static inline const char *auth_name_id (unsigned id) {
++      static char buf[16];
++      snprintf(buf, sizeof(buf), "_ID%d", id);
++      return buf;
++}
++#define IPS_XFORM_NAME(x) \
++      PROTO2TXT((x)->ips_said.proto), \
++      (x)->ips_said.proto == IPPROTO_COMP ? \
++              ((x)->ips_encalg == SADB_X_CALG_DEFLATE ? \
++               "_DEFLATE" : "_UNKNOWN_comp") : \
++      (x)->ips_encalg == ESP_NONE ? "" : \
++      (x)->ips_encalg == ESP_3DES ? "_3DES" : \
++      (x)->ips_encalg == ESP_AES ? "_AES" : \
++      (x)->ips_encalg == ESP_SERPENT ? "_SERPENT" : \
++      (x)->ips_encalg == ESP_TWOFISH ? "_TWOFISH" : \
++      enc_name_id(x->ips_encalg)/* "_UNKNOWN_encr" */, \
++      (x)->ips_authalg == AH_NONE ? "" : \
++      (x)->ips_authalg == AH_MD5 ? "_HMAC_MD5" : \
++      (x)->ips_authalg == AH_SHA ? "_HMAC_SHA1" : \
++      (x)->ips_authalg == AH_SHA2_256 ? "_HMAC_SHA2_256" : \
++      (x)->ips_authalg == AH_SHA2_384 ? "_HMAC_SHA2_384" : \
++      (x)->ips_authalg == AH_SHA2_512 ? "_HMAC_SHA2_512" : \
++      auth_name_id(x->ips_authalg) /* "_UNKNOWN_auth" */ \
++
++#ifdef __KERNEL__
++struct ipsec_rcv_state;
++struct ipsec_xmit_state;
++
++struct xform_functions {
++      enum ipsec_rcv_value (*rcv_checks)(struct ipsec_rcv_state *irs,
++                                     struct sk_buff *skb);
++        enum ipsec_rcv_value (*rcv_decrypt)(struct ipsec_rcv_state *irs);
++
++      enum ipsec_rcv_value (*rcv_setup_auth)(struct ipsec_rcv_state *irs,
++                                         struct sk_buff *skb,
++                                         __u32          *replay,
++                                         unsigned char **authenticator);
++      enum ipsec_rcv_value (*rcv_calc_auth)(struct ipsec_rcv_state *irs,
++                                      struct sk_buff *skb);
++
++      enum ipsec_xmit_value (*xmit_setup)(struct ipsec_xmit_state *ixs);
++        enum ipsec_xmit_value (*xmit_encrypt)(struct ipsec_xmit_state *ixs);
++
++      enum ipsec_xmit_value (*xmit_setup_auth)(struct ipsec_xmit_state *ixs,
++                                         struct sk_buff *skb,
++                                         __u32          *replay,
++                                         unsigned char **authenticator);
++      enum ipsec_xmit_value (*xmit_calc_auth)(struct ipsec_xmit_state *ixs,
++                                      struct sk_buff *skb);
++        int  xmit_headroom;
++      int  xmit_needtailroom;
++};
++
++#endif /* __KERNEL__ */
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern void ipsec_dmp(char *s, caddr_t bb, int len);
++#else /* CONFIG_KLIPS_DEBUG */
++#define ipsec_dmp(_x, _y, _z) 
++#endif /* CONFIG_KLIPS_DEBUG */
++
++
++#define _IPSEC_XFORM_H_
++#endif /* _IPSEC_XFORM_H_ */
++
++/*
++ * $Log: ipsec_xform.h,v $
++ * Revision 1.41  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.40  2004/04/06 02:49:08  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.39  2004/04/05 19:55:07  mcr
++ * Moved from linux/include/freeswan/ipsec_xform.h,v
++ *
++ * Revision 1.38  2004/04/05 19:41:05  mcr
++ *    merged alg-branch code.
++ *
++ * Revision 1.37  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.36.34.1  2003/12/22 15:25:52  jjo
++ *      Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.36  2002/04/24 07:36:48  mcr
++ * Moved from ./klips/net/ipsec/ipsec_xform.h,v
++ *
++ * Revision 1.35  2001/11/26 09:23:51  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.33.2.1  2001/09/25 02:24:58  mcr
++ *    struct tdb -> struct ipsec_sa.
++ *    sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
++ *    ipsec_xform.c removed. header file still contains useful things.
++ *
++ * Revision 1.34  2001/11/06 19:47:17  rgb
++ * Changed lifetime_packets to uint32 from uint64.
++ *
++ * Revision 1.33  2001/09/08 21:13:34  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.32  2001/07/06 07:40:01  rgb
++ * Reformatted for readability.
++ * Added inbound policy checking fields for use with IPIP SAs.
++ *
++ * Revision 1.31  2001/06/14 19:35:11  rgb
++ * Update copyright date.
++ *
++ * Revision 1.30  2001/05/30 08:14:03  rgb
++ * Removed vestiges of esp-null transforms.
++ *
++ * Revision 1.29  2001/01/30 23:42:47  rgb
++ * Allow pfkey msgs from pid other than user context required for ACQUIRE
++ * and subsequent ADD or UDATE.
++ *
++ * Revision 1.28  2000/11/06 04:30:40  rgb
++ * Add Svenning's adaptive content compression.
++ *
++ * Revision 1.27  2000/09/19 00:38:25  rgb
++ * Fixed algorithm name bugs introduced for ipcomp.
++ *
++ * Revision 1.26  2000/09/17 21:36:48  rgb
++ * Added proto2txt macro.
++ *
++ * Revision 1.25  2000/09/17 18:56:47  rgb
++ * Added IPCOMP support.
++ *
++ * Revision 1.24  2000/09/12 19:34:12  rgb
++ * Defined XF_IP6 from Gerhard for ipv6 tunnel support.
++ *
++ * Revision 1.23  2000/09/12 03:23:14  rgb
++ * Cleaned out now unused tdb_xform and tdb_xdata members of struct tdb.
++ *
++ * Revision 1.22  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.21  2000/09/01 18:32:43  rgb
++ * Added (disabled) sensitivity members to tdb struct.
++ *
++ * Revision 1.20  2000/08/30 05:31:01  rgb
++ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst.
++ * Kill remainder of tdb_xform, tdb_xdata, xformsw.
++ *
++ * Revision 1.19  2000/08/01 14:51:52  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.18  2000/01/21 06:17:45  rgb
++ * Tidied up spacing.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/ipsec_xmit.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,198 @@
++/*
++ * IPSEC tunneling code
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_xmit.h,v 1.14 2005/05/11 01:00:26 mcr Exp $
++ */
++
++#include "openswan/ipsec_sa.h"
++
++enum ipsec_xmit_value
++{
++      IPSEC_XMIT_STOLEN=2,
++      IPSEC_XMIT_PASS=1,
++      IPSEC_XMIT_OK=0,
++      IPSEC_XMIT_ERRMEMALLOC=-1,
++      IPSEC_XMIT_ESP_BADALG=-2,
++      IPSEC_XMIT_BADPROTO=-3,
++      IPSEC_XMIT_ESP_PUSHPULLERR=-4,
++      IPSEC_XMIT_BADLEN=-5,
++      IPSEC_XMIT_AH_BADALG=-6,
++      IPSEC_XMIT_SAIDNOTFOUND=-7,
++      IPSEC_XMIT_SAIDNOTLIVE=-8,
++      IPSEC_XMIT_REPLAYROLLED=-9,
++      IPSEC_XMIT_LIFETIMEFAILED=-10,
++      IPSEC_XMIT_CANNOTFRAG=-11,
++      IPSEC_XMIT_MSSERR=-12,
++      IPSEC_XMIT_ERRSKBALLOC=-13,
++      IPSEC_XMIT_ENCAPFAIL=-14,
++      IPSEC_XMIT_NODEV=-15,
++      IPSEC_XMIT_NOPRIVDEV=-16,
++      IPSEC_XMIT_NOPHYSDEV=-17,
++      IPSEC_XMIT_NOSKB=-18,
++      IPSEC_XMIT_NOIPV6=-19,
++      IPSEC_XMIT_NOIPOPTIONS=-20,
++      IPSEC_XMIT_TTLEXPIRED=-21,
++      IPSEC_XMIT_BADHHLEN=-22,
++      IPSEC_XMIT_PUSHPULLERR=-23,
++      IPSEC_XMIT_ROUTEERR=-24,
++      IPSEC_XMIT_RECURSDETECT=-25,
++      IPSEC_XMIT_IPSENDFAILURE=-26,
++      IPSEC_XMIT_ESPUDP=-27,
++      IPSEC_XMIT_ESPUDP_BADTYPE=-28,
++};
++
++struct ipsec_xmit_state
++{
++      struct sk_buff *skb;            /* working skb pointer */
++      struct net_device *dev;         /* working dev pointer */
++      struct ipsecpriv *prv;          /* Our device' private space */
++      struct sk_buff *oskb;           /* Original skb pointer */
++      struct net_device_stats *stats; /* This device's statistics */
++      struct iphdr  *iph;             /* Our new IP header */
++      __u32   newdst;                 /* The other SG's IP address */
++      __u32   orgdst;                 /* Original IP destination address */
++      __u32   orgedst;                /* 1st SG's IP address */
++      __u32   newsrc;                 /* The new source SG's IP address */
++      __u32   orgsrc;                 /* Original IP source address */
++      __u32   innersrc;               /* Innermost IP source address */
++      int     iphlen;                 /* IP header length */
++      int     pyldsz;                 /* upper protocol payload size */
++      int     headroom;
++      int     tailroom;
++        int     authlen;
++      int     max_headroom;           /* The extra header space needed */
++      int     max_tailroom;           /* The extra stuffing needed */
++      int     ll_headroom;            /* The extra link layer hard_header space needed */
++      int     tot_headroom;           /* The total header space needed */
++      int     tot_tailroom;           /* The totalstuffing needed */
++      __u8    *saved_header;          /* saved copy of the hard header */
++      unsigned short   sport, dport;
++
++      struct sockaddr_encap matcher;  /* eroute search key */
++      struct eroute *eroute;
++      struct ipsec_sa *ipsp, *ipsq;   /* ipsec_sa pointers */
++      char sa_txt[SATOT_BUF];
++      size_t sa_len;
++      int hard_header_stripped;       /* has the hard header been removed yet? */
++      int hard_header_len;
++      struct net_device *physdev;
++/*    struct device *virtdev; */
++      short physmtu;
++      short cur_mtu;          /* copy of prv->mtu, cause prv may == NULL */
++      short mtudiff;
++#ifdef NET_21
++      struct rtable *route;
++#endif /* NET_21 */
++      ip_said outgoing_said;
++#ifdef NET_21
++      int pass;
++#endif /* NET_21 */
++      int error;
++      uint32_t eroute_pid;
++      struct ipsec_sa ips;
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      uint8_t natt_type;
++      uint8_t natt_head;
++      uint16_t natt_sport;
++      uint16_t natt_dport;
++#endif
++};
++
++enum ipsec_xmit_value
++ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs);
++
++enum ipsec_xmit_value
++ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs);
++
++enum ipsec_xmit_value
++ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs);
++
++extern void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er);
++
++
++extern int ipsec_xmit_trap_count;
++extern int ipsec_xmit_trap_sendcount;
++
++#ifdef CONFIG_KLIPS_DEBUG
++extern int debug_tunnel;
++
++#define debug_xmit debug_tunnel
++
++#define ipsec_xmit_dmp(_x,_y, _z) if (debug_xmit && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z)
++#else
++#define ipsec_xmit_dmp(_x,_y, _z) do {} while(0)
++
++#endif /* CONFIG_KLIPS_DEBUG */
++
++extern int sysctl_ipsec_debug_verbose;
++extern int sysctl_ipsec_icmp;
++extern int sysctl_ipsec_tos;
++
++
++/*
++ * $Log: ipsec_xmit.h,v $
++ * Revision 1.14  2005/05/11 01:00:26  mcr
++ *    do not call debug routines if !defined KLIPS_DEBUG.
++ *
++ * Revision 1.13  2005/04/29 05:01:38  mcr
++ *    use ipsec_dmp_block.
++ *    added cur_mtu to ixs instead of using ixs->dev.
++ *
++ * Revision 1.12  2004/08/20 21:45:37  mcr
++ *    CONFIG_KLIPS_NAT_TRAVERSAL is not used in an attempt to
++ *    be 26sec compatible. But, some defines where changed.
++ *
++ * Revision 1.11  2004/08/03 18:18:21  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.10  2004/07/10 19:08:41  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.9  2004/04/06 02:49:08  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.8  2004/04/05 19:55:07  mcr
++ * Moved from linux/include/freeswan/ipsec_xmit.h,v
++ *
++ * Revision 1.7  2004/02/03 03:11:40  mcr
++ *    new xmit type if the UDP encapsulation is wrong.
++ *
++ * Revision 1.6  2003/12/13 19:10:16  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.5  2003/12/10 01:20:06  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.4  2003/12/06 16:37:04  mcr
++ *    1.4.7a X.509 patch applied.
++ *
++ * Revision 1.3  2003/10/31 02:27:05  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.2.4.2  2003/10/29 01:10:19  mcr
++ *    elimited "struct sa_id"
++ *
++ * Revision 1.2.4.1  2003/09/21 13:59:38  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.2  2003/06/20 01:42:13  mcr
++ *    added counters to measure how many ACQUIREs we send to pluto,
++ *    and how many are successfully sent.
++ *
++ * Revision 1.1  2003/02/12 19:31:03  rgb
++ * Refactored from ipsec_tunnel.c
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/passert.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,75 @@
++/*
++ * sanitize a string into a printable format.
++ *
++ * Copyright (C) 1998-2002  D. Hugh Redelmeier.
++ * Copyright (C) 2003  Michael Richardson <mcr@freeswan.org>
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: passert.h,v 1.7 2004/10/21 18:44:42 mcr Exp $
++ */
++
++#include "openswan.h"
++
++#ifndef _OPENSWAN_PASSERT_H
++#define _OPENSWAN_PASSERT_H
++/* our versions of assert: log result */
++
++#ifdef DEBUG
++
++typedef void (*openswan_passert_fail_t)(const char *pred_str,
++                                      const char *file_str,
++                                      unsigned long line_no) NEVER_RETURNS;
++
++openswan_passert_fail_t openswan_passert_fail;
++
++extern void pexpect_log(const char *pred_str
++                      , const char *file_str, unsigned long line_no);
++
++# define impossible() do { \
++    if(openswan_passert_fail) {                                       \
++      (*openswan_passert_fail)("impossible", __FILE__, __LINE__); \
++    }} while(0)
++
++extern void switch_fail(int n
++    , const char *file_str, unsigned long line_no) NEVER_RETURNS;
++
++# define bad_case(n) switch_fail((int) n, __FILE__, __LINE__)
++
++# define passert(pred) do { \
++      if (!(pred)) \
++        if(openswan_passert_fail) { \
++          (*openswan_passert_fail)(#pred, __FILE__, __LINE__);        \
++        } \
++  } while(0)
++
++# define pexpect(pred) do { \
++      if (!(pred)) \
++          pexpect_log(#pred, __FILE__, __LINE__); \
++  } while(0)
++
++/* assert that an err_t is NULL; evaluate exactly once */
++# define happy(x) { \
++      err_t ugh = x; \
++      if (ugh != NULL) \
++        if(openswan_passert_fail) { (*openswan_passert_fail)(ugh, __FILE__, __LINE__); }  \
++    }
++
++#else /*!DEBUG*/
++
++# define impossible() abort()
++# define bad_case(n) abort()
++# define passert(pred)  { }   /* do nothing */
++# define happy(x)  { (void) x; }      /* evaluate non-judgementally */
++
++#endif /*!DEBUG*/
++
++#endif /* _OPENSWAN_PASSERT_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/pfkey_debug.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,54 @@
++/*
++ * sanitize a string into a printable format.
++ *
++ * Copyright (C) 1998-2002  D. Hugh Redelmeier.
++ * Copyright (C) 2003  Michael Richardson <mcr@freeswan.org>
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: pfkey_debug.h,v 1.3 2004/04/05 19:55:07 mcr Exp $
++ */
++
++#ifndef _FREESWAN_PFKEY_DEBUG_H
++#define _FREESWAN_PFKEY_DEBUG_H
++
++#ifdef __KERNEL__
++
++/* note, kernel version ignores pfkey levels */
++# define DEBUGGING(level,args...) \
++         KLIPS_PRINT(debug_pfkey, "klips_debug:" args)
++
++# define ERROR(args...) printk(KERN_ERR "klips:" args)
++
++#else
++
++extern unsigned int pfkey_lib_debug;
++
++extern void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1);
++extern void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1);
++
++#define DEBUGGING(level,args...)  if(pfkey_lib_debug & level) { \
++                              if(pfkey_debug_func != NULL) { \
++                                (*pfkey_debug_func)("pfkey_lib_debug:" args); \
++                              } else { \
++                                printf("pfkey_lib_debug:" args); \
++                              } }
++
++#define ERROR(args...)      if(pfkey_error_func != NULL) { \
++                                (*pfkey_error_func)("pfkey_lib_debug:" args); \
++                              } 
++
++# define MALLOC(size) malloc(size)
++# define FREE(obj) free(obj)
++
++#endif
++
++#endif
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/openswan/radij.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,280 @@
++/*
++ * RCSID $Id: radij.h,v 1.13 2004/04/05 19:55:08 mcr Exp $
++ */
++
++/*
++ * This file is defived from ${SRC}/sys/net/radix.h of BSD 4.4lite
++ *
++ * Variable and procedure names have been modified so that they don't
++ * conflict with the original BSD code, as a small number of modifications
++ * have been introduced and we may want to reuse this code in BSD.
++ * 
++ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek
++ * chi or a German ch sound (as `doch', not as in `milch'), or even a 
++ * spanish j as in Juan.  It is not as far back in the throat like
++ * the corresponding Hebrew sound, nor is it a soft breath like the English h.
++ * It has nothing to do with the Dutch ij sound.
++ * 
++ * Here is the appropriate copyright notice:
++ */
++
++/*
++ * Copyright (c) 1988, 1989, 1993
++ *    The Regents of the University of California.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    This product includes software developed by the University of
++ *    California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ *    @(#)radix.h     8.1 (Berkeley) 6/10/93
++ */
++
++#ifndef _RADIJ_H_
++#define       _RADIJ_H_
++
++/* 
++#define RJ_DEBUG
++*/
++
++#ifdef __KERNEL__
++
++#ifndef __P
++#ifdef __STDC__
++#define __P(x)  x
++#else
++#define __P(x)  ()
++#endif
++#endif
++
++/*
++ * Radix search tree node layout.
++ */
++
++struct radij_node
++{
++      struct  radij_mask *rj_mklist;  /* list of masks contained in subtree */
++      struct  radij_node *rj_p;       /* parent */
++      short   rj_b;                   /* bit offset; -1-index(netmask) */
++      char    rj_bmask;               /* node: mask for bit test*/
++      u_char  rj_flags;               /* enumerated next */
++#define RJF_NORMAL    1               /* leaf contains normal route */
++#define RJF_ROOT      2               /* leaf is root leaf for tree */
++#define RJF_ACTIVE    4               /* This node is alive (for rtfree) */
++      union {
++              struct {                        /* leaf only data: */
++                      caddr_t rj_Key; /* object of search */
++                      caddr_t rj_Mask;        /* netmask, if present */
++                      struct  radij_node *rj_Dupedkey;
++              } rj_leaf;
++              struct {                        /* node only data: */
++                      int     rj_Off;         /* where to start compare */
++                      struct  radij_node *rj_L;/* progeny */
++                      struct  radij_node *rj_R;/* progeny */
++              }rj_node;
++      }               rj_u;
++#ifdef RJ_DEBUG
++      int rj_info;
++      struct radij_node *rj_twin;
++      struct radij_node *rj_ybro;
++#endif
++};
++
++#define rj_dupedkey rj_u.rj_leaf.rj_Dupedkey
++#define rj_key rj_u.rj_leaf.rj_Key
++#define rj_mask rj_u.rj_leaf.rj_Mask
++#define rj_off rj_u.rj_node.rj_Off
++#define rj_l rj_u.rj_node.rj_L
++#define rj_r rj_u.rj_node.rj_R
++
++/*
++ * Annotations to tree concerning potential routes applying to subtrees.
++ */
++
++extern struct radij_mask {
++      short   rm_b;                   /* bit offset; -1-index(netmask) */
++      char    rm_unused;              /* cf. rj_bmask */
++      u_char  rm_flags;               /* cf. rj_flags */
++      struct  radij_mask *rm_mklist;  /* more masks to try */
++      caddr_t rm_mask;                /* the mask */
++      int     rm_refs;                /* # of references to this struct */
++} *rj_mkfreelist;
++
++#define MKGet(m) {\
++      if (rj_mkfreelist) {\
++              m = rj_mkfreelist; \
++              rj_mkfreelist = (m)->rm_mklist; \
++      } else \
++              R_Malloc(m, struct radij_mask *, sizeof (*(m))); }\
++
++#define MKFree(m) { (m)->rm_mklist = rj_mkfreelist; rj_mkfreelist = (m);}
++
++struct radij_node_head {
++      struct  radij_node *rnh_treetop;
++      int     rnh_addrsize;           /* permit, but not require fixed keys */
++      int     rnh_pktsize;            /* permit, but not require fixed keys */
++#if 0
++      struct  radij_node *(*rnh_addaddr)      /* add based on sockaddr */
++              __P((void *v, void *mask,
++                   struct radij_node_head *head, struct radij_node nodes[]));
++#endif
++      int (*rnh_addaddr)      /* add based on sockaddr */
++              __P((void *v, void *mask,
++                   struct radij_node_head *head, struct radij_node nodes[]));
++      struct  radij_node *(*rnh_addpkt)       /* add based on packet hdr */
++              __P((void *v, void *mask,
++                   struct radij_node_head *head, struct radij_node nodes[]));
++#if 0
++      struct  radij_node *(*rnh_deladdr)      /* remove based on sockaddr */
++              __P((void *v, void *mask, struct radij_node_head *head));
++#endif
++      int (*rnh_deladdr)      /* remove based on sockaddr */
++              __P((void *v, void *mask, struct radij_node_head *head, struct radij_node **node));
++      struct  radij_node *(*rnh_delpkt)       /* remove based on packet hdr */
++              __P((void *v, void *mask, struct radij_node_head *head));
++      struct  radij_node *(*rnh_matchaddr)    /* locate based on sockaddr */
++              __P((void *v, struct radij_node_head *head));
++      struct  radij_node *(*rnh_matchpkt)     /* locate based on packet hdr */
++              __P((void *v, struct radij_node_head *head));
++      int     (*rnh_walktree)                 /* traverse tree */
++              __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w));
++      struct  radij_node rnh_nodes[3];        /* empty tree for common case */
++};
++
++
++#define Bcmp(a, b, n) memcmp(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n))
++#define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n))
++#define Bzero(p, n) memset((caddr_t)(p), 0, (unsigned)(n))
++#define R_Malloc(p, t, n) ((p = (t) kmalloc((size_t)(n), GFP_ATOMIC)), Bzero((p),(n)))
++#define Free(p) kfree((caddr_t)p);
++
++void   rj_init __P((void));
++int    rj_inithead __P((void **, int));
++int    rj_refines __P((void *, void *));
++int    rj_walktree __P((struct radij_node_head *head, int (*f)(struct radij_node *rn, void *w), void *w));
++struct radij_node
++       *rj_addmask __P((void *, int, int)) /* , rgb */ ;
++int /* * */ rj_addroute __P((void *, void *, struct radij_node_head *,
++                      struct radij_node [2])) /* , rgb */ ;
++int /* * */ rj_delete __P((void *, void *, struct radij_node_head *, struct radij_node **)) /* , rgb */ ;
++struct radij_node /* rgb */
++       *rj_insert __P((void *, struct radij_node_head *, int *,
++                      struct radij_node [2])),
++       *rj_match __P((void *, struct radij_node_head *)),
++       *rj_newpair __P((void *, int, struct radij_node[2])),
++       *rj_search __P((void *, struct radij_node *)),
++       *rj_search_m __P((void *, struct radij_node *, void *));
++
++void rj_deltree(struct radij_node_head *);
++void rj_delnodes(struct radij_node *);
++void rj_free_mkfreelist(void);
++int radijcleartree(void);
++int radijcleanup(void);
++
++extern struct radij_node_head *mask_rjhead;
++extern int maj_keylen;
++#endif /* __KERNEL__ */
++
++#endif /* _RADIJ_H_ */
++
++
++/*
++ * $Log: radij.h,v $
++ * Revision 1.13  2004/04/05 19:55:08  mcr
++ * Moved from linux/include/freeswan/radij.h,v
++ *
++ * Revision 1.12  2002/04/24 07:36:48  mcr
++ * Moved from ./klips/net/ipsec/radij.h,v
++ *
++ * Revision 1.11  2001/09/20 15:33:00  rgb
++ * Min/max cleanup.
++ *
++ * Revision 1.10  1999/11/18 04:09:20  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ *
++ * Revision 1.9  1999/05/05 22:02:33  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.8  1999/04/29 15:24:58  rgb
++ * Add check for existence of macros min/max.
++ *
++ * Revision 1.7  1999/04/11 00:29:02  henry
++ * GPL boilerplate
++ *
++ * Revision 1.6  1999/04/06 04:54:29  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.5  1999/01/22 06:30:32  rgb
++ * 64-bit clean-up.
++ *
++ * Revision 1.4  1998/11/30 13:22:55  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.3  1998/10/25 02:43:27  rgb
++ * Change return type on rj_addroute and rj_delete and add and argument
++ * to the latter to be able to transmit more infomation about errors.
++ *
++ * Revision 1.2  1998/07/14 18:09:51  rgb
++ * Add a routine to clear eroute table.
++ * Added #ifdef __KERNEL__ directives to restrict scope of header.
++ *
++ * Revision 1.1  1998/06/18 21:30:22  henry
++ * move sources from klips/src to klips/net/ipsec to keep stupid kernel
++ * build scripts happier about symlinks
++ *
++ * Revision 1.4  1998/05/25 20:34:16  rgb
++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
++ *
++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
++ * add ipsec_rj_walker_delete.
++ *
++ * Recover memory for eroute table on unload of module.
++ *
++ * Revision 1.3  1998/04/22 16:51:37  rgb
++ * Tidy up radij debug code from recent rash of modifications to debug code.
++ *
++ * Revision 1.2  1998/04/14 17:30:38  rgb
++ * Fix up compiling errors for radij tree memory reclamation.
++ *
++ * Revision 1.1  1998/04/09 03:06:16  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:44:45  ji
++ * Release update only.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/pfkey.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,529 @@
++/*
++ * FreeS/WAN specific PF_KEY headers
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey.h,v 1.49 2005/05/11 00:57:29 mcr Exp $
++ */
++
++#ifndef __NET_IPSEC_PF_KEY_H
++#define __NET_IPSEC_PF_KEY_H
++#ifdef __KERNEL__
++extern struct proto_ops pfkey_proto_ops;
++typedef struct sock pfkey_sock;
++extern int debug_pfkey;
++
++extern /* void */ int pfkey_init(void);
++extern /* void */ int pfkey_cleanup(void);
++
++struct socket_list
++{
++      struct socket *socketp;
++      struct socket_list *next;
++};
++extern int pfkey_list_insert_socket(struct socket*, struct socket_list**);
++extern int pfkey_list_remove_socket(struct socket*, struct socket_list**);
++extern struct socket_list *pfkey_open_sockets;
++extern struct socket_list *pfkey_registered_sockets[];
++
++struct ipsec_alg_supported
++{
++      uint16_t ias_exttype;
++      uint8_t  ias_id;
++      uint8_t  ias_ivlen;
++      uint16_t ias_keyminbits;
++      uint16_t ias_keymaxbits;
++        char    *ias_name;
++};
++
++extern struct supported_list *pfkey_supported_list[];
++struct supported_list
++{
++      struct ipsec_alg_supported *supportedp;
++      struct supported_list *next;
++};
++extern int pfkey_list_insert_supported(struct ipsec_alg_supported*, struct supported_list**);
++extern int pfkey_list_remove_supported(struct ipsec_alg_supported*, struct supported_list**);
++
++struct sockaddr_key
++{
++      uint16_t        key_family;     /* PF_KEY */
++      uint16_t        key_pad;        /* not used */
++      uint32_t        key_pid;        /* process ID */
++};
++
++struct pfkey_extracted_data
++{
++      struct ipsec_sa* ips;
++      struct ipsec_sa* ips2;
++      struct eroute *eroute;
++};
++
++/* forward reference */
++struct sadb_ext;
++struct sadb_msg;
++struct sockaddr;
++struct sadb_comb;
++struct sadb_sadb;
++struct sadb_alg;
++
++extern int
++pfkey_alloc_eroute(struct eroute** eroute);
++
++extern int
++pfkey_sa_process(struct sadb_ext *pfkey_ext,
++               struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_lifetime_process(struct sadb_ext *pfkey_ext,
++                     struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_address_process(struct sadb_ext *pfkey_ext,
++                    struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_key_process(struct sadb_ext *pfkey_ext,
++                struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_ident_process(struct sadb_ext *pfkey_ext,
++                  struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_sens_process(struct sadb_ext *pfkey_ext,
++                 struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_prop_process(struct sadb_ext *pfkey_ext,
++                 struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_supported_process(struct sadb_ext *pfkey_ext,
++                      struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_spirange_process(struct sadb_ext *pfkey_ext,
++                     struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext,
++                        struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_x_satype_process(struct sadb_ext *pfkey_ext,
++                     struct pfkey_extracted_data* extr);
++
++extern int
++pfkey_x_debug_process(struct sadb_ext *pfkey_ext,
++                    struct pfkey_extracted_data* extr);
++
++extern int pfkey_upmsg(struct socket *, struct sadb_msg *);
++extern int pfkey_expire(struct ipsec_sa *, int);
++extern int pfkey_acquire(struct ipsec_sa *);
++#else /* ! __KERNEL__ */
++
++extern void (*pfkey_debug_func)(const char *message, ...);
++extern void (*pfkey_error_func)(const char *message, ...);
++extern void pfkey_print(struct sadb_msg *msg, FILE *out);
++
++
++#endif /* __KERNEL__ */
++
++extern uint8_t satype2proto(uint8_t satype);
++extern uint8_t proto2satype(uint8_t proto);
++extern char* satype2name(uint8_t satype);
++extern char* proto2name(uint8_t proto);
++
++struct key_opt
++{
++      uint32_t        key_pid;        /* process ID */
++      struct sock     *sk;
++};
++
++#define key_pid(sk) ((struct key_opt*)&((sk)->sk_protinfo))->key_pid
++
++/* XXX-mcr this is not an alignment, this is because the count is in 64-bit
++ * words.
++ */
++#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t))
++#define BITS_PER_OCTET 8
++#define OCTETBITS 8
++#define PFKEYBITS 64
++#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */
++#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */
++
++#define IPSEC_PFKEYv2_LEN(x)   ((x) * IPSEC_PFKEYv2_ALIGN)
++#define IPSEC_PFKEYv2_WORDS(x) ((x) / IPSEC_PFKEYv2_ALIGN)
++
++
++#define PFKEYv2_MAX_MSGSIZE 4096
++
++/*
++ * PF_KEYv2 permitted and required extensions in and out bitmaps
++ */
++struct pf_key_ext_parsers_def {
++      int  (*parser)(struct sadb_ext*);
++      char  *parser_name;
++};
++
++
++#define SADB_EXTENSIONS_MAX 31
++extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_EXTENSIONS_MAX];
++#define EXT_BITS_IN 0
++#define EXT_BITS_OUT 1
++#define EXT_BITS_PERM 0
++#define EXT_BITS_REQ 1
++
++extern void pfkey_extensions_init(struct sadb_ext *extensions[]);
++extern void pfkey_extensions_free(struct sadb_ext *extensions[]);
++extern void pfkey_msg_free(struct sadb_msg **pfkey_msg);
++
++extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg,
++                         struct pf_key_ext_parsers_def *ext_parsers[],
++                         struct sadb_ext **extensions,
++                         int dir);
++
++extern int pfkey_register_reply(int satype, struct sadb_msg *sadb_msg);
++
++/*
++ * PF_KEYv2 build function prototypes
++ */
++
++int
++pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext,
++                  uint8_t             msg_type,
++                  uint8_t             satype,
++                  uint8_t             msg_errno,
++                  uint32_t            seq,
++                  uint32_t            pid);
++
++int
++pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext,
++             uint16_t                 exttype,
++             uint32_t                 spi, /* in network order */
++             uint8_t                  replay_window,
++             uint8_t                  sa_state,
++             uint8_t                  auth,
++             uint8_t                  encrypt,
++             uint32_t                 flags,
++             uint32_t/*IPsecSAref_t*/ ref);
++
++int
++pfkey_sa_build(struct sadb_ext **     pfkey_ext,
++             uint16_t                 exttype,
++             uint32_t                 spi, /* in network order */
++             uint8_t                  replay_window,
++             uint8_t                  sa_state,
++             uint8_t                  auth,
++             uint8_t                  encrypt,
++             uint32_t                 flags);
++
++int
++pfkey_lifetime_build(struct sadb_ext **       pfkey_ext,
++                   uint16_t           exttype,
++                   uint32_t           allocations,
++                   uint64_t           bytes,
++                   uint64_t           addtime,
++                   uint64_t           usetime,
++                   uint32_t           packets);
++
++int
++pfkey_address_build(struct sadb_ext** pfkey_ext,
++                  uint16_t            exttype,
++                  uint8_t             proto,
++                  uint8_t             prefixlen,
++                  struct sockaddr*    address);
++
++int
++pfkey_key_build(struct sadb_ext**     pfkey_ext,
++              uint16_t                exttype,
++              uint16_t                key_bits,
++              char*                   key);
++
++int
++pfkey_ident_build(struct sadb_ext**   pfkey_ext,
++                uint16_t              exttype,
++                uint16_t              ident_type,
++                uint64_t              ident_id,
++                uint8_t               ident_len,
++                char*                 ident_string);
++
++#ifdef __KERNEL__
++extern int pfkey_nat_t_new_mapping(struct ipsec_sa *, struct sockaddr *, __u16);
++extern int pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr);
++extern int pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr);
++#endif /* __KERNEL__ */
++int
++pfkey_x_nat_t_type_build(struct sadb_ext**  pfkey_ext,
++            uint8_t         type);
++int
++pfkey_x_nat_t_port_build(struct sadb_ext**  pfkey_ext,
++            uint16_t         exttype,
++            uint16_t         port);
++
++int
++pfkey_sens_build(struct sadb_ext**    pfkey_ext,
++               uint32_t               dpd,
++               uint8_t                sens_level,
++               uint8_t                sens_len,
++               uint64_t*              sens_bitmap,
++               uint8_t                integ_level,
++               uint8_t                integ_len,
++               uint64_t*              integ_bitmap);
++
++int pfkey_x_protocol_build(struct sadb_ext **, uint8_t);
++
++
++int
++pfkey_prop_build(struct sadb_ext**    pfkey_ext,
++               uint8_t                replay,
++               unsigned int           comb_num,
++               struct sadb_comb*      comb);
++
++int
++pfkey_supported_build(struct sadb_ext**       pfkey_ext,
++                    uint16_t          exttype,
++                    unsigned int      alg_num,
++                    struct sadb_alg*  alg);
++
++int
++pfkey_spirange_build(struct sadb_ext**        pfkey_ext,
++                   uint16_t           exttype,
++                   uint32_t           min,
++                   uint32_t           max);
++
++int
++pfkey_x_kmprivate_build(struct sadb_ext**     pfkey_ext);
++
++int
++pfkey_x_satype_build(struct sadb_ext**        pfkey_ext,
++                   uint8_t            satype);
++
++int
++pfkey_x_debug_build(struct sadb_ext** pfkey_ext,
++                  uint32_t            tunnel,
++                  uint32_t            netlink,
++                  uint32_t            xform,
++                  uint32_t            eroute,
++                  uint32_t            spi,
++                  uint32_t            radij,
++                  uint32_t            esp,
++                  uint32_t            ah,
++                  uint32_t            rcv,
++                  uint32_t            pfkey,
++                  uint32_t            ipcomp,
++                  uint32_t            verbose);
++
++int
++pfkey_msg_build(struct sadb_msg**     pfkey_msg,
++              struct sadb_ext*        extensions[],
++              int                     dir);
++
++/* in pfkey_v2_debug.c - routines to decode numbers -> strings */
++const char *
++pfkey_v2_sadb_ext_string(int extnum);
++
++const char *
++pfkey_v2_sadb_type_string(int sadb_type);
++
++
++#endif /* __NET_IPSEC_PF_KEY_H */
++
++/*
++ * $Log: pfkey.h,v $
++ * Revision 1.49  2005/05/11 00:57:29  mcr
++ *    rename struct supported -> struct ipsec_alg_supported.
++ *    make pfkey.h more standalone.
++ *
++ * Revision 1.48  2005/05/01 03:12:50  mcr
++ *    include name of algorithm in datastructure.
++ *
++ * Revision 1.47  2004/08/21 00:44:14  mcr
++ *    simplify definition of nat_t related prototypes.
++ *
++ * Revision 1.46  2004/08/04 16:27:22  mcr
++ *    2.6 sk_ options.
++ *
++ * Revision 1.45  2004/04/06 02:49:00  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.44  2003/12/10 01:20:01  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.43  2003/10/31 02:26:44  mcr
++ *    pulled up port-selector patches.
++ *
++ * Revision 1.42.2.2  2003/10/29 01:09:32  mcr
++ *    added debugging for pfkey library.
++ *
++ * Revision 1.42.2.1  2003/09/21 13:59:34  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.42  2003/08/25 22:08:19  mcr
++ *    removed pfkey_proto_init() from pfkey.h for 2.6 support.
++ *
++ * Revision 1.41  2003/05/07 17:28:57  mcr
++ *    new function pfkey_debug_func added for us in debugging from
++
++ *    pfkey library.
++ *
++ * Revision 1.40  2003/01/30 02:31:34  rgb
++ *
++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
++ *
++ * Revision 1.39  2002/09/20 15:40:21  rgb
++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc().
++ * Added ref parameter to pfkey_sa_build().
++ * Cleaned out unused cruft.
++ *
++ * Revision 1.38  2002/05/14 02:37:24  rgb
++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips,
++ * ipsec_sa or ipsec_sa.
++ * Added function prototypes for the functions moved to
++ * pfkey_v2_ext_process.c.
++ *
++ * Revision 1.37  2002/04/24 07:36:49  mcr
++ * Moved from ./lib/pfkey.h,v
++ *
++ * Revision 1.36  2002/01/20 20:34:49  mcr
++ *    added pfkey_v2_sadb_type_string to decode sadb_type to string.
++ *
++ * Revision 1.35  2001/11/27 05:27:47  mcr
++ *    pfkey parses are now maintained by a structure
++ *    that includes their name for debug purposes.
++ *
++ * Revision 1.34  2001/11/26 09:23:53  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.33  2001/11/06 19:47:47  rgb
++ * Added packet parameter to lifetime and comb structures.
++ *
++ * Revision 1.32  2001/09/08 21:13:34  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.31  2001/06/14 19:35:16  rgb
++ * Update copyright date.
++ *
++ * Revision 1.30  2001/02/27 07:04:52  rgb
++ * Added satype2name prototype.
++ *
++ * Revision 1.29  2001/02/26 19:59:33  rgb
++ * Ditch unused sadb_satype2proto[], replaced by satype2proto().
++ *
++ * Revision 1.28  2000/10/10 20:10:19  rgb
++ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
++ *
++ * Revision 1.27  2000/09/21 04:20:45  rgb
++ * Fixed array size off-by-one error.  (Thanks Svenning!)
++ *
++ * Revision 1.26  2000/09/12 03:26:05  rgb
++ * Added pfkey_acquire prototype.
++ *
++ * Revision 1.25  2000/09/08 19:21:28  rgb
++ * Fix pfkey_prop_build() parameter to be only single indirection.
++ *
++ * Revision 1.24  2000/09/01 18:46:42  rgb
++ * Added a supported algorithms array lists, one per satype and registered
++ * existing algorithms.
++ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to
++ * list.
++ *
++ * Revision 1.23  2000/08/27 01:55:26  rgb
++ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code.
++ *
++ * Revision 1.22  2000/08/20 21:39:23  rgb
++ * Added kernel prototypes for kernel funcitions pfkey_upmsg() and
++ * pfkey_expire().
++ *
++ * Revision 1.21  2000/08/15 17:29:23  rgb
++ * Fixes from SZI to untested pfkey_prop_build().
++ *
++ * Revision 1.20  2000/05/10 20:14:19  rgb
++ * Fleshed out sensitivity, proposal and supported extensions.
++ *
++ * Revision 1.19  2000/03/16 14:07:23  rgb
++ * Renamed ALIGN macro to avoid fighting with others in kernel.
++ *
++ * Revision 1.18  2000/01/22 23:24:06  rgb
++ * Added prototypes for proto2satype(), satype2proto() and proto2name().
++ *
++ * Revision 1.17  2000/01/21 06:26:59  rgb
++ * Converted from double tdb arguments to one structure (extr)
++ * containing pointers to all temporary information structures.
++ * Added klipsdebug switching capability.
++ * Dropped unused argument to pfkey_x_satype_build().
++ *
++ * Revision 1.16  1999/12/29 21:17:41  rgb
++ * Changed pfkey_msg_build() I/F to include a struct sadb_msg**
++ * parameter for cleaner manipulation of extensions[] and to guard
++ * against potential memory leaks.
++ * Changed the I/F to pfkey_msg_free() for the same reason.
++ *
++ * Revision 1.15  1999/12/09 23:12:54  rgb
++ * Added macro for BITS_PER_OCTET.
++ * Added argument to pfkey_sa_build() to do eroutes.
++ *
++ * Revision 1.14  1999/12/08 20:33:25  rgb
++ * Changed sa_family_t to uint16_t for 2.0.xx compatibility.
++ *
++ * Revision 1.13  1999/12/07 19:53:40  rgb
++ * Removed unused first argument from extension parsers.
++ * Changed __u* types to uint* to avoid use of asm/types.h and
++ * sys/types.h in userspace code.
++ * Added function prototypes for pfkey message and extensions
++ * initialisation and cleanup.
++ *
++ * Revision 1.12  1999/12/01 22:19:38  rgb
++ * Change pfkey_sa_build to accept an SPI in network byte order.
++ *
++ * Revision 1.11  1999/11/27 11:55:26  rgb
++ * Added extern sadb_satype2proto to enable moving protocol lookup table
++ * to lib/pfkey_v2_parse.c.
++ * Delete unused, moved typedefs.
++ * Add argument to pfkey_msg_parse() for direction.
++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
++ *
++ * Revision 1.10  1999/11/23 22:29:21  rgb
++ * This file has been moved in the distribution from klips/net/ipsec to
++ * lib.
++ * Add macros for dealing with alignment and rounding up more opaquely.
++ * The uint<n>_t type defines have been moved to freeswan.h to avoid
++ * chicken-and-egg problems.
++ * Add macros for dealing with alignment and rounding up more opaque.
++ * Added prototypes for using extention header bitmaps.
++ * Added prototypes of all the build functions.
++ *
++ * Revision 1.9  1999/11/20 21:59:48  rgb
++ * Moved socketlist type declarations and prototypes for shared use.
++ * Slightly modified scope of sockaddr_key declaration.
++ *
++ * Revision 1.8  1999/11/17 14:34:25  rgb
++ * Protect sa_family_t from being used in userspace with GLIBC<2.
++ *
++ * Revision 1.7  1999/10/27 19:40:35  rgb
++ * Add a maximum PFKEY packet size macro.
++ *
++ * Revision 1.6  1999/10/26 16:58:58  rgb
++ * Created a sockaddr_key and key_opt socket extension structures.
++ *
++ * Revision 1.5  1999/06/10 05:24:41  rgb
++ * Renamed variables to reduce confusion.
++ *
++ * Revision 1.4  1999/04/29 15:21:11  rgb
++ * Add pfkey support to debugging.
++ * Add return values to init and cleanup functions.
++ *
++ * Revision 1.3  1999/04/15 17:58:07  rgb
++ * Add RCSID labels.
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/pfkeyv2.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,472 @@
++/*
++ * RCSID $Id: pfkeyv2.h,v 1.31 2005/04/14 01:14:54 mcr Exp $
++ */
++
++/*
++RFC 2367               PF_KEY Key Management API               July 1998
++
++
++Appendix D: Sample Header File
++
++This file defines structures and symbols for the PF_KEY Version 2
++key management interface. It was written at the U.S. Naval Research
++Laboratory. This file is in the public domain. The authors ask that
++you leave this credit intact on any copies of this file.
++*/
++#ifndef __PFKEY_V2_H
++#define __PFKEY_V2_H 1
++
++#define PF_KEY_V2 2
++#define PFKEYV2_REVISION        199806L
++
++#define SADB_RESERVED    0
++#define SADB_GETSPI      1
++#define SADB_UPDATE      2
++#define SADB_ADD         3
++#define SADB_DELETE      4
++#define SADB_GET         5
++#define SADB_ACQUIRE     6
++#define SADB_REGISTER    7
++#define SADB_EXPIRE      8
++#define SADB_FLUSH       9
++#define SADB_DUMP       10
++#define SADB_X_PROMISC  11
++#define SADB_X_PCHANGE  12
++#define SADB_X_GRPSA    13
++#define SADB_X_ADDFLOW        14
++#define SADB_X_DELFLOW        15
++#define SADB_X_DEBUG  16
++#define SADB_X_NAT_T_NEW_MAPPING  17
++#define SADB_MAX                  17
++
++struct sadb_msg {
++  uint8_t sadb_msg_version;
++  uint8_t sadb_msg_type;
++  uint8_t sadb_msg_errno;
++  uint8_t sadb_msg_satype;
++  uint16_t sadb_msg_len;
++  uint16_t sadb_msg_reserved;
++  uint32_t sadb_msg_seq;
++  uint32_t sadb_msg_pid;
++};
++
++struct sadb_ext {
++  uint16_t sadb_ext_len;
++  uint16_t sadb_ext_type;
++};
++
++struct sadb_sa {
++  uint16_t sadb_sa_len;
++  uint16_t sadb_sa_exttype;
++  uint32_t sadb_sa_spi;
++  uint8_t sadb_sa_replay;
++  uint8_t sadb_sa_state;
++  uint8_t sadb_sa_auth;
++  uint8_t sadb_sa_encrypt;
++  uint32_t sadb_sa_flags;
++  uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */
++  uint8_t sadb_x_reserved[4];
++};
++
++struct sadb_sa_v1 {
++  uint16_t sadb_sa_len;
++  uint16_t sadb_sa_exttype;
++  uint32_t sadb_sa_spi;
++  uint8_t sadb_sa_replay;
++  uint8_t sadb_sa_state;
++  uint8_t sadb_sa_auth;
++  uint8_t sadb_sa_encrypt;
++  uint32_t sadb_sa_flags;
++};
++
++struct sadb_lifetime {
++  uint16_t sadb_lifetime_len;
++  uint16_t sadb_lifetime_exttype;
++  uint32_t sadb_lifetime_allocations;
++  uint64_t sadb_lifetime_bytes;
++  uint64_t sadb_lifetime_addtime;
++  uint64_t sadb_lifetime_usetime;
++  uint32_t sadb_x_lifetime_packets;
++  uint32_t sadb_x_lifetime_reserved;
++};
++
++struct sadb_address {
++  uint16_t sadb_address_len;
++  uint16_t sadb_address_exttype;
++  uint8_t sadb_address_proto;
++  uint8_t sadb_address_prefixlen;
++  uint16_t sadb_address_reserved;
++};
++
++struct sadb_key {
++  uint16_t sadb_key_len;
++  uint16_t sadb_key_exttype;
++  uint16_t sadb_key_bits;
++  uint16_t sadb_key_reserved;
++};
++
++struct sadb_ident {
++  uint16_t sadb_ident_len;
++  uint16_t sadb_ident_exttype;
++  uint16_t sadb_ident_type;
++  uint16_t sadb_ident_reserved;
++  uint64_t sadb_ident_id;
++};
++
++struct sadb_sens {
++  uint16_t sadb_sens_len;
++  uint16_t sadb_sens_exttype;
++  uint32_t sadb_sens_dpd;
++  uint8_t sadb_sens_sens_level;
++  uint8_t sadb_sens_sens_len;
++  uint8_t sadb_sens_integ_level;
++  uint8_t sadb_sens_integ_len;
++  uint32_t sadb_sens_reserved;
++};
++
++struct sadb_prop {
++  uint16_t sadb_prop_len;
++  uint16_t sadb_prop_exttype;
++  uint8_t sadb_prop_replay;
++  uint8_t sadb_prop_reserved[3];
++};
++
++struct sadb_comb {
++  uint8_t sadb_comb_auth;
++  uint8_t sadb_comb_encrypt;
++  uint16_t sadb_comb_flags;
++  uint16_t sadb_comb_auth_minbits;
++  uint16_t sadb_comb_auth_maxbits;
++  uint16_t sadb_comb_encrypt_minbits;
++  uint16_t sadb_comb_encrypt_maxbits;
++  uint32_t sadb_comb_reserved;
++  uint32_t sadb_comb_soft_allocations;
++  uint32_t sadb_comb_hard_allocations;
++  uint64_t sadb_comb_soft_bytes;
++  uint64_t sadb_comb_hard_bytes;
++  uint64_t sadb_comb_soft_addtime;
++  uint64_t sadb_comb_hard_addtime;
++  uint64_t sadb_comb_soft_usetime;
++  uint64_t sadb_comb_hard_usetime;
++  uint32_t sadb_x_comb_soft_packets;
++  uint32_t sadb_x_comb_hard_packets;
++};
++
++struct sadb_supported {
++  uint16_t sadb_supported_len;
++  uint16_t sadb_supported_exttype;
++  uint32_t sadb_supported_reserved;
++};
++
++struct sadb_alg {
++  uint8_t sadb_alg_id;
++  uint8_t sadb_alg_ivlen;
++  uint16_t sadb_alg_minbits;
++  uint16_t sadb_alg_maxbits;
++  uint16_t sadb_alg_reserved;
++};
++
++struct sadb_spirange {
++  uint16_t sadb_spirange_len;
++  uint16_t sadb_spirange_exttype;
++  uint32_t sadb_spirange_min;
++  uint32_t sadb_spirange_max;
++  uint32_t sadb_spirange_reserved;
++};
++
++struct sadb_x_kmprivate {
++  uint16_t sadb_x_kmprivate_len;
++  uint16_t sadb_x_kmprivate_exttype;
++  uint32_t sadb_x_kmprivate_reserved;
++};
++
++struct sadb_x_satype {
++  uint16_t sadb_x_satype_len;
++  uint16_t sadb_x_satype_exttype;
++  uint8_t sadb_x_satype_satype;
++  uint8_t sadb_x_satype_reserved[3];
++};
++  
++struct sadb_x_policy {
++  uint16_t sadb_x_policy_len;
++  uint16_t sadb_x_policy_exttype;
++  uint16_t sadb_x_policy_type;
++  uint8_t sadb_x_policy_dir;
++  uint8_t sadb_x_policy_reserved;
++  uint32_t sadb_x_policy_id;
++  uint32_t sadb_x_policy_reserved2;
++};
++ 
++struct sadb_x_debug {
++  uint16_t sadb_x_debug_len;
++  uint16_t sadb_x_debug_exttype;
++  uint32_t sadb_x_debug_tunnel;
++  uint32_t sadb_x_debug_netlink;
++  uint32_t sadb_x_debug_xform;
++  uint32_t sadb_x_debug_eroute;
++  uint32_t sadb_x_debug_spi;
++  uint32_t sadb_x_debug_radij;
++  uint32_t sadb_x_debug_esp;
++  uint32_t sadb_x_debug_ah;
++  uint32_t sadb_x_debug_rcv;
++  uint32_t sadb_x_debug_pfkey;
++  uint32_t sadb_x_debug_ipcomp;
++  uint32_t sadb_x_debug_verbose;
++  uint8_t sadb_x_debug_reserved[4];
++};
++
++struct sadb_x_nat_t_type {
++  uint16_t sadb_x_nat_t_type_len;
++  uint16_t sadb_x_nat_t_type_exttype;
++  uint8_t sadb_x_nat_t_type_type;
++  uint8_t sadb_x_nat_t_type_reserved[3];
++};
++struct sadb_x_nat_t_port {
++  uint16_t sadb_x_nat_t_port_len;
++  uint16_t sadb_x_nat_t_port_exttype;
++  uint16_t sadb_x_nat_t_port_port;
++  uint16_t sadb_x_nat_t_port_reserved;
++};
++
++/*
++ * A protocol structure for passing through the transport level
++ * protocol.  It contains more fields than are actually used/needed
++ * but it is this way to be compatible with the structure used in
++ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
++ */
++struct sadb_protocol {
++  uint16_t sadb_protocol_len;
++  uint16_t sadb_protocol_exttype;
++  uint8_t  sadb_protocol_proto;
++  uint8_t  sadb_protocol_direction;
++  uint8_t  sadb_protocol_flags;
++  uint8_t  sadb_protocol_reserved2;
++};
++
++#define SADB_EXT_RESERVED             0
++#define SADB_EXT_SA                   1
++#define SADB_EXT_LIFETIME_CURRENT     2
++#define SADB_EXT_LIFETIME_HARD        3
++#define SADB_EXT_LIFETIME_SOFT        4
++#define SADB_EXT_ADDRESS_SRC          5
++#define SADB_EXT_ADDRESS_DST          6
++#define SADB_EXT_ADDRESS_PROXY        7
++#define SADB_EXT_KEY_AUTH             8
++#define SADB_EXT_KEY_ENCRYPT          9
++#define SADB_EXT_IDENTITY_SRC         10
++#define SADB_EXT_IDENTITY_DST         11
++#define SADB_EXT_SENSITIVITY          12
++#define SADB_EXT_PROPOSAL             13
++#define SADB_EXT_SUPPORTED_AUTH       14
++#define SADB_EXT_SUPPORTED_ENCRYPT    15
++#define SADB_EXT_SPIRANGE             16
++#define SADB_X_EXT_KMPRIVATE          17
++#define SADB_X_EXT_SATYPE2            18
++#ifdef KERNEL26_HAS_KAME_DUPLICATES
++#define SADB_X_EXT_POLICY             18
++#endif
++#define SADB_X_EXT_SA2                19
++#define SADB_X_EXT_ADDRESS_DST2       20
++#define SADB_X_EXT_ADDRESS_SRC_FLOW   21
++#define SADB_X_EXT_ADDRESS_DST_FLOW   22
++#define SADB_X_EXT_ADDRESS_SRC_MASK   23
++#define SADB_X_EXT_ADDRESS_DST_MASK   24
++#define SADB_X_EXT_DEBUG              25
++#define SADB_X_EXT_PROTOCOL           26
++#define SADB_X_EXT_NAT_T_TYPE         27
++#define SADB_X_EXT_NAT_T_SPORT        28
++#define SADB_X_EXT_NAT_T_DPORT        29
++#define SADB_X_EXT_NAT_T_OA           30
++#define SADB_EXT_MAX                  30
++
++/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
++#define SADB_X_EXT_ADDRESS_DELFLOW \
++      ( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
++      | (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
++      | (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
++      | (1<<SADB_X_EXT_ADDRESS_DST_MASK))
++
++#define SADB_SATYPE_UNSPEC    0
++#define SADB_SATYPE_AH        2
++#define SADB_SATYPE_ESP       3
++#define SADB_SATYPE_RSVP      5
++#define SADB_SATYPE_OSPFV2    6
++#define SADB_SATYPE_RIPV2     7
++#define SADB_SATYPE_MIP       8
++#define SADB_X_SATYPE_IPIP    9
++#ifdef KERNEL26_HAS_KAME_DUPLICATES
++#define SADB_X_SATYPE_IPCOMP  9   /* ICK! */
++#endif
++#define SADB_X_SATYPE_COMP    10
++#define SADB_X_SATYPE_INT     11
++#define SADB_SATYPE_MAX       11
++
++enum sadb_sastate {
++  SADB_SASTATE_LARVAL=0,
++  SADB_SASTATE_MATURE=1,
++  SADB_SASTATE_DYING=2,
++  SADB_SASTATE_DEAD=3
++};
++#define SADB_SASTATE_MAX 3
++
++#define SADB_SAFLAGS_PFS              1
++#define SADB_X_SAFLAGS_REPLACEFLOW    2
++#define SADB_X_SAFLAGS_CLEARFLOW      4
++#define SADB_X_SAFLAGS_INFLOW         8
++
++/* not obvious, but these are the same values as used in isakmp,
++ * and in freeswan/ipsec_policy.h. If you need to add any, they
++ * should be added as according to 
++ *   http://www.iana.org/assignments/isakmp-registry
++ * 
++ * and if not, then please try to use a private-use value, and
++ * consider asking IANA to assign a value.
++ */
++#define SADB_AALG_NONE                  0
++#define SADB_AALG_MD5HMAC               2
++#define SADB_AALG_SHA1HMAC              3
++#define SADB_X_AALG_SHA2_256HMAC      5
++#define SADB_X_AALG_SHA2_384HMAC      6
++#define SADB_X_AALG_SHA2_512HMAC      7
++#define SADB_X_AALG_RIPEMD160HMAC     8
++#define SADB_X_AALG_NULL              251     /* kame */
++#define SADB_AALG_MAX                 251
++
++#define SADB_EALG_NONE                  0
++#define SADB_EALG_DESCBC                2
++#define SADB_EALG_3DESCBC               3
++#define SADB_X_EALG_CASTCBC           6
++#define SADB_X_EALG_BLOWFISHCBC               7
++#define SADB_EALG_NULL                        11
++#define SADB_X_EALG_AESCBC            12
++#define SADB_EALG_MAX                 255
++
++#define SADB_X_CALG_NONE          0
++#define SADB_X_CALG_OUI           1
++#define SADB_X_CALG_DEFLATE       2
++#define SADB_X_CALG_LZS           3
++#define SADB_X_CALG_V42BIS        4
++#ifdef KERNEL26_HAS_KAME_DUPLICATES
++#define SADB_X_CALG_LZJH          4
++#endif
++#define SADB_X_CALG_MAX           4
++
++#define SADB_X_TALG_NONE          0
++#define SADB_X_TALG_IPv4_in_IPv4  1
++#define SADB_X_TALG_IPv6_in_IPv4  2
++#define SADB_X_TALG_IPv4_in_IPv6  3
++#define SADB_X_TALG_IPv6_in_IPv6  4
++#define SADB_X_TALG_MAX           4
++
++
++#define SADB_IDENTTYPE_RESERVED   0
++#define SADB_IDENTTYPE_PREFIX     1
++#define SADB_IDENTTYPE_FQDN       2
++#define SADB_IDENTTYPE_USERFQDN   3
++#define SADB_X_IDENTTYPE_CONNECTION 4
++#define SADB_IDENTTYPE_MAX        4
++
++#define SADB_KEY_FLAGS_MAX     0
++#endif /* __PFKEY_V2_H */
++
++/*
++ * $Log: pfkeyv2.h,v $
++ * Revision 1.31  2005/04/14 01:14:54  mcr
++ *    change sadb_state to an enum.
++ *
++ * Revision 1.30  2004/04/06 02:49:00  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.29  2003/12/22 21:35:58  mcr
++ *    new patches from Dr{Who}.
++ *
++ * Revision 1.28  2003/12/22 19:33:15  mcr
++ *    added 0.6c NAT-T patch.
++ *
++ * Revision 1.27  2003/12/10 01:20:01  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.26  2003/10/31 02:26:44  mcr
++ *    pulled up port-selector patches.
++ *
++ * Revision 1.25.4.1  2003/09/21 13:59:34  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.25  2003/07/31 23:59:17  mcr
++ *    re-introduce kernel 2.6 duplicate values for now.
++ *    hope to get them changed!
++ *
++ * Revision 1.24  2003/07/31 22:55:27  mcr
++ *    added some definitions to keep pfkeyv2.h files in sync.
++ *
++ * Revision 1.23  2003/05/11 00:43:48  mcr
++ *    added comment about origin of values used
++ *
++ * Revision 1.22  2003/01/30 02:31:34  rgb
++ *
++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
++ *
++ * Revision 1.21  2002/12/16 19:26:49  mcr
++ *    added definition of FS 1.xx sadb structure
++ *
++ * Revision 1.20  2002/09/20 15:40:25  rgb
++ * Added sadb_x_sa_ref to struct sadb_sa.
++ *
++ * Revision 1.19  2002/04/24 07:36:49  mcr
++ * Moved from ./lib/pfkeyv2.h,v
++ *
++ * Revision 1.18  2001/11/06 19:47:47  rgb
++ * Added packet parameter to lifetime and comb structures.
++ *
++ * Revision 1.17  2001/09/08 21:13:35  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.16  2001/07/06 19:49:46  rgb
++ * Added SADB_X_SAFLAGS_INFLOW for supporting incoming policy checks.
++ *
++ * Revision 1.15  2001/02/26 20:00:43  rgb
++ * Added internal IP protocol 61 for magic SAs.
++ *
++ * Revision 1.14  2001/02/08 18:51:05  rgb
++ * Include RFC document title and appendix subsection title.
++ *
++ * Revision 1.13  2000/10/10 20:10:20  rgb
++ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
++ *
++ * Revision 1.12  2000/09/15 06:41:50  rgb
++ * Added V42BIS constant.
++ *
++ * Revision 1.11  2000/09/12 22:35:37  rgb
++ * Restructured to remove unused extensions from CLEARFLOW messages.
++ *
++ * Revision 1.10  2000/09/12 18:50:09  rgb
++ * Added IPIP tunnel types as algo support.
++ *
++ * Revision 1.9  2000/08/21 16:47:19  rgb
++ * Added SADB_X_CALG_* macros for IPCOMP.
++ *
++ * Revision 1.8  2000/08/09 20:43:34  rgb
++ * Fixed bitmask value for SADB_X_SAFLAGS_CLEAREROUTE.
++ *
++ * Revision 1.7  2000/01/21 06:28:37  rgb
++ * Added flow add/delete message type macros.
++ * Added flow address extension type macros.
++ * Tidied up spacing.
++ * Added klipsdebug switching capability.
++ *
++ * Revision 1.6  1999/11/27 11:56:08  rgb
++ * Add SADB_X_SATYPE_COMP for compression, eventually.
++ *
++ * Revision 1.5  1999/11/23 22:23:16  rgb
++ * This file has been moved in the distribution from klips/net/ipsec to
++ * lib.
++ *
++ * Revision 1.4  1999/04/29 15:23:29  rgb
++ * Add GRPSA support.
++ * Add support for a second SATYPE, SA and DST_ADDRESS.
++ * Add IPPROTO_IPIP support.
++ *
++ * Revision 1.3  1999/04/15 17:58:08  rgb
++ * Add RCSID labels.
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/zlib/zconf.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,309 @@
++/* zconf.h -- configuration of the zlib compression library
++ * Copyright (C) 1995-2002 Jean-loup Gailly.
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* @(#) $Id: zconf.h,v 1.4 2004/07/10 07:48:40 mcr Exp $ */
++
++#ifndef _ZCONF_H
++#define _ZCONF_H
++
++/*
++ * If you *really* need a unique prefix for all types and library functions,
++ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
++ */
++#ifdef IPCOMP_PREFIX
++#  define deflateInit_        ipcomp_deflateInit_
++#  define deflate     ipcomp_deflate
++#  define deflateEnd  ipcomp_deflateEnd
++#  define inflateInit_        ipcomp_inflateInit_
++#  define inflate     ipcomp_inflate
++#  define inflateEnd  ipcomp_inflateEnd
++#  define deflateInit2_       ipcomp_deflateInit2_
++#  define deflateSetDictionary ipcomp_deflateSetDictionary
++#  define deflateCopy ipcomp_deflateCopy
++#  define deflateReset        ipcomp_deflateReset
++#  define deflateParams       ipcomp_deflateParams
++#  define inflateInit2_       ipcomp_inflateInit2_
++#  define inflateSetDictionary ipcomp_inflateSetDictionary
++#  define inflateSync ipcomp_inflateSync
++#  define inflateSyncPoint ipcomp_inflateSyncPoint
++#  define inflateReset        ipcomp_inflateReset
++#  define compress    ipcomp_compress
++#  define compress2   ipcomp_compress2
++#  define uncompress  ipcomp_uncompress
++#  define adler32     ipcomp_adler32
++#  define crc32               ipcomp_crc32
++#  define get_crc_table ipcomp_get_crc_table
++/* SSS: these also need to be prefixed to avoid clash with ppp_deflate and ext2compression */
++#  define inflate_blocks ipcomp_deflate_blocks
++#  define inflate_blocks_free ipcomp_deflate_blocks_free
++#  define inflate_blocks_new ipcomp_inflate_blocks_new
++#  define inflate_blocks_reset ipcomp_inflate_blocks_reset
++#  define inflate_blocks_sync_point ipcomp_inflate_blocks_sync_point
++#  define inflate_set_dictionary ipcomp_inflate_set_dictionary
++#  define inflate_codes ipcomp_inflate_codes
++#  define inflate_codes_free ipcomp_inflate_codes_free
++#  define inflate_codes_new ipcomp_inflate_codes_new
++#  define inflate_fast ipcomp_inflate_fast
++#  define inflate_trees_bits ipcomp_inflate_trees_bits
++#  define inflate_trees_dynamic ipcomp_inflate_trees_dynamic
++#  define inflate_trees_fixed ipcomp_inflate_trees_fixed
++#  define inflate_flush ipcomp_inflate_flush
++#  define inflate_mask ipcomp_inflate_mask
++#  define _dist_code _ipcomp_dist_code
++#  define _length_code _ipcomp_length_code
++#  define _tr_align _ipcomp_tr_align
++#  define _tr_flush_block _ipcomp_tr_flush_block
++#  define _tr_init _ipcomp_tr_init
++#  define _tr_stored_block _ipcomp_tr_stored_block
++#  define _tr_tally _ipcomp_tr_tally
++#  define zError ipcomp_zError
++#  define z_errmsg ipcomp_z_errmsg
++#  define zlibVersion ipcomp_zlibVersion
++#  define match_init ipcomp_match_init
++#  define longest_match ipcomp_longest_match
++#endif
++
++#ifdef Z_PREFIX
++#  define Byte                z_Byte
++#  define uInt                z_uInt
++#  define uLong               z_uLong
++#  define Bytef               z_Bytef
++#  define charf               z_charf
++#  define intf                z_intf
++#  define uIntf               z_uIntf
++#  define uLongf      z_uLongf
++#  define voidpf      z_voidpf
++#  define voidp               z_voidp
++#endif
++
++#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
++#  define WIN32
++#endif
++#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
++#  ifndef __32BIT__
++#    define __32BIT__
++#  endif
++#endif
++#if defined(__MSDOS__) && !defined(MSDOS)
++#  define MSDOS
++#endif
++
++/*
++ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
++ * than 64k bytes at a time (needed on systems with 16-bit int).
++ */
++#if defined(MSDOS) && !defined(__32BIT__)
++#  define MAXSEG_64K
++#endif
++#ifdef MSDOS
++#  define UNALIGNED_OK
++#endif
++
++#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32))  && !defined(STDC)
++#  define STDC
++#endif
++#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
++#  ifndef STDC
++#    define STDC
++#  endif
++#endif
++
++#ifndef STDC
++#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
++#    define const
++#  endif
++#endif
++
++/* Some Mac compilers merge all .h files incorrectly: */
++#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
++#  define NO_DUMMY_DECL
++#endif
++
++/* Old Borland C incorrectly complains about missing returns: */
++#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
++#  define NEED_DUMMY_RETURN
++#endif
++
++
++/* Maximum value for memLevel in deflateInit2 */
++#ifndef MAX_MEM_LEVEL
++#  ifdef MAXSEG_64K
++#    define MAX_MEM_LEVEL 8
++#  else
++#    define MAX_MEM_LEVEL 9
++#  endif
++#endif
++
++/* Maximum value for windowBits in deflateInit2 and inflateInit2.
++ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
++ * created by gzip. (Files created by minigzip can still be extracted by
++ * gzip.)
++ */
++#ifndef MAX_WBITS
++#  define MAX_WBITS   15 /* 32K LZ77 window */
++#endif
++
++/* The memory requirements for deflate are (in bytes):
++            (1 << (windowBits+2)) +  (1 << (memLevel+9))
++ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
++ plus a few kilobytes for small objects. For example, if you want to reduce
++ the default memory requirements from 256K to 128K, compile with
++     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
++ Of course this will generally degrade compression (there's no free lunch).
++
++   The memory requirements for inflate are (in bytes) 1 << windowBits
++ that is, 32K for windowBits=15 (default value) plus a few kilobytes
++ for small objects.
++*/
++
++                        /* Type declarations */
++
++#ifndef OF /* function prototypes */
++#  ifdef STDC
++#    define OF(args)  args
++#  else
++#    define OF(args)  ()
++#  endif
++#endif
++
++/* The following definitions for FAR are needed only for MSDOS mixed
++ * model programming (small or medium model with some far allocations).
++ * This was tested only with MSC; for other MSDOS compilers you may have
++ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
++ * just define FAR to be empty.
++ */
++#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
++   /* MSC small or medium model */
++#  define SMALL_MEDIUM
++#  ifdef _MSC_VER
++#    define FAR _far
++#  else
++#    define FAR far
++#  endif
++#endif
++#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
++#  ifndef __32BIT__
++#    define SMALL_MEDIUM
++#    define FAR _far
++#  endif
++#endif
++
++/* Compile with -DZLIB_DLL for Windows DLL support */
++#if defined(ZLIB_DLL)
++#  if defined(_WINDOWS) || defined(WINDOWS)
++#    ifdef FAR
++#      undef FAR
++#    endif
++#    include <windows.h>
++#    define ZEXPORT  WINAPI
++#    ifdef WIN32
++#      define ZEXPORTVA  WINAPIV
++#    else
++#      define ZEXPORTVA  FAR _cdecl _export
++#    endif
++#  endif
++#  if defined (__BORLANDC__)
++#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
++#      include <windows.h>
++#      define ZEXPORT __declspec(dllexport) WINAPI
++#      define ZEXPORTRVA __declspec(dllexport) WINAPIV
++#    else
++#      if defined (_Windows) && defined (__DLL__)
++#        define ZEXPORT _export
++#        define ZEXPORTVA _export
++#      endif
++#    endif
++#  endif
++#endif
++
++#if defined (__BEOS__)
++#  if defined (ZLIB_DLL)
++#    define ZEXTERN extern __declspec(dllexport)
++#  else
++#    define ZEXTERN extern __declspec(dllimport)
++#  endif
++#endif
++
++#ifndef ZEXPORT
++#  define ZEXPORT
++#endif
++#ifndef ZEXPORTVA
++#  define ZEXPORTVA
++#endif
++#ifndef ZEXTERN
++#  define ZEXTERN extern
++#endif
++
++#ifndef FAR
++#   define FAR
++#endif
++
++#if !defined(MACOS) && !defined(TARGET_OS_MAC)
++typedef unsigned char  Byte;  /* 8 bits */
++#endif
++typedef unsigned int   uInt;  /* 16 bits or more */
++typedef unsigned long  uLong; /* 32 bits or more */
++
++#ifdef SMALL_MEDIUM
++   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
++#  define Bytef Byte FAR
++#else
++   typedef Byte  FAR Bytef;
++#endif
++typedef char  FAR charf;
++typedef int   FAR intf;
++typedef uInt  FAR uIntf;
++typedef uLong FAR uLongf;
++
++#ifdef STDC
++   typedef void FAR *voidpf;
++   typedef void     *voidp;
++#else
++   typedef Byte FAR *voidpf;
++   typedef Byte     *voidp;
++#endif
++
++#ifdef HAVE_UNISTD_H
++#  include <sys/types.h> /* for off_t */
++#  include <unistd.h>    /* for SEEK_* and off_t */
++#  define z_off_t  off_t
++#endif
++#ifndef SEEK_SET
++#  define SEEK_SET        0       /* Seek from beginning of file.  */
++#  define SEEK_CUR        1       /* Seek from current position.  */
++#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
++#endif
++#ifndef z_off_t
++#  define  z_off_t long
++#endif
++
++/* MVS linker does not support external names larger than 8 bytes */
++#if defined(__MVS__)
++#   pragma map(deflateInit_,"DEIN")
++#   pragma map(deflateInit2_,"DEIN2")
++#   pragma map(deflateEnd,"DEEND")
++#   pragma map(inflateInit_,"ININ")
++#   pragma map(inflateInit2_,"ININ2")
++#   pragma map(inflateEnd,"INEND")
++#   pragma map(inflateSync,"INSY")
++#   pragma map(inflateSetDictionary,"INSEDI")
++#   pragma map(inflate_blocks,"INBL")
++#   pragma map(inflate_blocks_new,"INBLNE")
++#   pragma map(inflate_blocks_free,"INBLFR")
++#   pragma map(inflate_blocks_reset,"INBLRE")
++#   pragma map(inflate_codes_free,"INCOFR")
++#   pragma map(inflate_codes,"INCO")
++#   pragma map(inflate_fast,"INFA")
++#   pragma map(inflate_flush,"INFLU")
++#   pragma map(inflate_mask,"INMA")
++#   pragma map(inflate_set_dictionary,"INSEDI2")
++#   pragma map(ipcomp_inflate_copyright,"INCOPY")
++#   pragma map(inflate_trees_bits,"INTRBI")
++#   pragma map(inflate_trees_dynamic,"INTRDY")
++#   pragma map(inflate_trees_fixed,"INTRFI")
++#   pragma map(inflate_trees_free,"INTRFR")
++#endif
++
++#endif /* _ZCONF_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/zlib/zlib.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,893 @@
++/* zlib.h -- interface of the 'zlib' general purpose compression library
++  version 1.1.4, March 11th, 2002
++
++  Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
++
++  This software is provided 'as-is', without any express or implied
++  warranty.  In no event will the authors be held liable for any damages
++  arising from the use of this software.
++
++  Permission is granted to anyone to use this software for any purpose,
++  including commercial applications, and to alter it and redistribute it
++  freely, subject to the following restrictions:
++
++  1. The origin of this software must not be misrepresented; you must not
++     claim that you wrote the original software. If you use this software
++     in a product, an acknowledgment in the product documentation would be
++     appreciated but is not required.
++  2. Altered source versions must be plainly marked as such, and must not be
++     misrepresented as being the original software.
++  3. This notice may not be removed or altered from any source distribution.
++
++  Jean-loup Gailly        Mark Adler
++  jloup@gzip.org          madler@alumni.caltech.edu
++
++
++  The data format used by the zlib library is described by RFCs (Request for
++  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
++  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
++*/
++
++#ifndef _ZLIB_H
++#define _ZLIB_H
++
++#include "zconf.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define ZLIB_VERSION "1.1.4"
++
++/* 
++     The 'zlib' compression library provides in-memory compression and
++  decompression functions, including integrity checks of the uncompressed
++  data.  This version of the library supports only one compression method
++  (deflation) but other algorithms will be added later and will have the same
++  stream interface.
++
++     Compression can be done in a single step if the buffers are large
++  enough (for example if an input file is mmap'ed), or can be done by
++  repeated calls of the compression function.  In the latter case, the
++  application must provide more input and/or consume the output
++  (providing more output space) before each call.
++
++     The library also supports reading and writing files in gzip (.gz) format
++  with an interface similar to that of stdio.
++
++     The library does not install any signal handler. The decoder checks
++  the consistency of the compressed data, so the library should never
++  crash even in case of corrupted input.
++*/
++
++typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
++typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
++
++struct internal_state;
++
++typedef struct z_stream_s {
++    Bytef    *next_in;  /* next input byte */
++    uInt     avail_in;  /* number of bytes available at next_in */
++    uLong    total_in;  /* total nb of input bytes read so far */
++
++    Bytef    *next_out; /* next output byte should be put there */
++    uInt     avail_out; /* remaining free space at next_out */
++    uLong    total_out; /* total nb of bytes output so far */
++
++    const char     *msg;      /* last error message, NULL if no error */
++    struct internal_state FAR *state; /* not visible by applications */
++
++    alloc_func zalloc;  /* used to allocate the internal state */
++    free_func  zfree;   /* used to free the internal state */
++    voidpf     opaque;  /* private data object passed to zalloc and zfree */
++
++    int     data_type;  /* best guess about the data type: ascii or binary */
++    uLong   adler;      /* adler32 value of the uncompressed data */
++    uLong   reserved;   /* reserved for future use */
++} z_stream;
++
++typedef z_stream FAR *z_streamp;
++
++/*
++   The application must update next_in and avail_in when avail_in has
++   dropped to zero. It must update next_out and avail_out when avail_out
++   has dropped to zero. The application must initialize zalloc, zfree and
++   opaque before calling the init function. All other fields are set by the
++   compression library and must not be updated by the application.
++
++   The opaque value provided by the application will be passed as the first
++   parameter for calls of zalloc and zfree. This can be useful for custom
++   memory management. The compression library attaches no meaning to the
++   opaque value.
++
++   zalloc must return Z_NULL if there is not enough memory for the object.
++   If zlib is used in a multi-threaded application, zalloc and zfree must be
++   thread safe.
++
++   On 16-bit systems, the functions zalloc and zfree must be able to allocate
++   exactly 65536 bytes, but will not be required to allocate more than this
++   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
++   pointers returned by zalloc for objects of exactly 65536 bytes *must*
++   have their offset normalized to zero. The default allocation function
++   provided by this library ensures this (see zutil.c). To reduce memory
++   requirements and avoid any allocation of 64K objects, at the expense of
++   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
++
++   The fields total_in and total_out can be used for statistics or
++   progress reports. After compression, total_in holds the total size of
++   the uncompressed data and may be saved for use in the decompressor
++   (particularly if the decompressor wants to decompress everything in
++   a single step).
++*/
++
++                        /* constants */
++
++#define Z_NO_FLUSH      0
++#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
++#define Z_SYNC_FLUSH    2
++#define Z_FULL_FLUSH    3
++#define Z_FINISH        4
++/* Allowed flush values; see deflate() below for details */
++
++#define Z_OK            0
++#define Z_STREAM_END    1
++#define Z_NEED_DICT     2
++#define Z_ERRNO        (-1)
++#define Z_STREAM_ERROR (-2)
++#define Z_DATA_ERROR   (-3)
++#define Z_MEM_ERROR    (-4)
++#define Z_BUF_ERROR    (-5)
++#define Z_VERSION_ERROR (-6)
++/* Return codes for the compression/decompression functions. Negative
++ * values are errors, positive values are used for special but normal events.
++ */
++
++#define Z_NO_COMPRESSION         0
++#define Z_BEST_SPEED             1
++#define Z_BEST_COMPRESSION       9
++#define Z_DEFAULT_COMPRESSION  (-1)
++/* compression levels */
++
++#define Z_FILTERED            1
++#define Z_HUFFMAN_ONLY        2
++#define Z_DEFAULT_STRATEGY    0
++/* compression strategy; see deflateInit2() below for details */
++
++#define Z_BINARY   0
++#define Z_ASCII    1
++#define Z_UNKNOWN  2
++/* Possible values of the data_type field */
++
++#define Z_DEFLATED   8
++/* The deflate compression method (the only one supported in this version) */
++
++#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
++
++#define zlib_version zlibVersion()
++/* for compatibility with versions < 1.0.2 */
++
++                        /* basic functions */
++
++ZEXTERN const char * ZEXPORT zlibVersion OF((void));
++/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
++   If the first character differs, the library code actually used is
++   not compatible with the zlib.h header file used by the application.
++   This check is automatically made by deflateInit and inflateInit.
++ */
++
++/* 
++ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
++
++     Initializes the internal stream state for compression. The fields
++   zalloc, zfree and opaque must be initialized before by the caller.
++   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
++   use default allocation functions.
++
++     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
++   1 gives best speed, 9 gives best compression, 0 gives no compression at
++   all (the input data is simply copied a block at a time).
++   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
++   compression (currently equivalent to level 6).
++
++     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
++   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
++   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
++   with the version assumed by the caller (ZLIB_VERSION).
++   msg is set to null if there is no error message.  deflateInit does not
++   perform any compression: this will be done by deflate().
++*/
++
++
++ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
++/*
++    deflate compresses as much data as possible, and stops when the input
++  buffer becomes empty or the output buffer becomes full. It may introduce some
++  output latency (reading input without producing any output) except when
++  forced to flush.
++
++    The detailed semantics are as follows. deflate performs one or both of the
++  following actions:
++
++  - Compress more input starting at next_in and update next_in and avail_in
++    accordingly. If not all input can be processed (because there is not
++    enough room in the output buffer), next_in and avail_in are updated and
++    processing will resume at this point for the next call of deflate().
++
++  - Provide more output starting at next_out and update next_out and avail_out
++    accordingly. This action is forced if the parameter flush is non zero.
++    Forcing flush frequently degrades the compression ratio, so this parameter
++    should be set only when necessary (in interactive applications).
++    Some output may be provided even if flush is not set.
++
++  Before the call of deflate(), the application should ensure that at least
++  one of the actions is possible, by providing more input and/or consuming
++  more output, and updating avail_in or avail_out accordingly; avail_out
++  should never be zero before the call. The application can consume the
++  compressed output when it wants, for example when the output buffer is full
++  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
++  and with zero avail_out, it must be called again after making room in the
++  output buffer because there might be more output pending.
++
++    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
++  flushed to the output buffer and the output is aligned on a byte boundary, so
++  that the decompressor can get all input data available so far. (In particular
++  avail_in is zero after the call if enough output space has been provided
++  before the call.)  Flushing may degrade compression for some compression
++  algorithms and so it should be used only when necessary.
++
++    If flush is set to Z_FULL_FLUSH, all output is flushed as with
++  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
++  restart from this point if previous compressed data has been damaged or if
++  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
++  the compression.
++
++    If deflate returns with avail_out == 0, this function must be called again
++  with the same value of the flush parameter and more output space (updated
++  avail_out), until the flush is complete (deflate returns with non-zero
++  avail_out).
++
++    If the parameter flush is set to Z_FINISH, pending input is processed,
++  pending output is flushed and deflate returns with Z_STREAM_END if there
++  was enough output space; if deflate returns with Z_OK, this function must be
++  called again with Z_FINISH and more output space (updated avail_out) but no
++  more input data, until it returns with Z_STREAM_END or an error. After
++  deflate has returned Z_STREAM_END, the only possible operations on the
++  stream are deflateReset or deflateEnd.
++  
++    Z_FINISH can be used immediately after deflateInit if all the compression
++  is to be done in a single step. In this case, avail_out must be at least
++  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
++  Z_STREAM_END, then it must be called again as described above.
++
++    deflate() sets strm->adler to the adler32 checksum of all input read
++  so far (that is, total_in bytes).
++
++    deflate() may update data_type if it can make a good guess about
++  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
++  binary. This field is only for information purposes and does not affect
++  the compression algorithm in any manner.
++
++    deflate() returns Z_OK if some progress has been made (more input
++  processed or more output produced), Z_STREAM_END if all input has been
++  consumed and all output has been produced (only when flush is set to
++  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
++  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
++  (for example avail_in or avail_out was zero).
++*/
++
++
++ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
++/*
++     All dynamically allocated data structures for this stream are freed.
++   This function discards any unprocessed input and does not flush any
++   pending output.
++
++     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
++   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
++   prematurely (some input or output was discarded). In the error case,
++   msg may be set but then points to a static string (which must not be
++   deallocated).
++*/
++
++
++/* 
++ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
++
++     Initializes the internal stream state for decompression. The fields
++   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
++   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
++   value depends on the compression method), inflateInit determines the
++   compression method from the zlib header and allocates all data structures
++   accordingly; otherwise the allocation will be deferred to the first call of
++   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
++   use default allocation functions.
++
++     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
++   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
++   version assumed by the caller.  msg is set to null if there is no error
++   message. inflateInit does not perform any decompression apart from reading
++   the zlib header if present: this will be done by inflate().  (So next_in and
++   avail_in may be modified, but next_out and avail_out are unchanged.)
++*/
++
++
++ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
++/*
++    inflate decompresses as much data as possible, and stops when the input
++  buffer becomes empty or the output buffer becomes full. It may some
++  introduce some output latency (reading input without producing any output)
++  except when forced to flush.
++
++  The detailed semantics are as follows. inflate performs one or both of the
++  following actions:
++
++  - Decompress more input starting at next_in and update next_in and avail_in
++    accordingly. If not all input can be processed (because there is not
++    enough room in the output buffer), next_in is updated and processing
++    will resume at this point for the next call of inflate().
++
++  - Provide more output starting at next_out and update next_out and avail_out
++    accordingly.  inflate() provides as much output as possible, until there
++    is no more input data or no more space in the output buffer (see below
++    about the flush parameter).
++
++  Before the call of inflate(), the application should ensure that at least
++  one of the actions is possible, by providing more input and/or consuming
++  more output, and updating the next_* and avail_* values accordingly.
++  The application can consume the uncompressed output when it wants, for
++  example when the output buffer is full (avail_out == 0), or after each
++  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
++  must be called again after making room in the output buffer because there
++  might be more output pending.
++
++    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
++  output as possible to the output buffer. The flushing behavior of inflate is
++  not specified for values of the flush parameter other than Z_SYNC_FLUSH
++  and Z_FINISH, but the current implementation actually flushes as much output
++  as possible anyway.
++
++    inflate() should normally be called until it returns Z_STREAM_END or an
++  error. However if all decompression is to be performed in a single step
++  (a single call of inflate), the parameter flush should be set to
++  Z_FINISH. In this case all pending input is processed and all pending
++  output is flushed; avail_out must be large enough to hold all the
++  uncompressed data. (The size of the uncompressed data may have been saved
++  by the compressor for this purpose.) The next operation on this stream must
++  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
++  is never required, but can be used to inform inflate that a faster routine
++  may be used for the single inflate() call.
++
++     If a preset dictionary is needed at this point (see inflateSetDictionary
++  below), inflate sets strm-adler to the adler32 checksum of the
++  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
++  it sets strm->adler to the adler32 checksum of all output produced
++  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
++  an error code as described below. At the end of the stream, inflate()
++  checks that its computed adler32 checksum is equal to that saved by the
++  compressor and returns Z_STREAM_END only if the checksum is correct.
++
++    inflate() returns Z_OK if some progress has been made (more input processed
++  or more output produced), Z_STREAM_END if the end of the compressed data has
++  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
++  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
++  corrupted (input stream not conforming to the zlib format or incorrect
++  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
++  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
++  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
++  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
++  case, the application may then call inflateSync to look for a good
++  compression block.
++*/
++
++
++ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
++/*
++     All dynamically allocated data structures for this stream are freed.
++   This function discards any unprocessed input and does not flush any
++   pending output.
++
++     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
++   was inconsistent. In the error case, msg may be set but then points to a
++   static string (which must not be deallocated).
++*/
++
++                        /* Advanced functions */
++
++/*
++    The following functions are needed only in some special applications.
++*/
++
++/*   
++ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
++                                     int  level,
++                                     int  method,
++                                     int  windowBits,
++                                     int  memLevel,
++                                     int  strategy));
++
++     This is another version of deflateInit with more compression options. The
++   fields next_in, zalloc, zfree and opaque must be initialized before by
++   the caller.
++
++     The method parameter is the compression method. It must be Z_DEFLATED in
++   this version of the library.
++
++     The windowBits parameter is the base two logarithm of the window size
++   (the size of the history buffer).  It should be in the range 8..15 for this
++   version of the library. Larger values of this parameter result in better
++   compression at the expense of memory usage. The default value is 15 if
++   deflateInit is used instead.
++
++     The memLevel parameter specifies how much memory should be allocated
++   for the internal compression state. memLevel=1 uses minimum memory but
++   is slow and reduces compression ratio; memLevel=9 uses maximum memory
++   for optimal speed. The default value is 8. See zconf.h for total memory
++   usage as a function of windowBits and memLevel.
++
++     The strategy parameter is used to tune the compression algorithm. Use the
++   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
++   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
++   string match).  Filtered data consists mostly of small values with a
++   somewhat random distribution. In this case, the compression algorithm is
++   tuned to compress them better. The effect of Z_FILTERED is to force more
++   Huffman coding and less string matching; it is somewhat intermediate
++   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
++   the compression ratio but not the correctness of the compressed output even
++   if it is not set appropriately.
++
++      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
++   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
++   method). msg is set to null if there is no error message.  deflateInit2 does
++   not perform any compression: this will be done by deflate().
++*/
++                            
++ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
++                                             const Bytef *dictionary,
++                                             uInt  dictLength));
++/*
++     Initializes the compression dictionary from the given byte sequence
++   without producing any compressed output. This function must be called
++   immediately after deflateInit, deflateInit2 or deflateReset, before any
++   call of deflate. The compressor and decompressor must use exactly the same
++   dictionary (see inflateSetDictionary).
++
++     The dictionary should consist of strings (byte sequences) that are likely
++   to be encountered later in the data to be compressed, with the most commonly
++   used strings preferably put towards the end of the dictionary. Using a
++   dictionary is most useful when the data to be compressed is short and can be
++   predicted with good accuracy; the data can then be compressed better than
++   with the default empty dictionary.
++
++     Depending on the size of the compression data structures selected by
++   deflateInit or deflateInit2, a part of the dictionary may in effect be
++   discarded, for example if the dictionary is larger than the window size in
++   deflate or deflate2. Thus the strings most likely to be useful should be
++   put at the end of the dictionary, not at the front.
++
++     Upon return of this function, strm->adler is set to the Adler32 value
++   of the dictionary; the decompressor may later use this value to determine
++   which dictionary has been used by the compressor. (The Adler32 value
++   applies to the whole dictionary even if only a subset of the dictionary is
++   actually used by the compressor.)
++
++     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
++   parameter is invalid (such as NULL dictionary) or the stream state is
++   inconsistent (for example if deflate has already been called for this stream
++   or if the compression method is bsort). deflateSetDictionary does not
++   perform any compression: this will be done by deflate().
++*/
++
++ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
++                                    z_streamp source));
++/*
++     Sets the destination stream as a complete copy of the source stream.
++
++     This function can be useful when several compression strategies will be
++   tried, for example when there are several ways of pre-processing the input
++   data with a filter. The streams that will be discarded should then be freed
++   by calling deflateEnd.  Note that deflateCopy duplicates the internal
++   compression state which can be quite large, so this strategy is slow and
++   can consume lots of memory.
++
++     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
++   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
++   (such as zalloc being NULL). msg is left unchanged in both source and
++   destination.
++*/
++
++ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
++/*
++     This function is equivalent to deflateEnd followed by deflateInit,
++   but does not free and reallocate all the internal compression state.
++   The stream will keep the same compression level and any other attributes
++   that may have been set by deflateInit2.
++
++      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
++   stream state was inconsistent (such as zalloc or state being NULL).
++*/
++
++ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
++                                    int level,
++                                    int strategy));
++/*
++     Dynamically update the compression level and compression strategy.  The
++   interpretation of level and strategy is as in deflateInit2.  This can be
++   used to switch between compression and straight copy of the input data, or
++   to switch to a different kind of input data requiring a different
++   strategy. If the compression level is changed, the input available so far
++   is compressed with the old level (and may be flushed); the new level will
++   take effect only at the next call of deflate().
++
++     Before the call of deflateParams, the stream state must be set as for
++   a call of deflate(), since the currently available input may have to
++   be compressed and flushed. In particular, strm->avail_out must be non-zero.
++
++     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
++   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
++   if strm->avail_out was zero.
++*/
++
++/*   
++ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
++                                     int  windowBits));
++
++     This is another version of inflateInit with an extra parameter. The
++   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
++   before by the caller.
++
++     The windowBits parameter is the base two logarithm of the maximum window
++   size (the size of the history buffer).  It should be in the range 8..15 for
++   this version of the library. The default value is 15 if inflateInit is used
++   instead. If a compressed stream with a larger window size is given as
++   input, inflate() will return with the error code Z_DATA_ERROR instead of
++   trying to allocate a larger window.
++
++      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
++   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
++   memLevel). msg is set to null if there is no error message.  inflateInit2
++   does not perform any decompression apart from reading the zlib header if
++   present: this will be done by inflate(). (So next_in and avail_in may be
++   modified, but next_out and avail_out are unchanged.)
++*/
++
++ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
++                                             const Bytef *dictionary,
++                                             uInt  dictLength));
++/*
++     Initializes the decompression dictionary from the given uncompressed byte
++   sequence. This function must be called immediately after a call of inflate
++   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
++   can be determined from the Adler32 value returned by this call of
++   inflate. The compressor and decompressor must use exactly the same
++   dictionary (see deflateSetDictionary).
++
++     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
++   parameter is invalid (such as NULL dictionary) or the stream state is
++   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
++   expected one (incorrect Adler32 value). inflateSetDictionary does not
++   perform any decompression: this will be done by subsequent calls of
++   inflate().
++*/
++
++ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
++/* 
++    Skips invalid compressed data until a full flush point (see above the
++  description of deflate with Z_FULL_FLUSH) can be found, or until all
++  available input is skipped. No output is provided.
++
++    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
++  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
++  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
++  case, the application may save the current current value of total_in which
++  indicates where valid compressed data was found. In the error case, the
++  application may repeatedly call inflateSync, providing more input each time,
++  until success or end of the input data.
++*/
++
++ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
++/*
++     This function is equivalent to inflateEnd followed by inflateInit,
++   but does not free and reallocate all the internal decompression state.
++   The stream will keep attributes that may have been set by inflateInit2.
++
++      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
++   stream state was inconsistent (such as zalloc or state being NULL).
++*/
++
++
++                        /* utility functions */
++
++/*
++     The following utility functions are implemented on top of the
++   basic stream-oriented functions. To simplify the interface, some
++   default options are assumed (compression level and memory usage,
++   standard memory allocation functions). The source code of these
++   utility functions can easily be modified if you need special options.
++*/
++
++ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
++                                 const Bytef *source, uLong sourceLen));
++/*
++     Compresses the source buffer into the destination buffer.  sourceLen is
++   the byte length of the source buffer. Upon entry, destLen is the total
++   size of the destination buffer, which must be at least 0.1% larger than
++   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
++   compressed buffer.
++     This function can be used to compress a whole file at once if the
++   input file is mmap'ed.
++     compress returns Z_OK if success, Z_MEM_ERROR if there was not
++   enough memory, Z_BUF_ERROR if there was not enough room in the output
++   buffer.
++*/
++
++ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
++                                  const Bytef *source, uLong sourceLen,
++                                  int level));
++/*
++     Compresses the source buffer into the destination buffer. The level
++   parameter has the same meaning as in deflateInit.  sourceLen is the byte
++   length of the source buffer. Upon entry, destLen is the total size of the
++   destination buffer, which must be at least 0.1% larger than sourceLen plus
++   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
++
++     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
++   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
++   Z_STREAM_ERROR if the level parameter is invalid.
++*/
++
++ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
++                                   const Bytef *source, uLong sourceLen));
++/*
++     Decompresses the source buffer into the destination buffer.  sourceLen is
++   the byte length of the source buffer. Upon entry, destLen is the total
++   size of the destination buffer, which must be large enough to hold the
++   entire uncompressed data. (The size of the uncompressed data must have
++   been saved previously by the compressor and transmitted to the decompressor
++   by some mechanism outside the scope of this compression library.)
++   Upon exit, destLen is the actual size of the compressed buffer.
++     This function can be used to decompress a whole file at once if the
++   input file is mmap'ed.
++
++     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
++   enough memory, Z_BUF_ERROR if there was not enough room in the output
++   buffer, or Z_DATA_ERROR if the input data was corrupted.
++*/
++
++
++typedef voidp gzFile;
++
++ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
++/*
++     Opens a gzip (.gz) file for reading or writing. The mode parameter
++   is as in fopen ("rb" or "wb") but can also include a compression level
++   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
++   Huffman only compression as in "wb1h". (See the description
++   of deflateInit2 for more information about the strategy parameter.)
++
++     gzopen can be used to read a file which is not in gzip format; in this
++   case gzread will directly read from the file without decompression.
++
++     gzopen returns NULL if the file could not be opened or if there was
++   insufficient memory to allocate the (de)compression state; errno
++   can be checked to distinguish the two cases (if errno is zero, the
++   zlib error is Z_MEM_ERROR).  */
++
++ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
++/*
++     gzdopen() associates a gzFile with the file descriptor fd.  File
++   descriptors are obtained from calls like open, dup, creat, pipe or
++   fileno (in the file has been previously opened with fopen).
++   The mode parameter is as in gzopen.
++     The next call of gzclose on the returned gzFile will also close the
++   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
++   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
++     gzdopen returns NULL if there was insufficient memory to allocate
++   the (de)compression state.
++*/
++
++ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
++/*
++     Dynamically update the compression level or strategy. See the description
++   of deflateInit2 for the meaning of these parameters.
++     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
++   opened for writing.
++*/
++
++ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
++/*
++     Reads the given number of uncompressed bytes from the compressed file.
++   If the input file was not in gzip format, gzread copies the given number
++   of bytes into the buffer.
++     gzread returns the number of uncompressed bytes actually read (0 for
++   end of file, -1 for error). */
++
++ZEXTERN int ZEXPORT    gzwrite OF((gzFile file, 
++                                 const voidp buf, unsigned len));
++/*
++     Writes the given number of uncompressed bytes into the compressed file.
++   gzwrite returns the number of uncompressed bytes actually written
++   (0 in case of error).
++*/
++
++ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
++/*
++     Converts, formats, and writes the args to the compressed file under
++   control of the format string, as in fprintf. gzprintf returns the number of
++   uncompressed bytes actually written (0 in case of error).
++*/
++
++ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
++/*
++      Writes the given null-terminated string to the compressed file, excluding
++   the terminating null character.
++      gzputs returns the number of characters written, or -1 in case of error.
++*/
++
++ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
++/*
++      Reads bytes from the compressed file until len-1 characters are read, or
++   a newline character is read and transferred to buf, or an end-of-file
++   condition is encountered.  The string is then terminated with a null
++   character.
++      gzgets returns buf, or Z_NULL in case of error.
++*/
++
++ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
++/*
++      Writes c, converted to an unsigned char, into the compressed file.
++   gzputc returns the value that was written, or -1 in case of error.
++*/
++
++ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
++/*
++      Reads one byte from the compressed file. gzgetc returns this byte
++   or -1 in case of end of file or error.
++*/
++
++ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
++/*
++     Flushes all pending output into the compressed file. The parameter
++   flush is as in the deflate() function. The return value is the zlib
++   error number (see function gzerror below). gzflush returns Z_OK if
++   the flush parameter is Z_FINISH and all output could be flushed.
++     gzflush should be called only when strictly necessary because it can
++   degrade compression.
++*/
++
++ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
++                                    z_off_t offset, int whence));
++/* 
++      Sets the starting position for the next gzread or gzwrite on the
++   given compressed file. The offset represents a number of bytes in the
++   uncompressed data stream. The whence parameter is defined as in lseek(2);
++   the value SEEK_END is not supported.
++     If the file is opened for reading, this function is emulated but can be
++   extremely slow. If the file is opened for writing, only forward seeks are
++   supported; gzseek then compresses a sequence of zeroes up to the new
++   starting position.
++
++      gzseek returns the resulting offset location as measured in bytes from
++   the beginning of the uncompressed stream, or -1 in case of error, in
++   particular if the file is opened for writing and the new starting position
++   would be before the current position.
++*/
++
++ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
++/*
++     Rewinds the given file. This function is supported only for reading.
++
++   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
++*/
++
++ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
++/*
++     Returns the starting position for the next gzread or gzwrite on the
++   given compressed file. This position represents a number of bytes in the
++   uncompressed data stream.
++
++   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
++*/
++
++ZEXTERN int ZEXPORT gzeof OF((gzFile file));
++/*
++     Returns 1 when EOF has previously been detected reading the given
++   input stream, otherwise zero.
++*/
++
++ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
++/*
++     Flushes all pending output if necessary, closes the compressed file
++   and deallocates all the (de)compression state. The return value is the zlib
++   error number (see function gzerror below).
++*/
++
++ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
++/*
++     Returns the error message for the last error which occurred on the
++   given compressed file. errnum is set to zlib error number. If an
++   error occurred in the file system and not in the compression library,
++   errnum is set to Z_ERRNO and the application may consult errno
++   to get the exact error code.
++*/
++
++                        /* checksum functions */
++
++/*
++     These functions are not related to compression but are exported
++   anyway because they might be useful in applications using the
++   compression library.
++*/
++
++ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
++
++/*
++     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
++   return the updated checksum. If buf is NULL, this function returns
++   the required initial value for the checksum.
++   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
++   much faster. Usage example:
++
++     uLong adler = adler32(0L, Z_NULL, 0);
++
++     while (read_buffer(buffer, length) != EOF) {
++       adler = adler32(adler, buffer, length);
++     }
++     if (adler != original_adler) error();
++*/
++
++ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
++/*
++     Update a running crc with the bytes buf[0..len-1] and return the updated
++   crc. If buf is NULL, this function returns the required initial value
++   for the crc. Pre- and post-conditioning (one's complement) is performed
++   within this function so it shouldn't be done by the application.
++   Usage example:
++
++     uLong crc = crc32(0L, Z_NULL, 0);
++
++     while (read_buffer(buffer, length) != EOF) {
++       crc = crc32(crc, buffer, length);
++     }
++     if (crc != original_crc) error();
++*/
++
++
++                        /* various hacks, don't look :) */
++
++/* deflateInit and inflateInit are macros to allow checking the zlib version
++ * and the compiler's view of z_stream:
++ */
++ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
++                                     const char *version, int stream_size));
++ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
++                                     const char *version, int stream_size));
++ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
++                                      int windowBits, int memLevel,
++                                      int strategy, const char *version,
++                                      int stream_size));
++ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
++                                      const char *version, int stream_size));
++#define deflateInit(strm, level) \
++        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
++#define inflateInit(strm) \
++        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
++#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
++        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
++                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
++#define inflateInit2(strm, windowBits) \
++        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
++
++
++#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
++    struct internal_state {int dummy;}; /* hack for buggy compilers */
++#endif
++
++ZEXTERN const char   * ZEXPORT zError           OF((int err));
++ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
++ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _ZLIB_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/include/zlib/zutil.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,225 @@
++/* zutil.h -- internal interface and configuration of the compression library
++ * Copyright (C) 1995-2002 Jean-loup Gailly.
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++/* @(#) $Id: zutil.h,v 1.4 2002/04/24 07:36:48 mcr Exp $ */
++
++#ifndef _Z_UTIL_H
++#define _Z_UTIL_H
++
++#include "zlib.h"
++
++#include <linux/string.h>
++#define HAVE_MEMCPY
++
++#if 0 // #ifdef STDC
++#  include <stddef.h>
++#  include <string.h>
++#  include <stdlib.h>
++#endif
++#ifndef __KERNEL__
++#ifdef NO_ERRNO_H
++    extern int errno;
++#else
++#   include <errno.h>
++#endif
++#endif
++
++#ifndef local
++#  define local static
++#endif
++/* compile with -Dlocal if your debugger can't find static symbols */
++
++typedef unsigned char  uch;
++typedef uch FAR uchf;
++typedef unsigned short ush;
++typedef ush FAR ushf;
++typedef unsigned long  ulg;
++
++extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
++/* (size given to avoid silly warnings with Visual C++) */
++
++#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
++
++#define ERR_RETURN(strm,err) \
++  return (strm->msg = ERR_MSG(err), (err))
++/* To be used only when the state is known to be valid */
++
++        /* common constants */
++
++#ifndef DEF_WBITS
++#  define DEF_WBITS MAX_WBITS
++#endif
++/* default windowBits for decompression. MAX_WBITS is for compression only */
++
++#if MAX_MEM_LEVEL >= 8
++#  define DEF_MEM_LEVEL 8
++#else
++#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
++#endif
++/* default memLevel */
++
++#define STORED_BLOCK 0
++#define STATIC_TREES 1
++#define DYN_TREES    2
++/* The three kinds of block type */
++
++#define MIN_MATCH  3
++#define MAX_MATCH  258
++/* The minimum and maximum match lengths */
++
++#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
++
++        /* target dependencies */
++
++#ifdef MSDOS
++#  define OS_CODE  0x00
++#  if defined(__TURBOC__) || defined(__BORLANDC__)
++#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
++       /* Allow compilation with ANSI keywords only enabled */
++       void _Cdecl farfree( void *block );
++       void *_Cdecl farmalloc( unsigned long nbytes );
++#    else
++#     include <alloc.h>
++#    endif
++#  else /* MSC or DJGPP */
++#    include <malloc.h>
++#  endif
++#endif
++
++#ifdef OS2
++#  define OS_CODE  0x06
++#endif
++
++#ifdef WIN32 /* Window 95 & Windows NT */
++#  define OS_CODE  0x0b
++#endif
++
++#if defined(VAXC) || defined(VMS)
++#  define OS_CODE  0x02
++#  define F_OPEN(name, mode) \
++     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
++#endif
++
++#ifdef AMIGA
++#  define OS_CODE  0x01
++#endif
++
++#if defined(ATARI) || defined(atarist)
++#  define OS_CODE  0x05
++#endif
++
++#if defined(MACOS) || defined(TARGET_OS_MAC)
++#  define OS_CODE  0x07
++#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
++#    include <unix.h> /* for fdopen */
++#  else
++#    ifndef fdopen
++#      define fdopen(fd,mode) NULL /* No fdopen() */
++#    endif
++#  endif
++#endif
++
++#ifdef __50SERIES /* Prime/PRIMOS */
++#  define OS_CODE  0x0F
++#endif
++
++#ifdef TOPS20
++#  define OS_CODE  0x0a
++#endif
++
++#if defined(_BEOS_) || defined(RISCOS)
++#  define fdopen(fd,mode) NULL /* No fdopen() */
++#endif
++
++#if (defined(_MSC_VER) && (_MSC_VER > 600))
++#  define fdopen(fd,type)  _fdopen(fd,type)
++#endif
++
++
++        /* Common defaults */
++
++#ifndef OS_CODE
++#  define OS_CODE  0x03  /* assume Unix */
++#endif
++
++#ifndef F_OPEN
++#  define F_OPEN(name, mode) fopen((name), (mode))
++#endif
++
++         /* functions */
++
++#ifdef HAVE_STRERROR
++   extern char *strerror OF((int));
++#  define zstrerror(errnum) strerror(errnum)
++#else
++#  define zstrerror(errnum) ""
++#endif
++
++#if defined(pyr)
++#  define NO_MEMCPY
++#endif
++#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
++ /* Use our own functions for small and medium model with MSC <= 5.0.
++  * You may have to use the same strategy for Borland C (untested).
++  * The __SC__ check is for Symantec.
++  */
++#  define NO_MEMCPY
++#endif
++#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
++#  define HAVE_MEMCPY
++#endif
++#ifdef HAVE_MEMCPY
++#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
++#    define zmemcpy _fmemcpy
++#    define zmemcmp _fmemcmp
++#    define zmemzero(dest, len) _fmemset(dest, 0, len)
++#  else
++#    define zmemcpy memcpy
++#    define zmemcmp memcmp
++#    define zmemzero(dest, len) memset(dest, 0, len)
++#  endif
++#else
++   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
++   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
++   extern void zmemzero OF((Bytef* dest, uInt len));
++#endif
++
++/* Diagnostic functions */
++#ifdef DEBUG
++#  include <stdio.h>
++   extern int z_verbose;
++   extern void z_error    OF((char *m));
++#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
++#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
++#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
++#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
++#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
++#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
++#else
++#  define Assert(cond,msg)
++#  define Trace(x)
++#  define Tracev(x)
++#  define Tracevv(x)
++#  define Tracec(c,x)
++#  define Tracecv(c,x)
++#endif
++
++
++typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
++                                     uInt len));
++voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
++void   zcfree  OF((voidpf opaque, voidpf ptr));
++
++#define ZALLOC(strm, items, size) \
++           (*((strm)->zalloc))((strm)->opaque, (items), (size))
++#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
++#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
++
++#endif /* _Z_UTIL_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/lib/libfreeswan/Makefile.objs     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,21 @@
++obj-y += satot.o
++obj-y += addrtot.o
++obj-y += ultot.o 
++obj-y += addrtypeof.o
++obj-y += anyaddr.o
++obj-y += initaddr.o
++obj-y += ultoa.o 
++obj-y += addrtoa.o 
++obj-y += subnettoa.o 
++obj-y += subnetof.o 
++obj-y += goodmask.o 
++obj-y += datatot.o 
++obj-y += rangetoa.o 
++obj-y += prng.o 
++obj-y += pfkey_v2_parse.o 
++obj-y += pfkey_v2_build.o 
++obj-y += pfkey_v2_debug.o 
++obj-y += pfkey_v2_ext_bits.o 
++
++#version.c:   ${LIBFREESWANDIR}/version.in.c ${OPENSWANSRCDIR}/Makefile.ver
++#     sed '/"/s/xxx/$(IPSECVERSION)/' ${LIBFREESWANDIR}/version.in.c >$@
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/lib/zlib/Makefile     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,118 @@
++# (kernel) Makefile for IPCOMP zlib deflate code
++# Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++# Copyright (C) 2000  Svenning Soerensen
++# 
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++# 
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# RCSID $Id: Makefile,v 1.9 2002/04/24 07:55:32 mcr Exp $
++#
++
++
++
++include ../Makefile.inc
++
++
++
++ifndef TOPDIR
++TOPDIR  := /usr/src/linux
++endif
++
++
++L_TARGET := zlib.a
++
++obj-y :=
++
++include Makefile.objs
++
++EXTRA_CFLAGS += $(KLIPSCOMPILE)
++
++EXTRA_CFLAGS += -Wall 
++#EXTRA_CFLAGS += -Wconversion 
++#EXTRA_CFLAGS += -Wmissing-prototypes 
++EXTRA_CFLAGS += -Wpointer-arith 
++#EXTRA_CFLAGS += -Wcast-qual 
++#EXTRA_CFLAGS += -Wmissing-declarations 
++EXTRA_CFLAGS += -Wstrict-prototypes
++#EXTRA_CFLAGS += -pedantic
++#EXTRA_CFLAGS += -W
++#EXTRA_CFLAGS += -Wwrite-strings 
++EXTRA_CFLAGS += -Wbad-function-cast 
++EXTRA_CFLAGS += -DIPCOMP_PREFIX
++
++.S.o:
++      $(CC) -D__ASSEMBLY__ -DNO_UNDERLINE -traditional -c $< -o $*.o
++
++asm-obj-$(CONFIG_M586)                += match586.o
++asm-obj-$(CONFIG_M586TSC)     += match586.o
++asm-obj-$(CONFIG_M586MMX)     += match586.o
++asm-obj-$(CONFIG_M686)                += match686.o
++asm-obj-$(CONFIG_MPENTIUMIII) += match686.o
++asm-obj-$(CONFIG_MPENTIUM4)   += match686.o
++asm-obj-$(CONFIG_MK6)         += match586.o
++asm-obj-$(CONFIG_MK7)         += match686.o
++asm-obj-$(CONFIG_MCRUSOE)     += match586.o
++asm-obj-$(CONFIG_MWINCHIPC6)  += match586.o
++asm-obj-$(CONFIG_MWINCHIP2)   += match686.o
++asm-obj-$(CONFIG_MWINCHIP3D)  += match686.o
++
++obj-y += $(asm-obj-y)
++ifneq ($(strip $(asm-obj-y)),)
++  EXTRA_CFLAGS += -DASMV
++endif
++
++active-objs     := $(sort $(obj-y) $(obj-m))
++L_OBJS          := $(obj-y)
++M_OBJS          := $(obj-m)
++MIX_OBJS        := $(filter $(export-objs), $(active-objs))
++
++include $(TOPDIR)/Rules.make
++
++$(obj-y) :  $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h
++
++
++clean:
++      -rm -f *.o *.a
++
++checkprograms:
++programs: $(L_TARGET)
++
++#
++# $Log: Makefile,v $
++# Revision 1.9  2002/04/24 07:55:32  mcr
++#     #include patches and Makefiles for post-reorg compilation.
++#
++# Revision 1.8  2002/04/24 07:36:44  mcr
++# Moved from ./zlib/Makefile,v
++#
++# Revision 1.7  2002/03/27 23:34:35  mcr
++#     added programs: target
++#
++# Revision 1.6  2001/12/05 20:19:08  henry
++# use new compile-control variable
++#
++# Revision 1.5  2001/11/27 16:38:08  mcr
++#     added new "checkprograms" target to deal with programs that
++#     are required for "make check", but that may not be ready to
++#     build for every user due to external dependancies.
++#
++# Revision 1.4  2001/10/24 14:46:24  henry
++# Makefile.inc
++#
++# Revision 1.3  2001/04/21 23:05:24  rgb
++# Update asm directives for 2.4 style makefiles.
++#
++# Revision 1.2  2001/01/29 22:22:00  rgb
++# Convert to 2.4 new style with back compat.
++#
++# Revision 1.1.1.1  2000/09/29 18:51:33  rgb
++# zlib_beginnings
++#
++#
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/lib/zlib/Makefile.objs     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,27 @@
++obj-$(CONFIG_IPSEC_IPCOMP) += adler32.o
++obj-$(CONFIG_IPSEC_IPCOMP) += deflate.o
++obj-$(CONFIG_IPSEC_IPCOMP) += infblock.o
++obj-$(CONFIG_IPSEC_IPCOMP) += infcodes.o
++obj-$(CONFIG_IPSEC_IPCOMP) += inffast.o
++obj-$(CONFIG_IPSEC_IPCOMP) += inflate.o
++obj-$(CONFIG_IPSEC_IPCOMP) += inftrees.o
++obj-$(CONFIG_IPSEC_IPCOMP) += infutil.o
++obj-$(CONFIG_IPSEC_IPCOMP) += trees.o
++obj-$(CONFIG_IPSEC_IPCOMP) += zutil.o
++
++asm-obj-$(CONFIG_M586)          += ${LIBZLIBSRCDIR}/match586.o
++asm-obj-$(CONFIG_M586TSC)       += ${LIBZLIBSRCDIR}/match586.o
++asm-obj-$(CONFIG_M586MMX)       += ${LIBZLIBSRCDIR}/match586.o
++asm-obj-$(CONFIG_M686)          += ${LIBZLIBSRCDIR}/match686.o
++asm-obj-$(CONFIG_MPENTIUMIII)   += ${LIBZLIBSRCDIR}/match686.o
++asm-obj-$(CONFIG_MPENTIUM4)     += ${LIBZLIBSRCDIR}/match686.o
++asm-obj-$(CONFIG_MK6)           += ${LIBZLIBSRCDIR}/match586.o
++asm-obj-$(CONFIG_MK7)           += ${LIBZLIBSRCDIR}/match686.o
++asm-obj-$(CONFIG_MCRUSOE)       += ${LIBZLIBSRCDIR}/match586.o
++asm-obj-$(CONFIG_MWINCHIPC6)    += ${LIBZLIBSRCDIR}/match586.o
++asm-obj-$(CONFIG_MWINCHIP2)     += ${LIBZLIBSRCDIR}/match686.o
++asm-obj-$(CONFIG_MWINCHIP3D)    += ${LIBZLIBSRCDIR}/match686.o
++
++EXTRA_CFLAGS += -DIPCOMP_PREFIX
++
++
+--- swan26/net/Kconfig.preipsec        2005-09-01 18:15:19.000000000 -0400
++++ swan26/net/Kconfig 2005-09-03 16:51:17.000000000 -0400
+@@ -215,2 +215,6 @@
++if INET
++source "net/ipsec/Kconfig"
++endif # if INET
++
+ endif   # if NET
+--- /distros/kernel/linux-2.6.3-rc4/net/Makefile       Mon Feb 16 21:22:12 2004
++++ ref26/net/Makefile Thu Feb 19 21:02:25 2004
+@@ -42,3 +42,6 @@
+ ifeq ($(CONFIG_NET),y)
+ obj-$(CONFIG_SYSCTL)          += sysctl_net.o
+ endif
++
++obj-$(CONFIG_KLIPS)             += ipsec/
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/Kconfig     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,161 @@
++#
++# IPSEC configuration
++# Copyright (C) 2004 Michael Richardson <mcr@freeswan.org>
++# 
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++# 
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# RCSID $Id: Kconfig,v 1.6.2.2 2006/10/11 18:14:33 paul Exp $
++
++config KLIPS
++      tristate "Openswan IPsec (KLIPS26)"
++      default n
++      help
++        KLIPS is the Openswan (www.openswan.org) Kernel Level IP Security
++        system. It is extensively tested, and has interoperated with
++        many other systems. 
++          It provides "ipsecX" devices on which one can do firewalling.
++          The userland, is compatible with both KLIPS and 26sec.
++
++menu "KLIPS options"
++      depends on KLIPS
++
++config KLIPS_ESP
++      bool 'Encapsulating Security Payload - ESP ("VPN")'
++      default y
++      help
++         This option provides support for the IPSEC Encapsulation Security
++         Payload (IP protocol 50) which provides packet layer content
++           hiding, and content authentication.
++         It is recommended to enable this.  RFC2406
++
++config KLIPS_AH
++      bool 'Authentication Header - AH'
++      default n
++      help
++           This option provides support for the IPSEC Authentication Header
++           (IP protocol 51) which provides packet layer sender and content
++           authentication. It does not provide for confidentiality.
++         It is not recommended to enable this.  RFC2402
++
++config KLIPS_AUTH_HMAC_MD5
++      bool 'HMAC-MD5 authentication algorithm' 
++      default y
++      help
++           The HMAC-MD5 algorithm is used by ESP (and AH) to guarantee packet
++         integrity. There is little reason not to include it.
++
++config KLIPS_AUTH_HMAC_SHA1
++      bool 'HMAC-SHA1 authentication algorithm' 
++      default y
++      help
++           The HMAC-SHA1 algorithm is used by ESP (and AH) to guarantee packet
++         integrity. SHA1 is a little slower than MD5, but is said to be 
++         a bit more secure. There is little reason not to include it.
++
++config KLIPS_ENC_CRYPTOAPI
++      bool 'CryptoAPI algorithm interface'
++      default n
++      help
++         Enable the algorithm interface to make all CryptoAPI 1.0 algorithms
++         available to KLIPS.
++
++config KLIPS_ENC_1DES
++      bool 'Include 1DES with CryptoAPI'
++      default n
++      depends on KLIPS_ENC_CRYPTOAPI
++      help
++         The CryptoAPI interface does not include support for every algorithm
++         yet, and one that it doesn't support by default is the VERY WEAK
++         1DES. Select this if you are terminally stupid.
++      
++config KLIPS_ENC_3DES
++      bool '3DES encryption algorithm'
++      default y
++      help
++           The 3DES algorithm is used by ESP to provide for packet privacy.
++         3DES is 3-repeats of the DES algorithm. 3DES is widely supported,
++         and analyzed and is considered very secure. 1DES is not supported.
++
++config KLIPS_ENC_AES
++      bool 'AES encryption algorithm'
++      default y
++      help
++           The AES algorithm is used by ESP to provide for packet privacy.
++         AES the NIST replacement for DES. AES is being widely analyzed,
++           and is very fast.
++
++config KLIPS_ENC_NULL
++      bool 'NULL NON-encryption algorithm'
++      default n
++      help
++         NON encryption algo , maybe useful for ESP auth only scenarios
++         (eg: with NAT-T), see RFC 2410.
++
++config KLIPS_IPCOMP
++      bool 'IP compression'
++      default y
++      help
++           The IPcomp protocol is used prior to ESP to make the packet
++         smaller. Once encrypted, compression will fail, so any link
++         layer efforts (e.g. PPP) will not work. 
++
++config KLIPS_DEBUG
++      bool 'IPsec debugging'
++      default y 
++      help
++           KLIPS includes a lot of debugging code. Unless there is a real
++         tangible benefit to removing this code, it should be left in place.
++         Debugging connections without access to kernel level debugging is
++         essentially impossible. Leave this on.
++
++endmenu
++
++#
++#
++# $Log: Kconfig,v $
++# Revision 1.6.2.2  2006/10/11 18:14:33  paul
++# Add JuanJo Ciarlante's ESP_NULL patches for KLIPS, but leave it disabled
++# per default.
++#
++# Revision 1.6.2.1  2006/04/20 16:33:06  mcr
++# remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++# Fix in-kernel module compilation. Sub-makefiles do not work.
++#
++# Revision 1.6  2005/05/18 20:55:27  mcr
++#     default cryptoapi to n.
++#
++# Revision 1.5  2005/05/11 01:23:25  mcr
++#     added 1DES option to cryptoapi.
++#
++# Revision 1.4  2005/04/29 05:29:54  mcr
++#     add option to include cryptoapi algorithms.
++#
++# Revision 1.3  2004/08/17 03:27:23  mcr
++#     klips 2.6 edits.
++#
++# Revision 1.2  2004/08/14 03:27:39  mcr
++#     2.6 kernel build/configuration files.
++#
++# Revision 1.1  2004/08/14 02:47:55  mcr
++#     kernel build/config patches
++#
++# Revision 1.3  2004/02/24 17:17:04  mcr
++#     s/CONFIG_IPSEC/CONFIG_KLIPS/ as 26sec uses "CONFIG_IPSEC" to
++#     turn it on/off as well.
++#
++# Revision 1.2  2004/02/22 06:50:42  mcr
++#     kernel 2.6 port - merged with 2.4 code.
++#
++# Revision 1.1.2.1  2004/02/20 02:07:53  mcr
++#     module configuration for KLIPS 2.6
++#
++#
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/Makefile     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,195 @@
++# Makefile for KLIPS kernel code as a module    for 2.6 kernels
++#
++# Makefile for KLIPS kernel code as a module
++# Copyright (C) 1998, 1999, 2000,2001  Richard Guy Briggs.
++# Copyright (C) 2002-2004     Michael Richardson <mcr@freeswan.org>
++# 
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++# 
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# RCSID $Id: Makefile.fs2_6,v 1.8.2.2 2006/10/11 18:14:33 paul Exp $
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++
++OPENSWANSRCDIR?=.
++KLIPS_TOP?=.
++
++-include ${OPENSWANSRCDIR}/Makefile.ver
++
++base-klips-objs := 
++
++base-klips-objs+= ipsec_init.o ipsec_sa.o ipsec_radij.o radij.o
++base-klips-objs+= ipsec_life.o ipsec_proc.o
++base-klips-objs+= ipsec_tunnel.o ipsec_xmit.o ipsec_rcv.o ipsec_ipip.o
++base-klips-objs+= ipsec_snprintf.o
++base-klips-objs+= sysctl_net_ipsec.o 
++base-klips-objs+= pfkey_v2.o pfkey_v2_parser.o pfkey_v2_ext_process.o 
++base-klips-objs+= version.o
++
++base-klips-objs+= satot.o
++base-klips-objs+= addrtot.o
++base-klips-objs+= ultot.o 
++base-klips-objs+= addrtypeof.o
++base-klips-objs+= anyaddr.o
++base-klips-objs+= initaddr.o
++base-klips-objs+= ultoa.o 
++base-klips-objs+= addrtoa.o 
++base-klips-objs+= subnettoa.o 
++base-klips-objs+= subnetof.o 
++base-klips-objs+= goodmask.o 
++base-klips-objs+= datatot.o 
++base-klips-objs+= rangetoa.o 
++base-klips-objs+= prng.o 
++base-klips-objs+= pfkey_v2_parse.o 
++base-klips-objs+= pfkey_v2_build.o 
++base-klips-objs+= pfkey_v2_debug.o 
++base-klips-objs+= pfkey_v2_ext_bits.o 
++base-klips-objs+= version.o
++
++obj-${CONFIG_KLIPS} += ipsec.o
++
++ipsec-objs += ${base-klips-objs}
++
++ipsec-$(CONFIG_KLIPS_ESP)     += ipsec_esp.o
++ipsec-$(CONFIG_KLIPS_IPCOMP)  += ipsec_ipcomp.o
++ipsec-$(CONFIG_KLIPS_AUTH_HMAC_MD5)  += ipsec_md5c.o
++ipsec-$(CONFIG_KLIPS_AUTH_HMAC_SHA1) += ipsec_sha1.o
++
++# AH, if you really think you need it.
++ipsec-$(CONFIG_KLIPS_AH)   += ipsec_ah.o
++
++ipsec-y += ipsec_alg.o 
++
++# include code from DES subdir
++crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ipsec_alg_3des.o
++crypto-$(CONFIG_KLIPS_ENC_3DES) += des/cbc_enc.o
++crypto-$(CONFIG_KLIPS_ENC_3DES) += des/ecb_enc.o
++crypto-$(CONFIG_KLIPS_ENC_3DES) += des/set_key.o
++
++ifeq ($(strip ${SUBARCH}),)
++SUBARCH:=${ARCH}
++endif
++
++# the assembly version expects frame pointers, which are
++# optional in many kernel builds. If you want speed, you should
++# probably use cryptoapi code instead.
++USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER}
++ifeq (${USEASSEMBLY},i386y)
++crypto-$(CONFIG_KLIPS_ENC_3DES) += des/dx86unix.o
++else
++crypto-$(CONFIG_KLIPS_ENC_3DES) += des/des_enc.o
++endif
++
++# include code from AES subdir
++crypto-$(CONFIG_KLIPS_ENC_AES) += aes/ipsec_alg_aes.o
++crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_xcbc_mac.o
++crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes_cbc.o
++
++ifeq ($(strip ${SUBARCH}),)
++SUBARCH:=${ARCH}
++endif
++
++USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER}
++ifeq (${USEASSEMBLY},i386y)
++crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes-i586.o
++else
++crypto-$(CONFIG_KLIPS_ENC_AES) += aes/aes.o
++endif
++
++crypto-$(CONFIG_KLIPS_ENC_NULL) += null/ipsec_alg_null.o
++
++ipsec-y += ${crypto-y}
++
++ipsec-$(CONFIG_KLIPS_ENC_CRYPTOAPI) += ipsec_alg_cryptoapi.o
++
++# IPcomp stuff
++base-ipcomp-objs := ipcomp.o 
++base-ipcomp-objs += adler32.o
++base-ipcomp-objs += deflate.o
++base-ipcomp-objs += infblock.o
++base-ipcomp-objs += infcodes.o
++base-ipcomp-objs += inffast.o
++base-ipcomp-objs += inflate.o
++base-ipcomp-objs += inftrees.o
++base-ipcomp-objs += infutil.o
++base-ipcomp-objs += trees.o
++base-ipcomp-objs += zutil.o
++asm-ipcomp-obj-$(CONFIG_M586)          += match586.o
++asm-ipcomp-obj-$(CONFIG_M586TSC)       += match586.o
++asm-ipcomp-obj-$(CONFIG_M586MMX)       += match586.o
++asm-ipcomp-obj-$(CONFIG_M686)          += match686.o
++asm-ipcomp-obj-$(CONFIG_MPENTIUMIII)   += match686.o
++asm-ipcomp-obj-$(CONFIG_MPENTIUM4)     += match686.o
++asm-ipcomp-obj-$(CONFIG_MK6)           += match586.o
++asm-ipcomp-obj-$(CONFIG_MK7)           += match686.o
++asm-ipcomp-obj-$(CONFIG_MCRUSOE)       += match586.o
++asm-ipcomp-obj-$(CONFIG_MWINCHIPC6)    += match586.o
++asm-ipcomp-obj-$(CONFIG_MWINCHIP2)     += match686.o
++asm-ipcomp-obj-$(CONFIG_MWINCHIP3D)    += match686.o
++base-ipcomp-objs += ${asm-ipcomp-obj-y}
++
++ipsec-$(CONFIG_KLIPS_IPCOMP) += ${base-ipcomp-objs}
++
++EXTRA_CFLAGS += -DIPCOMP_PREFIX
++
++#
++# $Log: Makefile.fs2_6,v $
++# Revision 1.8.2.2  2006/10/11 18:14:33  paul
++# Add JuanJo Ciarlante's ESP_NULL patches for KLIPS, but leave it disabled
++# per default.
++#
++# Revision 1.8.2.1  2006/04/20 16:33:06  mcr
++# remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++# Fix in-kernel module compilation. Sub-makefiles do not work.
++#
++# Revision 1.8  2005/05/11 03:15:42  mcr
++#     adjusted makefiles to sanely build modules properly.
++#
++# Revision 1.7  2005/04/13 22:52:12  mcr
++#     moved KLIPS specific snprintf() wrapper to seperate file.
++#
++# Revision 1.6  2004/08/22 05:02:03  mcr
++#     organized symbols such that it is easier to build modules.
++#
++# Revision 1.5  2004/08/18 01:43:56  mcr
++#     adjusted makefile enumation so that it can be used by module
++#     wrapper.
++#
++# Revision 1.4  2004/08/17 03:27:23  mcr
++#     klips 2.6 edits.
++#
++# Revision 1.3  2004/08/04 16:50:13  mcr
++#     removed duplicate definition of dx86unix.o
++#
++# Revision 1.2  2004/08/03 18:21:09  mcr
++#     only set KLIPS_TOP and OPENSWANSRCDIR if not already set.
++#
++# Revision 1.1  2004/07/26 15:02:22  mcr
++#     makefile for KLIPS module for 2.6.
++#
++# Revision 1.3  2004/02/24 17:17:04  mcr
++#     s/CONFIG_IPSEC/CONFIG_KLIPS/ as 26sec uses "CONFIG_IPSEC" to
++#     turn it on/off as well.
++#
++# Revision 1.2  2004/02/22 06:50:42  mcr
++#     kernel 2.6 port - merged with 2.4 code.
++#
++# Revision 1.1.2.1  2004/02/20 02:07:53  mcr
++#     module configuration for KLIPS 2.6
++#
++#
++# Local Variables:
++# compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)"
++# End Variables:
++#
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/README-zlib     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,147 @@
++zlib 1.1.4 is a general purpose data compression library.  All the code
++is thread safe.  The data format used by the zlib library
++is described by RFCs (Request for Comments) 1950 to 1952 in the files 
++http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
++format) and rfc1952.txt (gzip format). These documents are also available in
++other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
++
++All functions of the compression library are documented in the file zlib.h
++(volunteer to write man pages welcome, contact jloup@gzip.org). A usage
++example of the library is given in the file example.c which also tests that
++the library is working correctly. Another example is given in the file
++minigzip.c. The compression library itself is composed of all source files
++except example.c and minigzip.c.
++
++To compile all files and run the test program, follow the instructions
++given at the top of Makefile. In short "make test; make install"
++should work for most machines. For Unix: "./configure; make test; make install"
++For MSDOS, use one of the special makefiles such as Makefile.msc.
++For VMS, use Make_vms.com or descrip.mms.
++
++Questions about zlib should be sent to <zlib@gzip.org>, or to
++Gilles Vollant <info@winimage.com> for the Windows DLL version.
++The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/
++Before reporting a problem, please check this site to verify that
++you have the latest version of zlib; otherwise get the latest version and
++check whether the problem still exists or not.
++
++PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html
++before asking for help.
++
++Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
++issue of  Dr. Dobb's Journal; a copy of the article is available in
++http://dogma.net/markn/articles/zlibtool/zlibtool.htm
++
++The changes made in version 1.1.4 are documented in the file ChangeLog.
++The only changes made since 1.1.3 are bug corrections:
++
++- ZFREE was repeated on same allocation on some error conditions.
++  This creates a security problem described in
++  http://www.zlib.org/advisory-2002-03-11.txt
++- Returned incorrect error (Z_MEM_ERROR) on some invalid data
++- Avoid accesses before window for invalid distances with inflate window
++  less than 32K.
++- force windowBits > 8 to avoid a bug in the encoder for a window size
++  of 256 bytes. (A complete fix will be available in 1.1.5).
++
++The beta version 1.1.5beta includes many more changes. A new official
++version 1.1.5 will be released as soon as extensive testing has been
++completed on it.
++
++
++Unsupported third party contributions are provided in directory "contrib".
++
++A Java implementation of zlib is available in the Java Development Kit
++http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
++See the zlib home page http://www.zlib.org for details.
++
++A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk>
++is in the CPAN (Comprehensive Perl Archive Network) sites
++http://www.cpan.org/modules/by-module/Compress/
++
++A Python interface to zlib written by A.M. Kuchling <amk@magnet.com>
++is available in Python 1.5 and later versions, see
++http://www.python.org/doc/lib/module-zlib.html
++
++A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com>
++is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
++
++An experimental package to read and write files in .zip format,
++written on top of zlib by Gilles Vollant <info@winimage.com>, is
++available at http://www.winimage.com/zLibDll/unzip.html
++and also in the contrib/minizip directory of zlib.
++
++
++Notes for some targets:
++
++- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
++  and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
++  The zlib DLL support was initially done by Alessandro Iacopetti and is
++  now maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL
++  home page at http://www.winimage.com/zLibDll
++
++  From Visual Basic, you can call the DLL functions which do not take
++  a structure as argument: compress, uncompress and all gz* functions.
++  See contrib/visual-basic.txt for more information, or get
++  http://www.tcfb.com/dowseware/cmp-z-it.zip
++
++- For 64-bit Irix, deflate.c must be compiled without any optimization.
++  With -O, one libpng test fails. The test works in 32 bit mode (with
++  the -n32 compiler flag). The compiler bug has been reported to SGI.
++
++- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1   
++  it works when compiled with cc.
++
++- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
++  is necessary to get gzprintf working correctly. This is done by configure.
++
++- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
++  with other compilers. Use "make test" to check your compiler.
++
++- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
++
++- For Turbo C the small model is supported only with reduced performance to
++  avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
++
++- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html
++  Per Harald Myrvang <perm@stud.cs.uit.no>
++
++
++Acknowledgments:
++
++  The deflate format used by zlib was defined by Phil Katz. The deflate
++  and zlib specifications were written by L. Peter Deutsch. Thanks to all the
++  people who reported problems and suggested various improvements in zlib;
++  they are too numerous to cite here.
++
++Copyright notice:
++
++ (C) 1995-2002 Jean-loup Gailly and Mark Adler
++
++  This software is provided 'as-is', without any express or implied
++  warranty.  In no event will the authors be held liable for any damages
++  arising from the use of this software.
++
++  Permission is granted to anyone to use this software for any purpose,
++  including commercial applications, and to alter it and redistribute it
++  freely, subject to the following restrictions:
++
++  1. The origin of this software must not be misrepresented; you must not
++     claim that you wrote the original software. If you use this software
++     in a product, an acknowledgment in the product documentation would be
++     appreciated but is not required.
++  2. Altered source versions must be plainly marked as such, and must not be
++     misrepresented as being the original software.
++  3. This notice may not be removed or altered from any source distribution.
++
++  Jean-loup Gailly        Mark Adler
++  jloup@gzip.org          madler@alumni.caltech.edu
++
++If you use the zlib library in a product, we would appreciate *not*
++receiving lengthy legal documents to sign. The sources are provided
++for free but without warranty of any kind.  The library has been
++entirely written by Jean-loup Gailly and Mark Adler; it does not
++include third-party code.
++
++If you redistribute modified sources, we would appreciate that you include
++in the file ChangeLog history information documenting your changes.
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/README-zlib.freeswan     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,13 @@
++The only changes made to these files for use in FreeS/WAN are:
++
++ - In zconf.h, macros are defined to prefix global symbols with "ipcomp_"
++   (or "_ipcomp"), when compiled with -DIPCOMP_PREFIX.
++ - The copyright strings are defined local (static)
++
++ The above changes are made to avoid name collisions with ppp_deflate
++ and ext2compr.
++
++ - Files not needed for FreeS/WAN have been removed
++
++ See the "README" file for information about where to obtain the complete
++ zlib package.
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/addrtoa.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,67 @@
++/*
++ * addresses to ASCII
++ * Copyright (C) 1998, 1999  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: addrtoa.c,v 1.10 2004/07/10 07:43:47 mcr Exp $
++ */
++#include "openswan.h"
++
++#define       NBYTES  4               /* bytes in an address */
++#define       PERBYTE 4               /* three digits plus a dot or NUL */
++#define       BUFLEN  (NBYTES*PERBYTE)
++
++#if BUFLEN != ADDRTOA_BUF
++#error        "ADDRTOA_BUF in openswan.h inconsistent with addrtoa() code"
++#endif
++
++/*
++ - addrtoa - convert binary address to ASCII dotted decimal
++ */
++size_t                                /* space needed for full conversion */
++addrtoa(addr, format, dst, dstlen)
++struct in_addr addr;
++int format;                   /* character */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      unsigned long a = ntohl(addr.s_addr);
++      int i;
++      size_t n;
++      unsigned long byte;
++      char buf[BUFLEN];
++      char *p;
++
++      switch (format) {
++      case 0:
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      p = buf;
++      for (i = NBYTES-1; i >= 0; i--) {
++              byte = (a >> (i*8)) & 0xff;
++              p += ultoa(byte, 10, p, PERBYTE);
++              if (i != 0)
++                      *(p-1) = '.';
++      }
++      n = p - buf;
++
++      if (dstlen > 0) {
++              if (n > dstlen)
++                      buf[dstlen - 1] = '\0';
++              strcpy(dst, buf);
++      }
++      return n;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/addrtot.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,423 @@
++/*
++ * addresses to text
++ * Copyright (C) 2000  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: addrtot.c,v 1.22.2.1 2005/11/17 22:30:49 paul Exp $
++ */
++
++#if defined(__KERNEL__) && defined(__HAVE_ARCH_STRSTR)
++#include <linux/string.h>
++#endif
++
++#include "openswan.h"
++
++#define       IP4BYTES        4       /* bytes in an IPv4 address */
++#define       PERBYTE         4       /* three digits plus a dot or NUL */
++#define       IP6BYTES        16      /* bytes in an IPv6 address */
++
++/* forwards */
++static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp);
++static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish);
++static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp);
++static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp);
++
++#if defined(__KERNEL__) && !defined(__HAVE_ARCH_STRSTR) 
++#define strstr ipsec_strstr
++/*
++ * Find the first occurrence of find in s.
++ * (from NetBSD 1.6's /src/lib/libc/string/strstr.c)
++ */
++static char *
++strstr(s, find)
++      const char *s, *find;
++{
++      char c, sc;
++      size_t len;
++
++      if ((c = *find++) != 0) {
++              len = strlen(find);
++              do {
++                      do {
++                              if ((sc = *s++) == 0)
++                                      return (NULL);
++                      } while (sc != c);
++              } while (strncmp(s, find, len) != 0);
++              s--;
++      }
++      /* LINTED interface specification */
++      return ((char *)s);
++}
++#endif
++
++/*
++ - addrtot - convert binary address to text (dotted decimal or IPv6 string)
++ */
++size_t                                /* space needed for full conversion */
++addrtot(src, format, dst, dstlen)
++const ip_address *src;
++int format;                   /* character */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      const unsigned char *b;
++      size_t n;
++      char buf[1+ADDRTOT_BUF+1];      /* :address: */
++      char *p;
++      int t = addrtypeof(src);
++#     define  TF(t, f)        (((t)<<8) | (f))
++
++      n = addrbytesptr(src, &b);
++      if (n == 0) {
++      bad:
++        dst[0]='\0';
++        strncat(dst, "<invalid>", dstlen);
++        return sizeof("<invalid>");
++      }
++
++      switch (TF(t, format)) {
++      case TF(AF_INET, 0):
++              n = normal4(b, n, buf, &p);
++              break;
++      case TF(AF_INET6, 0):
++              n = normal6(b, n, buf, &p, 1);
++              break;
++      case TF(AF_INET, 'Q'):
++              n = normal4(b, n, buf, &p);
++              break;
++      case TF(AF_INET6, 'Q'):
++              n = normal6(b, n, buf, &p, 0);
++              break;
++      case TF(AF_INET, 'r'):
++              n = reverse4(b, n, buf, &p);
++              break;
++      case TF(AF_INET6, 'r'):
++              n = reverse6(b, n, buf, &p);
++              break;
++      default:                /* including (AF_INET, 'R') */
++              goto bad;
++              break;
++      }
++
++      if (dstlen > 0) {
++              if (dstlen < n)
++                      p[dstlen - 1] = '\0';
++              strcpy(dst, p);
++      }
++      return n;
++}
++
++/*
++ - normal4 - normal IPv4 address-text conversion
++ */
++static size_t                 /* size of text, including NUL */
++normal4(srcp, srclen, buf, dstp)
++const unsigned char *srcp;
++size_t srclen;
++char *buf;                    /* guaranteed large enough */
++char **dstp;                  /* where to put result pointer */
++{
++      int i;
++      char *p;
++
++      if (srclen != IP4BYTES) /* "can't happen" */
++              return 0;
++      p = buf;
++      for (i = 0; i < IP4BYTES; i++) {
++              p += ultot(srcp[i], 10, p, PERBYTE);
++              if (i != IP4BYTES - 1)
++                      *(p-1) = '.';   /* overwrites the NUL */
++      }
++      *dstp = buf;
++      return p - buf;
++}
++
++/*
++ - normal6 - normal IPv6 address-text conversion
++ */
++static size_t                 /* size of text, including NUL */
++normal6(srcp, srclen, buf, dstp, squish)
++const unsigned char *srcp;
++size_t srclen;
++char *buf;                    /* guaranteed large enough, plus 2 */
++char **dstp;                  /* where to put result pointer */
++int    squish;                  /* whether to squish out 0:0 */
++{
++      int i;
++      unsigned long piece;
++      char *p;
++      char *q;
++
++      if (srclen != IP6BYTES) /* "can't happen" */
++              return 0;
++      p = buf;
++      *p++ = ':';
++      for (i = 0; i < IP6BYTES/2; i++) {
++              piece = (srcp[2*i] << 8) + srcp[2*i + 1];
++              p += ultot(piece, 16, p, 5);    /* 5 = abcd + NUL */
++              *(p-1) = ':';   /* overwrites the NUL */
++      }
++      *p = '\0';
++      q = strstr(buf, ":0:0:");
++      if (squish && q != NULL) {      /* zero squishing is possible */
++              p = q + 1;
++              while (*p == '0' && *(p+1) == ':')
++                      p += 2;
++              q++;
++              *q++ = ':';     /* overwrite first 0 */
++              while (*p != '\0')
++                      *q++ = *p++;
++              *q = '\0';
++              if (!(*(q-1) == ':' && *(q-2) == ':'))
++                      *--q = '\0';    /* strip final : unless :: */
++              p = buf;
++              if (!(*p == ':' && *(p+1) == ':'))
++                      p++;    /* skip initial : unless :: */
++      } else {
++              q = p;
++              *--q = '\0';    /* strip final : */
++              p = buf + 1;    /* skip initial : */
++      }
++      *dstp = p;
++      return q - p + 1;
++}
++
++/*
++ - reverse4 - IPv4 reverse-lookup conversion
++ */
++static size_t                 /* size of text, including NUL */
++reverse4(srcp, srclen, buf, dstp)
++const unsigned char *srcp;
++size_t srclen;
++char *buf;                    /* guaranteed large enough */
++char **dstp;                  /* where to put result pointer */
++{
++      int i;
++      char *p;
++
++      if (srclen != IP4BYTES) /* "can't happen" */
++              return 0;
++      p = buf;
++      for (i = IP4BYTES-1; i >= 0; i--) {
++              p += ultot(srcp[i], 10, p, PERBYTE);
++              *(p-1) = '.';   /* overwrites the NUL */
++      }
++      strcpy(p, "IN-ADDR.ARPA.");
++      *dstp = buf;
++      return strlen(buf) + 1;
++}
++
++/*
++ - reverse6 - IPv6 reverse-lookup conversion (RFC 1886)
++ * A trifle inefficient, really shouldn't use ultot...
++ */
++static size_t                 /* size of text, including NUL */
++reverse6(srcp, srclen, buf, dstp)
++const unsigned char *srcp;
++size_t srclen;
++char *buf;                    /* guaranteed large enough */
++char **dstp;                  /* where to put result pointer */
++{
++      int i;
++      unsigned long piece;
++      char *p;
++
++      if (srclen != IP6BYTES) /* "can't happen" */
++              return 0;
++      p = buf;
++      for (i = IP6BYTES-1; i >= 0; i--) {
++              piece = srcp[i];
++              p += ultot(piece&0xf, 16, p, 2);
++              *(p-1) = '.';
++              p += ultot(piece>>4, 16, p, 2);
++              *(p-1) = '.';
++      }
++      strcpy(p, "IP6.ARPA.");
++      *dstp = buf;
++      return strlen(buf) + 1;
++}
++
++/*
++ - reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
++ * this version removed as it was obsoleted in the end.
++ */
++
++#ifdef ADDRTOT_MAIN
++
++#include <stdio.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++
++void regress(void);
++
++int
++main(int argc, char *argv[])
++{
++      if (argc < 2) {
++              fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
++                                                              argv[0]);
++              exit(2);
++      }
++
++      if (strcmp(argv[1], "-r") == 0) {
++              regress();
++              fprintf(stderr, "regress() returned?!?\n");
++              exit(1);
++      }
++      exit(0);
++}
++
++struct rtab {
++      char *input;
++        char  format;
++      char *output;                   /* NULL means error expected */
++} rtab[] = {
++      {"1.2.3.0",                     0, "1.2.3.0"},
++      {"1:2::3:4",                    0, "1:2::3:4"},
++      {"1:2::3:4",                   'Q', "1:2:0:0:0:0:3:4"},
++      {"1:2:0:0:3:4:0:0",             0, "1:2::3:4:0:0"},
++      {"1.2.3.4",                    'r' , "4.3.2.1.IN-ADDR.ARPA."},
++      /*                                    0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */
++      {"1:2::3:4",                   'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."},
++       {NULL,                         0, NULL}
++};
++
++void
++regress()
++{
++      struct rtab *r;
++      int status = 0;
++      ip_address a;
++      char in[100];
++      char buf[100];
++      const char *oops;
++      size_t n;
++
++      for (r = rtab; r->input != NULL; r++) {
++              strcpy(in, r->input);
++
++              /* convert it *to* internal format */
++              oops = ttoaddr(in, strlen(in), 0, &a);
++
++              /* now convert it back */
++
++              n = addrtot(&a, r->format, buf, sizeof(buf));
++
++              if (n == 0 && r->output == NULL)
++                      {}              /* okay, error expected */
++              
++              else if (n == 0) {
++                      printf("`%s' atoasr failed\n", r->input);
++                      status = 1;
++                      
++              } else if (r->output == NULL) {
++                      printf("`%s' atoasr succeeded unexpectedly '%c'\n",
++                                                      r->input, r->format);
++                      status = 1;
++              } else {
++                if (strcasecmp(r->output, buf) != 0) {
++                  printf("`%s' '%c' gave `%s', expected `%s'\n",
++                         r->input, r->format, buf, r->output);
++                  status = 1;
++                }
++              }
++      }
++      exit(status);
++}
++
++#endif /* ADDRTOT_MAIN */
++
++/*
++ * $Log: addrtot.c,v $
++ * Revision 1.22.2.1  2005/11/17 22:30:49  paul
++ * pull up strstr fix from head.
++ *
++ * Revision 1.22  2005/05/20 16:47:40  mcr
++ *    make strstr static if we need it.
++ *
++ * Revision 1.21  2005/03/21 00:35:12  mcr
++ *     test for strstr properly
++ *
++ * Revision 1.20  2004/11/09 22:52:20  mcr
++ *    until we figure out which kernels have strsep and which
++ *    do not (UML does not under certain circumstances), then
++ *    let's just provide our own.
++ *
++ * Revision 1.19  2004/10/08 16:30:33  mcr
++ *    pull-up of initial crypto-offload work.
++ *
++ * Revision 1.18  2004/09/18 19:33:08  mcr
++ *    use an appropriate kernel happy ifdef for strstr.
++ *
++ * Revision 1.17  2004/09/15 21:49:02  mcr
++ *    use local copy of strstr() if this is going in the kernel.
++ *    Not clear why this worked before, or why this shows up
++ *    for modules only.
++ *
++ * Revision 1.16  2004/07/10 07:43:47  mcr
++ * Moved from linux/lib/libfreeswan/addrtot.c,v
++ *
++ * Revision 1.15  2004/04/11 17:39:25  mcr
++ *    removed internal.h requirements.
++ *
++ * Revision 1.14  2004/03/08 01:59:08  ken
++ * freeswan.h -> openswan.h
++ *
++ * Revision 1.13  2004/01/05 23:21:05  mcr
++ *    if the address type is invalid, then return length of <invalid>
++ *    string!
++ *
++ * Revision 1.12  2003/12/30 06:42:48  mcr
++ *    added $Log: addrtot.c,v $
++ *    added Revision 1.22.2.1  2005/11/17 22:30:49  paul
++ *    added pull up strstr fix from head.
++ *    added
++ *    added Revision 1.22  2005/05/20 16:47:40  mcr
++ *    added   make strstr static if we need it.
++ *    added
++ *    added Revision 1.21  2005/03/21 00:35:12  mcr
++ *    added     test for strstr properly
++ *    added
++ *    added Revision 1.20  2004/11/09 22:52:20  mcr
++ *    added   until we figure out which kernels have strsep and which
++ *    added   do not (UML does not under certain circumstances), then
++ *    added   let's just provide our own.
++ *    added
++ *    added Revision 1.19  2004/10/08 16:30:33  mcr
++ *    added   pull-up of initial crypto-offload work.
++ *    added
++ *    added Revision 1.18  2004/09/18 19:33:08  mcr
++ *    added   use an appropriate kernel happy ifdef for strstr.
++ *    added
++ *    added Revision 1.17  2004/09/15 21:49:02  mcr
++ *    added   use local copy of strstr() if this is going in the kernel.
++ *    added   Not clear why this worked before, or why this shows up
++ *    added   for modules only.
++ *    added
++ *    added Revision 1.16  2004/07/10 07:43:47  mcr
++ *    added Moved from linux/lib/libfreeswan/addrtot.c,v
++ *    added
++ *    added Revision 1.15  2004/04/11 17:39:25  mcr
++ *    added   removed internal.h requirements.
++ *    added
++ *    added Revision 1.14  2004/03/08 01:59:08  ken
++ *    added freeswan.h -> openswan.h
++ *    added
++ *    added Revision 1.13  2004/01/05 23:21:05  mcr
++ *    added   if the address type is invalid, then return length of <invalid>
++ *    added   string!
++ *    added
++ *
++ *
++ */
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/addrtypeof.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,93 @@
++/*
++ * extract parts of an ip_address
++ * Copyright (C) 2000  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: addrtypeof.c,v 1.10 2004/07/10 07:43:47 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - addrtypeof - get the type of an ip_address
++ */
++int
++addrtypeof(src)
++const ip_address *src;
++{
++      return src->u.v4.sin_family;
++}
++
++/*
++ - addrbytesptr - get pointer to the address bytes of an ip_address
++ */
++size_t                                /* 0 for error */
++addrbytesptr(src, dstp)
++const ip_address *src;
++const unsigned char **dstp;   /* NULL means just a size query */
++{
++      const unsigned char *p;
++      size_t n;
++
++      switch (src->u.v4.sin_family) {
++      case AF_INET:
++              p = (const unsigned char *)&src->u.v4.sin_addr.s_addr;
++              n = 4;
++              break;
++      case AF_INET6:
++              p = (const unsigned char *)&src->u.v6.sin6_addr;
++              n = 16;
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      if (dstp != NULL)
++              *dstp = p;
++      return n;
++}
++
++/*
++ - addrlenof - get length of the address bytes of an ip_address
++ */
++size_t                                /* 0 for error */
++addrlenof(src)
++const ip_address *src;
++{
++      return addrbytesptr(src, NULL);
++}
++
++/*
++ - addrbytesof - get the address bytes of an ip_address
++ */
++size_t                                /* 0 for error */
++addrbytesof(src, dst, dstlen)
++const ip_address *src;
++unsigned char *dst;
++size_t dstlen;
++{
++      const unsigned char *p;
++      size_t n;
++      size_t ncopy;
++
++      n = addrbytesptr(src, &p);
++      if (n == 0)
++              return 0;
++
++      if (dstlen > 0) {
++              ncopy = n;
++              if (ncopy > dstlen)
++                      ncopy = dstlen;
++              memcpy(dst, p, ncopy);
++      }
++      return n;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/adler32.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,49 @@
++/* adler32.c -- compute the Adler-32 checksum of a data stream
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* @(#) $Id: adler32.c,v 1.6 2004/07/10 19:11:18 mcr Exp $ */
++
++#include <zlib/zlib.h>
++#include <zlib/zconf.h>
++
++#define BASE 65521L /* largest prime smaller than 65536 */
++#define NMAX 5552
++/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
++
++#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
++#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
++#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
++#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
++#define DO16(buf)   DO8(buf,0); DO8(buf,8);
++
++/* ========================================================================= */
++uLong ZEXPORT adler32(adler, buf, len)
++    uLong adler;
++    const Bytef *buf;
++    uInt len;
++{
++    unsigned long s1 = adler & 0xffff;
++    unsigned long s2 = (adler >> 16) & 0xffff;
++    int k;
++
++    if (buf == Z_NULL) return 1L;
++
++    while (len > 0) {
++        k = len < NMAX ? len : NMAX;
++        len -= k;
++        while (k >= 16) {
++            DO16(buf);
++          buf += 16;
++            k -= 16;
++        }
++        if (k != 0) do {
++            s1 += *buf++;
++          s2 += s1;
++        } while (--k);
++        s1 %= BASE;
++        s2 %= BASE;
++    }
++    return (s2 << 16) | s1;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/aes/Makefile     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,59 @@
++# Makefile for KLIPS 3DES kernel code as a module    for 2.6 kernels
++#
++# Makefile for KLIPS kernel code as a module
++# Copyright (C) 2002-2004     Michael Richardson <mcr@xelerance.com>
++# 
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++# 
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# RCSID $Id: Makefile.fs2_6,v 1.1.10.1 2005/08/12 16:10:05 ken Exp $
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++
++obj-$(CONFIG_KLIPS_ENC_AES) += ipsec_alg_aes.o
++obj-$(CONFIG_KLIPS_ENC_AES) += aes_xcbc_mac.o
++obj-$(CONFIG_KLIPS_ENC_AES) += aes_cbc.o
++
++ifeq ($(strip ${SUBARCH}),)
++SUBARCH:=${ARCH}
++endif
++
++# the assembly version expects frame pointers, which are
++# optional in many kernel builds. If you want speed, you should
++# probably use cryptoapi code instead.
++USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER}
++ifeq (${USEASSEMBLY},i386y)
++obj-$(CONFIG_KLIPS_ENC_AES) += aes-i586.o
++else
++obj-$(CONFIG_KLIPS_ENC_AES) += aes.o
++endif
++
++
++#
++# $Log: Makefile.fs2_6,v $
++# Revision 1.1.10.1  2005/08/12 16:10:05  ken
++# do not use assembly code with there are no frame pointers
++#
++# Revision 1.2  2005/08/12 14:13:58  mcr
++#     do not use assembly code with there are no frame pointers,
++#     as it does not have the right linkages.
++#
++# Revision 1.1  2004/08/17 03:31:34  mcr
++#     klips 2.6 edits.
++#
++#
++# Local Variables:
++# compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)"
++# End Variables:
++#
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/aes/aes-i586.S     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,892 @@
++//
++// Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
++// All rights reserved.
++//
++// TERMS
++//
++//  Redistribution and use in source and binary forms, with or without
++//  modification, are permitted subject to the following conditions:
++//
++//  1. Redistributions of source code must retain the above copyright
++//     notice, this list of conditions and the following disclaimer.
++//
++//  2. Redistributions in binary form must reproduce the above copyright
++//     notice, this list of conditions and the following disclaimer in the
++//     documentation and/or other materials provided with the distribution.
++//
++//  3. The copyright holder's name must not be used to endorse or promote
++//     any products derived from this software without his specific prior
++//     written permission.
++//
++//  This software is provided 'as is' with no express or implied warranties
++//  of correctness or fitness for purpose.
++
++// Modified by Jari Ruusu,  December 24 2001
++//  - Converted syntax to GNU CPP/assembler syntax
++//  - C programming interface converted back to "old" API
++//  - Minor portability cleanups and speed optimizations
++
++// An AES (Rijndael) implementation for the Pentium. This version only
++// implements the standard AES block length (128 bits, 16 bytes). This code
++// does not preserve the eax, ecx or edx registers or the artihmetic status
++// flags. However, the ebx, esi, edi, and ebp registers are preserved across
++// calls.
++
++// void aes_set_key(aes_context *cx, const unsigned char key[], const int key_len, const int f)
++// void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
++// void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
++
++#if defined(USE_UNDERLINE)
++# define aes_set_key _aes_set_key
++# define aes_encrypt _aes_encrypt
++# define aes_decrypt _aes_decrypt
++#endif
++#if !defined(ALIGN32BYTES)
++# define ALIGN32BYTES 32
++#endif
++
++      .file   "aes-i586.S"
++      .globl  aes_set_key
++      .globl  aes_encrypt
++      .globl  aes_decrypt
++
++#define tlen  1024    // length of each of 4 'xor' arrays (256 32-bit words)
++
++// offsets to parameters with one register pushed onto stack
++
++#define ctx   8       // AES context structure
++#define in_blk        12      // input byte array address parameter
++#define out_blk       16      // output byte array address parameter
++
++// offsets in context structure
++
++#define nkey  0       // key length, size 4
++#define nrnd  4       // number of rounds, size 4
++#define ekey  8       // encryption key schedule base address, size 256
++#define dkey  264     // decryption key schedule base address, size 256
++
++// This macro performs a forward encryption cycle. It is entered with
++// the first previous round column values in %eax, %ebx, %esi and %edi and
++// exits with the final values in the same registers.
++
++#define fwd_rnd(p1,p2)                         \
++      mov     %ebx,(%esp)             ;\
++      movzbl  %al,%edx                ;\
++      mov     %eax,%ecx               ;\
++      mov     p2(%ebp),%eax           ;\
++      mov     %edi,4(%esp)            ;\
++      mov     p2+12(%ebp),%edi        ;\
++      xor     p1(,%edx,4),%eax        ;\
++      movzbl  %ch,%edx                ;\
++      shr     $16,%ecx                ;\
++      mov     p2+4(%ebp),%ebx         ;\
++      xor     p1+tlen(,%edx,4),%edi   ;\
++      movzbl  %cl,%edx                ;\
++      movzbl  %ch,%ecx                ;\
++      xor     p1+3*tlen(,%ecx,4),%ebx ;\
++      mov     %esi,%ecx               ;\
++      mov     p1+2*tlen(,%edx,4),%esi ;\
++      movzbl  %cl,%edx                ;\
++      xor     p1(,%edx,4),%esi        ;\
++      movzbl  %ch,%edx                ;\
++      shr     $16,%ecx                ;\
++      xor     p1+tlen(,%edx,4),%ebx   ;\
++      movzbl  %cl,%edx                ;\
++      movzbl  %ch,%ecx                ;\
++      xor     p1+2*tlen(,%edx,4),%eax ;\
++      mov     (%esp),%edx             ;\
++      xor     p1+3*tlen(,%ecx,4),%edi ;\
++      movzbl  %dl,%ecx                ;\
++      xor     p2+8(%ebp),%esi         ;\
++      xor     p1(,%ecx,4),%ebx        ;\
++      movzbl  %dh,%ecx                ;\
++      shr     $16,%edx                ;\
++      xor     p1+tlen(,%ecx,4),%eax   ;\
++      movzbl  %dl,%ecx                ;\
++      movzbl  %dh,%edx                ;\
++      xor     p1+2*tlen(,%ecx,4),%edi ;\
++      mov     4(%esp),%ecx            ;\
++      xor     p1+3*tlen(,%edx,4),%esi ;\
++      movzbl  %cl,%edx                ;\
++      xor     p1(,%edx,4),%edi        ;\
++      movzbl  %ch,%edx                ;\
++      shr     $16,%ecx                ;\
++      xor     p1+tlen(,%edx,4),%esi   ;\
++      movzbl  %cl,%edx                ;\
++      movzbl  %ch,%ecx                ;\
++      xor     p1+2*tlen(,%edx,4),%ebx ;\
++      xor     p1+3*tlen(,%ecx,4),%eax
++
++// This macro performs an inverse encryption cycle. It is entered with
++// the first previous round column values in %eax, %ebx, %esi and %edi and
++// exits with the final values in the same registers.
++
++#define inv_rnd(p1,p2)                         \
++      movzbl  %al,%edx                ;\
++      mov     %ebx,(%esp)             ;\
++      mov     %eax,%ecx               ;\
++      mov     p2(%ebp),%eax           ;\
++      mov     %edi,4(%esp)            ;\
++      mov     p2+4(%ebp),%ebx         ;\
++      xor     p1(,%edx,4),%eax        ;\
++      movzbl  %ch,%edx                ;\
++      shr     $16,%ecx                ;\
++      mov     p2+12(%ebp),%edi        ;\
++      xor     p1+tlen(,%edx,4),%ebx   ;\
++      movzbl  %cl,%edx                ;\
++      movzbl  %ch,%ecx                ;\
++      xor     p1+3*tlen(,%ecx,4),%edi ;\
++      mov     %esi,%ecx               ;\
++      mov     p1+2*tlen(,%edx,4),%esi ;\
++      movzbl  %cl,%edx                ;\
++      xor     p1(,%edx,4),%esi        ;\
++      movzbl  %ch,%edx                ;\
++      shr     $16,%ecx                ;\
++      xor     p1+tlen(,%edx,4),%edi   ;\
++      movzbl  %cl,%edx                ;\
++      movzbl  %ch,%ecx                ;\
++      xor     p1+2*tlen(,%edx,4),%eax ;\
++      mov     (%esp),%edx             ;\
++      xor     p1+3*tlen(,%ecx,4),%ebx ;\
++      movzbl  %dl,%ecx                ;\
++      xor     p2+8(%ebp),%esi         ;\
++      xor     p1(,%ecx,4),%ebx        ;\
++      movzbl  %dh,%ecx                ;\
++      shr     $16,%edx                ;\
++      xor     p1+tlen(,%ecx,4),%esi   ;\
++      movzbl  %dl,%ecx                ;\
++      movzbl  %dh,%edx                ;\
++      xor     p1+2*tlen(,%ecx,4),%edi ;\
++      mov     4(%esp),%ecx            ;\
++      xor     p1+3*tlen(,%edx,4),%eax ;\
++      movzbl  %cl,%edx                ;\
++      xor     p1(,%edx,4),%edi        ;\
++      movzbl  %ch,%edx                ;\
++      shr     $16,%ecx                ;\
++      xor     p1+tlen(,%edx,4),%eax   ;\
++      movzbl  %cl,%edx                ;\
++      movzbl  %ch,%ecx                ;\
++      xor     p1+2*tlen(,%edx,4),%ebx ;\
++      xor     p1+3*tlen(,%ecx,4),%esi
++
++// AES (Rijndael) Encryption Subroutine
++
++      .text
++      .align  ALIGN32BYTES
++aes_encrypt:
++      push    %ebp
++      mov     ctx(%esp),%ebp          // pointer to context
++      mov     in_blk(%esp),%ecx
++      push    %ebx
++      push    %esi
++      push    %edi
++      mov     nrnd(%ebp),%edx         // number of rounds
++      lea     ekey+16(%ebp),%ebp      // key pointer
++
++// input four columns and xor in first round key
++
++      mov     (%ecx),%eax
++      mov     4(%ecx),%ebx
++      mov     8(%ecx),%esi
++      mov     12(%ecx),%edi
++      xor     -16(%ebp),%eax
++      xor     -12(%ebp),%ebx
++      xor     -8(%ebp),%esi
++      xor     -4(%ebp),%edi
++
++      sub     $8,%esp                 // space for register saves on stack
++
++      sub     $10,%edx
++      je      aes_15
++      add     $32,%ebp
++      sub     $2,%edx
++      je      aes_13
++      add     $32,%ebp
++
++      fwd_rnd(aes_ft_tab,-64)         // 14 rounds for 256-bit key
++      fwd_rnd(aes_ft_tab,-48)
++aes_13:       fwd_rnd(aes_ft_tab,-32)         // 12 rounds for 192-bit key
++      fwd_rnd(aes_ft_tab,-16)
++aes_15:       fwd_rnd(aes_ft_tab,0)           // 10 rounds for 128-bit key
++      fwd_rnd(aes_ft_tab,16)
++      fwd_rnd(aes_ft_tab,32)
++      fwd_rnd(aes_ft_tab,48)
++      fwd_rnd(aes_ft_tab,64)
++      fwd_rnd(aes_ft_tab,80)
++      fwd_rnd(aes_ft_tab,96)
++      fwd_rnd(aes_ft_tab,112)
++      fwd_rnd(aes_ft_tab,128)
++      fwd_rnd(aes_fl_tab,144)         // last round uses a different table
++
++// move final values to the output array.
++
++      mov     out_blk+20(%esp),%ebp
++      add     $8,%esp
++      mov     %eax,(%ebp)
++      mov     %ebx,4(%ebp)
++      mov     %esi,8(%ebp)
++      mov     %edi,12(%ebp)
++      pop     %edi
++      pop     %esi
++      pop     %ebx
++      pop     %ebp
++      ret
++
++
++// AES (Rijndael) Decryption Subroutine
++
++      .align  ALIGN32BYTES
++aes_decrypt:
++      push    %ebp
++      mov     ctx(%esp),%ebp          // pointer to context
++      mov     in_blk(%esp),%ecx
++      push    %ebx
++      push    %esi
++      push    %edi
++      mov     nrnd(%ebp),%edx         // number of rounds
++      lea     dkey+16(%ebp),%ebp      // key pointer
++
++// input four columns and xor in first round key
++
++      mov     (%ecx),%eax
++      mov     4(%ecx),%ebx
++      mov     8(%ecx),%esi
++      mov     12(%ecx),%edi
++      xor     -16(%ebp),%eax
++      xor     -12(%ebp),%ebx
++      xor     -8(%ebp),%esi
++      xor     -4(%ebp),%edi
++
++      sub     $8,%esp                 // space for register saves on stack
++
++      sub     $10,%edx
++      je      aes_25
++      add     $32,%ebp
++      sub     $2,%edx
++      je      aes_23
++      add     $32,%ebp
++
++      inv_rnd(aes_it_tab,-64)         // 14 rounds for 256-bit key
++      inv_rnd(aes_it_tab,-48)
++aes_23:       inv_rnd(aes_it_tab,-32)         // 12 rounds for 192-bit key
++      inv_rnd(aes_it_tab,-16)
++aes_25:       inv_rnd(aes_it_tab,0)           // 10 rounds for 128-bit key
++      inv_rnd(aes_it_tab,16)
++      inv_rnd(aes_it_tab,32)
++      inv_rnd(aes_it_tab,48)
++      inv_rnd(aes_it_tab,64)
++      inv_rnd(aes_it_tab,80)
++      inv_rnd(aes_it_tab,96)
++      inv_rnd(aes_it_tab,112)
++      inv_rnd(aes_it_tab,128)
++      inv_rnd(aes_il_tab,144)         // last round uses a different table
++
++// move final values to the output array.
++
++      mov     out_blk+20(%esp),%ebp
++      add     $8,%esp
++      mov     %eax,(%ebp)
++      mov     %ebx,4(%ebp)
++      mov     %esi,8(%ebp)
++      mov     %edi,12(%ebp)
++      pop     %edi
++      pop     %esi
++      pop     %ebx
++      pop     %ebp
++      ret
++
++// AES (Rijndael) Key Schedule Subroutine
++
++// input/output parameters
++
++#define aes_cx        12      // AES context
++#define in_key        16      // key input array address
++#define key_ln        20      // key length, bytes (16,24,32) or bits (128,192,256)
++#define ed_flg        24      // 0=create both encr/decr keys, 1=create encr key only
++
++// offsets for locals
++
++#define cnt   -4
++#define kpf   -8
++#define slen  8
++
++// This macro performs a column mixing operation on an input 32-bit
++// word to give a 32-bit result. It uses each of the 4 bytes in the
++// the input column to index 4 different tables of 256 32-bit words
++// that are xored together to form the output value.
++
++#define mix_col(p1)                    \
++      movzbl  %bl,%ecx                ;\
++      mov     p1(,%ecx,4),%eax        ;\
++      movzbl  %bh,%ecx                ;\
++      ror     $16,%ebx                ;\
++      xor     p1+tlen(,%ecx,4),%eax   ;\
++      movzbl  %bl,%ecx                ;\
++      xor     p1+2*tlen(,%ecx,4),%eax ;\
++      movzbl  %bh,%ecx                ;\
++      xor     p1+3*tlen(,%ecx,4),%eax
++
++// Key Schedule Macros
++
++#define ksc4(p1)                       \
++      rol     $24,%ebx                ;\
++      mix_col(aes_fl_tab)             ;\
++      ror     $8,%ebx                 ;\
++      xor     4*p1+aes_rcon_tab,%eax  ;\
++      xor     %eax,%esi               ;\
++      xor     %esi,%ebp               ;\
++      mov     %esi,16*p1(%edi)        ;\
++      mov     %ebp,16*p1+4(%edi)      ;\
++      xor     %ebp,%edx               ;\
++      xor     %edx,%ebx               ;\
++      mov     %edx,16*p1+8(%edi)      ;\
++      mov     %ebx,16*p1+12(%edi)
++
++#define ksc6(p1)                       \
++      rol     $24,%ebx                ;\
++      mix_col(aes_fl_tab)             ;\
++      ror     $8,%ebx                 ;\
++      xor     4*p1+aes_rcon_tab,%eax  ;\
++      xor     24*p1-24(%edi),%eax     ;\
++      mov     %eax,24*p1(%edi)        ;\
++      xor     24*p1-20(%edi),%eax     ;\
++      mov     %eax,24*p1+4(%edi)      ;\
++      xor     %eax,%esi               ;\
++      xor     %esi,%ebp               ;\
++      mov     %esi,24*p1+8(%edi)      ;\
++      mov     %ebp,24*p1+12(%edi)     ;\
++      xor     %ebp,%edx               ;\
++      xor     %edx,%ebx               ;\
++      mov     %edx,24*p1+16(%edi)     ;\
++      mov     %ebx,24*p1+20(%edi)
++
++#define ksc8(p1)                       \
++      rol     $24,%ebx                ;\
++      mix_col(aes_fl_tab)             ;\
++      ror     $8,%ebx                 ;\
++      xor     4*p1+aes_rcon_tab,%eax  ;\
++      xor     32*p1-32(%edi),%eax     ;\
++      mov     %eax,32*p1(%edi)        ;\
++      xor     32*p1-28(%edi),%eax     ;\
++      mov     %eax,32*p1+4(%edi)      ;\
++      xor     32*p1-24(%edi),%eax     ;\
++      mov     %eax,32*p1+8(%edi)      ;\
++      xor     32*p1-20(%edi),%eax     ;\
++      mov     %eax,32*p1+12(%edi)     ;\
++      push    %ebx                    ;\
++      mov     %eax,%ebx               ;\
++      mix_col(aes_fl_tab)             ;\
++      pop     %ebx                    ;\
++      xor     %eax,%esi               ;\
++      xor     %esi,%ebp               ;\
++      mov     %esi,32*p1+16(%edi)     ;\
++      mov     %ebp,32*p1+20(%edi)     ;\
++      xor     %ebp,%edx               ;\
++      xor     %edx,%ebx               ;\
++      mov     %edx,32*p1+24(%edi)     ;\
++      mov     %ebx,32*p1+28(%edi)
++
++      .align  ALIGN32BYTES
++aes_set_key:
++      pushfl
++      push    %ebp
++      mov     %esp,%ebp
++      sub     $slen,%esp
++      push    %ebx
++      push    %esi
++      push    %edi
++
++      mov     aes_cx(%ebp),%edx       // edx -> AES context
++
++      mov     key_ln(%ebp),%ecx       // key length
++      cmpl    $128,%ecx
++      jb      aes_30
++      shr     $3,%ecx
++aes_30:       cmpl    $32,%ecx
++      je      aes_32
++      cmpl    $24,%ecx
++      je      aes_32
++      mov     $16,%ecx
++aes_32:       shr     $2,%ecx
++      mov     %ecx,nkey(%edx)
++
++      lea     6(%ecx),%eax            // 10/12/14 for 4/6/8 32-bit key length
++      mov     %eax,nrnd(%edx)
++
++      mov     in_key(%ebp),%esi       // key input array
++      lea     ekey(%edx),%edi         // key position in AES context
++      cld
++      push    %ebp
++      mov     %ecx,%eax               // save key length in eax
++      rep ;   movsl                   // words in the key schedule
++      mov     -4(%esi),%ebx           // put some values in registers
++      mov     -8(%esi),%edx           // to allow faster code
++      mov     -12(%esi),%ebp
++      mov     -16(%esi),%esi
++
++      cmpl    $4,%eax                 // jump on key size
++      je      aes_36
++      cmpl    $6,%eax
++      je      aes_35
++
++      ksc8(0)
++      ksc8(1)
++      ksc8(2)
++      ksc8(3)
++      ksc8(4)
++      ksc8(5)
++      ksc8(6)
++      jmp     aes_37
++aes_35:       ksc6(0)
++      ksc6(1)
++      ksc6(2)
++      ksc6(3)
++      ksc6(4)
++      ksc6(5)
++      ksc6(6)
++      ksc6(7)
++      jmp     aes_37
++aes_36:       ksc4(0)
++      ksc4(1)
++      ksc4(2)
++      ksc4(3)
++      ksc4(4)
++      ksc4(5)
++      ksc4(6)
++      ksc4(7)
++      ksc4(8)
++      ksc4(9)
++aes_37:       pop     %ebp
++      mov     aes_cx(%ebp),%edx       // edx -> AES context
++      cmpl    $0,ed_flg(%ebp)
++      jne     aes_39
++
++// compile decryption key schedule from encryption schedule - reverse
++// order and do mix_column operation on round keys except first and last
++
++      mov     nrnd(%edx),%eax         // kt = cx->d_key + nc * cx->Nrnd
++      shl     $2,%eax
++      lea     dkey(%edx,%eax,4),%edi
++      lea     ekey(%edx),%esi         // kf = cx->e_key
++
++      movsl                           // copy first round key (unmodified)
++      movsl
++      movsl
++      movsl
++      sub     $32,%edi
++      movl    $1,cnt(%ebp)
++aes_38:                                       // do mix column on each column of
++      lodsl                           // each round key
++      mov     %eax,%ebx
++      mix_col(aes_im_tab)
++      stosl
++      lodsl
++      mov     %eax,%ebx
++      mix_col(aes_im_tab)
++      stosl
++      lodsl
++      mov     %eax,%ebx
++      mix_col(aes_im_tab)
++      stosl
++      lodsl
++      mov     %eax,%ebx
++      mix_col(aes_im_tab)
++      stosl
++      sub     $32,%edi
++
++      incl    cnt(%ebp)
++      mov     cnt(%ebp),%eax
++      cmp     nrnd(%edx),%eax
++      jb      aes_38
++
++      movsl                           // copy last round key (unmodified)
++      movsl
++      movsl
++      movsl
++aes_39:       pop     %edi
++      pop     %esi
++      pop     %ebx
++      mov     %ebp,%esp
++      pop     %ebp
++      popfl
++      ret
++
++
++// finite field multiplies by {02}, {04} and {08}
++
++#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b))
++#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))
++#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))
++
++// finite field multiplies required in table generation
++
++#define f3(x) (f2(x) ^ x)
++#define f9(x) (f8(x) ^ x)
++#define fb(x) (f8(x) ^ f2(x) ^ x)
++#define fd(x) (f8(x) ^ f4(x) ^ x)
++#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
++
++// These defines generate the forward table entries
++
++#define u0(x) ((f3(x) << 24) | (x << 16) | (x << 8) | f2(x))
++#define u1(x) ((x << 24) | (x << 16) | (f2(x) << 8) | f3(x))
++#define u2(x) ((x << 24) | (f2(x) << 16) | (f3(x) << 8) | x)
++#define u3(x) ((f2(x) << 24) | (f3(x) << 16) | (x << 8) | x)
++
++// These defines generate the inverse table entries
++
++#define v0(x) ((fb(x) << 24) | (fd(x) << 16) | (f9(x) << 8) | fe(x))
++#define v1(x) ((fd(x) << 24) | (f9(x) << 16) | (fe(x) << 8) | fb(x))
++#define v2(x) ((f9(x) << 24) | (fe(x) << 16) | (fb(x) << 8) | fd(x))
++#define v3(x) ((fe(x) << 24) | (fb(x) << 16) | (fd(x) << 8) | f9(x))
++
++// These defines generate entries for the last round tables
++
++#define w0(x) (x)
++#define w1(x) (x <<  8)
++#define w2(x) (x << 16)
++#define w3(x) (x << 24)
++
++// macro to generate inverse mix column tables (needed for the key schedule)
++
++#define im_data0(p1) \
++      .long   p1(0x00),p1(0x01),p1(0x02),p1(0x03),p1(0x04),p1(0x05),p1(0x06),p1(0x07) ;\
++      .long   p1(0x08),p1(0x09),p1(0x0a),p1(0x0b),p1(0x0c),p1(0x0d),p1(0x0e),p1(0x0f) ;\
++      .long   p1(0x10),p1(0x11),p1(0x12),p1(0x13),p1(0x14),p1(0x15),p1(0x16),p1(0x17) ;\
++      .long   p1(0x18),p1(0x19),p1(0x1a),p1(0x1b),p1(0x1c),p1(0x1d),p1(0x1e),p1(0x1f)
++#define im_data1(p1) \
++      .long   p1(0x20),p1(0x21),p1(0x22),p1(0x23),p1(0x24),p1(0x25),p1(0x26),p1(0x27) ;\
++      .long   p1(0x28),p1(0x29),p1(0x2a),p1(0x2b),p1(0x2c),p1(0x2d),p1(0x2e),p1(0x2f) ;\
++      .long   p1(0x30),p1(0x31),p1(0x32),p1(0x33),p1(0x34),p1(0x35),p1(0x36),p1(0x37) ;\
++      .long   p1(0x38),p1(0x39),p1(0x3a),p1(0x3b),p1(0x3c),p1(0x3d),p1(0x3e),p1(0x3f)
++#define im_data2(p1) \
++      .long   p1(0x40),p1(0x41),p1(0x42),p1(0x43),p1(0x44),p1(0x45),p1(0x46),p1(0x47) ;\
++      .long   p1(0x48),p1(0x49),p1(0x4a),p1(0x4b),p1(0x4c),p1(0x4d),p1(0x4e),p1(0x4f) ;\
++      .long   p1(0x50),p1(0x51),p1(0x52),p1(0x53),p1(0x54),p1(0x55),p1(0x56),p1(0x57) ;\
++      .long   p1(0x58),p1(0x59),p1(0x5a),p1(0x5b),p1(0x5c),p1(0x5d),p1(0x5e),p1(0x5f)
++#define im_data3(p1) \
++      .long   p1(0x60),p1(0x61),p1(0x62),p1(0x63),p1(0x64),p1(0x65),p1(0x66),p1(0x67) ;\
++      .long   p1(0x68),p1(0x69),p1(0x6a),p1(0x6b),p1(0x6c),p1(0x6d),p1(0x6e),p1(0x6f) ;\
++      .long   p1(0x70),p1(0x71),p1(0x72),p1(0x73),p1(0x74),p1(0x75),p1(0x76),p1(0x77) ;\
++      .long   p1(0x78),p1(0x79),p1(0x7a),p1(0x7b),p1(0x7c),p1(0x7d),p1(0x7e),p1(0x7f)
++#define im_data4(p1) \
++      .long   p1(0x80),p1(0x81),p1(0x82),p1(0x83),p1(0x84),p1(0x85),p1(0x86),p1(0x87) ;\
++      .long   p1(0x88),p1(0x89),p1(0x8a),p1(0x8b),p1(0x8c),p1(0x8d),p1(0x8e),p1(0x8f) ;\
++      .long   p1(0x90),p1(0x91),p1(0x92),p1(0x93),p1(0x94),p1(0x95),p1(0x96),p1(0x97) ;\
++      .long   p1(0x98),p1(0x99),p1(0x9a),p1(0x9b),p1(0x9c),p1(0x9d),p1(0x9e),p1(0x9f)
++#define im_data5(p1) \
++      .long   p1(0xa0),p1(0xa1),p1(0xa2),p1(0xa3),p1(0xa4),p1(0xa5),p1(0xa6),p1(0xa7) ;\
++      .long   p1(0xa8),p1(0xa9),p1(0xaa),p1(0xab),p1(0xac),p1(0xad),p1(0xae),p1(0xaf) ;\
++      .long   p1(0xb0),p1(0xb1),p1(0xb2),p1(0xb3),p1(0xb4),p1(0xb5),p1(0xb6),p1(0xb7) ;\
++      .long   p1(0xb8),p1(0xb9),p1(0xba),p1(0xbb),p1(0xbc),p1(0xbd),p1(0xbe),p1(0xbf)
++#define im_data6(p1) \
++      .long   p1(0xc0),p1(0xc1),p1(0xc2),p1(0xc3),p1(0xc4),p1(0xc5),p1(0xc6),p1(0xc7) ;\
++      .long   p1(0xc8),p1(0xc9),p1(0xca),p1(0xcb),p1(0xcc),p1(0xcd),p1(0xce),p1(0xcf) ;\
++      .long   p1(0xd0),p1(0xd1),p1(0xd2),p1(0xd3),p1(0xd4),p1(0xd5),p1(0xd6),p1(0xd7) ;\
++      .long   p1(0xd8),p1(0xd9),p1(0xda),p1(0xdb),p1(0xdc),p1(0xdd),p1(0xde),p1(0xdf)
++#define im_data7(p1) \
++      .long   p1(0xe0),p1(0xe1),p1(0xe2),p1(0xe3),p1(0xe4),p1(0xe5),p1(0xe6),p1(0xe7) ;\
++      .long   p1(0xe8),p1(0xe9),p1(0xea),p1(0xeb),p1(0xec),p1(0xed),p1(0xee),p1(0xef) ;\
++      .long   p1(0xf0),p1(0xf1),p1(0xf2),p1(0xf3),p1(0xf4),p1(0xf5),p1(0xf6),p1(0xf7) ;\
++      .long   p1(0xf8),p1(0xf9),p1(0xfa),p1(0xfb),p1(0xfc),p1(0xfd),p1(0xfe),p1(0xff)
++
++// S-box data - 256 entries
++
++#define sb_data0(p1) \
++      .long   p1(0x63),p1(0x7c),p1(0x77),p1(0x7b),p1(0xf2),p1(0x6b),p1(0x6f),p1(0xc5) ;\
++      .long   p1(0x30),p1(0x01),p1(0x67),p1(0x2b),p1(0xfe),p1(0xd7),p1(0xab),p1(0x76) ;\
++      .long   p1(0xca),p1(0x82),p1(0xc9),p1(0x7d),p1(0xfa),p1(0x59),p1(0x47),p1(0xf0) ;\
++      .long   p1(0xad),p1(0xd4),p1(0xa2),p1(0xaf),p1(0x9c),p1(0xa4),p1(0x72),p1(0xc0)
++#define sb_data1(p1) \
++      .long   p1(0xb7),p1(0xfd),p1(0x93),p1(0x26),p1(0x36),p1(0x3f),p1(0xf7),p1(0xcc) ;\
++      .long   p1(0x34),p1(0xa5),p1(0xe5),p1(0xf1),p1(0x71),p1(0xd8),p1(0x31),p1(0x15) ;\
++      .long   p1(0x04),p1(0xc7),p1(0x23),p1(0xc3),p1(0x18),p1(0x96),p1(0x05),p1(0x9a) ;\
++      .long   p1(0x07),p1(0x12),p1(0x80),p1(0xe2),p1(0xeb),p1(0x27),p1(0xb2),p1(0x75)
++#define sb_data2(p1) \
++      .long   p1(0x09),p1(0x83),p1(0x2c),p1(0x1a),p1(0x1b),p1(0x6e),p1(0x5a),p1(0xa0) ;\
++      .long   p1(0x52),p1(0x3b),p1(0xd6),p1(0xb3),p1(0x29),p1(0xe3),p1(0x2f),p1(0x84) ;\
++      .long   p1(0x53),p1(0xd1),p1(0x00),p1(0xed),p1(0x20),p1(0xfc),p1(0xb1),p1(0x5b) ;\
++      .long   p1(0x6a),p1(0xcb),p1(0xbe),p1(0x39),p1(0x4a),p1(0x4c),p1(0x58),p1(0xcf)
++#define sb_data3(p1) \
++      .long   p1(0xd0),p1(0xef),p1(0xaa),p1(0xfb),p1(0x43),p1(0x4d),p1(0x33),p1(0x85) ;\
++      .long   p1(0x45),p1(0xf9),p1(0x02),p1(0x7f),p1(0x50),p1(0x3c),p1(0x9f),p1(0xa8) ;\
++      .long   p1(0x51),p1(0xa3),p1(0x40),p1(0x8f),p1(0x92),p1(0x9d),p1(0x38),p1(0xf5) ;\
++      .long   p1(0xbc),p1(0xb6),p1(0xda),p1(0x21),p1(0x10),p1(0xff),p1(0xf3),p1(0xd2)
++#define sb_data4(p1) \
++      .long   p1(0xcd),p1(0x0c),p1(0x13),p1(0xec),p1(0x5f),p1(0x97),p1(0x44),p1(0x17) ;\
++      .long   p1(0xc4),p1(0xa7),p1(0x7e),p1(0x3d),p1(0x64),p1(0x5d),p1(0x19),p1(0x73) ;\
++      .long   p1(0x60),p1(0x81),p1(0x4f),p1(0xdc),p1(0x22),p1(0x2a),p1(0x90),p1(0x88) ;\
++      .long   p1(0x46),p1(0xee),p1(0xb8),p1(0x14),p1(0xde),p1(0x5e),p1(0x0b),p1(0xdb)
++#define sb_data5(p1) \
++      .long   p1(0xe0),p1(0x32),p1(0x3a),p1(0x0a),p1(0x49),p1(0x06),p1(0x24),p1(0x5c) ;\
++      .long   p1(0xc2),p1(0xd3),p1(0xac),p1(0x62),p1(0x91),p1(0x95),p1(0xe4),p1(0x79) ;\
++      .long   p1(0xe7),p1(0xc8),p1(0x37),p1(0x6d),p1(0x8d),p1(0xd5),p1(0x4e),p1(0xa9) ;\
++      .long   p1(0x6c),p1(0x56),p1(0xf4),p1(0xea),p1(0x65),p1(0x7a),p1(0xae),p1(0x08)
++#define sb_data6(p1) \
++      .long   p1(0xba),p1(0x78),p1(0x25),p1(0x2e),p1(0x1c),p1(0xa6),p1(0xb4),p1(0xc6) ;\
++      .long   p1(0xe8),p1(0xdd),p1(0x74),p1(0x1f),p1(0x4b),p1(0xbd),p1(0x8b),p1(0x8a) ;\
++      .long   p1(0x70),p1(0x3e),p1(0xb5),p1(0x66),p1(0x48),p1(0x03),p1(0xf6),p1(0x0e) ;\
++      .long   p1(0x61),p1(0x35),p1(0x57),p1(0xb9),p1(0x86),p1(0xc1),p1(0x1d),p1(0x9e)
++#define sb_data7(p1) \
++      .long   p1(0xe1),p1(0xf8),p1(0x98),p1(0x11),p1(0x69),p1(0xd9),p1(0x8e),p1(0x94) ;\
++      .long   p1(0x9b),p1(0x1e),p1(0x87),p1(0xe9),p1(0xce),p1(0x55),p1(0x28),p1(0xdf) ;\
++      .long   p1(0x8c),p1(0xa1),p1(0x89),p1(0x0d),p1(0xbf),p1(0xe6),p1(0x42),p1(0x68) ;\
++      .long   p1(0x41),p1(0x99),p1(0x2d),p1(0x0f),p1(0xb0),p1(0x54),p1(0xbb),p1(0x16)
++
++// Inverse S-box data - 256 entries
++
++#define ib_data0(p1) \
++      .long   p1(0x52),p1(0x09),p1(0x6a),p1(0xd5),p1(0x30),p1(0x36),p1(0xa5),p1(0x38) ;\
++      .long   p1(0xbf),p1(0x40),p1(0xa3),p1(0x9e),p1(0x81),p1(0xf3),p1(0xd7),p1(0xfb) ;\
++      .long   p1(0x7c),p1(0xe3),p1(0x39),p1(0x82),p1(0x9b),p1(0x2f),p1(0xff),p1(0x87) ;\
++      .long   p1(0x34),p1(0x8e),p1(0x43),p1(0x44),p1(0xc4),p1(0xde),p1(0xe9),p1(0xcb)
++#define ib_data1(p1) \
++      .long   p1(0x54),p1(0x7b),p1(0x94),p1(0x32),p1(0xa6),p1(0xc2),p1(0x23),p1(0x3d) ;\
++      .long   p1(0xee),p1(0x4c),p1(0x95),p1(0x0b),p1(0x42),p1(0xfa),p1(0xc3),p1(0x4e) ;\
++      .long   p1(0x08),p1(0x2e),p1(0xa1),p1(0x66),p1(0x28),p1(0xd9),p1(0x24),p1(0xb2) ;\
++      .long   p1(0x76),p1(0x5b),p1(0xa2),p1(0x49),p1(0x6d),p1(0x8b),p1(0xd1),p1(0x25)
++#define ib_data2(p1) \
++      .long   p1(0x72),p1(0xf8),p1(0xf6),p1(0x64),p1(0x86),p1(0x68),p1(0x98),p1(0x16) ;\
++      .long   p1(0xd4),p1(0xa4),p1(0x5c),p1(0xcc),p1(0x5d),p1(0x65),p1(0xb6),p1(0x92) ;\
++      .long   p1(0x6c),p1(0x70),p1(0x48),p1(0x50),p1(0xfd),p1(0xed),p1(0xb9),p1(0xda) ;\
++      .long   p1(0x5e),p1(0x15),p1(0x46),p1(0x57),p1(0xa7),p1(0x8d),p1(0x9d),p1(0x84)
++#define ib_data3(p1) \
++      .long   p1(0x90),p1(0xd8),p1(0xab),p1(0x00),p1(0x8c),p1(0xbc),p1(0xd3),p1(0x0a) ;\
++      .long   p1(0xf7),p1(0xe4),p1(0x58),p1(0x05),p1(0xb8),p1(0xb3),p1(0x45),p1(0x06) ;\
++      .long   p1(0xd0),p1(0x2c),p1(0x1e),p1(0x8f),p1(0xca),p1(0x3f),p1(0x0f),p1(0x02) ;\
++      .long   p1(0xc1),p1(0xaf),p1(0xbd),p1(0x03),p1(0x01),p1(0x13),p1(0x8a),p1(0x6b)
++#define ib_data4(p1) \
++      .long   p1(0x3a),p1(0x91),p1(0x11),p1(0x41),p1(0x4f),p1(0x67),p1(0xdc),p1(0xea) ;\
++      .long   p1(0x97),p1(0xf2),p1(0xcf),p1(0xce),p1(0xf0),p1(0xb4),p1(0xe6),p1(0x73) ;\
++      .long   p1(0x96),p1(0xac),p1(0x74),p1(0x22),p1(0xe7),p1(0xad),p1(0x35),p1(0x85) ;\
++      .long   p1(0xe2),p1(0xf9),p1(0x37),p1(0xe8),p1(0x1c),p1(0x75),p1(0xdf),p1(0x6e)
++#define ib_data5(p1) \
++      .long   p1(0x47),p1(0xf1),p1(0x1a),p1(0x71),p1(0x1d),p1(0x29),p1(0xc5),p1(0x89) ;\
++      .long   p1(0x6f),p1(0xb7),p1(0x62),p1(0x0e),p1(0xaa),p1(0x18),p1(0xbe),p1(0x1b) ;\
++      .long   p1(0xfc),p1(0x56),p1(0x3e),p1(0x4b),p1(0xc6),p1(0xd2),p1(0x79),p1(0x20) ;\
++      .long   p1(0x9a),p1(0xdb),p1(0xc0),p1(0xfe),p1(0x78),p1(0xcd),p1(0x5a),p1(0xf4)
++#define ib_data6(p1) \
++      .long   p1(0x1f),p1(0xdd),p1(0xa8),p1(0x33),p1(0x88),p1(0x07),p1(0xc7),p1(0x31) ;\
++      .long   p1(0xb1),p1(0x12),p1(0x10),p1(0x59),p1(0x27),p1(0x80),p1(0xec),p1(0x5f) ;\
++      .long   p1(0x60),p1(0x51),p1(0x7f),p1(0xa9),p1(0x19),p1(0xb5),p1(0x4a),p1(0x0d) ;\
++      .long   p1(0x2d),p1(0xe5),p1(0x7a),p1(0x9f),p1(0x93),p1(0xc9),p1(0x9c),p1(0xef)
++#define ib_data7(p1) \
++      .long   p1(0xa0),p1(0xe0),p1(0x3b),p1(0x4d),p1(0xae),p1(0x2a),p1(0xf5),p1(0xb0) ;\
++      .long   p1(0xc8),p1(0xeb),p1(0xbb),p1(0x3c),p1(0x83),p1(0x53),p1(0x99),p1(0x61) ;\
++      .long   p1(0x17),p1(0x2b),p1(0x04),p1(0x7e),p1(0xba),p1(0x77),p1(0xd6),p1(0x26) ;\
++      .long   p1(0xe1),p1(0x69),p1(0x14),p1(0x63),p1(0x55),p1(0x21),p1(0x0c),p1(0x7d)
++
++// The rcon_table (needed for the key schedule)
++//
++// Here is original Dr Brian Gladman's source code:
++//    _rcon_tab:
++//    %assign x   1
++//    %rep 29
++//        dd  x
++//    %assign x f2(x)
++//    %endrep
++//
++// Here is precomputed output (it's more portable this way):
++
++      .align  ALIGN32BYTES
++aes_rcon_tab:
++      .long   0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
++      .long   0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f
++      .long   0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4
++      .long   0xb3,0x7d,0xfa,0xef,0xc5
++
++// The forward xor tables
++
++      .align  ALIGN32BYTES
++aes_ft_tab:
++      sb_data0(u0)
++      sb_data1(u0)
++      sb_data2(u0)
++      sb_data3(u0)
++      sb_data4(u0)
++      sb_data5(u0)
++      sb_data6(u0)
++      sb_data7(u0)
++
++      sb_data0(u1)
++      sb_data1(u1)
++      sb_data2(u1)
++      sb_data3(u1)
++      sb_data4(u1)
++      sb_data5(u1)
++      sb_data6(u1)
++      sb_data7(u1)
++
++      sb_data0(u2)
++      sb_data1(u2)
++      sb_data2(u2)
++      sb_data3(u2)
++      sb_data4(u2)
++      sb_data5(u2)
++      sb_data6(u2)
++      sb_data7(u2)
++
++      sb_data0(u3)
++      sb_data1(u3)
++      sb_data2(u3)
++      sb_data3(u3)
++      sb_data4(u3)
++      sb_data5(u3)
++      sb_data6(u3)
++      sb_data7(u3)
++
++      .align  ALIGN32BYTES
++aes_fl_tab:
++      sb_data0(w0)
++      sb_data1(w0)
++      sb_data2(w0)
++      sb_data3(w0)
++      sb_data4(w0)
++      sb_data5(w0)
++      sb_data6(w0)
++      sb_data7(w0)
++
++      sb_data0(w1)
++      sb_data1(w1)
++      sb_data2(w1)
++      sb_data3(w1)
++      sb_data4(w1)
++      sb_data5(w1)
++      sb_data6(w1)
++      sb_data7(w1)
++
++      sb_data0(w2)
++      sb_data1(w2)
++      sb_data2(w2)
++      sb_data3(w2)
++      sb_data4(w2)
++      sb_data5(w2)
++      sb_data6(w2)
++      sb_data7(w2)
++
++      sb_data0(w3)
++      sb_data1(w3)
++      sb_data2(w3)
++      sb_data3(w3)
++      sb_data4(w3)
++      sb_data5(w3)
++      sb_data6(w3)
++      sb_data7(w3)
++
++// The inverse xor tables
++
++      .align  ALIGN32BYTES
++aes_it_tab:
++      ib_data0(v0)
++      ib_data1(v0)
++      ib_data2(v0)
++      ib_data3(v0)
++      ib_data4(v0)
++      ib_data5(v0)
++      ib_data6(v0)
++      ib_data7(v0)
++
++      ib_data0(v1)
++      ib_data1(v1)
++      ib_data2(v1)
++      ib_data3(v1)
++      ib_data4(v1)
++      ib_data5(v1)
++      ib_data6(v1)
++      ib_data7(v1)
++
++      ib_data0(v2)
++      ib_data1(v2)
++      ib_data2(v2)
++      ib_data3(v2)
++      ib_data4(v2)
++      ib_data5(v2)
++      ib_data6(v2)
++      ib_data7(v2)
++
++      ib_data0(v3)
++      ib_data1(v3)
++      ib_data2(v3)
++      ib_data3(v3)
++      ib_data4(v3)
++      ib_data5(v3)
++      ib_data6(v3)
++      ib_data7(v3)
++
++      .align  ALIGN32BYTES
++aes_il_tab:
++      ib_data0(w0)
++      ib_data1(w0)
++      ib_data2(w0)
++      ib_data3(w0)
++      ib_data4(w0)
++      ib_data5(w0)
++      ib_data6(w0)
++      ib_data7(w0)
++
++      ib_data0(w1)
++      ib_data1(w1)
++      ib_data2(w1)
++      ib_data3(w1)
++      ib_data4(w1)
++      ib_data5(w1)
++      ib_data6(w1)
++      ib_data7(w1)
++
++      ib_data0(w2)
++      ib_data1(w2)
++      ib_data2(w2)
++      ib_data3(w2)
++      ib_data4(w2)
++      ib_data5(w2)
++      ib_data6(w2)
++      ib_data7(w2)
++
++      ib_data0(w3)
++      ib_data1(w3)
++      ib_data2(w3)
++      ib_data3(w3)
++      ib_data4(w3)
++      ib_data5(w3)
++      ib_data6(w3)
++      ib_data7(w3)
++
++// The inverse mix column tables
++
++      .align  ALIGN32BYTES
++aes_im_tab:
++      im_data0(v0)
++      im_data1(v0)
++      im_data2(v0)
++      im_data3(v0)
++      im_data4(v0)
++      im_data5(v0)
++      im_data6(v0)
++      im_data7(v0)
++
++      im_data0(v1)
++      im_data1(v1)
++      im_data2(v1)
++      im_data3(v1)
++      im_data4(v1)
++      im_data5(v1)
++      im_data6(v1)
++      im_data7(v1)
++
++      im_data0(v2)
++      im_data1(v2)
++      im_data2(v2)
++      im_data3(v2)
++      im_data4(v2)
++      im_data5(v2)
++      im_data6(v2)
++      im_data7(v2)
++
++      im_data0(v3)
++      im_data1(v3)
++      im_data2(v3)
++      im_data3(v3)
++      im_data4(v3)
++      im_data5(v3)
++      im_data6(v3)
++      im_data7(v3)
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/aes/aes.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1415 @@
++// I retain copyright in this code but I encourage its free use provided
++// that I don't carry any responsibility for the results. I am especially 
++// happy to see it used in free and open source software. If you do use 
++// it I would appreciate an acknowledgement of its origin in the code or
++// the product that results and I would also appreciate knowing a little
++// about the use to which it is being put. I am grateful to Frank Yellin
++// for some ideas that are used in this implementation.
++//
++// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001.
++//
++// This is an implementation of the AES encryption algorithm (Rijndael)
++// designed by Joan Daemen and Vincent Rijmen. This version is designed
++// to provide both fixed and dynamic block and key lengths and can also 
++// run with either big or little endian internal byte order (see aes.h). 
++// It inputs block and key lengths in bytes with the legal values being 
++// 16, 24 and 32.
++
++/*
++ * Modified by Jari Ruusu,  May 1 2001
++ *  - Fixed some compile warnings, code was ok but gcc warned anyway.
++ *  - Changed basic types: byte -> unsigned char, word -> u_int32_t
++ *  - Major name space cleanup: Names visible to outside now begin
++ *    with "aes_" or "AES_". A lot of stuff moved from aes.h to aes.c
++ *  - Removed C++ and DLL support as part of name space cleanup.
++ *  - Eliminated unnecessary recomputation of tables. (actual bug fix)
++ *  - Merged precomputed constant tables to aes.c file.
++ *  - Removed data alignment restrictions for portability reasons.
++ *  - Made block and key lengths accept bit count (128/192/256)
++ *    as well byte count (16/24/32).
++ *  - Removed all error checks. This change also eliminated the need
++ *    to preinitialize the context struct to zero.
++ *  - Removed some totally unused constants.
++ */
++
++#include "crypto/aes.h"
++
++// CONFIGURATION OPTIONS (see also aes.h)
++//
++// 1.  Define UNROLL for full loop unrolling in encryption and decryption.
++// 2.  Define PARTIAL_UNROLL to unroll two loops in encryption and decryption.
++// 3.  Define FIXED_TABLES for compiled rather than dynamic tables.
++// 4.  Define FF_TABLES to use tables for field multiplies and inverses.
++//     Do not enable this without understanding stack space requirements.
++// 5.  Define ARRAYS to use arrays to hold the local state block. If this
++//     is not defined, individually declared 32-bit words are used.
++// 6.  Define FAST_VARIABLE if a high speed variable block implementation
++//     is needed (essentially three separate fixed block size code sequences)
++// 7.  Define either ONE_TABLE or FOUR_TABLES for a fast table driven 
++//     version using 1 table (2 kbytes of table space) or 4 tables (8
++//     kbytes of table space) for higher speed.
++// 8.  Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed 
++//     increase by using tables for the last rounds but with more table
++//     space (2 or 8 kbytes extra).
++// 9.  If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but 
++//     slower version is provided.
++// 10. If fast decryption key scheduling is needed define ONE_IM_TABLE
++//     or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra).
++
++#define UNROLL
++//#define PARTIAL_UNROLL
++
++#define FIXED_TABLES
++//#define FF_TABLES
++//#define ARRAYS
++#define FAST_VARIABLE
++
++//#define ONE_TABLE
++#define FOUR_TABLES
++
++//#define ONE_LR_TABLE
++#define FOUR_LR_TABLES
++
++//#define ONE_IM_TABLE
++#define FOUR_IM_TABLES
++
++#if defined(UNROLL) && defined (PARTIAL_UNROLL)
++#error both UNROLL and PARTIAL_UNROLL are defined
++#endif
++
++#if defined(ONE_TABLE) && defined (FOUR_TABLES)
++#error both ONE_TABLE and FOUR_TABLES are defined
++#endif
++
++#if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES)
++#error both ONE_LR_TABLE and FOUR_LR_TABLES are defined
++#endif
++
++#if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES)
++#error both ONE_IM_TABLE and FOUR_IM_TABLES are defined
++#endif
++
++#if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && AES_BLOCK_SIZE != 32
++#error an illegal block size has been specified
++#endif  
++
++// upr(x,n): rotates bytes within words by n positions, moving bytes 
++// to higher index positions with wrap around into low positions
++// ups(x,n): moves bytes by n positions to higher index positions in 
++// words but without wrap around
++// bval(x,n): extracts a byte from a word
++
++#define upr(x,n)        (((x) << 8 * (n)) | ((x) >> (32 - 8 * (n))))
++#define ups(x,n)        ((x) << 8 * (n))
++#define bval(x,n)       ((unsigned char)((x) >> 8 * (n)))
++#define bytes2word(b0, b1, b2, b3)  \
++        ((u_int32_t)(b3) << 24 | (u_int32_t)(b2) << 16 | (u_int32_t)(b1) << 8 | (b0))
++
++
++/* little endian processor without data alignment restrictions: AES_LE_OK */
++/* original code: i386 */
++#if defined(i386) || defined(_I386) || defined(__i386__) || defined(__i386) 
++#define       AES_LE_OK 1
++/* added (tested): alpha  --jjo */
++#elif defined(__alpha__)|| defined (__alpha)
++#define AES_LE_OK 1
++/* added (tested): ia64  --jjo */
++#elif defined(__ia64__)|| defined (__ia64)
++#define AES_LE_OK 1
++#endif
++
++#ifdef AES_LE_OK
++/* little endian processor without data alignment restrictions */
++#define word_in(x)      *(u_int32_t*)(x)
++#define const_word_in(x)      *(const u_int32_t*)(x)
++#define word_out(x,v)   *(u_int32_t*)(x) = (v)
++#define const_word_out(x,v)   *(const u_int32_t*)(x) = (v)
++#else
++/* slower but generic big endian or with data alignment restrictions */
++/* some additional "const" touches to stop "gcc -Wcast-qual" complains --jjo */
++#define word_in(x)      ((u_int32_t)(((unsigned char *)(x))[0])|((u_int32_t)(((unsigned char *)(x))[1])<<8)|((u_int32_t)(((unsigned char *)(x))[2])<<16)|((u_int32_t)(((unsigned char *)(x))[3])<<24))
++#define const_word_in(x)      ((const u_int32_t)(((const unsigned char *)(x))[0])|((const u_int32_t)(((const unsigned char *)(x))[1])<<8)|((const u_int32_t)(((const unsigned char *)(x))[2])<<16)|((const u_int32_t)(((const unsigned char *)(x))[3])<<24))
++#define word_out(x,v)   ((unsigned char *)(x))[0]=(v),((unsigned char *)(x))[1]=((v)>>8),((unsigned char *)(x))[2]=((v)>>16),((unsigned char *)(x))[3]=((v)>>24)
++#define const_word_out(x,v)   ((const unsigned char *)(x))[0]=(v),((const unsigned char *)(x))[1]=((v)>>8),((const unsigned char *)(x))[2]=((v)>>16),((const unsigned char *)(x))[3]=((v)>>24)
++#endif
++
++// Disable at least some poor combinations of options
++
++#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
++#define FIXED_TABLES
++#undef  UNROLL
++#undef  ONE_LR_TABLE
++#undef  FOUR_LR_TABLES
++#undef  ONE_IM_TABLE
++#undef  FOUR_IM_TABLES
++#elif !defined(FOUR_TABLES)
++#ifdef  FOUR_LR_TABLES
++#undef  FOUR_LR_TABLES
++#define ONE_LR_TABLE
++#endif
++#ifdef  FOUR_IM_TABLES
++#undef  FOUR_IM_TABLES
++#define ONE_IM_TABLE
++#endif
++#elif !defined(AES_BLOCK_SIZE)
++#if defined(UNROLL)
++#define PARTIAL_UNROLL
++#undef UNROLL
++#endif
++#endif
++
++// the finite field modular polynomial and elements
++
++#define ff_poly 0x011b
++#define ff_hi   0x80
++
++// multiply four bytes in GF(2^8) by 'x' {02} in parallel
++
++#define m1  0x80808080
++#define m2  0x7f7f7f7f
++#define m3  0x0000001b
++#define FFmulX(x)  ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * m3))
++
++// The following defines provide alternative definitions of FFmulX that might
++// give improved performance if a fast 32-bit multiply is not available. Note
++// that a temporary variable u needs to be defined where FFmulX is used.
++
++// #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) 
++// #define m4  0x1b1b1b1b
++// #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) 
++
++// perform column mix operation on four bytes in parallel
++
++#define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ upr(x ^ f2,3) ^ upr(x,2) ^ upr(x,1))
++
++#if defined(FIXED_TABLES)
++
++// the S-Box table
++
++static const unsigned char s_box[256] =
++{
++    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
++    0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
++    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
++    0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
++    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
++    0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
++    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
++    0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
++    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
++    0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
++    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
++    0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
++    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
++    0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
++    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
++    0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
++    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
++    0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
++    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
++    0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
++    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
++    0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
++    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
++    0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
++    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
++    0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
++    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
++    0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
++    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
++    0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
++    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
++    0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
++};
++
++// the inverse S-Box table
++
++static const unsigned char inv_s_box[256] =
++{
++    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
++    0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
++    0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
++    0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
++    0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
++    0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
++    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
++    0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
++    0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
++    0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
++    0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
++    0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
++    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
++    0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
++    0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
++    0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
++    0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
++    0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
++    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
++    0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
++    0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
++    0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
++    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
++    0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
++    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
++    0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
++    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
++    0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
++    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
++    0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
++    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
++    0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
++};
++
++#define w0(p)          0x000000##p
++
++// Number of elements required in this table for different
++// block and key lengths is:
++//
++// Nk =      4  6  8
++//        ----------
++// Nb = 4 | 10  8  7
++//      6 | 19 12 11
++//      8 | 29 19 14
++//
++// this table can be a table of bytes if the key schedule
++// code is adjusted accordingly
++
++static const u_int32_t rcon_tab[29] =
++{
++    w0(01), w0(02), w0(04), w0(08),
++    w0(10), w0(20), w0(40), w0(80),
++    w0(1b), w0(36), w0(6c), w0(d8),
++    w0(ab), w0(4d), w0(9a), w0(2f),
++    w0(5e), w0(bc), w0(63), w0(c6),
++    w0(97), w0(35), w0(6a), w0(d4),
++    w0(b3), w0(7d), w0(fa), w0(ef),
++    w0(c5)
++};
++
++#undef  w0
++
++#define r0(p,q,r,s) 0x##p##q##r##s
++#define r1(p,q,r,s) 0x##q##r##s##p
++#define r2(p,q,r,s) 0x##r##s##p##q
++#define r3(p,q,r,s) 0x##s##p##q##r
++#define w0(p)          0x000000##p
++#define w1(p)        0x0000##p##00
++#define w2(p)        0x00##p##0000
++#define w3(p)        0x##p##000000
++
++#if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES)) 
++
++//  data for forward tables (other than last round)
++
++#define f_table \
++    r(a5,63,63,c6), r(84,7c,7c,f8), r(99,77,77,ee), r(8d,7b,7b,f6),\
++    r(0d,f2,f2,ff), r(bd,6b,6b,d6), r(b1,6f,6f,de), r(54,c5,c5,91),\
++    r(50,30,30,60), r(03,01,01,02), r(a9,67,67,ce), r(7d,2b,2b,56),\
++    r(19,fe,fe,e7), r(62,d7,d7,b5), r(e6,ab,ab,4d), r(9a,76,76,ec),\
++    r(45,ca,ca,8f), r(9d,82,82,1f), r(40,c9,c9,89), r(87,7d,7d,fa),\
++    r(15,fa,fa,ef), r(eb,59,59,b2), r(c9,47,47,8e), r(0b,f0,f0,fb),\
++    r(ec,ad,ad,41), r(67,d4,d4,b3), r(fd,a2,a2,5f), r(ea,af,af,45),\
++    r(bf,9c,9c,23), r(f7,a4,a4,53), r(96,72,72,e4), r(5b,c0,c0,9b),\
++    r(c2,b7,b7,75), r(1c,fd,fd,e1), r(ae,93,93,3d), r(6a,26,26,4c),\
++    r(5a,36,36,6c), r(41,3f,3f,7e), r(02,f7,f7,f5), r(4f,cc,cc,83),\
++    r(5c,34,34,68), r(f4,a5,a5,51), r(34,e5,e5,d1), r(08,f1,f1,f9),\
++    r(93,71,71,e2), r(73,d8,d8,ab), r(53,31,31,62), r(3f,15,15,2a),\
++    r(0c,04,04,08), r(52,c7,c7,95), r(65,23,23,46), r(5e,c3,c3,9d),\
++    r(28,18,18,30), r(a1,96,96,37), r(0f,05,05,0a), r(b5,9a,9a,2f),\
++    r(09,07,07,0e), r(36,12,12,24), r(9b,80,80,1b), r(3d,e2,e2,df),\
++    r(26,eb,eb,cd), r(69,27,27,4e), r(cd,b2,b2,7f), r(9f,75,75,ea),\
++    r(1b,09,09,12), r(9e,83,83,1d), r(74,2c,2c,58), r(2e,1a,1a,34),\
++    r(2d,1b,1b,36), r(b2,6e,6e,dc), r(ee,5a,5a,b4), r(fb,a0,a0,5b),\
++    r(f6,52,52,a4), r(4d,3b,3b,76), r(61,d6,d6,b7), r(ce,b3,b3,7d),\
++    r(7b,29,29,52), r(3e,e3,e3,dd), r(71,2f,2f,5e), r(97,84,84,13),\
++    r(f5,53,53,a6), r(68,d1,d1,b9), r(00,00,00,00), r(2c,ed,ed,c1),\
++    r(60,20,20,40), r(1f,fc,fc,e3), r(c8,b1,b1,79), r(ed,5b,5b,b6),\
++    r(be,6a,6a,d4), r(46,cb,cb,8d), r(d9,be,be,67), r(4b,39,39,72),\
++    r(de,4a,4a,94), r(d4,4c,4c,98), r(e8,58,58,b0), r(4a,cf,cf,85),\
++    r(6b,d0,d0,bb), r(2a,ef,ef,c5), r(e5,aa,aa,4f), r(16,fb,fb,ed),\
++    r(c5,43,43,86), r(d7,4d,4d,9a), r(55,33,33,66), r(94,85,85,11),\
++    r(cf,45,45,8a), r(10,f9,f9,e9), r(06,02,02,04), r(81,7f,7f,fe),\
++    r(f0,50,50,a0), r(44,3c,3c,78), r(ba,9f,9f,25), r(e3,a8,a8,4b),\
++    r(f3,51,51,a2), r(fe,a3,a3,5d), r(c0,40,40,80), r(8a,8f,8f,05),\
++    r(ad,92,92,3f), r(bc,9d,9d,21), r(48,38,38,70), r(04,f5,f5,f1),\
++    r(df,bc,bc,63), r(c1,b6,b6,77), r(75,da,da,af), r(63,21,21,42),\
++    r(30,10,10,20), r(1a,ff,ff,e5), r(0e,f3,f3,fd), r(6d,d2,d2,bf),\
++    r(4c,cd,cd,81), r(14,0c,0c,18), r(35,13,13,26), r(2f,ec,ec,c3),\
++    r(e1,5f,5f,be), r(a2,97,97,35), r(cc,44,44,88), r(39,17,17,2e),\
++    r(57,c4,c4,93), r(f2,a7,a7,55), r(82,7e,7e,fc), r(47,3d,3d,7a),\
++    r(ac,64,64,c8), r(e7,5d,5d,ba), r(2b,19,19,32), r(95,73,73,e6),\
++    r(a0,60,60,c0), r(98,81,81,19), r(d1,4f,4f,9e), r(7f,dc,dc,a3),\
++    r(66,22,22,44), r(7e,2a,2a,54), r(ab,90,90,3b), r(83,88,88,0b),\
++    r(ca,46,46,8c), r(29,ee,ee,c7), r(d3,b8,b8,6b), r(3c,14,14,28),\
++    r(79,de,de,a7), r(e2,5e,5e,bc), r(1d,0b,0b,16), r(76,db,db,ad),\
++    r(3b,e0,e0,db), r(56,32,32,64), r(4e,3a,3a,74), r(1e,0a,0a,14),\
++    r(db,49,49,92), r(0a,06,06,0c), r(6c,24,24,48), r(e4,5c,5c,b8),\
++    r(5d,c2,c2,9f), r(6e,d3,d3,bd), r(ef,ac,ac,43), r(a6,62,62,c4),\
++    r(a8,91,91,39), r(a4,95,95,31), r(37,e4,e4,d3), r(8b,79,79,f2),\
++    r(32,e7,e7,d5), r(43,c8,c8,8b), r(59,37,37,6e), r(b7,6d,6d,da),\
++    r(8c,8d,8d,01), r(64,d5,d5,b1), r(d2,4e,4e,9c), r(e0,a9,a9,49),\
++    r(b4,6c,6c,d8), r(fa,56,56,ac), r(07,f4,f4,f3), r(25,ea,ea,cf),\
++    r(af,65,65,ca), r(8e,7a,7a,f4), r(e9,ae,ae,47), r(18,08,08,10),\
++    r(d5,ba,ba,6f), r(88,78,78,f0), r(6f,25,25,4a), r(72,2e,2e,5c),\
++    r(24,1c,1c,38), r(f1,a6,a6,57), r(c7,b4,b4,73), r(51,c6,c6,97),\
++    r(23,e8,e8,cb), r(7c,dd,dd,a1), r(9c,74,74,e8), r(21,1f,1f,3e),\
++    r(dd,4b,4b,96), r(dc,bd,bd,61), r(86,8b,8b,0d), r(85,8a,8a,0f),\
++    r(90,70,70,e0), r(42,3e,3e,7c), r(c4,b5,b5,71), r(aa,66,66,cc),\
++    r(d8,48,48,90), r(05,03,03,06), r(01,f6,f6,f7), r(12,0e,0e,1c),\
++    r(a3,61,61,c2), r(5f,35,35,6a), r(f9,57,57,ae), r(d0,b9,b9,69),\
++    r(91,86,86,17), r(58,c1,c1,99), r(27,1d,1d,3a), r(b9,9e,9e,27),\
++    r(38,e1,e1,d9), r(13,f8,f8,eb), r(b3,98,98,2b), r(33,11,11,22),\
++    r(bb,69,69,d2), r(70,d9,d9,a9), r(89,8e,8e,07), r(a7,94,94,33),\
++    r(b6,9b,9b,2d), r(22,1e,1e,3c), r(92,87,87,15), r(20,e9,e9,c9),\
++    r(49,ce,ce,87), r(ff,55,55,aa), r(78,28,28,50), r(7a,df,df,a5),\
++    r(8f,8c,8c,03), r(f8,a1,a1,59), r(80,89,89,09), r(17,0d,0d,1a),\
++    r(da,bf,bf,65), r(31,e6,e6,d7), r(c6,42,42,84), r(b8,68,68,d0),\
++    r(c3,41,41,82), r(b0,99,99,29), r(77,2d,2d,5a), r(11,0f,0f,1e),\
++    r(cb,b0,b0,7b), r(fc,54,54,a8), r(d6,bb,bb,6d), r(3a,16,16,2c)
++
++//  data for inverse tables (other than last round)
++
++#define i_table \
++    r(50,a7,f4,51), r(53,65,41,7e), r(c3,a4,17,1a), r(96,5e,27,3a),\
++    r(cb,6b,ab,3b), r(f1,45,9d,1f), r(ab,58,fa,ac), r(93,03,e3,4b),\
++    r(55,fa,30,20), r(f6,6d,76,ad), r(91,76,cc,88), r(25,4c,02,f5),\
++    r(fc,d7,e5,4f), r(d7,cb,2a,c5), r(80,44,35,26), r(8f,a3,62,b5),\
++    r(49,5a,b1,de), r(67,1b,ba,25), r(98,0e,ea,45), r(e1,c0,fe,5d),\
++    r(02,75,2f,c3), r(12,f0,4c,81), r(a3,97,46,8d), r(c6,f9,d3,6b),\
++    r(e7,5f,8f,03), r(95,9c,92,15), r(eb,7a,6d,bf), r(da,59,52,95),\
++    r(2d,83,be,d4), r(d3,21,74,58), r(29,69,e0,49), r(44,c8,c9,8e),\
++    r(6a,89,c2,75), r(78,79,8e,f4), r(6b,3e,58,99), r(dd,71,b9,27),\
++    r(b6,4f,e1,be), r(17,ad,88,f0), r(66,ac,20,c9), r(b4,3a,ce,7d),\
++    r(18,4a,df,63), r(82,31,1a,e5), r(60,33,51,97), r(45,7f,53,62),\
++    r(e0,77,64,b1), r(84,ae,6b,bb), r(1c,a0,81,fe), r(94,2b,08,f9),\
++    r(58,68,48,70), r(19,fd,45,8f), r(87,6c,de,94), r(b7,f8,7b,52),\
++    r(23,d3,73,ab), r(e2,02,4b,72), r(57,8f,1f,e3), r(2a,ab,55,66),\
++    r(07,28,eb,b2), r(03,c2,b5,2f), r(9a,7b,c5,86), r(a5,08,37,d3),\
++    r(f2,87,28,30), r(b2,a5,bf,23), r(ba,6a,03,02), r(5c,82,16,ed),\
++    r(2b,1c,cf,8a), r(92,b4,79,a7), r(f0,f2,07,f3), r(a1,e2,69,4e),\
++    r(cd,f4,da,65), r(d5,be,05,06), r(1f,62,34,d1), r(8a,fe,a6,c4),\
++    r(9d,53,2e,34), r(a0,55,f3,a2), r(32,e1,8a,05), r(75,eb,f6,a4),\
++    r(39,ec,83,0b), r(aa,ef,60,40), r(06,9f,71,5e), r(51,10,6e,bd),\
++    r(f9,8a,21,3e), r(3d,06,dd,96), r(ae,05,3e,dd), r(46,bd,e6,4d),\
++    r(b5,8d,54,91), r(05,5d,c4,71), r(6f,d4,06,04), r(ff,15,50,60),\
++    r(24,fb,98,19), r(97,e9,bd,d6), r(cc,43,40,89), r(77,9e,d9,67),\
++    r(bd,42,e8,b0), r(88,8b,89,07), r(38,5b,19,e7), r(db,ee,c8,79),\
++    r(47,0a,7c,a1), r(e9,0f,42,7c), r(c9,1e,84,f8), r(00,00,00,00),\
++    r(83,86,80,09), r(48,ed,2b,32), r(ac,70,11,1e), r(4e,72,5a,6c),\
++    r(fb,ff,0e,fd), r(56,38,85,0f), r(1e,d5,ae,3d), r(27,39,2d,36),\
++    r(64,d9,0f,0a), r(21,a6,5c,68), r(d1,54,5b,9b), r(3a,2e,36,24),\
++    r(b1,67,0a,0c), r(0f,e7,57,93), r(d2,96,ee,b4), r(9e,91,9b,1b),\
++    r(4f,c5,c0,80), r(a2,20,dc,61), r(69,4b,77,5a), r(16,1a,12,1c),\
++    r(0a,ba,93,e2), r(e5,2a,a0,c0), r(43,e0,22,3c), r(1d,17,1b,12),\
++    r(0b,0d,09,0e), r(ad,c7,8b,f2), r(b9,a8,b6,2d), r(c8,a9,1e,14),\
++    r(85,19,f1,57), r(4c,07,75,af), r(bb,dd,99,ee), r(fd,60,7f,a3),\
++    r(9f,26,01,f7), r(bc,f5,72,5c), r(c5,3b,66,44), r(34,7e,fb,5b),\
++    r(76,29,43,8b), r(dc,c6,23,cb), r(68,fc,ed,b6), r(63,f1,e4,b8),\
++    r(ca,dc,31,d7), r(10,85,63,42), r(40,22,97,13), r(20,11,c6,84),\
++    r(7d,24,4a,85), r(f8,3d,bb,d2), r(11,32,f9,ae), r(6d,a1,29,c7),\
++    r(4b,2f,9e,1d), r(f3,30,b2,dc), r(ec,52,86,0d), r(d0,e3,c1,77),\
++    r(6c,16,b3,2b), r(99,b9,70,a9), r(fa,48,94,11), r(22,64,e9,47),\
++    r(c4,8c,fc,a8), r(1a,3f,f0,a0), r(d8,2c,7d,56), r(ef,90,33,22),\
++    r(c7,4e,49,87), r(c1,d1,38,d9), r(fe,a2,ca,8c), r(36,0b,d4,98),\
++    r(cf,81,f5,a6), r(28,de,7a,a5), r(26,8e,b7,da), r(a4,bf,ad,3f),\
++    r(e4,9d,3a,2c), r(0d,92,78,50), r(9b,cc,5f,6a), r(62,46,7e,54),\
++    r(c2,13,8d,f6), r(e8,b8,d8,90), r(5e,f7,39,2e), r(f5,af,c3,82),\
++    r(be,80,5d,9f), r(7c,93,d0,69), r(a9,2d,d5,6f), r(b3,12,25,cf),\
++    r(3b,99,ac,c8), r(a7,7d,18,10), r(6e,63,9c,e8), r(7b,bb,3b,db),\
++    r(09,78,26,cd), r(f4,18,59,6e), r(01,b7,9a,ec), r(a8,9a,4f,83),\
++    r(65,6e,95,e6), r(7e,e6,ff,aa), r(08,cf,bc,21), r(e6,e8,15,ef),\
++    r(d9,9b,e7,ba), r(ce,36,6f,4a), r(d4,09,9f,ea), r(d6,7c,b0,29),\
++    r(af,b2,a4,31), r(31,23,3f,2a), r(30,94,a5,c6), r(c0,66,a2,35),\
++    r(37,bc,4e,74), r(a6,ca,82,fc), r(b0,d0,90,e0), r(15,d8,a7,33),\
++    r(4a,98,04,f1), r(f7,da,ec,41), r(0e,50,cd,7f), r(2f,f6,91,17),\
++    r(8d,d6,4d,76), r(4d,b0,ef,43), r(54,4d,aa,cc), r(df,04,96,e4),\
++    r(e3,b5,d1,9e), r(1b,88,6a,4c), r(b8,1f,2c,c1), r(7f,51,65,46),\
++    r(04,ea,5e,9d), r(5d,35,8c,01), r(73,74,87,fa), r(2e,41,0b,fb),\
++    r(5a,1d,67,b3), r(52,d2,db,92), r(33,56,10,e9), r(13,47,d6,6d),\
++    r(8c,61,d7,9a), r(7a,0c,a1,37), r(8e,14,f8,59), r(89,3c,13,eb),\
++    r(ee,27,a9,ce), r(35,c9,61,b7), r(ed,e5,1c,e1), r(3c,b1,47,7a),\
++    r(59,df,d2,9c), r(3f,73,f2,55), r(79,ce,14,18), r(bf,37,c7,73),\
++    r(ea,cd,f7,53), r(5b,aa,fd,5f), r(14,6f,3d,df), r(86,db,44,78),\
++    r(81,f3,af,ca), r(3e,c4,68,b9), r(2c,34,24,38), r(5f,40,a3,c2),\
++    r(72,c3,1d,16), r(0c,25,e2,bc), r(8b,49,3c,28), r(41,95,0d,ff),\
++    r(71,01,a8,39), r(de,b3,0c,08), r(9c,e4,b4,d8), r(90,c1,56,64),\
++    r(61,84,cb,7b), r(70,b6,32,d5), r(74,5c,6c,48), r(42,57,b8,d0)
++
++// generate the required tables in the desired endian format
++
++#undef  r
++#define r   r0
++
++#if defined(ONE_TABLE)
++static const u_int32_t ft_tab[256] =
++    {   f_table };
++#elif defined(FOUR_TABLES)
++static const u_int32_t ft_tab[4][256] =
++{   {   f_table },
++#undef  r
++#define r   r1
++    {   f_table },
++#undef  r
++#define r   r2
++    {   f_table },
++#undef  r
++#define r   r3
++    {   f_table }
++};
++#endif
++
++#undef  r
++#define r   r0
++#if defined(ONE_TABLE)
++static const u_int32_t it_tab[256] =
++    {   i_table };
++#elif defined(FOUR_TABLES)
++static const u_int32_t it_tab[4][256] =
++{   {   i_table },
++#undef  r
++#define r   r1
++    {   i_table },
++#undef  r
++#define r   r2
++    {   i_table },
++#undef  r
++#define r   r3
++    {   i_table }
++};
++#endif
++
++#endif
++
++#if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES)) 
++
++//  data for inverse tables (last round)
++
++#define li_table    \
++    w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38),\
++    w(bf), w(40), w(a3), w(9e), w(81), w(f3), w(d7), w(fb),\
++    w(7c), w(e3), w(39), w(82), w(9b), w(2f), w(ff), w(87),\
++    w(34), w(8e), w(43), w(44), w(c4), w(de), w(e9), w(cb),\
++    w(54), w(7b), w(94), w(32), w(a6), w(c2), w(23), w(3d),\
++    w(ee), w(4c), w(95), w(0b), w(42), w(fa), w(c3), w(4e),\
++    w(08), w(2e), w(a1), w(66), w(28), w(d9), w(24), w(b2),\
++    w(76), w(5b), w(a2), w(49), w(6d), w(8b), w(d1), w(25),\
++    w(72), w(f8), w(f6), w(64), w(86), w(68), w(98), w(16),\
++    w(d4), w(a4), w(5c), w(cc), w(5d), w(65), w(b6), w(92),\
++    w(6c), w(70), w(48), w(50), w(fd), w(ed), w(b9), w(da),\
++    w(5e), w(15), w(46), w(57), w(a7), w(8d), w(9d), w(84),\
++    w(90), w(d8), w(ab), w(00), w(8c), w(bc), w(d3), w(0a),\
++    w(f7), w(e4), w(58), w(05), w(b8), w(b3), w(45), w(06),\
++    w(d0), w(2c), w(1e), w(8f), w(ca), w(3f), w(0f), w(02),\
++    w(c1), w(af), w(bd), w(03), w(01), w(13), w(8a), w(6b),\
++    w(3a), w(91), w(11), w(41), w(4f), w(67), w(dc), w(ea),\
++    w(97), w(f2), w(cf), w(ce), w(f0), w(b4), w(e6), w(73),\
++    w(96), w(ac), w(74), w(22), w(e7), w(ad), w(35), w(85),\
++    w(e2), w(f9), w(37), w(e8), w(1c), w(75), w(df), w(6e),\
++    w(47), w(f1), w(1a), w(71), w(1d), w(29), w(c5), w(89),\
++    w(6f), w(b7), w(62), w(0e), w(aa), w(18), w(be), w(1b),\
++    w(fc), w(56), w(3e), w(4b), w(c6), w(d2), w(79), w(20),\
++    w(9a), w(db), w(c0), w(fe), w(78), w(cd), w(5a), w(f4),\
++    w(1f), w(dd), w(a8), w(33), w(88), w(07), w(c7), w(31),\
++    w(b1), w(12), w(10), w(59), w(27), w(80), w(ec), w(5f),\
++    w(60), w(51), w(7f), w(a9), w(19), w(b5), w(4a), w(0d),\
++    w(2d), w(e5), w(7a), w(9f), w(93), w(c9), w(9c), w(ef),\
++    w(a0), w(e0), w(3b), w(4d), w(ae), w(2a), w(f5), w(b0),\
++    w(c8), w(eb), w(bb), w(3c), w(83), w(53), w(99), w(61),\
++    w(17), w(2b), w(04), w(7e), w(ba), w(77), w(d6), w(26),\
++    w(e1), w(69), w(14), w(63), w(55), w(21), w(0c), w(7d),
++
++// generate the required tables in the desired endian format
++
++#undef  r
++#define r(p,q,r,s)  w0(q)
++#if defined(ONE_LR_TABLE)
++static const u_int32_t fl_tab[256] =
++    {   f_table     };
++#elif defined(FOUR_LR_TABLES)
++static const u_int32_t fl_tab[4][256] =
++{   {   f_table    },
++#undef  r
++#define r(p,q,r,s)   w1(q)
++    {   f_table    },
++#undef  r
++#define r(p,q,r,s)   w2(q)
++    {   f_table    },
++#undef  r
++#define r(p,q,r,s)   w3(q)
++    {   f_table    }
++};
++#endif
++
++#undef  w
++#define w   w0
++#if defined(ONE_LR_TABLE)
++static const u_int32_t il_tab[256] =
++    {   li_table    };
++#elif defined(FOUR_LR_TABLES)
++static const u_int32_t il_tab[4][256] =
++{   {   li_table    },
++#undef  w
++#define w   w1
++    {   li_table    },
++#undef  w
++#define w   w2
++    {   li_table    },
++#undef  w
++#define w   w3
++    {   li_table    }
++};
++#endif
++
++#endif
++
++#if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES)) 
++
++#define m_table \
++    r(00,00,00,00), r(0b,0d,09,0e), r(16,1a,12,1c), r(1d,17,1b,12),\
++    r(2c,34,24,38), r(27,39,2d,36), r(3a,2e,36,24), r(31,23,3f,2a),\
++    r(58,68,48,70), r(53,65,41,7e), r(4e,72,5a,6c), r(45,7f,53,62),\
++    r(74,5c,6c,48), r(7f,51,65,46), r(62,46,7e,54), r(69,4b,77,5a),\
++    r(b0,d0,90,e0), r(bb,dd,99,ee), r(a6,ca,82,fc), r(ad,c7,8b,f2),\
++    r(9c,e4,b4,d8), r(97,e9,bd,d6), r(8a,fe,a6,c4), r(81,f3,af,ca),\
++    r(e8,b8,d8,90), r(e3,b5,d1,9e), r(fe,a2,ca,8c), r(f5,af,c3,82),\
++    r(c4,8c,fc,a8), r(cf,81,f5,a6), r(d2,96,ee,b4), r(d9,9b,e7,ba),\
++    r(7b,bb,3b,db), r(70,b6,32,d5), r(6d,a1,29,c7), r(66,ac,20,c9),\
++    r(57,8f,1f,e3), r(5c,82,16,ed), r(41,95,0d,ff), r(4a,98,04,f1),\
++    r(23,d3,73,ab), r(28,de,7a,a5), r(35,c9,61,b7), r(3e,c4,68,b9),\
++    r(0f,e7,57,93), r(04,ea,5e,9d), r(19,fd,45,8f), r(12,f0,4c,81),\
++    r(cb,6b,ab,3b), r(c0,66,a2,35), r(dd,71,b9,27), r(d6,7c,b0,29),\
++    r(e7,5f,8f,03), r(ec,52,86,0d), r(f1,45,9d,1f), r(fa,48,94,11),\
++    r(93,03,e3,4b), r(98,0e,ea,45), r(85,19,f1,57), r(8e,14,f8,59),\
++    r(bf,37,c7,73), r(b4,3a,ce,7d), r(a9,2d,d5,6f), r(a2,20,dc,61),\
++    r(f6,6d,76,ad), r(fd,60,7f,a3), r(e0,77,64,b1), r(eb,7a,6d,bf),\
++    r(da,59,52,95), r(d1,54,5b,9b), r(cc,43,40,89), r(c7,4e,49,87),\
++    r(ae,05,3e,dd), r(a5,08,37,d3), r(b8,1f,2c,c1), r(b3,12,25,cf),\
++    r(82,31,1a,e5), r(89,3c,13,eb), r(94,2b,08,f9), r(9f,26,01,f7),\
++    r(46,bd,e6,4d), r(4d,b0,ef,43), r(50,a7,f4,51), r(5b,aa,fd,5f),\
++    r(6a,89,c2,75), r(61,84,cb,7b), r(7c,93,d0,69), r(77,9e,d9,67),\
++    r(1e,d5,ae,3d), r(15,d8,a7,33), r(08,cf,bc,21), r(03,c2,b5,2f),\
++    r(32,e1,8a,05), r(39,ec,83,0b), r(24,fb,98,19), r(2f,f6,91,17),\
++    r(8d,d6,4d,76), r(86,db,44,78), r(9b,cc,5f,6a), r(90,c1,56,64),\
++    r(a1,e2,69,4e), r(aa,ef,60,40), r(b7,f8,7b,52), r(bc,f5,72,5c),\
++    r(d5,be,05,06), r(de,b3,0c,08), r(c3,a4,17,1a), r(c8,a9,1e,14),\
++    r(f9,8a,21,3e), r(f2,87,28,30), r(ef,90,33,22), r(e4,9d,3a,2c),\
++    r(3d,06,dd,96), r(36,0b,d4,98), r(2b,1c,cf,8a), r(20,11,c6,84),\
++    r(11,32,f9,ae), r(1a,3f,f0,a0), r(07,28,eb,b2), r(0c,25,e2,bc),\
++    r(65,6e,95,e6), r(6e,63,9c,e8), r(73,74,87,fa), r(78,79,8e,f4),\
++    r(49,5a,b1,de), r(42,57,b8,d0), r(5f,40,a3,c2), r(54,4d,aa,cc),\
++    r(f7,da,ec,41), r(fc,d7,e5,4f), r(e1,c0,fe,5d), r(ea,cd,f7,53),\
++    r(db,ee,c8,79), r(d0,e3,c1,77), r(cd,f4,da,65), r(c6,f9,d3,6b),\
++    r(af,b2,a4,31), r(a4,bf,ad,3f), r(b9,a8,b6,2d), r(b2,a5,bf,23),\
++    r(83,86,80,09), r(88,8b,89,07), r(95,9c,92,15), r(9e,91,9b,1b),\
++    r(47,0a,7c,a1), r(4c,07,75,af), r(51,10,6e,bd), r(5a,1d,67,b3),\
++    r(6b,3e,58,99), r(60,33,51,97), r(7d,24,4a,85), r(76,29,43,8b),\
++    r(1f,62,34,d1), r(14,6f,3d,df), r(09,78,26,cd), r(02,75,2f,c3),\
++    r(33,56,10,e9), r(38,5b,19,e7), r(25,4c,02,f5), r(2e,41,0b,fb),\
++    r(8c,61,d7,9a), r(87,6c,de,94), r(9a,7b,c5,86), r(91,76,cc,88),\
++    r(a0,55,f3,a2), r(ab,58,fa,ac), r(b6,4f,e1,be), r(bd,42,e8,b0),\
++    r(d4,09,9f,ea), r(df,04,96,e4), r(c2,13,8d,f6), r(c9,1e,84,f8),\
++    r(f8,3d,bb,d2), r(f3,30,b2,dc), r(ee,27,a9,ce), r(e5,2a,a0,c0),\
++    r(3c,b1,47,7a), r(37,bc,4e,74), r(2a,ab,55,66), r(21,a6,5c,68),\
++    r(10,85,63,42), r(1b,88,6a,4c), r(06,9f,71,5e), r(0d,92,78,50),\
++    r(64,d9,0f,0a), r(6f,d4,06,04), r(72,c3,1d,16), r(79,ce,14,18),\
++    r(48,ed,2b,32), r(43,e0,22,3c), r(5e,f7,39,2e), r(55,fa,30,20),\
++    r(01,b7,9a,ec), r(0a,ba,93,e2), r(17,ad,88,f0), r(1c,a0,81,fe),\
++    r(2d,83,be,d4), r(26,8e,b7,da), r(3b,99,ac,c8), r(30,94,a5,c6),\
++    r(59,df,d2,9c), r(52,d2,db,92), r(4f,c5,c0,80), r(44,c8,c9,8e),\
++    r(75,eb,f6,a4), r(7e,e6,ff,aa), r(63,f1,e4,b8), r(68,fc,ed,b6),\
++    r(b1,67,0a,0c), r(ba,6a,03,02), r(a7,7d,18,10), r(ac,70,11,1e),\
++    r(9d,53,2e,34), r(96,5e,27,3a), r(8b,49,3c,28), r(80,44,35,26),\
++    r(e9,0f,42,7c), r(e2,02,4b,72), r(ff,15,50,60), r(f4,18,59,6e),\
++    r(c5,3b,66,44), r(ce,36,6f,4a), r(d3,21,74,58), r(d8,2c,7d,56),\
++    r(7a,0c,a1,37), r(71,01,a8,39), r(6c,16,b3,2b), r(67,1b,ba,25),\
++    r(56,38,85,0f), r(5d,35,8c,01), r(40,22,97,13), r(4b,2f,9e,1d),\
++    r(22,64,e9,47), r(29,69,e0,49), r(34,7e,fb,5b), r(3f,73,f2,55),\
++    r(0e,50,cd,7f), r(05,5d,c4,71), r(18,4a,df,63), r(13,47,d6,6d),\
++    r(ca,dc,31,d7), r(c1,d1,38,d9), r(dc,c6,23,cb), r(d7,cb,2a,c5),\
++    r(e6,e8,15,ef), r(ed,e5,1c,e1), r(f0,f2,07,f3), r(fb,ff,0e,fd),\
++    r(92,b4,79,a7), r(99,b9,70,a9), r(84,ae,6b,bb), r(8f,a3,62,b5),\
++    r(be,80,5d,9f), r(b5,8d,54,91), r(a8,9a,4f,83), r(a3,97,46,8d)
++
++#undef r
++#define r   r0
++
++#if defined(ONE_IM_TABLE)
++static const u_int32_t im_tab[256] =
++    {   m_table };
++#elif defined(FOUR_IM_TABLES)
++static const u_int32_t im_tab[4][256] =
++{   {   m_table },
++#undef  r
++#define r   r1
++    {   m_table },
++#undef  r
++#define r   r2
++    {   m_table },
++#undef  r
++#define r   r3
++    {   m_table }
++};
++#endif
++
++#endif
++
++#else
++
++static int tab_gen = 0;
++
++static unsigned char  s_box[256];            // the S box
++static unsigned char  inv_s_box[256];        // the inverse S box
++static u_int32_t  rcon_tab[AES_RC_LENGTH];   // table of round constants
++
++#if defined(ONE_TABLE)
++static u_int32_t  ft_tab[256];
++static u_int32_t  it_tab[256];
++#elif defined(FOUR_TABLES)
++static u_int32_t  ft_tab[4][256];
++static u_int32_t  it_tab[4][256];
++#endif
++
++#if defined(ONE_LR_TABLE)
++static u_int32_t  fl_tab[256];
++static u_int32_t  il_tab[256];
++#elif defined(FOUR_LR_TABLES)
++static u_int32_t  fl_tab[4][256];
++static u_int32_t  il_tab[4][256];
++#endif
++
++#if defined(ONE_IM_TABLE)
++static u_int32_t  im_tab[256];
++#elif defined(FOUR_IM_TABLES)
++static u_int32_t  im_tab[4][256];
++#endif
++
++// Generate the tables for the dynamic table option
++
++#if !defined(FF_TABLES)
++
++// It will generally be sensible to use tables to compute finite 
++// field multiplies and inverses but where memory is scarse this 
++// code might sometimes be better.
++
++// return 2 ^ (n - 1) where n is the bit number of the highest bit
++// set in x with x in the range 1 < x < 0x00000200.   This form is
++// used so that locals within FFinv can be bytes rather than words
++
++static unsigned char hibit(const u_int32_t x)
++{   unsigned char r = (unsigned char)((x >> 1) | (x >> 2));
++    
++    r |= (r >> 2);
++    r |= (r >> 4);
++    return (r + 1) >> 1;
++}
++
++// return the inverse of the finite field element x
++
++static unsigned char FFinv(const unsigned char x)
++{   unsigned char    p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
++
++    if(x < 2) return x;
++
++    for(;;)
++    {
++        if(!n1) return v1;
++
++        while(n2 >= n1)
++        {   
++            n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
++        }
++        
++        if(!n2) return v2;
++
++        while(n1 >= n2)
++        {   
++            n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
++        }
++    }
++}
++
++// define the finite field multiplies required for Rijndael
++
++#define FFmul02(x)  ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0))
++#define FFmul03(x)  ((x) ^ FFmul02(x))
++#define FFmul09(x)  ((x) ^ FFmul02(FFmul02(FFmul02(x))))
++#define FFmul0b(x)  ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x))))
++#define FFmul0d(x)  ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x))))
++#define FFmul0e(x)  FFmul02((x) ^ FFmul02((x) ^ FFmul02(x)))
++
++#else
++
++#define FFinv(x)    ((x) ? pow[255 - log[x]]: 0)
++
++#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0)
++#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0)
++#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0)
++#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0)
++#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0)
++#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0)
++
++#endif
++
++// The forward and inverse affine transformations used in the S-box
++
++#define fwd_affine(x) \
++    (w = (u_int32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(unsigned char)(w^(w>>8)))
++
++#define inv_affine(x) \
++    (w = (u_int32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(unsigned char)(w^(w>>8)))
++
++static void gen_tabs(void)
++{   u_int32_t  i, w;
++
++#if defined(FF_TABLES)
++
++    unsigned char  pow[512], log[256];
++
++    // log and power tables for GF(2^8) finite field with
++    // 0x011b as modular polynomial - the simplest primitive
++    // root is 0x03, used here to generate the tables
++
++    i = 0; w = 1; 
++    do
++    {   
++        pow[i] = (unsigned char)w;
++        pow[i + 255] = (unsigned char)w;
++        log[w] = (unsigned char)i++;
++        w ^=  (w << 1) ^ (w & ff_hi ? ff_poly : 0);
++    }
++    while (w != 1);
++
++#endif
++
++    for(i = 0, w = 1; i < AES_RC_LENGTH; ++i)
++    {
++        rcon_tab[i] = bytes2word(w, 0, 0, 0);
++        w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
++    }
++
++    for(i = 0; i < 256; ++i)
++    {   unsigned char    b;
++
++        s_box[i] = b = fwd_affine(FFinv((unsigned char)i));
++
++        w = bytes2word(b, 0, 0, 0);
++#if defined(ONE_LR_TABLE)
++        fl_tab[i] = w;
++#elif defined(FOUR_LR_TABLES)
++        fl_tab[0][i] = w;
++        fl_tab[1][i] = upr(w,1);
++        fl_tab[2][i] = upr(w,2);
++        fl_tab[3][i] = upr(w,3);
++#endif
++        w = bytes2word(FFmul02(b), b, b, FFmul03(b));
++#if defined(ONE_TABLE)
++        ft_tab[i] = w;
++#elif defined(FOUR_TABLES)
++        ft_tab[0][i] = w;
++        ft_tab[1][i] = upr(w,1);
++        ft_tab[2][i] = upr(w,2);
++        ft_tab[3][i] = upr(w,3);
++#endif
++        inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i));
++
++        w = bytes2word(b, 0, 0, 0);
++#if defined(ONE_LR_TABLE)
++        il_tab[i] = w;
++#elif defined(FOUR_LR_TABLES)
++        il_tab[0][i] = w;
++        il_tab[1][i] = upr(w,1);
++        il_tab[2][i] = upr(w,2);
++        il_tab[3][i] = upr(w,3);
++#endif
++        w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b));
++#if defined(ONE_TABLE)
++        it_tab[i] = w;
++#elif defined(FOUR_TABLES)
++        it_tab[0][i] = w;
++        it_tab[1][i] = upr(w,1);
++        it_tab[2][i] = upr(w,2);
++        it_tab[3][i] = upr(w,3);
++#endif
++#if defined(ONE_IM_TABLE)
++        im_tab[b] = w;
++#elif defined(FOUR_IM_TABLES)
++        im_tab[0][b] = w;
++        im_tab[1][b] = upr(w,1);
++        im_tab[2][b] = upr(w,2);
++        im_tab[3][b] = upr(w,3);
++#endif
++
++    }
++}
++
++#endif
++
++#define no_table(x,box,vf,rf,c) bytes2word( \
++    box[bval(vf(x,0,c),rf(0,c))], \
++    box[bval(vf(x,1,c),rf(1,c))], \
++    box[bval(vf(x,2,c),rf(2,c))], \
++    box[bval(vf(x,3,c),rf(3,c))])
++
++#define one_table(x,op,tab,vf,rf,c) \
++ (     tab[bval(vf(x,0,c),rf(0,c))] \
++  ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
++  ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
++  ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
++
++#define four_tables(x,tab,vf,rf,c) \
++ (  tab[0][bval(vf(x,0,c),rf(0,c))] \
++  ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
++  ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
++  ^ tab[3][bval(vf(x,3,c),rf(3,c))])
++
++#define vf1(x,r,c)  (x)
++#define rf1(r,c)    (r)
++#define rf2(r,c)    ((r-c)&3)
++
++#if defined(FOUR_LR_TABLES)
++#define ls_box(x,c)     four_tables(x,fl_tab,vf1,rf2,c)
++#elif defined(ONE_LR_TABLE)
++#define ls_box(x,c)     one_table(x,upr,fl_tab,vf1,rf2,c)
++#else
++#define ls_box(x,c)     no_table(x,s_box,vf1,rf2,c)
++#endif
++
++#if defined(FOUR_IM_TABLES)
++#define inv_mcol(x)     four_tables(x,im_tab,vf1,rf1,0)
++#elif defined(ONE_IM_TABLE)
++#define inv_mcol(x)     one_table(x,upr,im_tab,vf1,rf1,0)
++#else
++#define inv_mcol(x) \
++    (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \
++    f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1))
++#endif
++
++// Subroutine to set the block size (if variable) in bytes, legal
++// values being 16, 24 and 32.
++
++#if defined(AES_BLOCK_SIZE)
++#define nc   (AES_BLOCK_SIZE / 4)
++#else
++#define nc   (cx->aes_Ncol)
++
++void aes_set_blk(aes_context *cx, int n_bytes)
++{
++#if !defined(FIXED_TABLES)
++    if(!tab_gen) { gen_tabs(); tab_gen = 1; }
++#endif
++
++    switch(n_bytes) {
++    case 32:        /* bytes */
++    case 256:       /* bits */
++        nc = 8;
++        break;
++    case 24:        /* bytes */
++    case 192:       /* bits */
++        nc = 6;
++        break;
++    case 16:        /* bytes */
++    case 128:       /* bits */
++    default:
++        nc = 4;
++        break;
++    }
++}
++
++#endif
++
++// Initialise the key schedule from the user supplied key. The key
++// length is now specified in bytes - 16, 24 or 32 as appropriate.
++// This corresponds to bit lengths of 128, 192 and 256 bits, and
++// to Nk values of 4, 6 and 8 respectively.
++
++#define mx(t,f) (*t++ = inv_mcol(*f),f++)
++#define cp(t,f) *t++ = *f++
++
++#if   AES_BLOCK_SIZE == 16
++#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s)
++#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s)
++#elif AES_BLOCK_SIZE == 24
++#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
++                    cp(d,s); cp(d,s)
++#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
++                    mx(d,s); mx(d,s)
++#elif AES_BLOCK_SIZE == 32
++#define cpy(d,s)    cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
++                    cp(d,s); cp(d,s); cp(d,s); cp(d,s)
++#define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
++                    mx(d,s); mx(d,s); mx(d,s); mx(d,s)
++#else
++
++#define cpy(d,s) \
++switch(nc) \
++{   case 8: cp(d,s); cp(d,s); \
++    case 6: cp(d,s); cp(d,s); \
++    case 4: cp(d,s); cp(d,s); \
++            cp(d,s); cp(d,s); \
++}
++
++#define mix(d,s) \
++switch(nc) \
++{   case 8: mx(d,s); mx(d,s); \
++    case 6: mx(d,s); mx(d,s); \
++    case 4: mx(d,s); mx(d,s); \
++            mx(d,s); mx(d,s); \
++}
++
++#endif
++
++void aes_set_key(aes_context *cx, const unsigned char in_key[], int n_bytes, const int f)
++{   u_int32_t    *kf, *kt, rci;
++
++#if !defined(FIXED_TABLES)
++    if(!tab_gen) { gen_tabs(); tab_gen = 1; }
++#endif
++
++    switch(n_bytes) {
++    case 32:                    /* bytes */
++    case 256:                   /* bits */
++        cx->aes_Nkey = 8;
++        break;
++    case 24:                    /* bytes */
++    case 192:                   /* bits */
++        cx->aes_Nkey = 6;
++        break;
++    case 16:                    /* bytes */
++    case 128:                   /* bits */
++    default:
++        cx->aes_Nkey = 4;
++        break;
++    }
++
++    cx->aes_Nrnd = (cx->aes_Nkey > nc ? cx->aes_Nkey : nc) + 6; 
++
++    cx->aes_e_key[0] = const_word_in(in_key     );
++    cx->aes_e_key[1] = const_word_in(in_key +  4);
++    cx->aes_e_key[2] = const_word_in(in_key +  8);
++    cx->aes_e_key[3] = const_word_in(in_key + 12);
++
++    kf = cx->aes_e_key; 
++    kt = kf + nc * (cx->aes_Nrnd + 1) - cx->aes_Nkey; 
++    rci = 0;
++
++    switch(cx->aes_Nkey)
++    {
++    case 4: do
++            {   kf[4] = kf[0] ^ ls_box(kf[3],3) ^ rcon_tab[rci++];
++                kf[5] = kf[1] ^ kf[4];
++                kf[6] = kf[2] ^ kf[5];
++                kf[7] = kf[3] ^ kf[6];
++                kf += 4;
++            }
++            while(kf < kt);
++            break;
++
++    case 6: cx->aes_e_key[4] = const_word_in(in_key + 16);
++            cx->aes_e_key[5] = const_word_in(in_key + 20);
++            do
++            {   kf[ 6] = kf[0] ^ ls_box(kf[5],3) ^ rcon_tab[rci++];
++                kf[ 7] = kf[1] ^ kf[ 6];
++                kf[ 8] = kf[2] ^ kf[ 7];
++                kf[ 9] = kf[3] ^ kf[ 8];
++                kf[10] = kf[4] ^ kf[ 9];
++                kf[11] = kf[5] ^ kf[10];
++                kf += 6;
++            }
++            while(kf < kt);
++            break;
++
++    case 8: cx->aes_e_key[4] = const_word_in(in_key + 16);
++            cx->aes_e_key[5] = const_word_in(in_key + 20);
++            cx->aes_e_key[6] = const_word_in(in_key + 24);
++            cx->aes_e_key[7] = const_word_in(in_key + 28);
++            do
++            {   kf[ 8] = kf[0] ^ ls_box(kf[7],3) ^ rcon_tab[rci++];
++                kf[ 9] = kf[1] ^ kf[ 8];
++                kf[10] = kf[2] ^ kf[ 9];
++                kf[11] = kf[3] ^ kf[10];
++                kf[12] = kf[4] ^ ls_box(kf[11],0);
++                kf[13] = kf[5] ^ kf[12];
++                kf[14] = kf[6] ^ kf[13];
++                kf[15] = kf[7] ^ kf[14];
++                kf += 8;
++            }
++            while (kf < kt);
++            break;
++    }
++
++    if(!f)
++    {   u_int32_t    i;
++        
++        kt = cx->aes_d_key + nc * cx->aes_Nrnd;
++        kf = cx->aes_e_key;
++        
++        cpy(kt, kf); kt -= 2 * nc;
++
++        for(i = 1; i < cx->aes_Nrnd; ++i)
++        { 
++#if defined(ONE_TABLE) || defined(FOUR_TABLES)
++#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES)
++            u_int32_t    f2, f4, f8, f9;
++#endif
++            mix(kt, kf);
++#else
++            cpy(kt, kf);
++#endif
++            kt -= 2 * nc;
++        }
++        
++        cpy(kt, kf);
++    }
++}
++
++// y = output word, x = input word, r = row, c = column
++// for r = 0, 1, 2 and 3 = column accessed for row r
++
++#if defined(ARRAYS)
++#define s(x,c) x[c]
++#else
++#define s(x,c) x##c
++#endif
++
++// I am grateful to Frank Yellin for the following constructions
++// which, given the column (c) of the output state variable that
++// is being computed, return the input state variables which are
++// needed for each row (r) of the state
++
++// For the fixed block size options, compilers reduce these two 
++// expressions to fixed variable references. For variable block 
++// size code conditional clauses will sometimes be returned
++
++#define unused  77  // Sunset Strip
++
++#define fwd_var(x,r,c) \
++ ( r==0 ?                     \
++    ( c==0 ? s(x,0) \
++    : c==1 ? s(x,1) \
++    : c==2 ? s(x,2) \
++    : c==3 ? s(x,3) \
++    : c==4 ? s(x,4) \
++    : c==5 ? s(x,5) \
++    : c==6 ? s(x,6) \
++    : s(x,7))         \
++ : r==1 ?                     \
++    ( c==0 ? s(x,1) \
++    : c==1 ? s(x,2) \
++    : c==2 ? s(x,3) \
++    : c==3 ? nc==4 ? s(x,0) : s(x,4) \
++    : c==4 ? s(x,5) \
++    : c==5 ? nc==8 ? s(x,6) : s(x,0) \
++    : c==6 ? s(x,7) \
++    : s(x,0))         \
++ : r==2 ?                     \
++    ( c==0 ? nc==8 ? s(x,3) : s(x,2) \
++    : c==1 ? nc==8 ? s(x,4) : s(x,3) \
++    : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
++    : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
++    : c==4 ? nc==8 ? s(x,7) : s(x,0) \
++    : c==5 ? nc==8 ? s(x,0) : s(x,1) \
++    : c==6 ? s(x,1) \
++    : s(x,2))         \
++ :                                    \
++    ( c==0 ? nc==8 ? s(x,4) : s(x,3) \
++    : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
++    : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
++    : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \
++    : c==4 ? nc==8 ? s(x,0) : s(x,1) \
++    : c==5 ? nc==8 ? s(x,1) : s(x,2) \
++    : c==6 ? s(x,2) \
++    : s(x,3)))
++
++#define inv_var(x,r,c) \
++ ( r==0 ?                     \
++    ( c==0 ? s(x,0) \
++    : c==1 ? s(x,1) \
++    : c==2 ? s(x,2) \
++    : c==3 ? s(x,3) \
++    : c==4 ? s(x,4) \
++    : c==5 ? s(x,5) \
++    : c==6 ? s(x,6) \
++    : s(x,7))         \
++ : r==1 ?                     \
++    ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \
++    : c==1 ? s(x,0) \
++    : c==2 ? s(x,1) \
++    : c==3 ? s(x,2) \
++    : c==4 ? s(x,3) \
++    : c==5 ? s(x,4) \
++    : c==6 ? s(x,5) \
++    : s(x,6))         \
++ : r==2 ?                     \
++    ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
++    : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
++    : c==2 ? nc==8 ? s(x,7) : s(x,0) \
++    : c==3 ? nc==8 ? s(x,0) : s(x,1) \
++    : c==4 ? nc==8 ? s(x,1) : s(x,2) \
++    : c==5 ? nc==8 ? s(x,2) : s(x,3) \
++    : c==6 ? s(x,3) \
++    : s(x,4))         \
++ :                                    \
++    ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \
++    : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
++    : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
++    : c==3 ? nc==8 ? s(x,7) : s(x,0) \
++    : c==4 ? nc==8 ? s(x,0) : s(x,1) \
++    : c==5 ? nc==8 ? s(x,1) : s(x,2) \
++    : c==6 ? s(x,2) \
++    : s(x,3)))
++
++#define si(y,x,k,c) s(y,c) = const_word_in(x + 4 * c) ^ k[c]
++#define so(y,x,c)   word_out(y + 4 * c, s(x,c))
++
++#if defined(FOUR_TABLES)
++#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c)
++#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c)
++#elif defined(ONE_TABLE)
++#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c)
++#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c)
++#else
++#define fwd_rnd(y,x,k,c)    s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c]
++#define inv_rnd(y,x,k,c)    s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c])
++#endif
++
++#if defined(FOUR_LR_TABLES)
++#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c)
++#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c)
++#elif defined(ONE_LR_TABLE)
++#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c)
++#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c)
++#else
++#define fwd_lrnd(y,x,k,c)   s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c]
++#define inv_lrnd(y,x,k,c)   s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]
++#endif
++
++#if AES_BLOCK_SIZE == 16
++
++#if defined(ARRAYS)
++#define locals(y,x)     x[4],y[4]
++#else
++#define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
++// the following defines prevent the compiler requiring the declaration
++// of generated but unused variables in the fwd_var and inv_var macros
++#define b04 unused
++#define b05 unused
++#define b06 unused
++#define b07 unused
++#define b14 unused
++#define b15 unused
++#define b16 unused
++#define b17 unused
++#endif
++#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
++                        s(y,2) = s(x,2); s(y,3) = s(x,3);
++#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
++#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
++#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
++
++#elif AES_BLOCK_SIZE == 24
++
++#if defined(ARRAYS)
++#define locals(y,x)     x[6],y[6]
++#else
++#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5, \
++                        y##0,y##1,y##2,y##3,y##4,y##5
++#define b06 unused
++#define b07 unused
++#define b16 unused
++#define b17 unused
++#endif
++#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
++                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
++                        s(y,4) = s(x,4); s(y,5) = s(x,5);
++#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
++                        si(y,x,k,3); si(y,x,k,4); si(y,x,k,5)
++#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); \
++                        so(y,x,3); so(y,x,4); so(y,x,5)
++#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
++                        rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5)
++#else
++
++#if defined(ARRAYS)
++#define locals(y,x)     x[8],y[8]
++#else
++#define locals(y,x)     x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \
++                        y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7
++#endif
++#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
++                        s(y,2) = s(x,2); s(y,3) = s(x,3); \
++                        s(y,4) = s(x,4); s(y,5) = s(x,5); \
++                        s(y,6) = s(x,6); s(y,7) = s(x,7);
++
++#if AES_BLOCK_SIZE == 32
++
++#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \
++                        si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7)
++#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \
++                        so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7)
++#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \
++                        rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7)
++#else
++
++#define state_in(y,x,k) \
++switch(nc) \
++{   case 8: si(y,x,k,7); si(y,x,k,6); \
++    case 6: si(y,x,k,5); si(y,x,k,4); \
++    case 4: si(y,x,k,3); si(y,x,k,2); \
++            si(y,x,k,1); si(y,x,k,0); \
++}
++
++#define state_out(y,x) \
++switch(nc) \
++{   case 8: so(y,x,7); so(y,x,6); \
++    case 6: so(y,x,5); so(y,x,4); \
++    case 4: so(y,x,3); so(y,x,2); \
++            so(y,x,1); so(y,x,0); \
++}
++
++#if defined(FAST_VARIABLE)
++
++#define round(rm,y,x,k) \
++switch(nc) \
++{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
++            rm(y,x,k,5); rm(y,x,k,4); \
++            rm(y,x,k,3); rm(y,x,k,2); \
++            rm(y,x,k,1); rm(y,x,k,0); \
++            break; \
++    case 6: rm(y,x,k,5); rm(y,x,k,4); \
++            rm(y,x,k,3); rm(y,x,k,2); \
++            rm(y,x,k,1); rm(y,x,k,0); \
++            break; \
++    case 4: rm(y,x,k,3); rm(y,x,k,2); \
++            rm(y,x,k,1); rm(y,x,k,0); \
++            break; \
++}
++#else
++
++#define round(rm,y,x,k) \
++switch(nc) \
++{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
++    case 6: rm(y,x,k,5); rm(y,x,k,4); \
++    case 4: rm(y,x,k,3); rm(y,x,k,2); \
++            rm(y,x,k,1); rm(y,x,k,0); \
++}
++
++#endif
++
++#endif
++#endif
++
++void aes_encrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
++{   u_int32_t        locals(b0, b1);
++    const u_int32_t  *kp = cx->aes_e_key;
++
++#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
++    u_int32_t        f2;
++#endif
++
++    state_in(b0, in_blk, kp); kp += nc;
++
++#if defined(UNROLL)
++
++    switch(cx->aes_Nrnd)
++    {
++    case 14:    round(fwd_rnd,  b1, b0, kp         ); 
++                round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
++    case 12:    round(fwd_rnd,  b1, b0, kp         ); 
++                round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
++    case 10:    round(fwd_rnd,  b1, b0, kp         );             
++                round(fwd_rnd,  b0, b1, kp +     nc);
++                round(fwd_rnd,  b1, b0, kp + 2 * nc); 
++                round(fwd_rnd,  b0, b1, kp + 3 * nc);
++                round(fwd_rnd,  b1, b0, kp + 4 * nc); 
++                round(fwd_rnd,  b0, b1, kp + 5 * nc);
++                round(fwd_rnd,  b1, b0, kp + 6 * nc); 
++                round(fwd_rnd,  b0, b1, kp + 7 * nc);
++                round(fwd_rnd,  b1, b0, kp + 8 * nc);
++                round(fwd_lrnd, b0, b1, kp + 9 * nc);
++    }
++
++#elif defined(PARTIAL_UNROLL)
++    {   u_int32_t    rnd;
++
++        for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd)
++        {
++            round(fwd_rnd, b1, b0, kp); 
++            round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc;
++        }
++
++        round(fwd_rnd,  b1, b0, kp);
++        round(fwd_lrnd, b0, b1, kp + nc);
++    }
++#else
++    {   u_int32_t    rnd;
++
++        for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd)
++        {
++            round(fwd_rnd, b1, b0, kp); 
++            l_copy(b0, b1); kp += nc;
++        }
++
++        round(fwd_lrnd, b0, b1, kp);
++    }
++#endif
++
++    state_out(out_blk, b0);
++}
++
++void aes_decrypt(const aes_context *cx, const unsigned char in_blk[], unsigned char out_blk[])
++{   u_int32_t        locals(b0, b1);
++    const u_int32_t  *kp = cx->aes_d_key;
++
++#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
++    u_int32_t        f2, f4, f8, f9; 
++#endif
++
++    state_in(b0, in_blk, kp); kp += nc;
++
++#if defined(UNROLL)
++
++    switch(cx->aes_Nrnd)
++    {
++    case 14:    round(inv_rnd,  b1, b0, kp         );
++                round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
++    case 12:    round(inv_rnd,  b1, b0, kp         );
++                round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
++    case 10:    round(inv_rnd,  b1, b0, kp         );             
++                round(inv_rnd,  b0, b1, kp +     nc);
++                round(inv_rnd,  b1, b0, kp + 2 * nc); 
++                round(inv_rnd,  b0, b1, kp + 3 * nc);
++                round(inv_rnd,  b1, b0, kp + 4 * nc); 
++                round(inv_rnd,  b0, b1, kp + 5 * nc);
++                round(inv_rnd,  b1, b0, kp + 6 * nc); 
++                round(inv_rnd,  b0, b1, kp + 7 * nc);
++                round(inv_rnd,  b1, b0, kp + 8 * nc);
++                round(inv_lrnd, b0, b1, kp + 9 * nc);
++    }
++
++#elif defined(PARTIAL_UNROLL)
++    {   u_int32_t    rnd;
++
++        for(rnd = 0; rnd < (cx->aes_Nrnd >> 1) - 1; ++rnd)
++        {
++            round(inv_rnd, b1, b0, kp); 
++            round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc;
++        }
++
++        round(inv_rnd,  b1, b0, kp);
++        round(inv_lrnd, b0, b1, kp + nc);
++    }
++#else
++    {   u_int32_t    rnd;
++
++        for(rnd = 0; rnd < cx->aes_Nrnd - 1; ++rnd)
++        {
++            round(inv_rnd, b1, b0, kp); 
++            l_copy(b0, b1); kp += nc;
++        }
++
++        round(inv_lrnd, b0, b1, kp);
++    }
++#endif
++
++    state_out(out_blk, b0);
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/aes/aes_cbc.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,46 @@
++/*
++// I retain copyright in this code but I encourage its free use provided
++// that I don't carry any responsibility for the results. I am especially 
++// happy to see it used in free and open source software. If you do use 
++// it I would appreciate an acknowledgement of its origin in the code or
++// the product that results and I would also appreciate knowing a little
++// about the use to which it is being put. I am grateful to Frank Yellin
++// for some ideas that are used in this implementation.
++//
++// Dr B. R. Gladman <brg@gladman.uk.net> 6th April 2001.
++//
++// This is an implementation of the AES encryption algorithm (Rijndael)
++// designed by Joan Daemen and Vincent Rijmen. This version is designed
++// to provide both fixed and dynamic block and key lengths and can also 
++// run with either big or little endian internal byte order (see aes.h). 
++// It inputs block and key lengths in bytes with the legal values being 
++// 16, 24 and 32.
++*
++*/
++
++#ifdef __KERNEL__
++#include <linux/types.h>
++#else
++#include <sys/types.h>
++#endif
++#include "crypto/aes_cbc.h"
++#include "crypto/cbc_generic.h"
++
++/* returns bool success */
++int AES_set_key(aes_context *aes_ctx, const u_int8_t *key, int keysize) {
++      aes_set_key(aes_ctx, key, keysize, 0);
++      return 1;       
++}
++CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt);
++
++
++/*
++ * $Log: aes_cbc.c,v $
++ * Revision 1.2  2004/07/10 07:48:40  mcr
++ * Moved from linux/crypto/ciphers/aes/aes_cbc.c,v
++ *
++ * Revision 1.1  2004/04/06 02:48:12  mcr
++ *    pullup of AES cipher from alg-branch.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/aes/aes_xcbc_mac.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,67 @@
++#ifdef __KERNEL__
++#include <linux/types.h>
++#include <linux/kernel.h>
++#define DEBUG(x) 
++#else
++#include <stdio.h>
++#include <sys/types.h>
++#define DEBUG(x) x
++#endif
++
++#include "crypto/aes.h"
++#include "crypto/aes_xcbc_mac.h"
++
++int AES_xcbc_mac_set_key(aes_context_mac *ctxm, const u_int8_t *key, int keylen)
++{
++      int ret=1;
++      aes_block kn[3] = { 
++              { 0x01010101, 0x01010101, 0x01010101, 0x01010101 },
++              { 0x02020202, 0x02020202, 0x02020202, 0x02020202 },
++              { 0x03030303, 0x03030303, 0x03030303, 0x03030303 },
++      };
++      aes_set_key(&ctxm->ctx_k1, key, keylen, 0);
++      aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[0], (u_int8_t *) kn[0]);
++      aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[1], (u_int8_t *) ctxm->k2);
++      aes_encrypt(&ctxm->ctx_k1, (u_int8_t *) kn[2], (u_int8_t *) ctxm->k3);
++      aes_set_key(&ctxm->ctx_k1, (u_int8_t *) kn[0], 16, 0);
++      return ret;
++}
++static void do_pad_xor(u_int8_t *out, const u_int8_t *in, int len) {
++      int pos=0;
++      for (pos=1; pos <= 16; pos++, in++, out++) {
++              if (pos <= len)
++                      *out ^= *in;
++              if (pos > len) {
++                      DEBUG(printf("put 0x80 at pos=%d\n", pos));
++                      *out ^= 0x80;
++                      break;
++              }
++      }
++}
++static void xor_block(aes_block res, const aes_block op) {
++      res[0] ^= op[0];
++      res[1] ^= op[1];
++      res[2] ^= op[2];
++      res[3] ^= op[3];
++}
++int AES_xcbc_mac_hash(const aes_context_mac *ctxm, const u_int8_t * in, int ilen, u_int8_t hash[16]) {
++      int ret=ilen;
++      u_int32_t out[4] = { 0, 0, 0, 0 }; 
++      for (; ilen > 16 ; ilen-=16) {
++              xor_block(out, (const u_int32_t*) &in[0]);
++              aes_encrypt(&ctxm->ctx_k1, in, (u_int8_t *)&out[0]);
++              in+=16; 
++      }
++      do_pad_xor((u_int8_t *)&out, in, ilen);
++      if (ilen==16) {
++              DEBUG(printf("using k3\n"));
++              xor_block(out, ctxm->k3);
++      }
++      else 
++      {
++              DEBUG(printf("using k2\n"));
++              xor_block(out, ctxm->k2);
++      }
++      aes_encrypt(&ctxm->ctx_k1, (u_int8_t *)out, hash);
++      return ret;
++} 
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/aes/ipsec_alg_aes.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,296 @@
++/*
++ * ipsec_alg AES cipher stubs
++ *
++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ * 
++ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * Fixes by:
++ *    PK:     Pawel Krawczyk <kravietz@aba.krakow.pl>
++ * Fixes list:
++ *    PK:     make XCBC comply with latest draft (keylength)
++ *
++ */
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++/*    
++ *    special case: ipsec core modular with this static algo inside:
++ *    must avoid MODULE magic for this file
++ */
++#if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_AES)
++#undef MODULE
++#endif
++
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/string.h>
++
++/* Check if __exit is defined, if not null it */
++#ifndef __exit
++#define __exit
++#endif
++
++/*    Low freeswan header coupling    */
++#include "openswan/ipsec_alg.h"
++#include "crypto/aes_cbc.h"
++
++#define CONFIG_KLIPS_ENC_AES_MAC 1
++
++#define AES_CONTEXT_T aes_context
++static int debug_aes=0;
++static int test_aes=0;
++static int excl_aes=0;
++static int keyminbits=0;
++static int keymaxbits=0;
++#if defined(CONFIG_KLIPS_ENC_AES_MODULE)
++MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
++#ifdef module_param
++module_param(debug_aes,int,0600)
++module_param(test_aes,int,0600)
++module_param(excl_aes,int,0600)
++module_param(keyminbits,int,0600)
++module_param(keymaxbits,int,0600)
++#else
++MODULE_PARM(debug_aes, "i");
++MODULE_PARM(test_aes, "i");
++MODULE_PARM(excl_aes, "i");
++MODULE_PARM(keyminbits, "i");
++MODULE_PARM(keymaxbits, "i");
++#endif
++#endif
++
++#if CONFIG_KLIPS_ENC_AES_MAC
++#include "crypto/aes_xcbc_mac.h"
++
++/*    
++ *    Not IANA number yet (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt).
++ *    We use 9 for non-modular algorithm and none for modular, thus
++ *    forcing user to specify one on module load. -kravietz
++ */
++#ifdef MODULE
++static int auth_id=0;
++#else
++static int auth_id=9;
++#endif
++#ifdef module_param
++module_param(auth_id, int, 0600);
++#else
++MODULE_PARM(auth_id, "i");
++#endif
++#endif
++
++#define ESP_AES                       12      /* truely _constant_  :)  */
++
++/* 128, 192 or 256 */
++#define ESP_AES_KEY_SZ_MIN    16      /* 128 bit secret key */
++#define ESP_AES_KEY_SZ_MAX    32      /* 256 bit secret key */
++#define ESP_AES_CBC_BLK_LEN   16      /* AES-CBC block size */
++
++/* Values according to draft-ietf-ipsec-ciph-aes-xcbc-mac-02.txt
++ * -kravietz
++ */
++#define ESP_AES_MAC_KEY_SZ    16      /* 128 bit MAC key */
++#define ESP_AES_MAC_BLK_LEN   16      /* 128 bit block */
++
++static int _aes_set_key(struct ipsec_alg_enc *alg,
++                      __u8 * key_e, const __u8 * key,
++                      size_t keysize)
++{
++      int ret;
++      AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e;
++      ret=AES_set_key(ctx, key, keysize)!=0? 0: -EINVAL;
++      if (debug_aes > 0)
++              printk(KERN_DEBUG "klips_debug:_aes_set_key:"
++                              "ret=%d key_e=%p key=%p keysize=%ld\n",
++                                ret, key_e, key, (unsigned long int) keysize);
++      return ret;
++}
++
++static int _aes_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e,
++                          __u8 * in, int ilen, const __u8 * iv,
++                          int encrypt)
++{
++      AES_CONTEXT_T *ctx=(AES_CONTEXT_T*)key_e;
++      if (debug_aes > 0)
++              printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:"
++                              "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
++                              key_e, in, ilen, iv, encrypt);
++      return AES_cbc_encrypt(ctx, in, in, ilen, iv, encrypt);
++}
++#if CONFIG_KLIPS_ENC_AES_MAC
++static int _aes_mac_set_key(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * key, int keylen) {
++      aes_context_mac *ctxm=(aes_context_mac *)key_a;
++      return AES_xcbc_mac_set_key(ctxm, key, keylen)? 0 : -EINVAL;
++}
++static int _aes_mac_hash(struct ipsec_alg_auth *alg, __u8 * key_a, const __u8 * dat, int len, __u8 * hash, int hashlen) {
++      int ret;
++      char hash_buf[16];
++      aes_context_mac *ctxm=(aes_context_mac *)key_a;
++      ret=AES_xcbc_mac_hash(ctxm, dat, len, hash_buf);
++      memcpy(hash, hash_buf, hashlen);
++      return ret;
++}
++static struct ipsec_alg_auth ipsec_alg_AES_MAC = {
++      ixt_common: { ixt_version:      IPSEC_ALG_VERSION,
++                    ixt_refcnt:       ATOMIC_INIT(0),
++                    ixt_name:         "aes_mac",
++                    ixt_blocksize:    ESP_AES_MAC_BLK_LEN,
++                    ixt_support: {
++                      ias_exttype:    IPSEC_ALG_TYPE_AUTH,
++                      ias_id:         0,
++                      ias_keyminbits: ESP_AES_MAC_KEY_SZ*8,
++                      ias_keymaxbits: ESP_AES_MAC_KEY_SZ*8,
++              },
++      },
++#if defined(CONFIG_KLIPS_ENC_AES_MODULE)
++      ixt_module:     THIS_MODULE,
++#endif
++      ixt_a_keylen:   ESP_AES_MAC_KEY_SZ,
++      ixt_a_ctx_size: sizeof(aes_context_mac),
++      ixt_a_hmac_set_key:     _aes_mac_set_key,
++      ixt_a_hmac_hash:_aes_mac_hash,
++};
++#endif /* CONFIG_KLIPS_ENC_AES_MAC */
++static struct ipsec_alg_enc ipsec_alg_AES = {
++      ixt_common: { ixt_version:      IPSEC_ALG_VERSION,
++                    ixt_refcnt:       ATOMIC_INIT(0),
++                    ixt_name:         "aes",
++                    ixt_blocksize:    ESP_AES_CBC_BLK_LEN, 
++                    ixt_support: {
++                      ias_exttype:    IPSEC_ALG_TYPE_ENCRYPT,
++                      ias_id:         ESP_AES,
++                      ias_keyminbits: ESP_AES_KEY_SZ_MIN*8,
++                      ias_keymaxbits: ESP_AES_KEY_SZ_MAX*8,
++              },
++      },
++#if defined(CONFIG_KLIPS_ENC_AES_MODULE)
++      ixt_module:     THIS_MODULE,
++#endif
++      ixt_e_keylen:   ESP_AES_KEY_SZ_MAX,
++      ixt_e_ctx_size: sizeof(AES_CONTEXT_T),
++      ixt_e_set_key:  _aes_set_key,
++      ixt_e_cbc_encrypt:_aes_cbc_encrypt,
++};
++
++#if defined(CONFIG_KLIPS_ENC_AES_MODULE)
++IPSEC_ALG_MODULE_INIT_MOD( ipsec_aes_init )
++#else
++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_aes_init )
++#endif
++{
++      int ret, test_ret;
++
++      if (keyminbits)
++              ipsec_alg_AES.ixt_common.ixt_support.ias_keyminbits=keyminbits;
++      if (keymaxbits) {
++              ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits=keymaxbits;
++              if (keymaxbits*8>ipsec_alg_AES.ixt_common.ixt_support.ias_keymaxbits)
++                      ipsec_alg_AES.ixt_e_keylen=keymaxbits*8;
++      }
++      if (excl_aes) ipsec_alg_AES.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL;
++      ret=register_ipsec_alg_enc(&ipsec_alg_AES);
++      printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
++                      ipsec_alg_AES.ixt_common.ixt_support.ias_exttype, 
++                      ipsec_alg_AES.ixt_common.ixt_support.ias_id, 
++                      ipsec_alg_AES.ixt_common.ixt_name, 
++                      ret);
++      if (ret==0 && test_aes) {
++              test_ret=ipsec_alg_test(
++                              ipsec_alg_AES.ixt_common.ixt_support.ias_exttype ,
++                              ipsec_alg_AES.ixt_common.ixt_support.ias_id, 
++                              test_aes);
++              printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
++                              ipsec_alg_AES.ixt_common.ixt_support.ias_exttype , 
++                              ipsec_alg_AES.ixt_common.ixt_support.ias_id, 
++                              test_ret);
++      }
++#if CONFIG_KLIPS_ENC_AES_MAC
++      if (auth_id!=0){
++              int ret;
++              ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id=auth_id;
++              ret=register_ipsec_alg_auth(&ipsec_alg_AES_MAC);
++              printk("ipsec_aes_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
++                              ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, 
++                              ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, 
++                              ipsec_alg_AES_MAC.ixt_common.ixt_name, 
++                              ret);
++              if (ret==0 && test_aes) {
++                      test_ret=ipsec_alg_test(
++                                      ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype,
++                                      ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, 
++                                      test_aes);
++                      printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
++                                      ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_exttype, 
++                                      ipsec_alg_AES_MAC.ixt_common.ixt_support.ias_id, 
++                                      test_ret);
++              }
++      } else {
++              printk(KERN_DEBUG "klips_debug: experimental ipsec_alg_AES_MAC not registered [Ok] (auth_id=%d)\n", auth_id);
++      }
++#endif /* CONFIG_KLIPS_ENC_AES_MAC */
++      return ret;
++}
++
++#if defined(CONFIG_KLIPS_ENC_AES_MODULE)
++IPSEC_ALG_MODULE_EXIT_MOD( ipsec_aes_fini )
++#else
++IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_aes_fini )
++#endif
++{
++#if CONFIG_KLIPS_ENC_AES_MAC
++      if (auth_id) unregister_ipsec_alg_auth(&ipsec_alg_AES_MAC);
++#endif /* CONFIG_KLIPS_ENC_AES_MAC */
++      unregister_ipsec_alg_enc(&ipsec_alg_AES);
++      return;
++}
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++
++#if 0  /* +NOT_YET */
++#ifndef MODULE
++/*
++ *    This is intended for static module setups, currently
++ *    doesn't work for modular ipsec.o with static algos inside
++ */
++static int setup_keybits(const char *str)
++{
++      unsigned aux;
++      char *end;
++
++      aux = simple_strtoul(str,&end,0);
++      if (aux != 128 && aux != 192 && aux != 256)
++              return 0;
++      keyminbits = aux;
++
++      if (*end == 0 || *end != ',')
++              return 1;
++      str=end+1;
++      aux = simple_strtoul(str, NULL, 0);
++      if (aux != 128 && aux != 192 && aux != 256)
++              return 0;
++      if (aux >= keyminbits)
++              keymaxbits = aux;
++      return 1;
++}
++__setup("ipsec_aes_keybits=", setup_keybits);
++#endif
++#endif
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/Config.alg_aes.in     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,3 @@
++if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
++  tristate '        AES encryption algorithm' CONFIG_IPSEC_ENC_AES
++fi
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/Config.alg_cryptoapi.in     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,6 @@
++if [ "$CONFIG_IPSEC_ALG" = "y" ]; then
++  dep_tristate '        CRYPTOAPI ciphers support (needs cryptoapi patch)' CONFIG_IPSEC_ALG_CRYPTOAPI $CONFIG_CRYPTO
++  if [ "$CONFIG_IPSEC_ALG_CRYPTOAPI" != "n" ]; then
++    bool '          CRYPTOAPI proprietary ciphers ' CONFIG_IPSEC_ALG_NON_LIBRE
++  fi
++fi
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/Config.in     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,3 @@
++#Placeholder
++source net/ipsec/alg/Config.alg_aes.in
++source net/ipsec/alg/Config.alg_cryptoapi.in
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/Makefile     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,112 @@
++# Makefile,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
++ifeq ($(strip $(KLIPSMODULE)),)
++FREESWANSRCDIR=.
++else
++FREESWANSRCDIR=../../../..
++endif
++ifeq ($(strip $(KLIPS_TOP)),)
++KLIPS_TOP=../../..
++override EXTRA_CFLAGS += -I$(KLIPS_TOP)/include
++endif
++
++ifeq ($(CONFIG_IPSEC_DEBUG),y)
++override EXTRA_CFLAGS += -g
++endif
++
++# LIBCRYPTO normally comes as an argument from "parent" Makefile
++# (this applies both to FS' "make module" and eg. Linux' "make modules"
++# But make dep doest follow same evaluations, so we need this default:
++LIBCRYPTO=$(TOPDIR)/lib/libcrypto
++
++override EXTRA_CFLAGS += -I$(LIBCRYPTO)/include
++override EXTRA_CFLAGS += -Wall -Wpointer-arith -Wstrict-prototypes
++
++MOD_LIST_NAME := NET_MISC_MODULES
++
++#O_TARGET := static_init.o
++
++subdir-  := 
++subdir-n := 
++subdir-y :=
++subdir-m :=
++
++obj-y := static_init.o
++
++ARCH_ASM-y :=
++ARCH_ASM-$(CONFIG_M586)               := i586
++ARCH_ASM-$(CONFIG_M586TSC)    := i586
++ARCH_ASM-$(CONFIG_M586MMX)    := i586
++ARCH_ASM-$(CONFIG_MK6)                := i586
++ARCH_ASM-$(CONFIG_M686)               := i686
++ARCH_ASM-$(CONFIG_MPENTIUMIII)        := i686
++ARCH_ASM-$(CONFIG_MPENTIUM4)  := i686
++ARCH_ASM-$(CONFIG_MK7)                := i686
++ARCH_ASM-$(CONFIG_MCRUSOE)    := i586
++ARCH_ASM-$(CONFIG_MWINCHIPC6) := i586
++ARCH_ASM-$(CONFIG_MWINCHIP2)  := i586
++ARCH_ASM-$(CONFIG_MWINCHIP3D) := i586
++ARCH_ASM-$(CONFIG_USERMODE)   := i586
++
++ARCH_ASM :=$(ARCH_ASM-y)
++ifdef NO_ASM
++ARCH_ASM :=
++endif
++
++# The algorithm makefiles may put dependences, short-circuit them
++null:
++
++makefiles=$(filter-out %.preipsec, $(wildcard Makefile.alg_*))
++ifneq ($(makefiles),)
++#include Makefile.alg_aes
++#include Makefile.alg_aes-opt
++include $(makefiles)
++endif
++
++# These rules translate from new to old makefile rules
++# Translate to Rules.make lists.
++multi-used      := $(filter $(list-multi), $(obj-y) $(obj-m))
++multi-objs      := $(foreach m, $(multi-used), $($(basename $(m))-objs))
++active-objs     := $(sort $(multi-objs) $(obj-y) $(obj-m))
++O_OBJS          := $(obj-y)
++M_OBJS          := $(obj-m)
++MIX_OBJS        := $(filter $(export-objs), $(active-objs))
++#OX_OBJS := $(export-objs)
++SUB_DIRS := $(subdir-y)
++ALL_SUB_DIRS := $(subdir-y) $(subdir-m)
++MOD_SUB_DIRS := $(subdir-m)
++
++
++static_init_mod.o: $(obj-y) 
++      rm -f $@
++      $(LD) $(LD_EXTRAFLAGS) $(obj-y) -r -o $@
++
++perlasm: ../../../crypto/ciphers/des/asm/perlasm
++      ln -sf $? $@
++
++$(obj-y) $(obj-m): $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h
++$(alg_obj-y) $(alg_obj-m): perlasm $(TOPDIR)/include/linux/config.h $(TOPDIR)/include/linux/autoconf.h $(KLIPS_TOP)/include/freeswan/ipsec_alg.h
++
++
++all_alg_modules: perlasm $(ALG_MODULES)
++      @echo "ALG_MODULES=$(ALG_MODULES)"
++
++
++#
++# Construct alg. init. function: call ipsec_ALGO_init() for every static algo
++# Needed when there are static algos (with static or modular ipsec.o)
++#
++static_init.c: $(TOPDIR)/include/linux/autoconf.h Makefile $(makefiles) scripts/mk-static_init.c.sh
++      @echo "Re-creating $@"
++      $(SHELL) scripts/mk-static_init.c.sh $(static_init-func-y) > $@
++
++clean:
++      @for i in $(ALG_SUBDIRS);do test -d $$i && make -C $$i clean;done;exit 0
++      @find . -type l  -exec rm -f {} \;
++      -rm -f perlasm
++      -rm -rf $(ALG_SUBDIRS)
++      -rm -f *.o static_init.c
++
++ifdef TOPDIR
++include $(TOPDIR)/Rules.make
++endif
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/Makefile.alg_aes     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,18 @@
++MOD_AES := ipsec_aes.o
++
++ALG_MODULES += $(MOD_AES)
++ALG_SUBDIRS += libaes
++
++obj-$(CONFIG_IPSEC_ALG_AES) += $(MOD_AES)
++static_init-func-$(CONFIG_IPSEC_ALG_AES)+= ipsec_aes_init
++alg_obj-$(CONFIG_IPSEC_ALG_AES) += ipsec_alg_aes.o
++
++AES_OBJS := ipsec_alg_aes.o $(LIBCRYPTO)/libaes/libaes.a 
++
++
++$(MOD_AES): $(AES_OBJS) 
++      $(LD) $(EXTRA_LDFLAGS) -r $(AES_OBJS) -o $@
++
++$(LIBCRYPTO)/libaes/libaes.a: 
++        $(MAKE) -C $(LIBCRYPTO)/libaes CC='$(CC)' 'ARCH_ASM=$(ARCH_ASM)' CFLAGS='$(CFLAGS) $(EXTRA_CFLAGS)' libaes.a
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/Makefile.alg_cryptoapi     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,14 @@
++MOD_CRYPTOAPI := ipsec_cryptoapi.o
++
++ifneq ($(wildcard $(TOPDIR)/include/linux/crypto.h),)
++ALG_MODULES += $(MOD_CRYPTOAPI)
++obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += $(MOD_CRYPTOAPI)
++static_init-func-$(CONFIG_IPSEC_ALG_CRYPTOAPI)+= ipsec_cryptoapi_init
++alg_obj-$(CONFIG_IPSEC_ALG_CRYPTOAPI) += ipsec_alg_cryptoapi.o
++else
++$(warning "Linux CryptoAPI (2.4.22+ or 2.6.x) not found, not building ipsec_cryptoapi.o")
++endif
++
++CRYPTOAPI_OBJS := ipsec_alg_cryptoapi.o 
++$(MOD_CRYPTOAPI): $(CRYPTOAPI_OBJS)
++      $(LD) -r $(CRYPTOAPI_OBJS) -o $@
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/ipsec_alg_cryptoapi.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,442 @@
++/*
++ * ipsec_alg to linux cryptoapi GLUE
++ *
++ * Authors: CODE.ar TEAM
++ *    Harpo MAxx <harpo@linuxmendoza.org.ar>
++ *    JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ *    Luciano Ruete <docemeses@softhome.net>
++ * 
++ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * Example usage:
++ *   modinfo -p ipsec_cryptoapi   (quite useful info, including supported algos)
++ *   modprobe ipsec_cryptoapi
++ *   modprobe ipsec_cryptoapi test=1
++ *   modprobe ipsec_cryptoapi excl=1                     (exclusive cipher/algo)
++ *   modprobe ipsec_cryptoapi noauto=1  aes=1 twofish=1  (only these ciphers)
++ *   modprobe ipsec_cryptoapi aes=128,128                (force these keylens)
++ *   modprobe ipsec_cryptoapi des_ede3=0                 (everything but 3DES)
++ */
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++/*    
++ *    special case: ipsec core modular with this static algo inside:
++ *    must avoid MODULE magic for this file
++ */
++#if CONFIG_IPSEC_MODULE && CONFIG_IPSEC_ALG_CRYPTOAPI
++#undef MODULE
++#endif
++
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/string.h>
++
++/* Check if __exit is defined, if not null it */
++#ifndef __exit
++#define __exit
++#endif
++
++/* warn the innocent */
++#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE)
++#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x"
++#define NO_CRYPTOAPI_SUPPORT
++#endif
++/*    Low freeswan header coupling    */
++#include "openswan/ipsec_alg.h"
++
++#include <linux/crypto.h>
++#ifdef CRYPTO_API_VERSION_CODE
++#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported"
++#define NO_CRYPTOAPI_SUPPORT
++#endif
++
++#ifdef NO_CRYPTOAPI_SUPPORT
++#warning "Building an unusable module :P"
++/* Catch old CryptoAPI by not allowing module to load */
++IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init )
++{
++      printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n");
++      return -EINVAL;
++}
++#else
++#include <asm/scatterlist.h>
++#include <asm/pgtable.h>
++#include <linux/mm.h>
++
++#define CIPHERNAME_AES                "aes"
++#define CIPHERNAME_3DES               "des3_ede"
++#define CIPHERNAME_BLOWFISH   "blowfish"
++#define CIPHERNAME_CAST               "cast5"
++#define CIPHERNAME_SERPENT    "serpent"
++#define CIPHERNAME_TWOFISH    "twofish"
++
++#define ESP_3DES              3
++#define ESP_AES                       12
++#define ESP_BLOWFISH          7       /* truely _constant_  :)  */
++#define ESP_CAST              6       /* quite constant :) */
++#define ESP_SERPENT           252     /* from ipsec drafts */
++#define ESP_TWOFISH           253     /* from ipsec drafts */
++
++#define AH_MD5                        2
++#define AH_SHA                        3
++#define DIGESTNAME_MD5                "md5"
++#define DIGESTNAME_SHA1               "sha1"
++
++MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete");
++static int debug=0;
++static int test=0;
++static int excl=0;
++static int noauto = 0;
++
++static int des_ede3[] = {-1, -1};
++static int aes[] = {-1, -1};
++static int blowfish[] = {-1, -1};
++static int cast[] = {-1, -1};
++static int serpent[] = {-1, -1};
++static int twofish[] = {-1, -1};
++
++#ifdef module_param
++module_param(debug,int,0600);
++module_param(test,int,0600);
++module_param(ebug,int,0600);
++
++module_param(noauto,int,0600);
++module_param(ebug,int,0600);
++
++module_param_array(des_ede3,int,NULL,0);
++module_param(aes,int,NULL,0);
++module_param(blowfish,int,NULL,0);
++module_param(cast,int,NULL,0);
++module_param(serpent,int,NULL,0);
++module_param(twofish,int,NULL,0);
++#else
++MODULE_PARM(debug, "i");
++MODULE_PARM(test, "i");
++MODULE_PARM(excl, "i");
++
++MODULE_PARM(noauto,"i");
++
++MODULE_PARM(des_ede3,"1-2i");
++MODULE_PARM(aes,"1-2i");
++MODULE_PARM(blowfish,"1-2i");
++MODULE_PARM(cast,"1-2i");
++MODULE_PARM(serpent,"1-2i");
++MODULE_PARM(twofish,"1-2i");
++#endif
++
++MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones");
++
++MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse");
++MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens");
++
++struct ipsec_alg_capi_cipher {
++      const char *ciphername; /* cryptoapi's ciphername */
++      unsigned blocksize;
++      unsigned short minbits;
++      unsigned short maxbits;
++      int *parm;              /* lkm param for this cipher */
++      struct ipsec_alg_enc alg;       /* note it's not a pointer */
++};
++static struct ipsec_alg_capi_cipher alg_capi_carray[] = {
++      { CIPHERNAME_AES ,     16, 128, 256, aes    , { ixt_alg_id: ESP_AES, }},
++      { CIPHERNAME_TWOFISH , 16, 128, 256, twofish, { ixt_alg_id: ESP_TWOFISH, }},
++      { CIPHERNAME_SERPENT , 16, 128, 256, serpent, { ixt_alg_id: ESP_SERPENT, }},
++      { CIPHERNAME_CAST ,     8, 128, 128, cast   , { ixt_alg_id: ESP_CAST, }},
++      { CIPHERNAME_BLOWFISH , 8,  96, 448, blowfish,{ ixt_alg_id: ESP_BLOWFISH, }},
++      { CIPHERNAME_3DES ,     8, 192, 192, des_ede3,{ ixt_alg_id: ESP_3DES, }},
++      { NULL, 0, 0, 0, NULL, {} }
++};
++#ifdef NOT_YET
++struct ipsec_alg_capi_digest {
++      const char *digestname; /* cryptoapi's digestname */
++      struct digest_implementation *di;
++      struct ipsec_alg_auth alg;      /* note it's not a pointer */
++};
++static struct ipsec_alg_capi_cipher alg_capi_darray[] = {
++      { DIGESTNAME_MD5,     NULL, { ixt_alg_id: AH_MD5, }},
++      { DIGESTNAME_SHA1,    NULL, { ixt_alg_id: AH_SHA, }},
++      { NULL, NULL, {} }
++};
++#endif
++/*
++ *    "generic" linux cryptoapi setup_cipher() function
++ */
++int setup_cipher(const char *ciphername)
++{
++      return crypto_alg_available(ciphername, 0);
++}
++
++/*
++ *    setups ipsec_alg_capi_cipher "hyper" struct components, calling
++ *    register_ipsec_alg for cointaned ipsec_alg object
++ */
++static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e);
++static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen);
++static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt);
++
++static int
++setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr)
++{
++      int ret;
++      cptr->alg.ixt_version = IPSEC_ALG_VERSION;
++      cptr->alg.ixt_module = THIS_MODULE;
++      atomic_set (& cptr->alg.ixt_refcnt, 0);
++      strncpy (cptr->alg.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_name));
++
++      cptr->alg.ixt_blocksize=cptr->blocksize;
++      cptr->alg.ixt_keyminbits=cptr->minbits;
++      cptr->alg.ixt_keymaxbits=cptr->maxbits;
++      cptr->alg.ixt_state = 0;
++      if (excl) cptr->alg.ixt_state |= IPSEC_ALG_ST_EXCL;
++      cptr->alg.ixt_e_keylen=cptr->alg.ixt_keymaxbits/8;
++      cptr->alg.ixt_e_ctx_size = 0;
++      cptr->alg.ixt_alg_type = IPSEC_ALG_TYPE_ENCRYPT;
++      cptr->alg.ixt_e_new_key = _capi_new_key;
++      cptr->alg.ixt_e_destroy_key = _capi_destroy_key;
++      cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt;
++      cptr->alg.ixt_data = cptr;
++
++      ret=register_ipsec_alg_enc(&cptr->alg);
++      printk("setup_ipsec_alg_capi_cipher(): " 
++                      "alg_type=%d alg_id=%d name=%s "
++                      "keyminbits=%d keymaxbits=%d, ret=%d\n", 
++                              cptr->alg.ixt_alg_type, 
++                              cptr->alg.ixt_alg_id, 
++                              cptr->alg.ixt_name, 
++                              cptr->alg.ixt_keyminbits,
++                              cptr->alg.ixt_keymaxbits,
++                              ret);
++      return ret;
++}
++/*
++ *    called in ipsec_sa_wipe() time, will destroy key contexts
++ *    and do 1 unbind()
++ */
++static void 
++_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e)
++{
++      struct crypto_tfm *tfm=(struct crypto_tfm*)key_e;
++      
++      if (debug > 0)
++              printk(KERN_DEBUG "klips_debug: _capi_destroy_key:"
++                              "name=%s key_e=%p \n",
++                              alg->ixt_name, key_e);
++      if (!key_e) {
++              printk(KERN_ERR "klips_debug: _capi_destroy_key:"
++                              "name=%s NULL key_e!\n",
++                              alg->ixt_name);
++              return;
++      }
++      crypto_free_tfm(tfm);
++}
++      
++/*
++ *    create new key context, need alg->ixt_data to know which
++ *    (of many) cipher inside this module is the target
++ */
++static __u8 *
++_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen)
++{
++      struct ipsec_alg_capi_cipher *cptr;
++      struct crypto_tfm *tfm=NULL;
++
++      cptr = alg->ixt_data;
++      if (!cptr) {
++              printk(KERN_ERR "_capi_new_key(): "
++                              "NULL ixt_data (?!) for \"%s\" algo\n" 
++                              , alg->ixt_name);
++              goto err;
++      }
++      if (debug > 0)
++              printk(KERN_DEBUG "klips_debug:_capi_new_key:"
++                              "name=%s cptr=%p key=%p keysize=%d\n",
++                              alg->ixt_name, cptr, key, keylen);
++      
++      /*      
++       *      alloc tfm
++       */
++      tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC);
++      if (!tfm) {
++              printk(KERN_ERR "_capi_new_key(): "
++                              "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" 
++                      , alg->ixt_name, cptr->ciphername);
++              goto err;
++      }
++      if (crypto_cipher_setkey(tfm, key, keylen) < 0) {
++              printk(KERN_ERR "_capi_new_key(): "
++                              "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" 
++                      , alg->ixt_name, keylen);
++              crypto_free_tfm(tfm);
++              tfm=NULL;
++      }
++err:
++      if (debug > 0)
++              printk(KERN_DEBUG "klips_debug:_capi_new_key:"
++                              "name=%s key=%p keylen=%d tfm=%p\n",
++                              alg->ixt_name, key, keylen, tfm);
++      return (__u8 *) tfm;
++}
++/*
++ *    core encryption function: will use cx->ci to call actual cipher's
++ *    cbc function
++ */
++static int 
++_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
++      int error =0;
++      struct crypto_tfm *tfm=(struct crypto_tfm *)key_e;
++      struct scatterlist sg = { 
++              .page = virt_to_page(in),
++              .offset = (unsigned long)(in) % PAGE_SIZE,
++              .length=ilen,
++      };
++      if (debug > 1)
++              printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:"
++                              "key_e=%p "
++                              "in=%p out=%p ilen=%d iv=%p encrypt=%d\n"
++                              , key_e
++                              , in, in, ilen, iv, encrypt);
++      crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm));
++      if (encrypt)
++              error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen);
++      else
++              error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen);
++      if (debug > 1)
++              printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:"
++                              "error=%d\n"
++                              , error);
++      return (error<0)? error : ilen;
++}
++/*
++ *    main initialization loop: for each cipher in list, do
++ *    1) setup cryptoapi cipher else continue
++ *    2) register ipsec_alg object
++ */
++static int
++setup_cipher_list (struct ipsec_alg_capi_cipher* clist) 
++{
++      struct ipsec_alg_capi_cipher *cptr;
++      /* foreach cipher in list ... */
++      for (cptr=clist;cptr->ciphername;cptr++) {
++              /* 
++               * see if cipher has been disabled (0) or
++               * if noauto set and not enabled (1)
++               */
++              if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) {
++                      if (debug>0)
++                              printk(KERN_INFO "setup_cipher_list(): "
++                                      "ciphername=%s skipped at user request: "
++                                      "noauto=%d parm[0]=%d parm[1]=%d\n"
++                                      , cptr->ciphername
++                                      , noauto
++                                      , cptr->parm[0]
++                                      , cptr->parm[1]);
++                      continue;
++              }
++              /* 
++               *      use a local ci to avoid touching cptr->ci,
++               *      if register ipsec_alg success then bind cipher
++               */
++              if( setup_cipher(cptr->ciphername) ) {
++                      if (debug > 0)
++                              printk(KERN_DEBUG "klips_debug:"
++                                              "setup_cipher_list():"
++                                              "ciphername=%s found\n"
++                              , cptr->ciphername);
++                      if (setup_ipsec_alg_capi_cipher(cptr) == 0) {
++                              
++                              
++                      } else {
++                              printk(KERN_ERR "klips_debug:"
++                                              "setup_cipher_list():"
++                                              "ciphername=%s failed ipsec_alg_register\n"
++                              , cptr->ciphername);
++                      }
++              } else {
++                      if (debug>0)
++                              printk(KERN_INFO "setup_cipher_list(): lookup for ciphername=%s: not found \n",
++                              cptr->ciphername);
++              }
++      }
++      return 0;
++}
++/*
++ *    deregister ipsec_alg objects and unbind ciphers
++ */
++static int
++unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) 
++{
++      struct ipsec_alg_capi_cipher *cptr;
++      /* foreach cipher in list ... */
++      for (cptr=clist;cptr->ciphername;cptr++) {
++              if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) {
++                      unregister_ipsec_alg_enc(&cptr->alg);
++              }
++      }
++      return 0;
++}
++/*
++ *    test loop for registered algos
++ */
++static int
++test_cipher_list (struct ipsec_alg_capi_cipher* clist) 
++{
++      int test_ret;
++      struct ipsec_alg_capi_cipher *cptr;
++      /* foreach cipher in list ... */
++      for (cptr=clist;cptr->ciphername;cptr++) {
++              if (cptr->alg.ixt_state & IPSEC_ALG_ST_REGISTERED) {
++                      test_ret=ipsec_alg_test(
++                                      cptr->alg.ixt_alg_type,
++                                      cptr->alg.ixt_alg_id, 
++                                      test);
++                      printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", 
++                                      cptr->alg.ixt_alg_type, 
++                                      cptr->alg.ixt_alg_id, 
++                                      test_ret);
++              }
++      }
++      return 0;
++}
++
++IPSEC_ALG_MODULE_INIT( ipsec_cryptoapi_init )
++{
++      int ret, test_ret;
++      if ((ret=setup_cipher_list(alg_capi_carray)) < 0)
++              return  -EPROTONOSUPPORT;
++      if (ret==0 && test) {
++              test_ret=test_cipher_list(alg_capi_carray);
++      }
++      return ret;
++}
++IPSEC_ALG_MODULE_EXIT( ipsec_cryptoapi_fini )
++{
++      unsetup_cipher_list(alg_capi_carray);
++      return;
++}
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++
++EXPORT_NO_SYMBOLS;
++#endif /* NO_CRYPTOAPI_SUPPORT */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/alg/scripts/mk-static_init.c.sh     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,18 @@
++#!/bin/sh
++cat << EOF
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include "freeswan/ipsec_alg.h"
++$(for i in $*; do
++      test -z "$i" && continue
++      echo "extern int $i(void);"
++done)
++void ipsec_alg_static_init(void){ 
++      int __attribute__ ((unused)) err=0;
++$(for i in $*; do
++      test -z "$i" && continue
++      echo "  if ((err=$i()) < 0)"
++      echo "          printk(KERN_WARNING \"$i() returned %d\", err);"
++done)
++}
++EOF
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/anyaddr.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,148 @@
++/*
++ * special addresses
++ * Copyright (C) 2000  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: anyaddr.c,v 1.10.10.1 2006/11/24 05:55:46 paul Exp $
++ */
++#include "openswan.h"
++
++/* these are mostly fallbacks for the no-IPv6-support-in-library case */
++#ifndef IN6ADDR_ANY_INIT
++#define       IN6ADDR_ANY_INIT        {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
++#endif
++#ifndef IN6ADDR_LOOPBACK_INIT
++#define       IN6ADDR_LOOPBACK_INIT   {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
++#endif
++
++static struct in6_addr v6any = IN6ADDR_ANY_INIT;
++static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT;
++
++/*
++ - anyaddr - initialize to the any-address value
++ */
++err_t                         /* NULL for success, else string literal */
++anyaddr(af, dst)
++int af;                               /* address family */
++ip_address *dst;
++{
++      uint32_t v4any = htonl(INADDR_ANY);
++
++      switch (af) {
++      case AF_INET:
++              return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst);
++              break;
++      case AF_INET6:
++              return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst);
++              break;
++      default:
++              return "unknown address family in anyaddr/unspecaddr";
++              break;
++      }
++}
++
++/*
++ - unspecaddr - initialize to the unspecified-address value
++ */
++err_t                         /* NULL for success, else string literal */
++unspecaddr(af, dst)
++int af;                               /* address family */
++ip_address *dst;
++{
++      return anyaddr(af, dst);
++}
++
++/*
++ - loopbackaddr - initialize to the loopback-address value
++ */
++err_t                         /* NULL for success, else string literal */
++loopbackaddr(af, dst)
++int af;                               /* address family */
++ip_address *dst;
++{
++      uint32_t v4loop = htonl(INADDR_LOOPBACK);
++
++      switch (af) {
++      case AF_INET:
++              return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst);
++              break;
++      case AF_INET6:
++              return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst);
++              break;
++      default:
++              return "unknown address family in loopbackaddr";
++              break;
++      }
++}
++
++/*
++ - isanyaddr - test for the any-address value
++ */
++int
++isanyaddr(src)
++const ip_address *src;
++{
++      uint32_t v4any = htonl(INADDR_ANY);
++      int cmp;
++
++      switch (src->u.v4.sin_family) {
++      case AF_INET:
++              cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any));
++              break;
++      case AF_INET6:
++              cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any));
++              break;
++      case 0:
++              /* a zeroed structure is considered any address */
++              return 1;
++      default:
++              return 0;
++              break;
++      }
++
++      return (cmp == 0) ? 1 : 0;
++}
++
++/*
++ - isunspecaddr - test for the unspecified-address value
++ */
++int
++isunspecaddr(src)
++const ip_address *src;
++{
++      return isanyaddr(src);
++}
++
++/*
++ - isloopbackaddr - test for the loopback-address value
++ */
++int
++isloopbackaddr(src)
++const ip_address *src;
++{
++      uint32_t v4loop = htonl(INADDR_LOOPBACK);
++      int cmp;
++
++      switch (src->u.v4.sin_family) {
++      case AF_INET:
++              cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop));
++              break;
++      case AF_INET6:
++              cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop));
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      return (cmp == 0) ? 1 : 0;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/datatot.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,234 @@
++/*
++ * convert from binary data (e.g. key) to text form
++ * Copyright (C) 2000  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: datatot.c,v 1.7 2005/04/14 20:48:43 mcr Exp $
++ */
++#include "openswan.h"
++
++static void convert(const char *src, size_t nreal, int format, char *out);
++
++/*
++ - datatot - convert data bytes to text
++ */
++size_t                                /* true length (with NUL) for success */
++datatot(src, srclen, format, dst, dstlen)
++const char *src;
++size_t srclen;
++int format;                   /* character indicating what format */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      size_t inblocksize;     /* process this many bytes at a time */
++      size_t outblocksize;    /* producing this many */
++      size_t breakevery;      /* add a _ every this many (0 means don't) */
++      size_t sincebreak;      /* output bytes since last _ */
++      char breakchar;         /* character used to break between groups */
++      char inblock[10];       /* enough for any format */
++      char outblock[10];      /* enough for any format */
++      char fake[1];           /* fake output area for dstlen == 0 */
++      size_t needed;          /* return value */
++      char *stop;             /* where the terminating NUL will go */
++      size_t ntodo;           /* remaining input */
++      size_t nreal;
++      char *out;
++      char *prefix;
++
++      breakevery = 0;
++      breakchar = '_';
++
++      switch (format) {
++      case 0:
++      case 'h':
++              format = 'x';
++              breakevery = 8;
++              /* FALLTHROUGH */
++      case 'x':
++              inblocksize = 1;
++              outblocksize = 2;
++              prefix = "0x";
++              break;
++      case ':':
++              format = 'x';
++              breakevery = 2;
++              breakchar = ':';
++              /* FALLTHROUGH */
++      case 16:
++              inblocksize = 1;
++              outblocksize = 2;
++              prefix = "";
++              format = 'x';
++              break;
++      case 's':
++              inblocksize = 3;
++              outblocksize = 4;
++              prefix = "0s";
++              break;
++      case 64:                /* beware, equals ' ' */
++              inblocksize = 3;
++              outblocksize = 4;
++              prefix = "";
++              format = 's';
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      user_assert(inblocksize < sizeof(inblock));
++      user_assert(outblocksize < sizeof(outblock));
++      user_assert(breakevery % outblocksize == 0);
++
++      if (srclen == 0)
++              return 0;
++      ntodo = srclen;
++
++      if (dstlen == 0) {      /* dispose of awkward special case */
++              dst = fake;
++              dstlen = 1;
++      }
++      stop = dst + dstlen - 1;
++
++      nreal = strlen(prefix);
++      needed = nreal;                 /* for starters */
++      if (dstlen <= nreal) {          /* prefix won't fit */
++              strncpy(dst, prefix, dstlen - 1);
++              dst += dstlen - 1;
++      } else {
++              strcpy(dst, prefix);
++              dst += nreal;
++      }
++
++      user_assert(dst <= stop);
++      sincebreak = 0;
++
++      while (ntodo > 0) {
++              if (ntodo < inblocksize) {      /* incomplete input */
++                      memset(inblock, 0, sizeof(inblock));
++                      memcpy(inblock, src, ntodo);
++                      src = inblock;
++                      nreal = ntodo;
++                      ntodo = inblocksize;
++              } else
++                      nreal = inblocksize;
++              out = (outblocksize > stop - dst) ? outblock : dst;
++
++              convert(src, nreal, format, out);
++              needed += outblocksize;
++              sincebreak += outblocksize;
++              if (dst < stop) {
++                      if (out != dst) {
++                              user_assert(outblocksize > stop - dst);
++                              memcpy(dst, out, stop - dst);
++                              dst = stop;
++                      } else
++                              dst += outblocksize;
++              }
++
++              src += inblocksize;
++              ntodo -= inblocksize;
++              if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) {
++                      if (dst < stop)
++                              *dst++ = breakchar;
++                      needed++;
++                      sincebreak = 0;
++              }
++      }
++
++      user_assert(dst <= stop);
++      *dst++ = '\0';
++      needed++;
++
++      return needed;
++}
++
++/*
++ - convert - convert one input block to one output block
++ */
++static void
++convert(src, nreal, format, out)
++const char *src;
++size_t nreal;                 /* how much of the input block is real */
++int format;
++char *out;
++{
++      static char hex[] = "0123456789abcdef";
++      static char base64[] =  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
++                              "abcdefghijklmnopqrstuvwxyz"
++                              "0123456789+/";
++      unsigned char c;
++      unsigned char c1, c2, c3;
++
++      user_assert(nreal > 0);
++      switch (format) {
++      case 'x':
++              user_assert(nreal == 1);
++              c = (unsigned char)*src;
++              *out++ = hex[c >> 4];
++              *out++ = hex[c & 0xf];
++              break;
++      case 's':
++              c1 = (unsigned char)*src++;
++              c2 = (unsigned char)*src++;
++              c3 = (unsigned char)*src++;
++              *out++ = base64[c1 >> 2];       /* top 6 bits of c1 */
++              c = (c1 & 0x3) << 4;            /* bottom 2 of c1... */
++              c |= c2 >> 4;                   /* ...top 4 of c2 */
++              *out++ = base64[c];
++              if (nreal == 1)
++                      *out++ = '=';
++              else {
++                      c = (c2 & 0xf) << 2;    /* bottom 4 of c2... */
++                      c |= c3 >> 6;           /* ...top 2 of c3 */
++                      *out++ = base64[c];
++              }
++              if (nreal <= 2)
++                      *out++ = '=';
++              else
++                      *out++ = base64[c3 & 0x3f];     /* bottom 6 of c3 */
++              break;
++      default:
++              user_assert(nreal == 0);        /* unknown format */
++              break;
++      }
++}
++
++/*
++ - datatoa - convert data to ASCII
++ * backward-compatibility synonym for datatot
++ */
++size_t                                /* true length (with NUL) for success */
++datatoa(src, srclen, format, dst, dstlen)
++const char *src;
++size_t srclen;
++int format;                   /* character indicating what format */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      return datatot(src, srclen, format, dst, dstlen);
++}
++
++/*
++ - bytestoa - convert data bytes to ASCII
++ * backward-compatibility synonym for datatot
++ */
++size_t                                /* true length (with NUL) for success */
++bytestoa(src, srclen, format, dst, dstlen)
++const char *src;
++size_t srclen;
++int format;                   /* character indicating what format */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      return datatot(src, srclen, format, dst, dstlen);
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/defconfig     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,148 @@
++
++#
++# RCSID $Id: defconfig,v 1.28.2.1 2006/10/11 18:14:33 paul Exp $
++#
++
++#
++# FreeS/WAN IPSec implementation, KLIPS kernel config defaults
++#
++
++#
++# First, lets override stuff already set or not in the kernel config.
++#
++# We can't even think about leaving this off...
++CONFIG_INET=y
++
++#
++# This must be on for subnet protection.
++CONFIG_IP_FORWARD=y
++
++# Shut off IPSEC masquerading if it has been enabled, since it will 
++# break the compile.  IPPROTO_ESP and IPPROTO_AH were included in 
++# net/ipv4/ip_masq.c when they should have gone into include/linux/in.h.
++CONFIG_IP_MASQUERADE_IPSEC=n
++
++#
++# Next, lets set the recommended FreeS/WAN configuration.
++#
++
++# To config as static (preferred), 'y'.  To config as module, 'm'.
++CONFIG_KLIPS=m
++
++# To do tunnel mode IPSec, this must be enabled.
++CONFIG_KLIPS_IPIP=y
++
++# To enable authentication, say 'y'.   (Highly recommended)
++CONFIG_KLIPS_AH=y
++
++# Authentication algorithm(s):
++CONFIG_KLIPS_AUTH_HMAC_MD5=y
++CONFIG_KLIPS_AUTH_HMAC_SHA1=y
++
++# To enable encryption, say 'y'.   (Highly recommended)
++CONFIG_KLIPS_ESP=y
++
++# modular algo extensions (and new ALGOs)
++CONFIG_KLIPS_ALG=y
++
++# Encryption algorithm(s):
++CONFIG_KLIPS_ENC_3DES=y
++CONFIG_KLIPS_ENC_AES=y
++# CONFIG_KLIPS_ENC_NULL=y
++
++# Use CryptoAPI for ALG? - by default, no.
++CONFIG_KLIPS_ENC_CRYPTOAPI=n
++
++# IP Compression: new, probably still has minor bugs.
++CONFIG_KLIPS_IPCOMP=y
++
++# To enable userspace-switchable KLIPS debugging, say 'y'.
++CONFIG_KLIPS_DEBUG=y
++
++# NAT Traversal
++CONFIG_IPSEC_NAT_TRAVERSAL=y
++
++#
++#
++# $Log: defconfig,v $
++# Revision 1.28.2.1  2006/10/11 18:14:33  paul
++# Add JuanJo Ciarlante's ESP_NULL patches for KLIPS, but leave it disabled
++# per default.
++#
++# Revision 1.28  2005/05/11 03:15:42  mcr
++#     adjusted makefiles to sanely build modules properly.
++#
++# Revision 1.27  2005/03/20 03:00:05  mcr
++#     default configuration should enable NAT_TRAVERSAL.
++#
++# Revision 1.26  2004/07/10 19:11:18  mcr
++#     CONFIG_IPSEC -> CONFIG_KLIPS.
++#
++# Revision 1.25  2004/07/05 01:03:53  mcr
++#     fix for adding cryptoapi code.
++#     keep it off for now, since UMLs do not have it yet.
++#
++# Revision 1.24  2004/04/06 02:49:25  mcr
++#     pullup of algo code from alg-branch.
++#
++# Revision 1.23.2.2  2004/04/05 04:30:46  mcr
++#     patches for alg-branch to compile/work with 2.x openswan
++#
++# Revision 1.23.2.1  2003/12/22 15:25:52  jjo
++# . Merged algo-0.8.1-rc11-test1 into alg-branch
++#
++# Revision 1.23  2003/12/10 01:14:27  mcr
++#     NAT-traversal patches to KLIPS.
++#
++# Revision 1.22  2003/02/24 19:37:27  mcr
++#     changed default compilation mode to static.
++#
++# Revision 1.21  2002/04/24 07:36:27  mcr
++# Moved from ./klips/net/ipsec/defconfig,v
++#
++# Revision 1.20  2002/04/02 04:07:40  mcr
++#     default build is now 'm'odule for KLIPS
++#
++# Revision 1.19  2002/03/08 18:57:17  rgb
++# Added a blank line at the beginning of the file to make it easier for
++# other projects to patch ./arch/i386/defconfig, for example
++# LIDS+grSecurity requested by Jason Pattie.
++#
++# Revision 1.18  2000/11/30 17:26:56  rgb
++# Cleaned out unused options and enabled ipcomp by default.
++#
++# Revision 1.17  2000/09/15 11:37:01  rgb
++# Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++# IPCOMP zlib deflate code.
++#
++# Revision 1.16  2000/09/08 19:12:55  rgb
++# Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++#
++# Revision 1.15  2000/05/24 19:37:13  rgb
++# *** empty log message ***
++#
++# Revision 1.14  2000/05/11 21:14:57  henry
++# just commenting the FOOBAR=y lines out is not enough
++#
++# Revision 1.13  2000/05/10 20:17:58  rgb
++# Comment out netlink defaults, which are no longer needed.
++#
++# Revision 1.12  2000/05/10 19:13:38  rgb
++# Added configure option to shut off no eroute passthrough.
++#
++# Revision 1.11  2000/03/16 07:09:46  rgb
++# Hardcode PF_KEYv2 support.
++# Disable IPSEC_ICMP by default.
++# Remove DES config option from defaults file.
++#
++# Revision 1.10  2000/01/11 03:09:42  rgb
++# Added a default of 'y' to PF_KEYv2 keying I/F.
++#
++# Revision 1.9  1999/05/08 21:23:12  rgb
++# Added support for 2.2.x kernels.
++#
++# Revision 1.8  1999/04/06 04:54:25  rgb
++# Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++# patch shell fixes.
++#
++#
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/deflate.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1351 @@
++/* deflate.c -- compress data using the deflation algorithm
++ * Copyright (C) 1995-2002 Jean-loup Gailly.
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/*
++ *  ALGORITHM
++ *
++ *      The "deflation" process depends on being able to identify portions
++ *      of the input text which are identical to earlier input (within a
++ *      sliding window trailing behind the input currently being processed).
++ *
++ *      The most straightforward technique turns out to be the fastest for
++ *      most input files: try all possible matches and select the longest.
++ *      The key feature of this algorithm is that insertions into the string
++ *      dictionary are very simple and thus fast, and deletions are avoided
++ *      completely. Insertions are performed at each input character, whereas
++ *      string matches are performed only when the previous match ends. So it
++ *      is preferable to spend more time in matches to allow very fast string
++ *      insertions and avoid deletions. The matching algorithm for small
++ *      strings is inspired from that of Rabin & Karp. A brute force approach
++ *      is used to find longer strings when a small match has been found.
++ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
++ *      (by Leonid Broukhis).
++ *         A previous version of this file used a more sophisticated algorithm
++ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
++ *      time, but has a larger average cost, uses more memory and is patented.
++ *      However the F&G algorithm may be faster for some highly redundant
++ *      files if the parameter max_chain_length (described below) is too large.
++ *
++ *  ACKNOWLEDGEMENTS
++ *
++ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
++ *      I found it in 'freeze' written by Leonid Broukhis.
++ *      Thanks to many people for bug reports and testing.
++ *
++ *  REFERENCES
++ *
++ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
++ *      Available in ftp://ds.internic.net/rfc/rfc1951.txt
++ *
++ *      A description of the Rabin and Karp algorithm is given in the book
++ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
++ *
++ *      Fiala,E.R., and Greene,D.H.
++ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
++ *
++ */
++
++/* @(#) $Id: deflate.c,v 1.4 2004/07/10 07:48:37 mcr Exp $ */
++
++#include "deflate.h"
++
++local const char deflate_copyright[] =
++   " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly ";
++/*
++  If you use the zlib library in a product, an acknowledgment is welcome
++  in the documentation of your product. If for some reason you cannot
++  include such an acknowledgment, I would appreciate that you keep this
++  copyright string in the executable of your product.
++ */
++
++/* ===========================================================================
++ *  Function prototypes.
++ */
++typedef enum {
++    need_more,      /* block not completed, need more input or more output */
++    block_done,     /* block flush performed */
++    finish_started, /* finish started, need only more output at next deflate */
++    finish_done     /* finish done, accept no more input or output */
++} block_state;
++
++typedef block_state (*compress_func) OF((deflate_state *s, int flush));
++/* Compression function. Returns the block state after the call. */
++
++local void fill_window    OF((deflate_state *s));
++local block_state deflate_stored OF((deflate_state *s, int flush));
++local block_state deflate_fast   OF((deflate_state *s, int flush));
++local block_state deflate_slow   OF((deflate_state *s, int flush));
++local void lm_init        OF((deflate_state *s));
++local void putShortMSB    OF((deflate_state *s, uInt b));
++local void flush_pending  OF((z_streamp strm));
++local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
++#ifdef ASMV
++      void match_init OF((void)); /* asm code initialization */
++      uInt longest_match  OF((deflate_state *s, IPos cur_match));
++#else
++local uInt longest_match  OF((deflate_state *s, IPos cur_match));
++#endif
++
++#ifdef DEBUG
++local  void check_match OF((deflate_state *s, IPos start, IPos match,
++                            int length));
++#endif
++
++/* ===========================================================================
++ * Local data
++ */
++
++#define NIL 0
++/* Tail of hash chains */
++
++#ifndef TOO_FAR
++#  define TOO_FAR 4096
++#endif
++/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
++
++#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
++/* Minimum amount of lookahead, except at the end of the input file.
++ * See deflate.c for comments about the MIN_MATCH+1.
++ */
++
++/* Values for max_lazy_match, good_match and max_chain_length, depending on
++ * the desired pack level (0..9). The values given below have been tuned to
++ * exclude worst case performance for pathological files. Better values may be
++ * found for specific files.
++ */
++typedef struct config_s {
++   ush good_length; /* reduce lazy search above this match length */
++   ush max_lazy;    /* do not perform lazy search above this match length */
++   ush nice_length; /* quit search above this match length */
++   ush max_chain;
++   compress_func func;
++} config;
++
++local const config configuration_table[10] = {
++/*      good lazy nice chain */
++/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
++/* 1 */ {4,    4,  8,    4, deflate_fast}, /* maximum speed, no lazy matches */
++/* 2 */ {4,    5, 16,    8, deflate_fast},
++/* 3 */ {4,    6, 32,   32, deflate_fast},
++
++/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
++/* 5 */ {8,   16, 32,   32, deflate_slow},
++/* 6 */ {8,   16, 128, 128, deflate_slow},
++/* 7 */ {8,   32, 128, 256, deflate_slow},
++/* 8 */ {32, 128, 258, 1024, deflate_slow},
++/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
++
++/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
++ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
++ * meaning.
++ */
++
++#define EQUAL 0
++/* result of memcmp for equal strings */
++
++struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
++
++/* ===========================================================================
++ * Update a hash value with the given input byte
++ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
++ *    input characters, so that a running hash key can be computed from the
++ *    previous key instead of complete recalculation each time.
++ */
++#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
++
++
++/* ===========================================================================
++ * Insert string str in the dictionary and set match_head to the previous head
++ * of the hash chain (the most recent string with same hash key). Return
++ * the previous length of the hash chain.
++ * If this file is compiled with -DFASTEST, the compression level is forced
++ * to 1, and no hash chains are maintained.
++ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
++ *    input characters and the first MIN_MATCH bytes of str are valid
++ *    (except for the last MIN_MATCH-1 bytes of the input file).
++ */
++#ifdef FASTEST
++#define INSERT_STRING(s, str, match_head) \
++   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
++    match_head = s->head[s->ins_h], \
++    s->head[s->ins_h] = (Pos)(str))
++#else
++#define INSERT_STRING(s, str, match_head) \
++   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
++    s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
++    s->head[s->ins_h] = (Pos)(str))
++#endif
++
++/* ===========================================================================
++ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
++ * prev[] will be initialized on the fly.
++ */
++#define CLEAR_HASH(s) \
++    s->head[s->hash_size-1] = NIL; \
++    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
++
++/* ========================================================================= */
++int ZEXPORT deflateInit_(strm, level, version, stream_size)
++    z_streamp strm;
++    int level;
++    const char *version;
++    int stream_size;
++{
++    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
++                       Z_DEFAULT_STRATEGY, version, stream_size);
++    /* To do: ignore strm->next_in if we use it as window */
++}
++
++/* ========================================================================= */
++int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
++                version, stream_size)
++    z_streamp strm;
++    int  level;
++    int  method;
++    int  windowBits;
++    int  memLevel;
++    int  strategy;
++    const char *version;
++    int stream_size;
++{
++    deflate_state *s;
++    int noheader = 0;
++    static const char* my_version = ZLIB_VERSION;
++
++    ushf *overlay;
++    /* We overlay pending_buf and d_buf+l_buf. This works since the average
++     * output size for (length,distance) codes is <= 24 bits.
++     */
++
++    if (version == Z_NULL || version[0] != my_version[0] ||
++        stream_size != sizeof(z_stream)) {
++      return Z_VERSION_ERROR;
++    }
++    if (strm == Z_NULL) return Z_STREAM_ERROR;
++
++    strm->msg = Z_NULL;
++    if (strm->zalloc == Z_NULL) {
++      return Z_STREAM_ERROR;
++/*    strm->zalloc = zcalloc;
++      strm->opaque = (voidpf)0;*/
++    }
++    if (strm->zfree == Z_NULL) return Z_STREAM_ERROR; /* strm->zfree = zcfree; */
++
++    if (level == Z_DEFAULT_COMPRESSION) level = 6;
++#ifdef FASTEST
++    level = 1;
++#endif
++
++    if (windowBits < 0) { /* undocumented feature: suppress zlib header */
++        noheader = 1;
++        windowBits = -windowBits;
++    }
++    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
++        windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
++      strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
++        return Z_STREAM_ERROR;
++    }
++    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
++    if (s == Z_NULL) return Z_MEM_ERROR;
++    strm->state = (struct internal_state FAR *)s;
++    s->strm = strm;
++
++    s->noheader = noheader;
++    s->w_bits = windowBits;
++    s->w_size = 1 << s->w_bits;
++    s->w_mask = s->w_size - 1;
++
++    s->hash_bits = memLevel + 7;
++    s->hash_size = 1 << s->hash_bits;
++    s->hash_mask = s->hash_size - 1;
++    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
++
++    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
++    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
++    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
++
++    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
++
++    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
++    s->pending_buf = (uchf *) overlay;
++    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
++
++    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
++        s->pending_buf == Z_NULL) {
++        strm->msg = ERR_MSG(Z_MEM_ERROR);
++        deflateEnd (strm);
++        return Z_MEM_ERROR;
++    }
++    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
++    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
++
++    s->level = level;
++    s->strategy = strategy;
++    s->method = (Byte)method;
++
++    return deflateReset(strm);
++}
++
++/* ========================================================================= */
++int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
++    z_streamp strm;
++    const Bytef *dictionary;
++    uInt  dictLength;
++{
++    deflate_state *s;
++    uInt length = dictLength;
++    uInt n;
++    IPos hash_head = 0;
++
++    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
++        strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
++
++    s = strm->state;
++    strm->adler = adler32(strm->adler, dictionary, dictLength);
++
++    if (length < MIN_MATCH) return Z_OK;
++    if (length > MAX_DIST(s)) {
++      length = MAX_DIST(s);
++#ifndef USE_DICT_HEAD
++      dictionary += dictLength - length; /* use the tail of the dictionary */
++#endif
++    }
++    zmemcpy(s->window, dictionary, length);
++    s->strstart = length;
++    s->block_start = (long)length;
++
++    /* Insert all strings in the hash table (except for the last two bytes).
++     * s->lookahead stays null, so s->ins_h will be recomputed at the next
++     * call of fill_window.
++     */
++    s->ins_h = s->window[0];
++    UPDATE_HASH(s, s->ins_h, s->window[1]);
++    for (n = 0; n <= length - MIN_MATCH; n++) {
++      INSERT_STRING(s, n, hash_head);
++    }
++    if (hash_head) hash_head = 0;  /* to make compiler happy */
++    return Z_OK;
++}
++
++/* ========================================================================= */
++int ZEXPORT deflateReset (strm)
++    z_streamp strm;
++{
++    deflate_state *s;
++    
++    if (strm == Z_NULL || strm->state == Z_NULL ||
++        strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
++
++    strm->total_in = strm->total_out = 0;
++    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
++    strm->data_type = Z_UNKNOWN;
++
++    s = (deflate_state *)strm->state;
++    s->pending = 0;
++    s->pending_out = s->pending_buf;
++
++    if (s->noheader < 0) {
++        s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
++    }
++    s->status = s->noheader ? BUSY_STATE : INIT_STATE;
++    strm->adler = 1;
++    s->last_flush = Z_NO_FLUSH;
++
++    _tr_init(s);
++    lm_init(s);
++
++    return Z_OK;
++}
++
++/* ========================================================================= */
++int ZEXPORT deflateParams(strm, level, strategy)
++    z_streamp strm;
++    int level;
++    int strategy;
++{
++    deflate_state *s;
++    compress_func func;
++    int err = Z_OK;
++
++    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
++    s = strm->state;
++
++    if (level == Z_DEFAULT_COMPRESSION) {
++      level = 6;
++    }
++    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
++      return Z_STREAM_ERROR;
++    }
++    func = configuration_table[s->level].func;
++
++    if (func != configuration_table[level].func && strm->total_in != 0) {
++      /* Flush the last buffer: */
++      err = deflate(strm, Z_PARTIAL_FLUSH);
++    }
++    if (s->level != level) {
++      s->level = level;
++      s->max_lazy_match   = configuration_table[level].max_lazy;
++      s->good_match       = configuration_table[level].good_length;
++      s->nice_match       = configuration_table[level].nice_length;
++      s->max_chain_length = configuration_table[level].max_chain;
++    }
++    s->strategy = strategy;
++    return err;
++}
++
++/* =========================================================================
++ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
++ * IN assertion: the stream state is correct and there is enough room in
++ * pending_buf.
++ */
++local void putShortMSB (s, b)
++    deflate_state *s;
++    uInt b;
++{
++    put_byte(s, (Byte)(b >> 8));
++    put_byte(s, (Byte)(b & 0xff));
++}   
++
++/* =========================================================================
++ * Flush as much pending output as possible. All deflate() output goes
++ * through this function so some applications may wish to modify it
++ * to avoid allocating a large strm->next_out buffer and copying into it.
++ * (See also read_buf()).
++ */
++local void flush_pending(strm)
++    z_streamp strm;
++{
++    unsigned len = strm->state->pending;
++
++    if (len > strm->avail_out) len = strm->avail_out;
++    if (len == 0) return;
++
++    zmemcpy(strm->next_out, strm->state->pending_out, len);
++    strm->next_out  += len;
++    strm->state->pending_out  += len;
++    strm->total_out += len;
++    strm->avail_out  -= len;
++    strm->state->pending -= len;
++    if (strm->state->pending == 0) {
++        strm->state->pending_out = strm->state->pending_buf;
++    }
++}
++
++/* ========================================================================= */
++int ZEXPORT deflate (strm, flush)
++    z_streamp strm;
++    int flush;
++{
++    int old_flush; /* value of flush param for previous deflate call */
++    deflate_state *s;
++
++    if (strm == Z_NULL || strm->state == Z_NULL ||
++      flush > Z_FINISH || flush < 0) {
++        return Z_STREAM_ERROR;
++    }
++    s = strm->state;
++
++    if (strm->next_out == Z_NULL ||
++        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
++      (s->status == FINISH_STATE && flush != Z_FINISH)) {
++        ERR_RETURN(strm, Z_STREAM_ERROR);
++    }
++    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
++
++    s->strm = strm; /* just in case */
++    old_flush = s->last_flush;
++    s->last_flush = flush;
++
++    /* Write the zlib header */
++    if (s->status == INIT_STATE) {
++
++        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
++        uInt level_flags = (s->level-1) >> 1;
++
++        if (level_flags > 3) level_flags = 3;
++        header |= (level_flags << 6);
++      if (s->strstart != 0) header |= PRESET_DICT;
++        header += 31 - (header % 31);
++
++        s->status = BUSY_STATE;
++        putShortMSB(s, header);
++
++      /* Save the adler32 of the preset dictionary: */
++      if (s->strstart != 0) {
++          putShortMSB(s, (uInt)(strm->adler >> 16));
++          putShortMSB(s, (uInt)(strm->adler & 0xffff));
++      }
++      strm->adler = 1L;
++    }
++
++    /* Flush as much pending output as possible */
++    if (s->pending != 0) {
++        flush_pending(strm);
++        if (strm->avail_out == 0) {
++          /* Since avail_out is 0, deflate will be called again with
++           * more output space, but possibly with both pending and
++           * avail_in equal to zero. There won't be anything to do,
++           * but this is not an error situation so make sure we
++           * return OK instead of BUF_ERROR at next call of deflate:
++             */
++          s->last_flush = -1;
++          return Z_OK;
++      }
++
++    /* Make sure there is something to do and avoid duplicate consecutive
++     * flushes. For repeated and useless calls with Z_FINISH, we keep
++     * returning Z_STREAM_END instead of Z_BUFF_ERROR.
++     */
++    } else if (strm->avail_in == 0 && flush <= old_flush &&
++             flush != Z_FINISH) {
++        ERR_RETURN(strm, Z_BUF_ERROR);
++    }
++
++    /* User must not provide more input after the first FINISH: */
++    if (s->status == FINISH_STATE && strm->avail_in != 0) {
++        ERR_RETURN(strm, Z_BUF_ERROR);
++    }
++
++    /* Start a new block or continue the current one.
++     */
++    if (strm->avail_in != 0 || s->lookahead != 0 ||
++        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
++        block_state bstate;
++
++      bstate = (*(configuration_table[s->level].func))(s, flush);
++
++        if (bstate == finish_started || bstate == finish_done) {
++            s->status = FINISH_STATE;
++        }
++        if (bstate == need_more || bstate == finish_started) {
++          if (strm->avail_out == 0) {
++              s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
++          }
++          return Z_OK;
++          /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
++           * of deflate should use the same flush parameter to make sure
++           * that the flush is complete. So we don't have to output an
++           * empty block here, this will be done at next call. This also
++           * ensures that for a very small output buffer, we emit at most
++           * one empty block.
++           */
++      }
++        if (bstate == block_done) {
++            if (flush == Z_PARTIAL_FLUSH) {
++                _tr_align(s);
++            } else { /* FULL_FLUSH or SYNC_FLUSH */
++                _tr_stored_block(s, (char*)0, 0L, 0);
++                /* For a full flush, this empty block will be recognized
++                 * as a special marker by inflate_sync().
++                 */
++                if (flush == Z_FULL_FLUSH) {
++                    CLEAR_HASH(s);             /* forget history */
++                }
++            }
++            flush_pending(strm);
++          if (strm->avail_out == 0) {
++            s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
++            return Z_OK;
++          }
++        }
++    }
++    Assert(strm->avail_out > 0, "bug2");
++
++    if (flush != Z_FINISH) return Z_OK;
++    if (s->noheader) return Z_STREAM_END;
++
++    /* Write the zlib trailer (adler32) */
++    putShortMSB(s, (uInt)(strm->adler >> 16));
++    putShortMSB(s, (uInt)(strm->adler & 0xffff));
++    flush_pending(strm);
++    /* If avail_out is zero, the application will call deflate again
++     * to flush the rest.
++     */
++    s->noheader = -1; /* write the trailer only once! */
++    return s->pending != 0 ? Z_OK : Z_STREAM_END;
++}
++
++/* ========================================================================= */
++int ZEXPORT deflateEnd (strm)
++    z_streamp strm;
++{
++    int status;
++
++    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
++
++    status = strm->state->status;
++    if (status != INIT_STATE && status != BUSY_STATE &&
++      status != FINISH_STATE) {
++      return Z_STREAM_ERROR;
++    }
++
++    /* Deallocate in reverse order of allocations: */
++    TRY_FREE(strm, strm->state->pending_buf);
++    TRY_FREE(strm, strm->state->head);
++    TRY_FREE(strm, strm->state->prev);
++    TRY_FREE(strm, strm->state->window);
++
++    ZFREE(strm, strm->state);
++    strm->state = Z_NULL;
++
++    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
++}
++
++/* =========================================================================
++ * Copy the source state to the destination state.
++ * To simplify the source, this is not supported for 16-bit MSDOS (which
++ * doesn't have enough memory anyway to duplicate compression states).
++ */
++int ZEXPORT deflateCopy (dest, source)
++    z_streamp dest;
++    z_streamp source;
++{
++#ifdef MAXSEG_64K
++    return Z_STREAM_ERROR;
++#else
++    deflate_state *ds;
++    deflate_state *ss;
++    ushf *overlay;
++
++
++    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
++        return Z_STREAM_ERROR;
++    }
++
++    ss = source->state;
++
++    *dest = *source;
++
++    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
++    if (ds == Z_NULL) return Z_MEM_ERROR;
++    dest->state = (struct internal_state FAR *) ds;
++    *ds = *ss;
++    ds->strm = dest;
++
++    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
++    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
++    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
++    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
++    ds->pending_buf = (uchf *) overlay;
++
++    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
++        ds->pending_buf == Z_NULL) {
++        deflateEnd (dest);
++        return Z_MEM_ERROR;
++    }
++    /* following zmemcpy do not work for 16-bit MSDOS */
++    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
++    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
++    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
++    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
++
++    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
++    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
++    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
++
++    ds->l_desc.dyn_tree = ds->dyn_ltree;
++    ds->d_desc.dyn_tree = ds->dyn_dtree;
++    ds->bl_desc.dyn_tree = ds->bl_tree;
++
++    return Z_OK;
++#endif
++}
++
++/* ===========================================================================
++ * Read a new buffer from the current input stream, update the adler32
++ * and total number of bytes read.  All deflate() input goes through
++ * this function so some applications may wish to modify it to avoid
++ * allocating a large strm->next_in buffer and copying from it.
++ * (See also flush_pending()).
++ */
++local int read_buf(strm, buf, size)
++    z_streamp strm;
++    Bytef *buf;
++    unsigned size;
++{
++    unsigned len = strm->avail_in;
++
++    if (len > size) len = size;
++    if (len == 0) return 0;
++
++    strm->avail_in  -= len;
++
++    if (!strm->state->noheader) {
++        strm->adler = adler32(strm->adler, strm->next_in, len);
++    }
++    zmemcpy(buf, strm->next_in, len);
++    strm->next_in  += len;
++    strm->total_in += len;
++
++    return (int)len;
++}
++
++/* ===========================================================================
++ * Initialize the "longest match" routines for a new zlib stream
++ */
++local void lm_init (s)
++    deflate_state *s;
++{
++    s->window_size = (ulg)2L*s->w_size;
++
++    CLEAR_HASH(s);
++
++    /* Set the default configuration parameters:
++     */
++    s->max_lazy_match   = configuration_table[s->level].max_lazy;
++    s->good_match       = configuration_table[s->level].good_length;
++    s->nice_match       = configuration_table[s->level].nice_length;
++    s->max_chain_length = configuration_table[s->level].max_chain;
++
++    s->strstart = 0;
++    s->block_start = 0L;
++    s->lookahead = 0;
++    s->match_length = s->prev_length = MIN_MATCH-1;
++    s->match_available = 0;
++    s->ins_h = 0;
++#ifdef ASMV
++    match_init(); /* initialize the asm code */
++#endif
++}
++
++/* ===========================================================================
++ * Set match_start to the longest match starting at the given string and
++ * return its length. Matches shorter or equal to prev_length are discarded,
++ * in which case the result is equal to prev_length and match_start is
++ * garbage.
++ * IN assertions: cur_match is the head of the hash chain for the current
++ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
++ * OUT assertion: the match length is not greater than s->lookahead.
++ */
++#ifndef ASMV
++/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
++ * match.S. The code will be functionally equivalent.
++ */
++#ifndef FASTEST
++local uInt longest_match(s, cur_match)
++    deflate_state *s;
++    IPos cur_match;                             /* current match */
++{
++    unsigned chain_length = s->max_chain_length;/* max hash chain length */
++    register Bytef *scan = s->window + s->strstart; /* current string */
++    register Bytef *match;                       /* matched string */
++    register int len;                           /* length of current match */
++    int best_len = s->prev_length;              /* best match length so far */
++    int nice_match = s->nice_match;             /* stop if match long enough */
++    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
++        s->strstart - (IPos)MAX_DIST(s) : NIL;
++    /* Stop when cur_match becomes <= limit. To simplify the code,
++     * we prevent matches with the string of window index 0.
++     */
++    Posf *prev = s->prev;
++    uInt wmask = s->w_mask;
++
++#ifdef UNALIGNED_OK
++    /* Compare two bytes at a time. Note: this is not always beneficial.
++     * Try with and without -DUNALIGNED_OK to check.
++     */
++    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
++    register ush scan_start = *(ushf*)scan;
++    register ush scan_end   = *(ushf*)(scan+best_len-1);
++#else
++    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
++    register Byte scan_end1  = scan[best_len-1];
++    register Byte scan_end   = scan[best_len];
++#endif
++
++    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
++     * It is easy to get rid of this optimization if necessary.
++     */
++    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
++
++    /* Do not waste too much time if we already have a good match: */
++    if (s->prev_length >= s->good_match) {
++        chain_length >>= 2;
++    }
++    /* Do not look for matches beyond the end of the input. This is necessary
++     * to make deflate deterministic.
++     */
++    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
++
++    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
++
++    do {
++        Assert(cur_match < s->strstart, "no future");
++        match = s->window + cur_match;
++
++        /* Skip to next match if the match length cannot increase
++         * or if the match length is less than 2:
++         */
++#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
++        /* This code assumes sizeof(unsigned short) == 2. Do not use
++         * UNALIGNED_OK if your compiler uses a different size.
++         */
++        if (*(ushf*)(match+best_len-1) != scan_end ||
++            *(ushf*)match != scan_start) continue;
++
++        /* It is not necessary to compare scan[2] and match[2] since they are
++         * always equal when the other bytes match, given that the hash keys
++         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
++         * strstart+3, +5, ... up to strstart+257. We check for insufficient
++         * lookahead only every 4th comparison; the 128th check will be made
++         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
++         * necessary to put more guard bytes at the end of the window, or
++         * to check more often for insufficient lookahead.
++         */
++        Assert(scan[2] == match[2], "scan[2]?");
++        scan++, match++;
++        do {
++        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
++                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
++                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
++                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
++                 scan < strend);
++        /* The funny "do {}" generates better code on most compilers */
++
++        /* Here, scan <= window+strstart+257 */
++        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
++        if (*scan == *match) scan++;
++
++        len = (MAX_MATCH - 1) - (int)(strend-scan);
++        scan = strend - (MAX_MATCH-1);
++
++#else /* UNALIGNED_OK */
++
++        if (match[best_len]   != scan_end  ||
++            match[best_len-1] != scan_end1 ||
++            *match            != *scan     ||
++            *++match          != scan[1])      continue;
++
++        /* The check at best_len-1 can be removed because it will be made
++         * again later. (This heuristic is not always a win.)
++         * It is not necessary to compare scan[2] and match[2] since they
++         * are always equal when the other bytes match, given that
++         * the hash keys are equal and that HASH_BITS >= 8.
++         */
++        scan += 2, match++;
++        Assert(*scan == *match, "match[2]?");
++
++        /* We check for insufficient lookahead only every 8th comparison;
++         * the 256th check will be made at strstart+258.
++         */
++        do {
++        } while (*++scan == *++match && *++scan == *++match &&
++                 *++scan == *++match && *++scan == *++match &&
++                 *++scan == *++match && *++scan == *++match &&
++                 *++scan == *++match && *++scan == *++match &&
++                 scan < strend);
++
++        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
++
++        len = MAX_MATCH - (int)(strend - scan);
++        scan = strend - MAX_MATCH;
++
++#endif /* UNALIGNED_OK */
++
++        if (len > best_len) {
++            s->match_start = cur_match;
++            best_len = len;
++            if (len >= nice_match) break;
++#ifdef UNALIGNED_OK
++            scan_end = *(ushf*)(scan+best_len-1);
++#else
++            scan_end1  = scan[best_len-1];
++            scan_end   = scan[best_len];
++#endif
++        }
++    } while ((cur_match = prev[cur_match & wmask]) > limit
++             && --chain_length != 0);
++
++    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
++    return s->lookahead;
++}
++
++#else /* FASTEST */
++/* ---------------------------------------------------------------------------
++ * Optimized version for level == 1 only
++ */
++local uInt longest_match(s, cur_match)
++    deflate_state *s;
++    IPos cur_match;                             /* current match */
++{
++    register Bytef *scan = s->window + s->strstart; /* current string */
++    register Bytef *match;                       /* matched string */
++    register int len;                           /* length of current match */
++    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
++
++    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
++     * It is easy to get rid of this optimization if necessary.
++     */
++    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
++
++    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
++
++    Assert(cur_match < s->strstart, "no future");
++
++    match = s->window + cur_match;
++
++    /* Return failure if the match length is less than 2:
++     */
++    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
++
++    /* The check at best_len-1 can be removed because it will be made
++     * again later. (This heuristic is not always a win.)
++     * It is not necessary to compare scan[2] and match[2] since they
++     * are always equal when the other bytes match, given that
++     * the hash keys are equal and that HASH_BITS >= 8.
++     */
++    scan += 2, match += 2;
++    Assert(*scan == *match, "match[2]?");
++
++    /* We check for insufficient lookahead only every 8th comparison;
++     * the 256th check will be made at strstart+258.
++     */
++    do {
++    } while (*++scan == *++match && *++scan == *++match &&
++           *++scan == *++match && *++scan == *++match &&
++           *++scan == *++match && *++scan == *++match &&
++           *++scan == *++match && *++scan == *++match &&
++           scan < strend);
++
++    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
++
++    len = MAX_MATCH - (int)(strend - scan);
++
++    if (len < MIN_MATCH) return MIN_MATCH - 1;
++
++    s->match_start = cur_match;
++    return len <= s->lookahead ? len : s->lookahead;
++}
++#endif /* FASTEST */
++#endif /* ASMV */
++
++#ifdef DEBUG
++/* ===========================================================================
++ * Check that the match at match_start is indeed a match.
++ */
++local void check_match(s, start, match, length)
++    deflate_state *s;
++    IPos start, match;
++    int length;
++{
++    /* check that the match is indeed a match */
++    if (zmemcmp(s->window + match,
++                s->window + start, length) != EQUAL) {
++        fprintf(stderr, " start %u, match %u, length %d\n",
++              start, match, length);
++        do {
++          fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
++      } while (--length != 0);
++        z_error("invalid match");
++    }
++    if (z_verbose > 1) {
++        fprintf(stderr,"\\[%d,%d]", start-match, length);
++        do { putc(s->window[start++], stderr); } while (--length != 0);
++    }
++}
++#else
++#  define check_match(s, start, match, length)
++#endif
++
++/* ===========================================================================
++ * Fill the window when the lookahead becomes insufficient.
++ * Updates strstart and lookahead.
++ *
++ * IN assertion: lookahead < MIN_LOOKAHEAD
++ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
++ *    At least one byte has been read, or avail_in == 0; reads are
++ *    performed for at least two bytes (required for the zip translate_eol
++ *    option -- not supported here).
++ */
++local void fill_window(s)
++    deflate_state *s;
++{
++    register unsigned n, m;
++    register Posf *p;
++    unsigned more;    /* Amount of free space at the end of the window. */
++    uInt wsize = s->w_size;
++
++    do {
++        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
++
++        /* Deal with !@#$% 64K limit: */
++        if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
++            more = wsize;
++
++        } else if (more == (unsigned)(-1)) {
++            /* Very unlikely, but possible on 16 bit machine if strstart == 0
++             * and lookahead == 1 (input done one byte at time)
++             */
++            more--;
++
++        /* If the window is almost full and there is insufficient lookahead,
++         * move the upper half to the lower one to make room in the upper half.
++         */
++        } else if (s->strstart >= wsize+MAX_DIST(s)) {
++
++            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
++            s->match_start -= wsize;
++            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
++            s->block_start -= (long) wsize;
++
++            /* Slide the hash table (could be avoided with 32 bit values
++               at the expense of memory usage). We slide even when level == 0
++               to keep the hash table consistent if we switch back to level > 0
++               later. (Using level 0 permanently is not an optimal usage of
++               zlib, so we don't care about this pathological case.)
++             */
++          n = s->hash_size;
++          p = &s->head[n];
++          do {
++              m = *--p;
++              *p = (Pos)(m >= wsize ? m-wsize : NIL);
++          } while (--n);
++
++          n = wsize;
++#ifndef FASTEST
++          p = &s->prev[n];
++          do {
++              m = *--p;
++              *p = (Pos)(m >= wsize ? m-wsize : NIL);
++              /* If n is not on any hash chain, prev[n] is garbage but
++               * its value will never be used.
++               */
++          } while (--n);
++#endif
++            more += wsize;
++        }
++        if (s->strm->avail_in == 0) return;
++
++        /* If there was no sliding:
++         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
++         *    more == window_size - lookahead - strstart
++         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
++         * => more >= window_size - 2*WSIZE + 2
++         * In the BIG_MEM or MMAP case (not yet supported),
++         *   window_size == input_size + MIN_LOOKAHEAD  &&
++         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
++         * Otherwise, window_size == 2*WSIZE so more >= 2.
++         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
++         */
++        Assert(more >= 2, "more < 2");
++
++        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
++        s->lookahead += n;
++
++        /* Initialize the hash value now that we have some input: */
++        if (s->lookahead >= MIN_MATCH) {
++            s->ins_h = s->window[s->strstart];
++            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
++#if MIN_MATCH != 3
++            Call UPDATE_HASH() MIN_MATCH-3 more times
++#endif
++        }
++        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
++         * but this is not important since only literal bytes will be emitted.
++         */
++
++    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
++}
++
++/* ===========================================================================
++ * Flush the current block, with given end-of-file flag.
++ * IN assertion: strstart is set to the end of the current match.
++ */
++#define FLUSH_BLOCK_ONLY(s, eof) { \
++   _tr_flush_block(s, (s->block_start >= 0L ? \
++                   (charf *)&s->window[(unsigned)s->block_start] : \
++                   (charf *)Z_NULL), \
++              (ulg)((long)s->strstart - s->block_start), \
++              (eof)); \
++   s->block_start = s->strstart; \
++   flush_pending(s->strm); \
++   Tracev((stderr,"[FLUSH]")); \
++}
++
++/* Same but force premature exit if necessary. */
++#define FLUSH_BLOCK(s, eof) { \
++   FLUSH_BLOCK_ONLY(s, eof); \
++   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
++}
++
++/* ===========================================================================
++ * Copy without compression as much as possible from the input stream, return
++ * the current block state.
++ * This function does not insert new strings in the dictionary since
++ * uncompressible data is probably not useful. This function is used
++ * only for the level=0 compression option.
++ * NOTE: this function should be optimized to avoid extra copying from
++ * window to pending_buf.
++ */
++local block_state deflate_stored(s, flush)
++    deflate_state *s;
++    int flush;
++{
++    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
++     * to pending_buf_size, and each stored block has a 5 byte header:
++     */
++    ulg max_block_size = 0xffff;
++    ulg max_start;
++
++    if (max_block_size > s->pending_buf_size - 5) {
++        max_block_size = s->pending_buf_size - 5;
++    }
++
++    /* Copy as much as possible from input to output: */
++    for (;;) {
++        /* Fill the window as much as possible: */
++        if (s->lookahead <= 1) {
++
++            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
++                 s->block_start >= (long)s->w_size, "slide too late");
++
++            fill_window(s);
++            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
++
++            if (s->lookahead == 0) break; /* flush the current block */
++        }
++      Assert(s->block_start >= 0L, "block gone");
++
++      s->strstart += s->lookahead;
++      s->lookahead = 0;
++
++      /* Emit a stored block if pending_buf will be full: */
++      max_start = s->block_start + max_block_size;
++        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
++          /* strstart == 0 is possible when wraparound on 16-bit machine */
++          s->lookahead = (uInt)(s->strstart - max_start);
++          s->strstart = (uInt)max_start;
++            FLUSH_BLOCK(s, 0);
++      }
++      /* Flush if we may have to slide, otherwise block_start may become
++         * negative and the data will be gone:
++         */
++        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
++            FLUSH_BLOCK(s, 0);
++      }
++    }
++    FLUSH_BLOCK(s, flush == Z_FINISH);
++    return flush == Z_FINISH ? finish_done : block_done;
++}
++
++/* ===========================================================================
++ * Compress as much as possible from the input stream, return the current
++ * block state.
++ * This function does not perform lazy evaluation of matches and inserts
++ * new strings in the dictionary only for unmatched strings or for short
++ * matches. It is used only for the fast compression options.
++ */
++local block_state deflate_fast(s, flush)
++    deflate_state *s;
++    int flush;
++{
++    IPos hash_head = NIL; /* head of the hash chain */
++    int bflush;           /* set if current block must be flushed */
++
++    for (;;) {
++        /* Make sure that we always have enough lookahead, except
++         * at the end of the input file. We need MAX_MATCH bytes
++         * for the next match, plus MIN_MATCH bytes to insert the
++         * string following the next match.
++         */
++        if (s->lookahead < MIN_LOOKAHEAD) {
++            fill_window(s);
++            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
++              return need_more;
++          }
++            if (s->lookahead == 0) break; /* flush the current block */
++        }
++
++        /* Insert the string window[strstart .. strstart+2] in the
++         * dictionary, and set hash_head to the head of the hash chain:
++         */
++        if (s->lookahead >= MIN_MATCH) {
++            INSERT_STRING(s, s->strstart, hash_head);
++        }
++
++        /* Find the longest match, discarding those <= prev_length.
++         * At this point we have always match_length < MIN_MATCH
++         */
++        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
++            /* To simplify the code, we prevent matches with the string
++             * of window index 0 (in particular we have to avoid a match
++             * of the string with itself at the start of the input file).
++             */
++            if (s->strategy != Z_HUFFMAN_ONLY) {
++                s->match_length = longest_match (s, hash_head);
++            }
++            /* longest_match() sets match_start */
++        }
++        if (s->match_length >= MIN_MATCH) {
++            check_match(s, s->strstart, s->match_start, s->match_length);
++
++            _tr_tally_dist(s, s->strstart - s->match_start,
++                           s->match_length - MIN_MATCH, bflush);
++
++            s->lookahead -= s->match_length;
++
++            /* Insert new strings in the hash table only if the match length
++             * is not too large. This saves time but degrades compression.
++             */
++#ifndef FASTEST
++            if (s->match_length <= s->max_insert_length &&
++                s->lookahead >= MIN_MATCH) {
++                s->match_length--; /* string at strstart already in hash table */
++                do {
++                    s->strstart++;
++                    INSERT_STRING(s, s->strstart, hash_head);
++                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
++                     * always MIN_MATCH bytes ahead.
++                     */
++                } while (--s->match_length != 0);
++                s->strstart++; 
++            } else
++#endif
++          {
++                s->strstart += s->match_length;
++                s->match_length = 0;
++                s->ins_h = s->window[s->strstart];
++                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
++#if MIN_MATCH != 3
++                Call UPDATE_HASH() MIN_MATCH-3 more times
++#endif
++                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
++                 * matter since it will be recomputed at next deflate call.
++                 */
++            }
++        } else {
++            /* No match, output a literal byte */
++            Tracevv((stderr,"%c", s->window[s->strstart]));
++            _tr_tally_lit (s, s->window[s->strstart], bflush);
++            s->lookahead--;
++            s->strstart++; 
++        }
++        if (bflush) FLUSH_BLOCK(s, 0);
++    }
++    FLUSH_BLOCK(s, flush == Z_FINISH);
++    return flush == Z_FINISH ? finish_done : block_done;
++}
++
++/* ===========================================================================
++ * Same as above, but achieves better compression. We use a lazy
++ * evaluation for matches: a match is finally adopted only if there is
++ * no better match at the next window position.
++ */
++local block_state deflate_slow(s, flush)
++    deflate_state *s;
++    int flush;
++{
++    IPos hash_head = NIL;    /* head of hash chain */
++    int bflush;              /* set if current block must be flushed */
++
++    /* Process the input block. */
++    for (;;) {
++        /* Make sure that we always have enough lookahead, except
++         * at the end of the input file. We need MAX_MATCH bytes
++         * for the next match, plus MIN_MATCH bytes to insert the
++         * string following the next match.
++         */
++        if (s->lookahead < MIN_LOOKAHEAD) {
++            fill_window(s);
++            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
++              return need_more;
++          }
++            if (s->lookahead == 0) break; /* flush the current block */
++        }
++
++        /* Insert the string window[strstart .. strstart+2] in the
++         * dictionary, and set hash_head to the head of the hash chain:
++         */
++        if (s->lookahead >= MIN_MATCH) {
++            INSERT_STRING(s, s->strstart, hash_head);
++        }
++
++        /* Find the longest match, discarding those <= prev_length.
++         */
++        s->prev_length = s->match_length, s->prev_match = s->match_start;
++        s->match_length = MIN_MATCH-1;
++
++        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
++            s->strstart - hash_head <= MAX_DIST(s)) {
++            /* To simplify the code, we prevent matches with the string
++             * of window index 0 (in particular we have to avoid a match
++             * of the string with itself at the start of the input file).
++             */
++            if (s->strategy != Z_HUFFMAN_ONLY) {
++                s->match_length = longest_match (s, hash_head);
++            }
++            /* longest_match() sets match_start */
++
++            if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
++                 (s->match_length == MIN_MATCH &&
++                  s->strstart - s->match_start > TOO_FAR))) {
++
++                /* If prev_match is also MIN_MATCH, match_start is garbage
++                 * but we will ignore the current match anyway.
++                 */
++                s->match_length = MIN_MATCH-1;
++            }
++        }
++        /* If there was a match at the previous step and the current
++         * match is not better, output the previous match:
++         */
++        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
++            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
++            /* Do not insert strings in hash table beyond this. */
++
++            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
++
++            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
++                         s->prev_length - MIN_MATCH, bflush);
++
++            /* Insert in hash table all strings up to the end of the match.
++             * strstart-1 and strstart are already inserted. If there is not
++             * enough lookahead, the last two strings are not inserted in
++             * the hash table.
++             */
++            s->lookahead -= s->prev_length-1;
++            s->prev_length -= 2;
++            do {
++                if (++s->strstart <= max_insert) {
++                    INSERT_STRING(s, s->strstart, hash_head);
++                }
++            } while (--s->prev_length != 0);
++            s->match_available = 0;
++            s->match_length = MIN_MATCH-1;
++            s->strstart++;
++
++            if (bflush) FLUSH_BLOCK(s, 0);
++
++        } else if (s->match_available) {
++            /* If there was no match at the previous position, output a
++             * single literal. If there was a match but the current match
++             * is longer, truncate the previous match to a single literal.
++             */
++            Tracevv((stderr,"%c", s->window[s->strstart-1]));
++          _tr_tally_lit(s, s->window[s->strstart-1], bflush);
++          if (bflush) {
++                FLUSH_BLOCK_ONLY(s, 0);
++            }
++            s->strstart++;
++            s->lookahead--;
++            if (s->strm->avail_out == 0) return need_more;
++        } else {
++            /* There is no previous match to compare with, wait for
++             * the next step to decide.
++             */
++            s->match_available = 1;
++            s->strstart++;
++            s->lookahead--;
++        }
++    }
++    Assert (flush != Z_NO_FLUSH, "no flush?");
++    if (s->match_available) {
++        Tracevv((stderr,"%c", s->window[s->strstart-1]));
++        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
++        s->match_available = 0;
++    }
++    FLUSH_BLOCK(s, flush == Z_FINISH);
++    return flush == Z_FINISH ? finish_done : block_done;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/deflate.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,318 @@
++/* deflate.h -- internal compression state
++ * Copyright (C) 1995-2002 Jean-loup Gailly
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++/* @(#) $Id: deflate.h,v 1.5 2004/07/10 07:48:38 mcr Exp $ */
++
++#ifndef _DEFLATE_H
++#define _DEFLATE_H
++
++#include "zlib/zutil.h"
++
++/* ===========================================================================
++ * Internal compression state.
++ */
++
++#define LENGTH_CODES 29
++/* number of length codes, not counting the special END_BLOCK code */
++
++#define LITERALS  256
++/* number of literal bytes 0..255 */
++
++#define L_CODES (LITERALS+1+LENGTH_CODES)
++/* number of Literal or Length codes, including the END_BLOCK code */
++
++#define D_CODES   30
++/* number of distance codes */
++
++#define BL_CODES  19
++/* number of codes used to transfer the bit lengths */
++
++#define HEAP_SIZE (2*L_CODES+1)
++/* maximum heap size */
++
++#define MAX_BITS 15
++/* All codes must not exceed MAX_BITS bits */
++
++#define INIT_STATE    42
++#define BUSY_STATE   113
++#define FINISH_STATE 666
++/* Stream status */
++
++
++/* Data structure describing a single value and its code string. */
++typedef struct ct_data_s {
++    union {
++        ush  freq;       /* frequency count */
++        ush  code;       /* bit string */
++    } fc;
++    union {
++        ush  dad;        /* father node in Huffman tree */
++        ush  len;        /* length of bit string */
++    } dl;
++} FAR ct_data;
++
++#define Freq fc.freq
++#define Code fc.code
++#define Dad  dl.dad
++#define Len  dl.len
++
++typedef struct static_tree_desc_s  static_tree_desc;
++
++typedef struct tree_desc_s {
++    ct_data *dyn_tree;           /* the dynamic tree */
++    int     max_code;            /* largest code with non zero frequency */
++    static_tree_desc *stat_desc; /* the corresponding static tree */
++} FAR tree_desc;
++
++typedef ush Pos;
++typedef Pos FAR Posf;
++typedef unsigned IPos;
++
++/* A Pos is an index in the character window. We use short instead of int to
++ * save space in the various tables. IPos is used only for parameter passing.
++ */
++
++typedef struct internal_state {
++    z_streamp strm;      /* pointer back to this zlib stream */
++    int   status;        /* as the name implies */
++    Bytef *pending_buf;  /* output still pending */
++    ulg   pending_buf_size; /* size of pending_buf */
++    Bytef *pending_out;  /* next pending byte to output to the stream */
++    int   pending;       /* nb of bytes in the pending buffer */
++    int   noheader;      /* suppress zlib header and adler32 */
++    Byte  data_type;     /* UNKNOWN, BINARY or ASCII */
++    Byte  method;        /* STORED (for zip only) or DEFLATED */
++    int   last_flush;    /* value of flush param for previous deflate call */
++
++                /* used by deflate.c: */
++
++    uInt  w_size;        /* LZ77 window size (32K by default) */
++    uInt  w_bits;        /* log2(w_size)  (8..16) */
++    uInt  w_mask;        /* w_size - 1 */
++
++    Bytef *window;
++    /* Sliding window. Input bytes are read into the second half of the window,
++     * and move to the first half later to keep a dictionary of at least wSize
++     * bytes. With this organization, matches are limited to a distance of
++     * wSize-MAX_MATCH bytes, but this ensures that IO is always
++     * performed with a length multiple of the block size. Also, it limits
++     * the window size to 64K, which is quite useful on MSDOS.
++     * To do: use the user input buffer as sliding window.
++     */
++
++    ulg window_size;
++    /* Actual size of window: 2*wSize, except when the user input buffer
++     * is directly used as sliding window.
++     */
++
++    Posf *prev;
++    /* Link to older string with same hash index. To limit the size of this
++     * array to 64K, this link is maintained only for the last 32K strings.
++     * An index in this array is thus a window index modulo 32K.
++     */
++
++    Posf *head; /* Heads of the hash chains or NIL. */
++
++    uInt  ins_h;          /* hash index of string to be inserted */
++    uInt  hash_size;      /* number of elements in hash table */
++    uInt  hash_bits;      /* log2(hash_size) */
++    uInt  hash_mask;      /* hash_size-1 */
++
++    uInt  hash_shift;
++    /* Number of bits by which ins_h must be shifted at each input
++     * step. It must be such that after MIN_MATCH steps, the oldest
++     * byte no longer takes part in the hash key, that is:
++     *   hash_shift * MIN_MATCH >= hash_bits
++     */
++
++    long block_start;
++    /* Window position at the beginning of the current output block. Gets
++     * negative when the window is moved backwards.
++     */
++
++    uInt match_length;           /* length of best match */
++    IPos prev_match;             /* previous match */
++    int match_available;         /* set if previous match exists */
++    uInt strstart;               /* start of string to insert */
++    uInt match_start;            /* start of matching string */
++    uInt lookahead;              /* number of valid bytes ahead in window */
++
++    uInt prev_length;
++    /* Length of the best match at previous step. Matches not greater than this
++     * are discarded. This is used in the lazy match evaluation.
++     */
++
++    uInt max_chain_length;
++    /* To speed up deflation, hash chains are never searched beyond this
++     * length.  A higher limit improves compression ratio but degrades the
++     * speed.
++     */
++
++    uInt max_lazy_match;
++    /* Attempt to find a better match only when the current match is strictly
++     * smaller than this value. This mechanism is used only for compression
++     * levels >= 4.
++     */
++#   define max_insert_length  max_lazy_match
++    /* Insert new strings in the hash table only if the match length is not
++     * greater than this length. This saves time but degrades compression.
++     * max_insert_length is used only for compression levels <= 3.
++     */
++
++    int level;    /* compression level (1..9) */
++    int strategy; /* favor or force Huffman coding*/
++
++    uInt good_match;
++    /* Use a faster search when the previous match is longer than this */
++
++    int nice_match; /* Stop searching when current match exceeds this */
++
++                /* used by trees.c: */
++    /* Didn't use ct_data typedef below to supress compiler warning */
++    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
++    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
++    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
++
++    struct tree_desc_s l_desc;               /* desc. for literal tree */
++    struct tree_desc_s d_desc;               /* desc. for distance tree */
++    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
++
++    ush bl_count[MAX_BITS+1];
++    /* number of codes at each bit length for an optimal tree */
++
++    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
++    int heap_len;               /* number of elements in the heap */
++    int heap_max;               /* element of largest frequency */
++    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
++     * The same heap array is used to build all trees.
++     */
++
++    uch depth[2*L_CODES+1];
++    /* Depth of each subtree used as tie breaker for trees of equal frequency
++     */
++
++    uchf *l_buf;          /* buffer for literals or lengths */
++
++    uInt  lit_bufsize;
++    /* Size of match buffer for literals/lengths.  There are 4 reasons for
++     * limiting lit_bufsize to 64K:
++     *   - frequencies can be kept in 16 bit counters
++     *   - if compression is not successful for the first block, all input
++     *     data is still in the window so we can still emit a stored block even
++     *     when input comes from standard input.  (This can also be done for
++     *     all blocks if lit_bufsize is not greater than 32K.)
++     *   - if compression is not successful for a file smaller than 64K, we can
++     *     even emit a stored file instead of a stored block (saving 5 bytes).
++     *     This is applicable only for zip (not gzip or zlib).
++     *   - creating new Huffman trees less frequently may not provide fast
++     *     adaptation to changes in the input data statistics. (Take for
++     *     example a binary file with poorly compressible code followed by
++     *     a highly compressible string table.) Smaller buffer sizes give
++     *     fast adaptation but have of course the overhead of transmitting
++     *     trees more frequently.
++     *   - I can't count above 4
++     */
++
++    uInt last_lit;      /* running index in l_buf */
++
++    ushf *d_buf;
++    /* Buffer for distances. To simplify the code, d_buf and l_buf have
++     * the same number of elements. To use different lengths, an extra flag
++     * array would be necessary.
++     */
++
++    ulg opt_len;        /* bit length of current block with optimal trees */
++    ulg static_len;     /* bit length of current block with static trees */
++    uInt matches;       /* number of string matches in current block */
++    int last_eob_len;   /* bit length of EOB code for last block */
++
++#ifdef DEBUG
++    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
++    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
++#endif
++
++    ush bi_buf;
++    /* Output buffer. bits are inserted starting at the bottom (least
++     * significant bits).
++     */
++    int bi_valid;
++    /* Number of valid bits in bi_buf.  All bits above the last valid bit
++     * are always zero.
++     */
++
++} FAR deflate_state;
++
++/* Output a byte on the stream.
++ * IN assertion: there is enough room in pending_buf.
++ */
++#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
++
++
++#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
++/* Minimum amount of lookahead, except at the end of the input file.
++ * See deflate.c for comments about the MIN_MATCH+1.
++ */
++
++#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
++/* In order to simplify the code, particularly on 16 bit machines, match
++ * distances are limited to MAX_DIST instead of WSIZE.
++ */
++
++        /* in trees.c */
++void _tr_init         OF((deflate_state *s));
++int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
++void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
++                        int eof));
++void _tr_align        OF((deflate_state *s));
++void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
++                          int eof));
++
++#define d_code(dist) \
++   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
++/* Mapping from a distance to a distance code. dist is the distance - 1 and
++ * must not have side effects. _dist_code[256] and _dist_code[257] are never
++ * used.
++ */
++
++#ifndef DEBUG
++/* Inline versions of _tr_tally for speed: */
++
++#if defined(GEN_TREES_H) || !defined(STDC)
++  extern uch _length_code[];
++  extern uch _dist_code[];
++#else
++  extern const uch _length_code[];
++  extern const uch _dist_code[];
++#endif
++
++# define _tr_tally_lit(s, c, flush) \
++  { uch cc = (c); \
++    s->d_buf[s->last_lit] = 0; \
++    s->l_buf[s->last_lit++] = cc; \
++    s->dyn_ltree[cc].Freq++; \
++    flush = (s->last_lit == s->lit_bufsize-1); \
++   }
++# define _tr_tally_dist(s, distance, length, flush) \
++  { uch len = (length); \
++    ush dist = (distance); \
++    s->d_buf[s->last_lit] = dist; \
++    s->l_buf[s->last_lit++] = len; \
++    dist--; \
++    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
++    s->dyn_dtree[d_code(dist)].Freq++; \
++    flush = (s->last_lit == s->lit_bufsize-1); \
++  }
++#else
++# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
++# define _tr_tally_dist(s, distance, length, flush) \
++              flush = _tr_tally(s, distance, length) 
++#endif
++
++#endif /* _DEFLATE_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/COPYRIGHT     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,50 @@
++Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++All rights reserved.
++
++This package is an DES implementation written by Eric Young (eay@cryptsoft.com).
++The implementation was written so as to conform with MIT's libdes.
++
++This library is free for commercial and non-commercial use as long as
++the following conditions are aheared to.  The following conditions
++apply to all code found in this distribution.
++
++Copyright remains Eric Young's, and as such any Copyright notices in
++the code are not to be removed.
++If this package is used in a product, Eric Young should be given attribution
++as the author of that the SSL library.  This can be in the form of a textual
++message at program startup or in documentation (online or textual) provided
++with the package.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions
++are met:
++1. Redistributions of source code must retain the copyright
++   notice, this list of conditions and the following disclaimer.
++2. Redistributions in binary form must reproduce the above copyright
++   notice, this list of conditions and the following disclaimer in the
++   documentation and/or other materials provided with the distribution.
++3. All advertising materials mentioning features or use of this software
++   must display the following acknowledgement:
++   This product includes software developed by Eric Young (eay@cryptsoft.com)
++
++THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++SUCH DAMAGE.
++
++The license and distribution terms for any publically available version or
++derivative of this code cannot be changed.  i.e. this code cannot simply be
++copied and put under another distrubution license
++[including the GNU Public License.]
++
++The reason behind this being stated in this direct manner is past
++experience in code simply being copied and the attribution removed
++from it and then being distributed as part of other packages. This
++implementation was a non-trivial and unpaid effort.
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/INSTALL     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,69 @@
++Check the CC and CFLAGS lines in the makefile
++
++If your C library does not support the times(3) function, change the
++#define TIMES to
++#undef TIMES in speed.c
++If it does, check the HZ value for the times(3) function.
++If your system does not define CLK_TCK it will be assumed to
++be 100.0.
++
++If possible use gcc v 2.7.?
++Turn on the maximum optimising (normally '-O3 -fomit-frame-pointer' for gcc)
++In recent times, some system compilers give better performace.
++
++type 'make'
++
++run './destest' to check things are ok.
++run './rpw' to check the tty code for reading passwords works.
++run './speed' to see how fast those optimisations make the library run :-)
++run './des_opts' to determin the best compile time options.
++
++The output from des_opts should be put in the makefile options and des_enc.c
++should be rebuilt.  For 64 bit computers, do not use the DES_PTR option.
++For the DEC Alpha, edit des.h and change DES_LONG to 'unsigned int'
++and then you can use the 'DES_PTR' option.
++
++The file options.txt has the options listed for best speed on quite a
++few systems.  Look and the options (UNROLL, PTR, RISC2 etc) and then
++turn on the relevent option in the Makefile
++
++There are some special Makefile targets that make life easier.
++make cc               - standard cc build
++make gcc      - standard gcc build
++make x86-elf  - x86 assembler (elf), linux-elf.
++make x86-out  - x86 assembler (a.out), FreeBSD
++make x86-solaris- x86 assembler
++make x86-bsdi - x86 assembler (a.out with primative assembler).
++
++If at all possible use the assembler (for Windows NT/95, use
++asm/win32.obj to link with).  The x86 assembler is very very fast.
++
++A make install will by default install
++libdes.a      in /usr/local/lib/libdes.a
++des           in /usr/local/bin/des
++des_crypt.man in /usr/local/man/man3/des_crypt.3
++des.man       in /usr/local/man/man1/des.1
++des.h         in /usr/include/des.h
++
++des(1) should be compatible with sunOS's but I have been unable to
++test it.
++
++These routines should compile on MSDOS, most 32bit and 64bit version
++of Unix (BSD and SYSV) and VMS, without modification.
++The only problems should be #include files that are in the wrong places.
++
++These routines can be compiled under MSDOS.
++I have successfully encrypted files using des(1) under MSDOS and then
++decrypted the files on a SparcStation.
++I have been able to compile and test the routines with
++Microsoft C v 5.1 and Turbo C v 2.0.
++The code in this library is in no way optimised for the 16bit
++operation of MSDOS.
++
++When building for glibc, ignore all of the above and just unpack into
++glibc-1.??/des and then gmake as per normal.
++
++As a final note on performace.  Certain CPUs like sparcs and Alpha often give
++a %10 speed difference depending on the link order.  It is rather anoying
++when one program reports 'x' DES encrypts a second and another reports
++'x*0.9' the speed.
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/Makefile     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,63 @@
++# Makefile for KLIPS kernel code as a module    for 2.6 kernels
++#
++# Makefile for KLIPS kernel code as a module
++# Copyright (C) 1998, 1999, 2000,2001  Richard Guy Briggs.
++# Copyright (C) 2002-2004     Michael Richardson <mcr@freeswan.org>
++# 
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++# 
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# RCSID $Id: Makefile.fs2_6,v 1.2.2.1 2005/08/12 16:10:57 ken Exp $
++#
++# Note! Dependencies are done automagically by 'make dep', which also
++# removes any old dependencies. DON'T put your own dependencies here
++# unless it's something special (ie not a .c file).
++#
++
++obj-$(CONFIG_KLIPS_ENC_3DES) += ipsec_alg_3des.o
++obj-$(CONFIG_KLIPS_ENC_3DES) += cbc_enc.o
++obj-$(CONFIG_KLIPS_ENC_3DES) += ecb_enc.o
++obj-$(CONFIG_KLIPS_ENC_3DES) += set_key.o
++
++ifeq ($(strip ${SUBARCH}),)
++SUBARCH:=${ARCH}
++endif
++
++# the assembly version expects frame pointers, which are
++# optional in many kernel builds. If you want speed, you should
++# probably use cryptoapi code instead.
++USEASSEMBLY=${SUBARCH}${CONFIG_FRAME_POINTER}
++ifeq (${USEASSEMBLY},i386y)
++obj-$(CONFIG_KLIPS_ENC_3DES) += dx86unix.o
++else
++obj-$(CONFIG_KLIPS_ENC_3DES) += des_enc.o
++endif
++
++#
++# $Log: Makefile.fs2_6,v $
++# Revision 1.2.2.1  2005/08/12 16:10:57  ken
++# do not use assembly code with there are no frame pointers
++#
++# Revision 1.3  2005/08/12 14:13:59  mcr
++#     do not use assembly code with there are no frame pointers,
++#     as it does not have the right linkages.
++#
++# Revision 1.2  2005/04/29 05:13:07  mcr
++#     3DES algorithm code.
++#
++# Revision 1.1  2004/08/17 03:27:30  mcr
++#     klips 2.6 edits.
++#
++#
++# Local Variables:
++# compile-command: "(cd ../../.. && source umlsetup.sh && make -C ${POOLSPACE} module/ipsec.o)"
++# End Variables:
++#
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/README     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,54 @@
++
++              libdes, Version 4.01 10-Jan-97
++
++              Copyright (c) 1997, Eric Young
++                        All rights reserved.
++
++    This program is free software; you can redistribute it and/or modify
++    it under the terms specified in COPYRIGHT.
++    
++--
++The primary ftp site for this library is
++ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz
++libdes is now also shipped with SSLeay.  Primary ftp site of
++ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.x.x.tar.gz
++
++The best way to build this library is to build it as part of SSLeay.
++
++This kit builds a DES encryption library and a DES encryption program.
++It supports ecb, cbc, ofb, cfb, triple ecb, triple cbc, triple ofb,
++triple cfb, desx, and MIT's pcbc encryption modes and also has a fast
++implementation of crypt(3).
++It contains support routines to read keys from a terminal,
++generate a random key, generate a key from an arbitrary length string,
++read/write encrypted data from/to a file descriptor.
++
++The implementation was written so as to conform with the manual entry
++for the des_crypt(3) library routines from MIT's project Athena.
++
++destest should be run after compilation to test the des routines.
++rpw should be run after compilation to test the read password routines.
++The des program is a replacement for the sun des command.  I believe it
++conforms to the sun version.
++
++The Imakefile is setup for use in the kerberos distribution.
++
++These routines are best compiled with gcc or any other good
++optimising compiler.
++Just turn you optimiser up to the highest settings and run destest
++after the build to make sure everything works.
++
++I believe these routines are close to the fastest and most portable DES
++routines that use small lookup tables (4.5k) that are publicly available.
++The fcrypt routine is faster than ufc's fcrypt (when compiling with
++gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines
++(on a sun3/260 168 vs 336).  It is a function of CPU on chip cache size.
++[ 10-Jan-97 and a function of an incorrect speed testing program in
++  ufc which gave much better test figures that reality ].
++
++It is worth noting that on sparc and Alpha CPUs, performance of the DES
++library can vary by upto %10 due to the positioning of files after application
++linkage.
++
++Eric Young (eay@cryptsoft.com)
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/README.freeswan     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,33 @@
++The only changes the FreeS/WAN project has made to libdes-lite 4.04b are:
++
++We #ifdef-ed the declaration of DES_LONG in des.h, so it's more efficient
++on the Alpha, instead of just noting the issue in a comment. 
++
++We #ifdef-ed out the des_options() function in ecb_enc.c, because we don't
++use it, and its call to sprintf() can cause subtle difficulties when KLIPS
++is built as a module (depending on details of Linux configuration options).
++
++We changed some instances of CC=$(CC) in the Makefile to CC='$(CC)' to make
++it cope better with Linux kernel Makefile stupidities, and took out an
++explicit CC=gcc (unwise on systems with strange compilers).
++
++We deleted some references to <stdio.h> and <stdlib.h>, and a declaration
++of one function found only in the full libdes (not in libdes-lite), to
++avoid dragging in bits of stdio/stdlib unnecessarily.  (Our thanks to Hans
++Schultz for spotting this and pointing out the fixes.)
++
++We deleted a couple of .obj files in the asm subdirectory, which appear to
++have been included in the original library by accident. 
++
++We have added an include of our Makefile.inc file, to permit overriding
++things like choice of compiler (although the libdes Makefile would
++probably need some work to make this effective).
++
++
++
++Note that Eric Young is no longer at the email address listed in these
++files, and is (alas) no longer working on free crypto software. 
++
++
++
++This file is RCSID $Id: README.freeswan,v 1.12 2004/07/10 08:06:51 mcr Exp $
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/VERSION     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,406 @@
++Version 4.04
++      Fixed a few tests in destest.  Also added x86 assember for
++      des_ncbc_encrypt() which is the standard cbc mode function.
++      This makes a very very large performace difference.
++      Ariel Glenn ariel@columbia.edu reports that the terminal
++      'turn echo off' can return (errno == EINVAL) under solaris
++      when redirection is used.  So I now catch that as well as ENOTTY.
++
++
++Version 4.03
++      Left a static out of enc_write.c, which caused to buffer to be
++      continiously malloc()ed.  Does anyone use these functions?  I keep
++      on feeling like removing them since I only had these in there
++      for a version of kerberised login.  Anyway, this was pointed out
++      by Theo de Raadt <deraadt@cvs.openbsd.org>
++      The 'n' bit ofb code was wrong, it was not shifting the shift
++      register. It worked correctly for n == 64.  Thanks to
++      Gigi Ankeny <Gigi.Ankeny@Eng.Sun.COM> for pointing this one out.
++
++Version 4.02
++      I was doing 'if (memcmp(weak_keys[i],key,sizeof(key)) == 0)'
++      when checking for weak keys which is wrong :-(, pointed out by
++      Markus F.X.J. Oberhumer <markus.oberhumer@jk.uni-linz.ac.at>.
++
++Version 4.01
++      Even faster inner loop in the DES assembler for x86 and a modification
++      for IP/FP which is faster on x86.  Both of these changes are
++      from Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk>.  His
++      changes make the assembler run %40 faster on a pentium.  This is just
++      a case of getting the instruction sequence 'just right'.
++      All credit to 'Svend' :-)
++      Quite a few special x86 'make' targets.
++      A libdes-l (lite) distribution.
++
++Version 4.00
++      After a bit of a pause, I'll up the major version number since this
++      is mostly a performace release.  I've added x86 assembler and
++      added more options for performance.  A %28 speedup for gcc 
++      on a pentium and the assembler is a %50 speedup.
++      MIPS CPU's, sparc and Alpha are the main CPU's with speedups.
++      Run des_opts to work out which options should be used.
++      DES_RISC1/DES_RISC2 use alternative inner loops which use
++      more registers but should give speedups on any CPU that does
++      dual issue (pentium).  DES_UNROLL unrolls the inner loop,
++      which costs in code size.
++
++Version 3.26
++      I've finally removed one of the shifts in D_ENCRYPT.  This
++      meant I've changed the des_SPtrans table (spr.h), the set_key()
++      function and some things in des_enc.c.  This has definitly
++      made things faster :-).  I've known about this one for some
++      time but I've been too lazy to follow it up :-).
++      Noticed that in the D_ENCRYPT() macro, we can just do L^=(..)^(..)^..
++      instead of L^=((..)|(..)|(..)..  This should save a register at
++      least.
++      Assember for x86.  The file to replace is des_enc.c, which is replaced
++      by one of the assembler files found in asm.  Look at des/asm/readme
++      for more info.
++
++      /* Modification to fcrypt so it can be compiled to support
++      HPUX 10.x's long password format, define -DLONGCRYPT to use this.
++      Thanks to Jens Kupferschmidt <bt1cu@hpboot.rz.uni-leipzig.de>. */
++
++      SIGWINCH case put in des_read_passwd() so the function does not
++      'exit' if this function is recieved.
++
++Version 3.25 17/07/96
++      Modified read_pwd.c so that stdin can be read if not a tty.
++      Thanks to Jeff Barber <jeffb@issl.atl.hp.com> for the patches.
++      des_init_random_number_generator() shortened due to VMS linker
++      limits.
++      Added RSA's DESX cbc mode.  It is a form of cbc encryption, with 2
++      8 byte quantites xored before and after encryption.
++      des_xcbc_encryption() - the name is funny to preserve the des_
++      prefix on all functions.
++
++Version 3.24 20/04/96
++      The DES_PTR macro option checked and used by SSLeay configuration
++
++Version 3.23 11/04/96
++      Added DES_LONG.  If defined to 'unsigned int' on the DEC Alpha,
++      it gives a %20 speedup :-)
++      Fixed the problem with des.pl under perl5.  The patches were
++      sent by Ed Kubaitis (ejk@uiuc.edu).
++      if fcrypt.c, changed values to handle illegal salt values the way
++      normal crypt() implementations do.  Some programs apparently use
++      them :-(. The patch was sent by Bjorn Gronvall <bg@sics.se>
++
++Version 3.22 29/11/95
++      Bug in des(1), an error with the uuencoding stuff when the
++      'data' is small, thanks to Geoff Keating <keagchon@mehta.anu.edu.au>
++      for the patch.
++
++Version 3.21 22/11/95
++      After some emailing back and forth with 
++      Colin Plumb <colin@nyx10.cs.du.edu>, I've tweaked a few things
++      and in a future version I will probably put in some of the
++      optimisation he suggested for use with the DES_USE_PTR option.
++      Extra routines from Mark Murray <mark@grondar.za> for use in
++      freeBSD.  They mostly involve random number generation for use
++      with kerberos.  They involve evil machine specific system calls
++      etc so I would normally suggest pushing this stuff into the
++      application and/or using RAND_seed()/RAND_bytes() if you are
++      using this DES library as part of SSLeay.
++      Redone the read_pw() function so that it is cleaner and
++      supports termios, thanks to Sameer Parekh <sameer@c2.org>
++      for the initial patches for this.
++      Renamed 3ecb_encrypt() to ecb3_encrypt().  This has been
++       done just to make things more consistent.
++      I have also now added triple DES versions of cfb and ofb.
++
++Version 3.20
++      Damn, Damn, Damn, as pointed out by Mike_Spreitzer.PARC@xerox.com,
++      my des_random_seed() function was only copying 4 bytes of the
++      passed seed into the init structure.  It is now fixed to copy 8.
++      My own suggestion is to used something like MD5 :-)
++
++Version 3.19 
++      While looking at my code one day, I though, why do I keep on
++      calling des_encrypt(in,out,ks,enc) when every function that
++      calls it has in and out the same.  So I dropped the 'out'
++      parameter, people should not be using this function.
++
++Version 3.18 30/08/95
++      Fixed a few bit with the distribution and the filenames.
++      3.17 had been munged via a move to DOS and back again.
++      NO CODE CHANGES
++
++Version 3.17 14/07/95
++      Fixed ede3 cbc which I had broken in 3.16.  I have also
++      removed some unneeded variables in 7-8 of the routines.
++
++Version 3.16 26/06/95
++      Added des_encrypt2() which does not use IP/FP, used by triple
++      des routines.  Tweaked things a bit elsewhere. %13 speedup on
++      sparc and %6 on a R4400 for ede3 cbc mode.
++
++Version 3.15 06/06/95
++      Added des_ncbc_encrypt(), it is des_cbc mode except that it is
++      'normal' and copies the new iv value back over the top of the
++      passed parameter.
++      CHANGED des_ede3_cbc_encrypt() so that it too now overwrites
++      the iv.  THIS WILL BREAK EXISTING CODE, but since this function
++      only new, I feel I can change it, not so with des_cbc_encrypt :-(.
++      I need to update the documentation.
++
++Version 3.14 31/05/95
++      New release upon the world, as part of my SSL implementation.
++      New copyright and usage stuff.  Basically free for all to use
++      as long as you say it came from me :-)
++
++Version 3.13 31/05/95
++      A fix in speed.c, if HZ is not defined, I set it to 100.0
++      which is reasonable for most unixes except SunOS 4.x.
++      I now have a #ifdef sun but timing for SunOS 4.x looked very
++      good :-(.  At my last job where I used SunOS 4.x, it was
++      defined to be 60.0 (look at the old INSTALL documentation), at
++      the last release had it changed to 100.0 since I now work with
++      Solaris2 and SVR4 boxes.
++      Thanks to  Rory Chisholm <rchishol@math.ethz.ch> for pointing this
++      one out.
++
++Version 3.12 08/05/95
++      As pointed out by The Crypt Keeper <tck@bend.UCSD.EDU>,
++      my D_ENCRYPT macro in crypt() had an un-necessary variable.
++      It has been removed.
++
++Version 3.11 03/05/95
++      Added des_ede3_cbc_encrypt() which is cbc mode des with 3 keys
++      and one iv.  It is a standard and I needed it for my SSL code.
++      It makes more sense to use this for triple DES than
++      3cbc_encrypt().  I have also added (or should I say tested :-)
++      cfb64_encrypt() which is cfb64 but it will encrypt a partial
++      number of bytes - 3 bytes in 3 bytes out.  Again this is for
++      my SSL library, as a form of encryption to use with SSL
++      telnet.
++
++Version 3.10 22/03/95
++      Fixed a bug in 3cbc_encrypt() :-(.  When making repeated calls
++      to cbc3_encrypt, the 2 iv values that were being returned to
++      be used in the next call were reversed :-(.
++      Many thanks to Bill Wade <wade@Stoner.COM> for pointing out
++      this error.
++
++Version 3.09 01/02/95
++      Fixed des_random_key to far more random, it was rather feeble
++      with regards to picking the initial seed.  The problem was
++      pointed out by Olaf Kirch <okir@monad.swb.de>.
++
++Version 3.08 14/12/94
++      Added Makefile.PL so libdes can be built into perl5.
++      Changed des_locl.h so RAND is always defined.
++
++Version 3.07 05/12/94
++      Added GNUmake and stuff so the library can be build with
++      glibc.
++
++Version 3.06 30/08/94
++      Added rpc_enc.c which contains _des_crypt.  This is for use in
++      secure_rpc v 4.0
++      Finally fixed the cfb_enc problems.
++      Fixed a few parameter parsing bugs in des (-3 and -b), thanks
++      to Rob McMillan <R.McMillan@its.gu.edu.au>
++
++Version 3.05 21/04/94
++      for unsigned long l; gcc does not produce ((l>>34) == 0)
++      This causes bugs in cfb_enc.
++      Thanks to Hadmut Danisch <danisch@ira.uka.de>
++
++Version 3.04 20/04/94
++      Added a version number to des.c and libdes.a
++
++Version 3.03 12/01/94
++      Fixed a bug in non zero iv in 3cbc_enc.
++
++Version 3.02 29/10/93
++      I now work in a place where there are 6+ architectures and 14+
++      OS versions :-).
++      Fixed TERMIO definition so the most sys V boxes will work :-)
++
++Release upon comp.sources.misc
++Version 3.01 08/10/93
++      Added des_3cbc_encrypt()
++
++Version 3.00 07/10/93
++      Fixed up documentation.
++      quad_cksum definitely compatible with MIT's now.
++
++Version 2.30 24/08/93
++      Triple DES now defaults to triple cbc but can do triple ecb
++       with the -b flag.
++      Fixed some MSDOS uuen/uudecoding problems, thanks to
++      Added prototypes.
++      
++Version 2.22 29/06/93
++      Fixed a bug in des_is_weak_key() which stopped it working :-(
++      thanks to engineering@MorningStar.Com.
++
++Version 2.21 03/06/93
++      des(1) with no arguments gives quite a bit of help.
++      Added -c (generate ckecksum) flag to des(1).
++      Added -3 (triple DES) flag to des(1).
++      Added cfb and ofb routines to the library.
++
++Version 2.20 11/03/93
++      Added -u (uuencode) flag to des(1).
++      I have been playing with byte order in quad_cksum to make it
++       compatible with MIT's version.  All I can say is avid this
++       function if possible since MIT's output is endian dependent.
++
++Version 2.12 14/10/92
++      Added MSDOS specific macro in ecb_encrypt which gives a %70
++       speed up when the code is compiled with turbo C.
++
++Version 2.11 12/10/92
++      Speedup in set_key (recoding of PC-1)
++       I now do it in 47 simple operations, down from 60.
++       Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
++       for motivating me to look for a faster system :-)
++       The speedup is probably less that 1% but it is still 13
++       instructions less :-).
++
++Version 2.10 06/10/92
++      The code now works on the 64bit ETA10 and CRAY without modifications or
++       #defines.  I believe the code should work on any machine that
++       defines long, int or short to be 8 bytes long.
++      Thanks to Shabbir J. Safdar (shabby@mentor.cc.purdue.edu)
++       for helping me fix the code to run on 64bit machines (he had
++       access to an ETA10).
++      Thanks also to John Fletcher <john_fletcher@lccmail.ocf.llnl.gov>
++       for testing the routines on a CRAY.
++      read_password.c has been renamed to read_passwd.c
++      string_to_key.c has been renamed to string2key.c
++
++Version 2.00 14/09/92
++      Made mods so that the library should work on 64bit CPU's.
++      Removed all my uchar and ulong defs.  To many different
++       versions of unix define them in their header files in too many
++       different combinations :-)
++      IRIX - Sillicon Graphics mods (mostly in read_password.c).
++       Thanks to Andrew Daviel (advax@erich.triumf.ca)
++
++Version 1.99 26/08/92
++      Fixed a bug or 2 in enc_read.c
++      Fixed a bug in enc_write.c
++      Fixed a pseudo bug in fcrypt.c (very obscure).
++
++Version 1.98 31/07/92
++      Support for the ETA10.  This is a strange machine that defines
++      longs and ints as 8 bytes and shorts as 4 bytes.
++      Since I do evil things with long * that assume that they are 4
++      bytes.  Look in the Makefile for the option to compile for
++      this machine.  quad_cksum appears to have problems but I
++      will don't have the time to fix it right now, and this is not
++      a function that uses DES and so will not effect the main uses
++      of the library.
++
++Version 1.97 20/05/92 eay
++      Fixed the Imakefile and made some changes to des.h to fix some
++      problems when building this package with Kerberos v 4.
++
++Version 1.96 18/05/92 eay
++      Fixed a small bug in string_to_key() where problems could
++      occur if des_check_key was set to true and the string
++      generated a weak key.
++
++Patch2 posted to comp.sources.misc
++Version 1.95 13/05/92 eay
++      Added an alternative version of the D_ENCRYPT macro in
++      ecb_encrypt and fcrypt.  Depending on the compiler, one version or the
++      other will be faster.  This was inspired by 
++      Dana How <how@isl.stanford.edu>, and her pointers about doing the
++      *(ulong *)((uchar *)ptr+(value&0xfc))
++      vs
++      ptr[value&0x3f]
++      to stop the C compiler doing a <<2 to convert the long array index.
++
++Version 1.94 05/05/92 eay
++      Fixed an incompatibility between my string_to_key and the MIT
++       version.  When the key is longer than 8 chars, I was wrapping
++       with a different method.  To use the old version, define
++       OLD_STR_TO_KEY in the makefile.  Thanks to
++       viktor@newsu.shearson.com (Viktor Dukhovni).
++
++Version 1.93 28/04/92 eay
++      Fixed the VMS mods so that echo is now turned off in
++       read_password.  Thanks again to brennan@coco.cchs.su.oz.AU.
++      MSDOS support added.  The routines can be compiled with
++       Turbo C (v2.0) and MSC (v5.1).  Make sure MSDOS is defined.
++
++Patch1 posted to comp.sources.misc
++Version 1.92 13/04/92 eay
++      Changed D_ENCRYPT so that the rotation of R occurs outside of
++       the loop.  This required rotating all the longs in sp.h (now
++       called spr.h). Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
++      speed.c has been changed so it will work without SIGALRM.  If
++       times(3) is not present it will try to use ftime() instead.
++
++Version 1.91 08/04/92 eay
++      Added -E/-D options to des(1) so it can use string_to_key.
++      Added SVR4 mods suggested by witr@rwwa.COM
++      Added VMS mods suggested by brennan@coco.cchs.su.oz.AU.  If
++      anyone knows how to turn of tty echo in VMS please tell me or
++      implement it yourself :-).
++      Changed FILE *IN/*OUT to *DES_IN/*DES_OUT since it appears VMS
++      does not like IN/OUT being used.
++
++Libdes posted to comp.sources.misc
++Version 1.9 24/03/92 eay
++      Now contains a fast small crypt replacement.
++      Added des(1) command.
++      Added des_rw_mode so people can use cbc encryption with
++      enc_read and enc_write.
++
++Version 1.8 15/10/91 eay
++      Bug in cbc_cksum.
++      Many thanks to Keith Reynolds (keithr@sco.COM) for pointing this
++      one out.
++
++Version 1.7 24/09/91 eay
++      Fixed set_key :-)
++      set_key is 4 times faster and takes less space.
++      There are a few minor changes that could be made.
++
++Version 1.6 19/09/1991 eay
++      Finally go IP and FP finished.
++      Now I need to fix set_key.
++      This version is quite a bit faster that 1.51
++
++Version 1.52 15/06/1991 eay
++      20% speedup in ecb_encrypt by changing the E bit selection
++      to use 2 32bit words.  This also required modification of the
++      sp table.  There is still a way to speedup the IP and IP-1
++      (hints from outer@sq.com) still working on this one :-(.
++
++Version 1.51 07/06/1991 eay
++      Faster des_encrypt by loop unrolling
++      Fixed bug in quad_cksum.c (thanks to hughes@logos.ucs.indiana.edu)
++
++Version 1.50 28/05/1991 eay
++      Optimised the code a bit more for the sparc.  I have improved the
++      speed of the inner des_encrypt by speeding up the initial and
++      final permutations.
++
++Version 1.40 23/10/1990 eay
++      Fixed des_random_key, it did not produce a random key :-(
++
++Version 1.30  2/10/1990 eay
++      Have made des_quad_cksum the same as MIT's, the full package
++      should be compatible with MIT's
++      Have tested on a DECstation 3100
++      Still need to fix des_set_key (make it faster).
++      Does des_cbc_encrypts at 70.5k/sec on a 3100.
++
++Version 1.20 18/09/1990 eay
++      Fixed byte order dependencies.
++      Fixed (I hope) all the word alignment problems.
++      Speedup in des_ecb_encrypt.
++
++Version 1.10 11/09/1990 eay
++      Added des_enc_read and des_enc_write.
++      Still need to fix des_quad_cksum.
++      Still need to document des_enc_read and des_enc_write.
++
++Version 1.00 27/08/1990 eay
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/asm/des-586.pl     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,251 @@
++#!/usr/local/bin/perl
++#
++# The inner loop instruction sequence and the IP/FP modifications are from
++# Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk>
++#
++
++push(@INC,"perlasm","../../perlasm");
++require "x86asm.pl";
++require "cbc.pl";
++require "desboth.pl";
++
++# base code is in microsft
++# op dest, source
++# format.
++#
++
++&asm_init($ARGV[0],"des-586.pl");
++
++$L="edi";
++$R="esi";
++
++&external_label("des_SPtrans");
++&des_encrypt("des_encrypt",1);
++&des_encrypt("des_encrypt2",0);
++&des_encrypt3("des_encrypt3",1);
++&des_encrypt3("des_decrypt3",0);
++&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
++&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
++
++&asm_finish();
++
++sub des_encrypt
++      {
++      local($name,$do_ip)=@_;
++
++      &function_begin_B($name,"EXTRN   _des_SPtrans:DWORD");
++
++      &push("esi");
++      &push("edi");
++
++      &comment("");
++      &comment("Load the 2 words");
++      $ks="ebp";
++
++      if ($do_ip)
++              {
++              &mov($R,&wparam(0));
++               &xor(  "ecx",          "ecx"           );
++
++              &push("ebx");
++              &push("ebp");
++
++              &mov("eax",&DWP(0,$R,"",0));
++               &mov("ebx",&wparam(2));        # get encrypt flag
++              &mov($L,&DWP(4,$R,"",0));
++              &comment("");
++              &comment("IP");
++              &IP_new("eax",$L,$R,3);
++              }
++      else
++              {
++              &mov("eax",&wparam(0));
++               &xor(  "ecx",          "ecx"           );
++
++              &push("ebx");
++              &push("ebp");
++
++              &mov($R,&DWP(0,"eax","",0));
++               &mov("ebx",&wparam(2));        # get encrypt flag
++              &rotl($R,3);
++              &mov($L,&DWP(4,"eax","",0));
++              &rotl($L,3);
++              }
++
++      &mov(   $ks,            &wparam(1)      );
++      &cmp("ebx","0");
++      &je(&label("start_decrypt"));
++
++      for ($i=0; $i<16; $i+=2)
++              {
++              &comment("");
++              &comment("Round $i");
++              &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
++
++              &comment("");
++              &comment("Round ".sprintf("%d",$i+1));
++              &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
++              }
++      &jmp(&label("end"));
++
++      &set_label("start_decrypt");
++
++      for ($i=15; $i>0; $i-=2)
++              {
++              &comment("");
++              &comment("Round $i");
++              &D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
++              &comment("");
++              &comment("Round ".sprintf("%d",$i-1));
++              &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx");
++              }
++
++      &set_label("end");
++
++      if ($do_ip)
++              {
++              &comment("");
++              &comment("FP");
++              &mov("edx",&wparam(0));
++              &FP_new($L,$R,"eax",3);
++
++              &mov(&DWP(0,"edx","",0),"eax");
++              &mov(&DWP(4,"edx","",0),$R);
++              }
++      else
++              {
++              &comment("");
++              &comment("Fixup");
++              &rotr($L,3);            # r
++               &mov("eax",&wparam(0));
++              &rotr($R,3);            # l
++               &mov(&DWP(0,"eax","",0),$L);
++               &mov(&DWP(4,"eax","",0),$R);
++              }
++
++      &pop("ebp");
++      &pop("ebx");
++      &pop("edi");
++      &pop("esi");
++      &ret();
++
++      &function_end_B($name);
++      }
++
++sub D_ENCRYPT
++      {
++      local($r,$L,$R,$S,$ks,$desSP,$u,$tmp1,$tmp2,$t)=@_;
++
++       &mov(  $u,             &DWP(&n2a($S*4),$ks,"",0));
++      &xor(   $tmp1,          $tmp1);
++       &mov(  $t,             &DWP(&n2a(($S+1)*4),$ks,"",0));
++      &xor(   $u,             $R);
++       &xor(  $t,             $R);
++      &and(   $u,             "0xfcfcfcfc"    );
++       &and(  $t,             "0xcfcfcfcf"    );
++      &movb(  &LB($tmp1),     &LB($u) );
++       &movb( &LB($tmp2),     &HB($u) );
++      &rotr(  $t,             4               );
++      &mov(   $ks,            &DWP("      $desSP",$tmp1,"",0));
++       &movb( &LB($tmp1),     &LB($t) );
++      &xor(   $L,             $ks);
++       &mov(  $ks,            &DWP("0x200+$desSP",$tmp2,"",0));
++      &xor(   $L,             $ks); ######
++       &movb( &LB($tmp2),     &HB($t) );
++      &shr(   $u,             16);
++       &mov(  $ks,            &DWP("0x100+$desSP",$tmp1,"",0));
++      &xor(   $L,             $ks); ######
++       &movb( &LB($tmp1),     &HB($u) );
++      &shr(   $t,             16);
++       &mov(  $ks,            &DWP("0x300+$desSP",$tmp2,"",0));
++      &xor(   $L,             $ks);
++       &mov(  $ks,            &wparam(1)      );
++      &movb(  &LB($tmp2),     &HB($t) );
++       &and(  $u,             "0xff"  );
++      &and(   $t,             "0xff"  );
++       &mov(  $tmp1,          &DWP("0x600+$desSP",$tmp1,"",0));
++      &xor(   $L,             $tmp1);
++       &mov(  $tmp1,          &DWP("0x700+$desSP",$tmp2,"",0));
++      &xor(   $L,             $tmp1);
++       &mov(  $tmp1,          &DWP("0x400+$desSP",$u,"",0));
++      &xor(   $L,             $tmp1);
++       &mov(  $tmp1,          &DWP("0x500+$desSP",$t,"",0));
++      &xor(   $L,             $tmp1);
++      }
++
++sub n2a
++      {
++      sprintf("%d",$_[0]);
++      }
++
++# now has a side affect of rotating $a by $shift
++sub R_PERM_OP
++      {
++      local($a,$b,$tt,$shift,$mask,$last)=@_;
++
++      &rotl(  $a,             $shift          ) if ($shift != 0);
++      &mov(   $tt,            $a              );
++      &xor(   $a,             $b              );
++      &and(   $a,             $mask           );
++      if (!$last eq $b)
++              {
++              &xor(   $b,             $a              );
++              &xor(   $tt,            $a              );
++              }
++      else
++              {
++              &xor(   $tt,            $a              );
++              &xor(   $b,             $a              );
++              }
++      &comment("");
++      }
++
++sub IP_new
++      {
++      local($l,$r,$tt,$lr)=@_;
++
++      &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l);
++      &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l);
++      &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r);
++      &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r);
++      &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r);
++      
++      if ($lr != 3)
++              {
++              if (($lr-3) < 0)
++                      { &rotr($tt,    3-$lr); }
++              else    { &rotl($tt,    $lr-3); }
++              }
++      if ($lr != 2)
++              {
++              if (($lr-2) < 0)
++                      { &rotr($r,     2-$lr); }
++              else    { &rotl($r,     $lr-2); }
++              }
++      }
++
++sub FP_new
++      {
++      local($l,$r,$tt,$lr)=@_;
++
++      if ($lr != 2)
++              {
++              if (($lr-2) < 0)
++                      { &rotl($r,     2-$lr); }
++              else    { &rotr($r,     $lr-2); }
++              }
++      if ($lr != 3)
++              {
++              if (($lr-3) < 0)
++                      { &rotl($l,     3-$lr); }
++              else    { &rotr($l,     $lr-3); }
++              }
++
++      &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r);
++      &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r);
++      &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l);
++      &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l);
++      &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r);
++      &rotr($tt       , 4);
++      }
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/asm/des686.pl     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,230 @@
++#!/usr/local/bin/perl
++
++$prog="des686.pl";
++
++# base code is in microsft
++# op dest, source
++# format.
++#
++
++# WILL NOT WORK ANYMORE WITH desboth.pl
++require "desboth.pl";
++
++if (  ($ARGV[0] eq "elf"))
++      { require "x86unix.pl"; }
++elsif (       ($ARGV[0] eq "a.out"))
++      { $aout=1; require "x86unix.pl"; }
++elsif (       ($ARGV[0] eq "sol"))
++      { $sol=1; require "x86unix.pl"; }
++elsif ( ($ARGV[0] eq "cpp"))
++      { $cpp=1; require "x86unix.pl"; }
++elsif (       ($ARGV[0] eq "win32"))
++      { require "x86ms.pl"; }
++else
++      {
++      print STDERR <<"EOF";
++Pick one target type from
++      elf     - linux, FreeBSD etc
++      a.out   - old linux
++      sol     - x86 solaris
++      cpp     - format so x86unix.cpp can be used
++      win32   - Windows 95/Windows NT
++EOF
++      exit(1);
++      }
++
++&comment("Don't even think of reading this code");
++&comment("It was automatically generated by $prog");
++&comment("Which is a perl program used to generate the x86 assember for");
++&comment("any of elf, a.out, Win32, or Solaris");
++&comment("It can be found in SSLeay 0.6.5+ or in libdes 3.26+");
++&comment("eric <eay\@cryptsoft.com>");
++&comment("");
++
++&file("dx86xxxx");
++
++$L="edi";
++$R="esi";
++
++&des_encrypt("des_encrypt",1);
++&des_encrypt("des_encrypt2",0);
++
++&des_encrypt3("des_encrypt3",1);
++&des_encrypt3("des_decrypt3",0);
++
++&file_end();
++
++sub des_encrypt
++      {
++      local($name,$do_ip)=@_;
++
++      &function_begin($name,"EXTRN   _des_SPtrans:DWORD");
++
++      &comment("");
++      &comment("Load the 2 words");
++      &mov("eax",&wparam(0));
++      &mov($L,&DWP(0,"eax","",0));
++      &mov($R,&DWP(4,"eax","",0));
++
++      $ksp=&wparam(1);
++
++      if ($do_ip)
++              {
++              &comment("");
++              &comment("IP");
++              &IP_new($L,$R,"eax");
++              }
++
++      &comment("");
++      &comment("fixup rotate");
++      &rotl($R,3);
++      &rotl($L,3);
++      &exch($L,$R);
++
++      &comment("");
++      &comment("load counter, key_schedule and enc flag");
++      &mov("eax",&wparam(2)); # get encrypt flag
++      &mov("ebp",&wparam(1)); # get ks
++      &cmp("eax","0");
++      &je(&label("start_decrypt"));
++
++      # encrypting part
++
++      for ($i=0; $i<16; $i+=2)
++              {
++              &comment("");
++              &comment("Round $i");
++              &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
++
++              &comment("");
++              &comment("Round ".sprintf("%d",$i+1));
++              &D_ENCRYPT($R,$L,($i+1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
++              }
++      &jmp(&label("end"));
++
++      &set_label("start_decrypt");
++
++      for ($i=15; $i>0; $i-=2)
++              {
++              &comment("");
++              &comment("Round $i");
++              &D_ENCRYPT($L,$R,$i*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
++              &comment("");
++              &comment("Round ".sprintf("%d",$i-1));
++              &D_ENCRYPT($R,$L,($i-1)*2,"ebp","des_SPtrans","ecx","edx","eax","ebx");
++              }
++
++      &set_label("end");
++
++      &comment("");
++      &comment("Fixup");
++      &rotr($L,3);            # r
++      &rotr($R,3);            # l
++
++      if ($do_ip)
++              {
++              &comment("");
++              &comment("FP");
++              &FP_new($R,$L,"eax");
++              }
++
++      &mov("eax",&wparam(0));
++      &mov(&DWP(0,"eax","",0),$L);
++      &mov(&DWP(4,"eax","",0),$R);
++
++      &function_end($name);
++      }
++
++
++# The logic is to load R into 2 registers and operate on both at the same time.
++# We also load the 2 R's into 2 more registers so we can do the 'move word down a byte'
++# while also masking the other copy and doing a lookup.  We then also accumulate the
++# L value in 2 registers then combine them at the end.
++sub D_ENCRYPT
++      {
++      local($L,$R,$S,$ks,$desSP,$u,$t,$tmp1,$tmp2,$tmp3)=@_;
++
++      &mov(   $u,             &DWP(&n2a($S*4),$ks,"",0));
++      &mov(   $t,             &DWP(&n2a(($S+1)*4),$ks,"",0));
++      &xor(   $u,             $R              );
++      &xor(   $t,             $R              );
++      &rotr(  $t,             4               );
++
++      # the numbers at the end of the line are origional instruction order
++      &mov(   $tmp2,          $u              );                      # 1 2
++      &mov(   $tmp1,          $t              );                      # 1 1
++      &and(   $tmp2,          "0xfc"          );                      # 1 4
++      &and(   $tmp1,          "0xfc"          );                      # 1 3
++      &shr(   $t,             8               );                      # 1 5
++      &xor(   $L,             &DWP("0x100+$desSP",$tmp1,"",0));       # 1 7
++      &shr(   $u,             8               );                      # 1 6
++      &mov(   $tmp1,          &DWP("      $desSP",$tmp2,"",0));       # 1 8
++
++      &mov(   $tmp2,          $u              );                      # 2 2
++      &xor(   $L,             $tmp1           );                      # 1 9
++      &and(   $tmp2,          "0xfc"          );                      # 2 4
++      &mov(   $tmp1,          $t              );                      # 2 1
++      &and(   $tmp1,          "0xfc"          );                      # 2 3
++      &shr(   $t,             8               );                      # 2 5
++      &xor(   $L,             &DWP("0x300+$desSP",$tmp1,"",0));       # 2 7
++      &shr(   $u,             8               );                      # 2 6
++      &mov(   $tmp1,          &DWP("0x200+$desSP",$tmp2,"",0));       # 2 8
++      &mov(   $tmp2,          $u              );                      # 3 2
++
++      &xor(   $L,             $tmp1           );                      # 2 9
++      &and(   $tmp2,          "0xfc"          );                      # 3 4
++
++      &mov(   $tmp1,          $t              );                      # 3 1 
++      &shr(   $u,             8               );                      # 3 6
++      &and(   $tmp1,          "0xfc"          );                      # 3 3
++      &shr(   $t,             8               );                      # 3 5
++      &xor(   $L,             &DWP("0x500+$desSP",$tmp1,"",0));       # 3 7
++      &mov(   $tmp1,          &DWP("0x400+$desSP",$tmp2,"",0));       # 3 8
++
++      &and(   $t,             "0xfc"          );                      # 4 1
++      &xor(   $L,             $tmp1           );                      # 3 9
++
++      &and(   $u,             "0xfc"          );                      # 4 2
++      &xor(   $L,             &DWP("0x700+$desSP",$t,"",0));          # 4 3
++      &xor(   $L,             &DWP("0x600+$desSP",$u,"",0));          # 4 4
++      }
++
++sub PERM_OP
++      {
++      local($a,$b,$tt,$shift,$mask)=@_;
++
++      &mov(   $tt,            $a              );
++      &shr(   $tt,            $shift          );
++      &xor(   $tt,            $b              );
++      &and(   $tt,            $mask           );
++      &xor(   $b,             $tt             );
++      &shl(   $tt,            $shift          );
++      &xor(   $a,             $tt             );
++      }
++
++sub IP_new
++      {
++      local($l,$r,$tt)=@_;
++
++      &PERM_OP($r,$l,$tt, 4,"0x0f0f0f0f");
++      &PERM_OP($l,$r,$tt,16,"0x0000ffff");
++      &PERM_OP($r,$l,$tt, 2,"0x33333333");
++      &PERM_OP($l,$r,$tt, 8,"0x00ff00ff");
++      &PERM_OP($r,$l,$tt, 1,"0x55555555");
++      }
++
++sub FP_new
++      {
++      local($l,$r,$tt)=@_;
++
++      &PERM_OP($l,$r,$tt, 1,"0x55555555");
++        &PERM_OP($r,$l,$tt, 8,"0x00ff00ff");
++        &PERM_OP($l,$r,$tt, 2,"0x33333333");
++        &PERM_OP($r,$l,$tt,16,"0x0000ffff");
++        &PERM_OP($l,$r,$tt, 4,"0x0f0f0f0f");
++      }
++
++sub n2a
++      {
++      sprintf("%d",$_[0]);
++      }
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/asm/desboth.pl     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,79 @@
++#!/usr/local/bin/perl
++
++$L="edi";
++$R="esi";
++
++sub des_encrypt3
++      {
++      local($name,$enc)=@_;
++
++      &function_begin_B($name,"");
++      &push("ebx");
++      &mov("ebx",&wparam(0));
++
++      &push("ebp");
++      &push("esi");
++
++      &push("edi");
++
++      &comment("");
++      &comment("Load the data words");
++      &mov($L,&DWP(0,"ebx","",0));
++      &mov($R,&DWP(4,"ebx","",0));
++      &stack_push(3);
++
++      &comment("");
++      &comment("IP");
++      &IP_new($L,$R,"edx",0);
++
++      # put them back
++      
++      if ($enc)
++              {
++              &mov(&DWP(4,"ebx","",0),$R);
++               &mov("eax",&wparam(1));
++              &mov(&DWP(0,"ebx","",0),"edx");
++               &mov("edi",&wparam(2));
++               &mov("esi",&wparam(3));
++              }
++      else
++              {
++              &mov(&DWP(4,"ebx","",0),$R);
++               &mov("esi",&wparam(1));
++              &mov(&DWP(0,"ebx","",0),"edx");
++               &mov("edi",&wparam(2));
++               &mov("eax",&wparam(3));
++              }
++      &mov(&swtmp(2), (($enc)?"1":"0"));
++      &mov(&swtmp(1), "eax");
++      &mov(&swtmp(0), "ebx");
++      &call("des_encrypt2");
++      &mov(&swtmp(2), (($enc)?"0":"1"));
++      &mov(&swtmp(1), "edi");
++      &mov(&swtmp(0), "ebx");
++      &call("des_encrypt2");
++      &mov(&swtmp(2), (($enc)?"1":"0"));
++      &mov(&swtmp(1), "esi");
++      &mov(&swtmp(0), "ebx");
++      &call("des_encrypt2");
++
++      &stack_pop(3);
++      &mov($L,&DWP(0,"ebx","",0));
++      &mov($R,&DWP(4,"ebx","",0));
++
++      &comment("");
++      &comment("FP");
++      &FP_new($L,$R,"eax",0);
++
++      &mov(&DWP(0,"ebx","",0),"eax");
++      &mov(&DWP(4,"ebx","",0),$R);
++
++      &pop("edi");
++      &pop("esi");
++      &pop("ebp");
++      &pop("ebx");
++      &ret();
++      &function_end_B($name);
++      }
++
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/asm/readme     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,131 @@
++First up, let me say I don't like writing in assembler.  It is not portable,
++dependant on the particular CPU architecture release and is generally a pig
++to debug and get right.  Having said that, the x86 architecture is probably
++the most important for speed due to number of boxes and since
++it appears to be the worst architecture to to get
++good C compilers for.  So due to this, I have lowered myself to do
++assembler for the inner DES routines in libdes :-).
++
++The file to implement in assembler is des_enc.c.  Replace the following
++4 functions
++des_encrypt(DES_LONG data[2],des_key_schedule ks, int encrypt);
++des_encrypt2(DES_LONG data[2],des_key_schedule ks, int encrypt);
++des_encrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3);
++des_decrypt3(DES_LONG data[2],des_key_schedule ks1,ks2,ks3);
++
++They encrypt/decrypt the 64 bits held in 'data' using
++the 'ks' key schedules.   The only difference between the 4 functions is that
++des_encrypt2() does not perform IP() or FP() on the data (this is an
++optimization for when doing triple DES and des_encrypt3() and des_decrypt3()
++perform triple des.  The triple DES routines are in here because it does
++make a big difference to have them located near the des_encrypt2 function
++at link time..
++
++Now as we all know, there are lots of different operating systems running on
++x86 boxes, and unfortunately they normally try to make sure their assembler
++formating is not the same as the other peoples.
++The 4 main formats I know of are
++Microsoft     Windows 95/Windows NT
++Elf           Includes Linux and FreeBSD(?).
++a.out         The older Linux.
++Solaris               Same as Elf but different comments :-(.
++
++Now I was not overly keen to write 4 different copies of the same code,
++so I wrote a few perl routines to output the correct assembler, given
++a target assembler type.  This code is ugly and is just a hack.
++The libraries are x86unix.pl and x86ms.pl.
++des586.pl, des686.pl and des-som[23].pl are the programs to actually
++generate the assembler.
++
++So to generate elf assembler
++perl des-som3.pl elf >dx86-elf.s
++For Windows 95/NT
++perl des-som2.pl win32 >win32.asm
++
++[ update 4 Jan 1996 ]
++I have added another way to do things.
++perl des-som3.pl cpp >dx86-cpp.s
++generates a file that will be included by dx86unix.cpp when it is compiled.
++To build for elf, a.out, solaris, bsdi etc,
++cc -E -DELF asm/dx86unix.cpp | as -o asm/dx86-elf.o
++cc -E -DSOL asm/dx86unix.cpp | as -o asm/dx86-sol.o
++cc -E -DOUT asm/dx86unix.cpp | as -o asm/dx86-out.o
++cc -E -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o
++This was done to cut down the number of files in the distribution.
++
++Now the ugly part.  I acquired my copy of Intels
++"Optimization's For Intel's 32-Bit Processors" and found a few interesting
++things.  First, the aim of the exersize is to 'extract' one byte at a time
++from a word and do an array lookup.  This involves getting the byte from
++the 4 locations in the word and moving it to a new word and doing the lookup.
++The most obvious way to do this is
++xor   eax,    eax                             # clear word
++movb  al,     cl                              # get low byte
++xor   edi     DWORD PTR 0x100+des_SP[eax]     # xor in word
++movb  al,     ch                              # get next byte
++xor   edi     DWORD PTR 0x300+des_SP[eax]     # xor in word
++shr   ecx     16
++which seems ok.  For the pentium, this system appears to be the best.
++One has to do instruction interleaving to keep both functional units
++operating, but it is basically very efficient.
++
++Now the crunch.  When a full register is used after a partial write, eg.
++mov   al,     cl
++xor   edi,    DWORD PTR 0x100+des_SP[eax]
++386   - 1 cycle stall
++486   - 1 cycle stall
++586   - 0 cycle stall
++686   - at least 7 cycle stall (page 22 of the above mentioned document).
++
++So the technique that produces the best results on a pentium, according to
++the documentation, will produce hideous results on a pentium pro.
++
++To get around this, des686.pl will generate code that is not as fast on
++a pentium, should be very good on a pentium pro.
++mov   eax,    ecx                             # copy word 
++shr   ecx,    8                               # line up next byte
++and   eax,    0fch                            # mask byte
++xor   edi     DWORD PTR 0x100+des_SP[eax]     # xor in array lookup
++mov   eax,    ecx                             # get word
++shr   ecx     8                               # line up next byte
++and   eax,    0fch                            # mask byte
++xor   edi     DWORD PTR 0x300+des_SP[eax]     # xor in array lookup
++
++Due to the execution units in the pentium, this actually works quite well.
++For a pentium pro it should be very good.  This is the type of output
++Visual C++ generates.
++
++There is a third option.  instead of using
++mov   al,     ch
++which is bad on the pentium pro, one may be able to use
++movzx eax,    ch
++which may not incur the partial write penalty.  On the pentium,
++this instruction takes 4 cycles so is not worth using but on the
++pentium pro it appears it may be worth while.  I need access to one to
++experiment :-).
++
++eric (20 Oct 1996)
++
++22 Nov 1996 - I have asked people to run the 2 different version on pentium
++pros and it appears that the intel documentation is wrong.  The
++mov al,bh is still faster on a pentium pro, so just use the des586.pl
++install des686.pl
++
++3 Dec 1996 - I added des_encrypt3/des_decrypt3 because I have moved these
++functions into des_enc.c because it does make a massive performance
++difference on some boxes to have the functions code located close to
++the des_encrypt2() function.
++
++9 Jan 1997 - des-som2.pl is now the correct perl script to use for
++pentiums.  It contains an inner loop from
++Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk> which does raw ecb DES calls at
++273,000 per second.  He had a previous version at 250,000 and the best
++I was able to get was 203,000.  The content has not changed, this is all
++due to instruction sequencing (and actual instructions choice) which is able
++to keep both functional units of the pentium going.
++We may have lost the ugly register usage restrictions when x86 went 32 bit
++but for the pentium it has been replaced by evil instruction ordering tricks.
++
++13 Jan 1997 - des-som3.pl, more optimizations from Svend Olaf.
++raw DES at 281,000 per second on a pentium 100.
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/cbc_enc.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,135 @@
++/* crypto/des/cbc_enc.c */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++#include "des/des_locl.h"
++
++void des_cbc_encrypt(input, output, length, schedule, ivec, enc)
++des_cblock (*input);
++des_cblock (*output);
++long length;
++des_key_schedule schedule;
++des_cblock (*ivec);
++int enc;
++      {
++      register DES_LONG tin0,tin1;
++      register DES_LONG tout0,tout1,xor0,xor1;
++      register unsigned char *in,*out;
++      register long l=length;
++      DES_LONG tin[2];
++      unsigned char *iv;
++
++      in=(unsigned char *)input;
++      out=(unsigned char *)output;
++      iv=(unsigned char *)ivec;
++
++      if (enc)
++              {
++              c2l(iv,tout0);
++              c2l(iv,tout1);
++              for (l-=8; l>=0; l-=8)
++                      {
++                      c2l(in,tin0);
++                      c2l(in,tin1);
++                      tin0^=tout0; tin[0]=tin0;
++                      tin1^=tout1; tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
++                      tout0=tin[0]; l2c(tout0,out);
++                      tout1=tin[1]; l2c(tout1,out);
++                      }
++              if (l != -8)
++                      {
++                      c2ln(in,tin0,tin1,l+8);
++                      tin0^=tout0; tin[0]=tin0;
++                      tin1^=tout1; tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
++                      tout0=tin[0]; l2c(tout0,out);
++                      tout1=tin[1]; l2c(tout1,out);
++                      }
++              }
++      else
++              {
++              c2l(iv,xor0);
++              c2l(iv,xor1);
++              for (l-=8; l>=0; l-=8)
++                      {
++                      c2l(in,tin0); tin[0]=tin0;
++                      c2l(in,tin1); tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
++                      tout0=tin[0]^xor0;
++                      tout1=tin[1]^xor1;
++                      l2c(tout0,out);
++                      l2c(tout1,out);
++                      xor0=tin0;
++                      xor1=tin1;
++                      }
++              if (l != -8)
++                      {
++                      c2l(in,tin0); tin[0]=tin0;
++                      c2l(in,tin1); tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
++                      tout0=tin[0]^xor0;
++                      tout1=tin[1]^xor1;
++                      l2cn(tout0,tout1,out,l+8);
++              /*      xor0=tin0;
++                      xor1=tin1; */
++                      }
++              }
++      tin0=tin1=tout0=tout1=xor0=xor1=0;
++      tin[0]=tin[1]=0;
++      }
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/des.doc     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,505 @@
++The DES library.
++
++Please note that this library was originally written to operate with
++eBones, a version of Kerberos that had had encryption removed when it left
++the USA and then put back in.  As such there are some routines that I will
++advise not using but they are still in the library for historical reasons.
++For all calls that have an 'input' and 'output' variables, they can be the
++same.
++
++This library requires the inclusion of 'des.h'.
++
++All of the encryption functions take what is called a des_key_schedule as an 
++argument.  A des_key_schedule is an expanded form of the des key.
++A des_key is 8 bytes of odd parity, the type used to hold the key is a
++des_cblock.  A des_cblock is an array of 8 bytes, often in this library
++description I will refer to input bytes when the function specifies
++des_cblock's as input or output, this just means that the variable should
++be a multiple of 8 bytes.
++
++The define DES_ENCRYPT is passed to specify encryption, DES_DECRYPT to
++specify decryption.  The functions and global variable are as follows:
++
++int des_check_key;
++      DES keys are supposed to be odd parity.  If this variable is set to
++      a non-zero value, des_set_key() will check that the key has odd
++      parity and is not one of the known weak DES keys.  By default this
++      variable is turned off;
++      
++void des_set_odd_parity(
++des_cblock *key );
++      This function takes a DES key (8 bytes) and sets the parity to odd.
++      
++int des_is_weak_key(
++des_cblock *key );
++      This function returns a non-zero value if the DES key passed is a
++      weak, DES key.  If it is a weak key, don't use it, try a different
++      one.  If you are using 'random' keys, the chances of hitting a weak
++      key are 1/2^52 so it is probably not worth checking for them.
++      
++int des_set_key(
++des_cblock *key,
++des_key_schedule schedule);
++      Des_set_key converts an 8 byte DES key into a des_key_schedule.
++      A des_key_schedule is an expanded form of the key which is used to
++      perform actual encryption.  It can be regenerated from the DES key
++      so it only needs to be kept when encryption or decryption is about
++      to occur.  Don't save or pass around des_key_schedule's since they
++      are CPU architecture dependent, DES keys are not.  If des_check_key
++      is non zero, zero is returned if the key has the wrong parity or
++      the key is a weak key, else 1 is returned.
++      
++int des_key_sched(
++des_cblock *key,
++des_key_schedule schedule);
++      An alternative name for des_set_key().
++
++int des_rw_mode;              /* defaults to DES_PCBC_MODE */
++      This flag holds either DES_CBC_MODE or DES_PCBC_MODE (default).
++      This specifies the function to use in the enc_read() and enc_write()
++      functions.
++
++void des_encrypt(
++unsigned long *data,
++des_key_schedule ks,
++int enc);
++      This is the DES encryption function that gets called by just about
++      every other DES routine in the library.  You should not use this
++      function except to implement 'modes' of DES.  I say this because the
++      functions that call this routine do the conversion from 'char *' to
++      long, and this needs to be done to make sure 'non-aligned' memory
++      access do not occur.  The characters are loaded 'little endian',
++      have a look at my source code for more details on how I use this
++      function.
++      Data is a pointer to 2 unsigned long's and ks is the
++      des_key_schedule to use.  enc, is non zero specifies encryption,
++      zero if decryption.
++
++void des_encrypt2(
++unsigned long *data,
++des_key_schedule ks,
++int enc);
++      This functions is the same as des_encrypt() except that the DES
++      initial permutation (IP) and final permutation (FP) have been left
++      out.  As for des_encrypt(), you should not use this function.
++      It is used by the routines in my library that implement triple DES.
++      IP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same
++      as des_encrypt() des_encrypt() des_encrypt() except faster :-).
++
++void des_ecb_encrypt(
++des_cblock *input,
++des_cblock *output,
++des_key_schedule ks,
++int enc);
++      This is the basic Electronic Code Book form of DES, the most basic
++      form.  Input is encrypted into output using the key represented by
++      ks.  If enc is non zero (DES_ENCRYPT), encryption occurs, otherwise
++      decryption occurs.  Input is 8 bytes long and output is 8 bytes.
++      (the des_cblock structure is 8 chars).
++      
++void des_ecb3_encrypt(
++des_cblock *input,
++des_cblock *output,
++des_key_schedule ks1,
++des_key_schedule ks2,
++des_key_schedule ks3,
++int enc);
++      This is the 3 key EDE mode of ECB DES.  What this means is that 
++      the 8 bytes of input is encrypted with ks1, decrypted with ks2 and
++      then encrypted again with ks3, before being put into output;
++      C=E(ks3,D(ks2,E(ks1,M))).  There is a macro, des_ecb2_encrypt()
++      that only takes 2 des_key_schedules that implements,
++      C=E(ks1,D(ks2,E(ks1,M))) in that the final encrypt is done with ks1.
++      
++void des_cbc_encrypt(
++des_cblock *input,
++des_cblock *output,
++long length,
++des_key_schedule ks,
++des_cblock *ivec,
++int enc);
++      This routine implements DES in Cipher Block Chaining mode.
++      Input, which should be a multiple of 8 bytes is encrypted
++      (or decrypted) to output which will also be a multiple of 8 bytes.
++      The number of bytes is in length (and from what I've said above,
++      should be a multiple of 8).  If length is not a multiple of 8, I'm
++      not being held responsible :-).  ivec is the initialisation vector.
++      This function does not modify this variable.  To correctly implement
++      cbc mode, you need to do one of 2 things; copy the last 8 bytes of
++      cipher text for use as the next ivec in your application,
++      or use des_ncbc_encrypt(). 
++      Only this routine has this problem with updating the ivec, all
++      other routines that are implementing cbc mode update ivec.
++      
++void des_ncbc_encrypt(
++des_cblock *input,
++des_cblock *output,
++long length,
++des_key_schedule sk,
++des_cblock *ivec,
++int enc);
++      For historical reasons, des_cbc_encrypt() did not update the
++      ivec with the value requires so that subsequent calls to
++      des_cbc_encrypt() would 'chain'.  This was needed so that the same
++      'length' values would not need to be used when decrypting.
++      des_ncbc_encrypt() does the right thing.  It is the same as
++      des_cbc_encrypt accept that ivec is updates with the correct value
++      to pass in subsequent calls to des_ncbc_encrypt().  I advise using
++      des_ncbc_encrypt() instead of des_cbc_encrypt();
++
++void des_xcbc_encrypt(
++des_cblock *input,
++des_cblock *output,
++long length,
++des_key_schedule sk,
++des_cblock *ivec,
++des_cblock *inw,
++des_cblock *outw,
++int enc);
++      This is RSA's DESX mode of DES.  It uses inw and outw to
++      'whiten' the encryption.  inw and outw are secret (unlike the iv)
++      and are as such, part of the key.  So the key is sort of 24 bytes.
++      This is much better than cbc des.
++      
++void des_3cbc_encrypt(
++des_cblock *input,
++des_cblock *output,
++long length,
++des_key_schedule sk1,
++des_key_schedule sk2,
++des_cblock *ivec1,
++des_cblock *ivec2,
++int enc);
++      This function is flawed, do not use it.  I have left it in the
++      library because it is used in my des(1) program and will function
++      correctly when used by des(1).  If I removed the function, people
++      could end up unable to decrypt files.
++      This routine implements outer triple cbc encryption using 2 ks and
++      2 ivec's.  Use des_ede2_cbc_encrypt() instead.
++      
++void des_ede3_cbc_encrypt(
++des_cblock *input,
++des_cblock *output, 
++long length,
++des_key_schedule ks1,
++des_key_schedule ks2, 
++des_key_schedule ks3, 
++des_cblock *ivec,
++int enc);
++      This function implements inner triple CBC DES encryption with 3
++      keys.  What this means is that each 'DES' operation
++      inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))).
++      Again, this is cbc mode so an ivec is requires.
++      This mode is used by SSL.
++      There is also a des_ede2_cbc_encrypt() that only uses 2
++      des_key_schedule's, the first being reused for the final
++      encryption.  C=E(ks1,D(ks2,E(ks1,M))).  This form of triple DES
++      is used by the RSAref library.
++      
++void des_pcbc_encrypt(
++des_cblock *input,
++des_cblock *output,
++long length,
++des_key_schedule ks,
++des_cblock *ivec,
++int enc);
++      This is Propagating Cipher Block Chaining mode of DES.  It is used
++      by Kerberos v4.  It's parameters are the same as des_ncbc_encrypt().
++      
++void des_cfb_encrypt(
++unsigned char *in,
++unsigned char *out,
++int numbits,
++long length,
++des_key_schedule ks,
++des_cblock *ivec,
++int enc);
++      Cipher Feedback Back mode of DES.  This implementation 'feeds back'
++      in numbit blocks.  The input (and output) is in multiples of numbits
++      bits.  numbits should to be a multiple of 8 bits.  Length is the
++      number of bytes input.  If numbits is not a multiple of 8 bits,
++      the extra bits in the bytes will be considered padding.  So if
++      numbits is 12, for each 2 input bytes, the 4 high bits of the
++      second byte will be ignored.  So to encode 72 bits when using
++      a numbits of 12 take 12 bytes.  To encode 72 bits when using
++      numbits of 9 will take 16 bytes.  To encode 80 bits when using
++      numbits of 16 will take 10 bytes. etc, etc.  This padding will
++      apply to both input and output.
++
++      
++void des_cfb64_encrypt(
++unsigned char *in,
++unsigned char *out,
++long length,
++des_key_schedule ks,
++des_cblock *ivec,
++int *num,
++int enc);
++      This is one of the more useful functions in this DES library, it
++      implements CFB mode of DES with 64bit feedback.  Why is this
++      useful you ask?  Because this routine will allow you to encrypt an
++      arbitrary number of bytes, no 8 byte padding.  Each call to this
++      routine will encrypt the input bytes to output and then update ivec
++      and num.  num contains 'how far' we are though ivec.  If this does
++      not make much sense, read more about cfb mode of DES :-).
++      
++void des_ede3_cfb64_encrypt(
++unsigned char *in,
++unsigned char *out,
++long length,
++des_key_schedule ks1,
++des_key_schedule ks2,
++des_key_schedule ks3,
++des_cblock *ivec,
++int *num,
++int enc);
++      Same as des_cfb64_encrypt() accept that the DES operation is
++      triple DES.  As usual, there is a macro for
++      des_ede2_cfb64_encrypt() which reuses ks1.
++
++void des_ofb_encrypt(
++unsigned char *in,
++unsigned char *out,
++int numbits,
++long length,
++des_key_schedule ks,
++des_cblock *ivec);
++      This is a implementation of Output Feed Back mode of DES.  It is
++      the same as des_cfb_encrypt() in that numbits is the size of the
++      units dealt with during input and output (in bits).
++      
++void des_ofb64_encrypt(
++unsigned char *in,
++unsigned char *out,
++long length,
++des_key_schedule ks,
++des_cblock *ivec,
++int *num);
++      The same as des_cfb64_encrypt() except that it is Output Feed Back
++      mode.
++
++void des_ede3_ofb64_encrypt(
++unsigned char *in,
++unsigned char *out,
++long length,
++des_key_schedule ks1,
++des_key_schedule ks2,
++des_key_schedule ks3,
++des_cblock *ivec,
++int *num);
++      Same as des_ofb64_encrypt() accept that the DES operation is
++      triple DES.  As usual, there is a macro for
++      des_ede2_ofb64_encrypt() which reuses ks1.
++
++int des_read_pw_string(
++char *buf,
++int length,
++char *prompt,
++int verify);
++      This routine is used to get a password from the terminal with echo
++      turned off.  Buf is where the string will end up and length is the
++      size of buf.  Prompt is a string presented to the 'user' and if
++      verify is set, the key is asked for twice and unless the 2 copies
++      match, an error is returned.  A return code of -1 indicates a
++      system error, 1 failure due to use interaction, and 0 is success.
++
++unsigned long des_cbc_cksum(
++des_cblock *input,
++des_cblock *output,
++long length,
++des_key_schedule ks,
++des_cblock *ivec);
++      This function produces an 8 byte checksum from input that it puts in
++      output and returns the last 4 bytes as a long.  The checksum is
++      generated via cbc mode of DES in which only the last 8 byes are
++      kept.  I would recommend not using this function but instead using
++      the EVP_Digest routines, or at least using MD5 or SHA.  This
++      function is used by Kerberos v4 so that is why it stays in the
++      library.
++      
++char *des_fcrypt(
++const char *buf,
++const char *salt
++char *ret);
++      This is my fast version of the unix crypt(3) function.  This version
++      takes only a small amount of space relative to other fast
++      crypt() implementations.  This is different to the normal crypt
++      in that the third parameter is the buffer that the return value
++      is written into.  It needs to be at least 14 bytes long.  This
++      function is thread safe, unlike the normal crypt.
++
++char *crypt(
++const char *buf,
++const char *salt);
++      This function calls des_fcrypt() with a static array passed as the
++      third parameter.  This emulates the normal non-thread safe semantics
++      of crypt(3).
++
++void des_string_to_key(
++char *str,
++des_cblock *key);
++      This function takes str and converts it into a DES key.  I would
++      recommend using MD5 instead and use the first 8 bytes of output.
++      When I wrote the first version of these routines back in 1990, MD5
++      did not exist but I feel these routines are still sound.  This
++      routines is compatible with the one in MIT's libdes.
++      
++void des_string_to_2keys(
++char *str,
++des_cblock *key1,
++des_cblock *key2);
++      This function takes str and converts it into 2 DES keys.
++      I would recommend using MD5 and using the 16 bytes as the 2 keys.
++      I have nothing against these 2 'string_to_key' routines, it's just
++      that if you say that your encryption key is generated by using the
++      16 bytes of an MD5 hash, every-one knows how you generated your
++      keys.
++
++int des_read_password(
++des_cblock *key,
++char *prompt,
++int verify);
++      This routine combines des_read_pw_string() with des_string_to_key().
++
++int des_read_2passwords(
++des_cblock *key1,
++des_cblock *key2,
++char *prompt,
++int verify);
++      This routine combines des_read_pw_string() with des_string_to_2key().
++
++void des_random_seed(
++des_cblock key);
++      This routine sets a starting point for des_random_key().
++      
++void des_random_key(
++des_cblock ret);
++      This function return a random key.  Make sure to 'seed' the random
++      number generator (with des_random_seed()) before using this function.
++      I personally now use a MD5 based random number system.
++
++int des_enc_read(
++int fd,
++char *buf,
++int len,
++des_key_schedule ks,
++des_cblock *iv);
++      This function will write to a file descriptor the encrypted data
++      from buf.  This data will be preceded by a 4 byte 'byte count' and
++      will be padded out to 8 bytes.  The encryption is either CBC of
++      PCBC depending on the value of des_rw_mode.  If it is DES_PCBC_MODE,
++      pcbc is used, if DES_CBC_MODE, cbc is used.  The default is to use
++      DES_PCBC_MODE.
++
++int des_enc_write(
++int fd,
++char *buf,
++int len,
++des_key_schedule ks,
++des_cblock *iv);
++      This routines read stuff written by des_enc_read() and decrypts it.
++      I have used these routines quite a lot but I don't believe they are
++      suitable for non-blocking io.  If you are after a full
++      authentication/encryption over networks, have a look at SSL instead.
++
++unsigned long des_quad_cksum(
++des_cblock *input,
++des_cblock *output,
++long length,
++int out_count,
++des_cblock *seed);
++      This is a function from Kerberos v4 that is not anything to do with
++      DES but was needed.  It is a cksum that is quicker to generate than
++      des_cbc_cksum();  I personally would use MD5 routines now.
++=====
++Modes of DES
++Quite a bit of the following information has been taken from
++      AS 2805.5.2
++      Australian Standard
++      Electronic funds transfer - Requirements for interfaces,
++      Part 5.2: Modes of operation for an n-bit block cipher algorithm
++      Appendix A
++
++There are several different modes in which DES can be used, they are
++as follows.
++
++Electronic Codebook Mode (ECB) (des_ecb_encrypt())
++- 64 bits are enciphered at a time.
++- The order of the blocks can be rearranged without detection.
++- The same plaintext block always produces the same ciphertext block
++  (for the same key) making it vulnerable to a 'dictionary attack'.
++- An error will only affect one ciphertext block.
++
++Cipher Block Chaining Mode (CBC) (des_cbc_encrypt())
++- a multiple of 64 bits are enciphered at a time.
++- The CBC mode produces the same ciphertext whenever the same
++  plaintext is encrypted using the same key and starting variable.
++- The chaining operation makes the ciphertext blocks dependent on the
++  current and all preceding plaintext blocks and therefore blocks can not
++  be rearranged.
++- The use of different starting variables prevents the same plaintext
++  enciphering to the same ciphertext.
++- An error will affect the current and the following ciphertext blocks.
++
++Cipher Feedback Mode (CFB) (des_cfb_encrypt())
++- a number of bits (j) <= 64 are enciphered at a time.
++- The CFB mode produces the same ciphertext whenever the same
++  plaintext is encrypted using the same key and starting variable.
++- The chaining operation makes the ciphertext variables dependent on the
++  current and all preceding variables and therefore j-bit variables are
++  chained together and can not be rearranged.
++- The use of different starting variables prevents the same plaintext
++  enciphering to the same ciphertext.
++- The strength of the CFB mode depends on the size of k (maximal if
++  j == k).  In my implementation this is always the case.
++- Selection of a small value for j will require more cycles through
++  the encipherment algorithm per unit of plaintext and thus cause
++  greater processing overheads.
++- Only multiples of j bits can be enciphered.
++- An error will affect the current and the following ciphertext variables.
++
++Output Feedback Mode (OFB) (des_ofb_encrypt())
++- a number of bits (j) <= 64 are enciphered at a time.
++- The OFB mode produces the same ciphertext whenever the same
++  plaintext enciphered using the same key and starting variable.  More
++  over, in the OFB mode the same key stream is produced when the same
++  key and start variable are used.  Consequently, for security reasons
++  a specific start variable should be used only once for a given key.
++- The absence of chaining makes the OFB more vulnerable to specific attacks.
++- The use of different start variables values prevents the same
++  plaintext enciphering to the same ciphertext, by producing different
++  key streams.
++- Selection of a small value for j will require more cycles through
++  the encipherment algorithm per unit of plaintext and thus cause
++  greater processing overheads.
++- Only multiples of j bits can be enciphered.
++- OFB mode of operation does not extend ciphertext errors in the
++  resultant plaintext output.  Every bit error in the ciphertext causes
++  only one bit to be in error in the deciphered plaintext.
++- OFB mode is not self-synchronising.  If the two operation of
++  encipherment and decipherment get out of synchronism, the system needs
++  to be re-initialised.
++- Each re-initialisation should use a value of the start variable
++ different from the start variable values used before with the same
++ key.  The reason for this is that an identical bit stream would be
++ produced each time from the same parameters.  This would be
++ susceptible to a ' known plaintext' attack.
++
++Triple ECB Mode (des_ecb3_encrypt())
++- Encrypt with key1, decrypt with key2 and encrypt with key3 again.
++- As for ECB encryption but increases the key length to 168 bits.
++  There are theoretic attacks that can be used that make the effective
++  key length 112 bits, but this attack also requires 2^56 blocks of
++  memory, not very likely, even for the NSA.
++- If both keys are the same it is equivalent to encrypting once with
++  just one key.
++- If the first and last key are the same, the key length is 112 bits.
++  There are attacks that could reduce the key space to 55 bit's but it
++  requires 2^56 blocks of memory.
++- If all 3 keys are the same, this is effectively the same as normal
++  ecb mode.
++
++Triple CBC Mode (des_ede3_cbc_encrypt())
++- Encrypt with key1, decrypt with key2 and then encrypt with key3.
++- As for CBC encryption but increases the key length to 168 bits with
++  the same restrictions as for triple ecb mode.
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/des_enc.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,502 @@
++/* crypto/des/des_enc.c */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++#include "des/des_locl.h"
++
++void des_encrypt(data, ks, enc)
++DES_LONG *data;
++des_key_schedule ks;
++int enc;
++      {
++      register DES_LONG l,r,t,u;
++#ifdef DES_PTR
++      register unsigned char *des_SP=(unsigned char *)des_SPtrans;
++#endif
++#ifndef DES_UNROLL
++      register int i;
++#endif
++      register DES_LONG *s;
++
++      r=data[0];
++      l=data[1];
++
++      IP(r,l);
++      /* Things have been modified so that the initial rotate is
++       * done outside the loop.  This required the
++       * des_SPtrans values in sp.h to be rotated 1 bit to the right.
++       * One perl script later and things have a 5% speed up on a sparc2.
++       * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
++       * for pointing this out. */
++      /* clear the top bits on machines with 8byte longs */
++      /* shift left by 2 */
++      r=ROTATE(r,29)&0xffffffffL;
++      l=ROTATE(l,29)&0xffffffffL;
++
++      s=(DES_LONG *)ks;
++      /* I don't know if it is worth the effort of loop unrolling the
++       * inner loop */
++      if (enc)
++              {
++#ifdef DES_UNROLL
++              D_ENCRYPT(l,r, 0); /*  1 */
++              D_ENCRYPT(r,l, 2); /*  2 */
++              D_ENCRYPT(l,r, 4); /*  3 */
++              D_ENCRYPT(r,l, 6); /*  4 */
++              D_ENCRYPT(l,r, 8); /*  5 */
++              D_ENCRYPT(r,l,10); /*  6 */
++              D_ENCRYPT(l,r,12); /*  7 */
++              D_ENCRYPT(r,l,14); /*  8 */
++              D_ENCRYPT(l,r,16); /*  9 */
++              D_ENCRYPT(r,l,18); /*  10 */
++              D_ENCRYPT(l,r,20); /*  11 */
++              D_ENCRYPT(r,l,22); /*  12 */
++              D_ENCRYPT(l,r,24); /*  13 */
++              D_ENCRYPT(r,l,26); /*  14 */
++              D_ENCRYPT(l,r,28); /*  15 */
++              D_ENCRYPT(r,l,30); /*  16 */
++#else
++              for (i=0; i<32; i+=8)
++                      {
++                      D_ENCRYPT(l,r,i+0); /*  1 */
++                      D_ENCRYPT(r,l,i+2); /*  2 */
++                      D_ENCRYPT(l,r,i+4); /*  3 */
++                      D_ENCRYPT(r,l,i+6); /*  4 */
++                      }
++#endif
++              }
++      else
++              {
++#ifdef DES_UNROLL
++              D_ENCRYPT(l,r,30); /* 16 */
++              D_ENCRYPT(r,l,28); /* 15 */
++              D_ENCRYPT(l,r,26); /* 14 */
++              D_ENCRYPT(r,l,24); /* 13 */
++              D_ENCRYPT(l,r,22); /* 12 */
++              D_ENCRYPT(r,l,20); /* 11 */
++              D_ENCRYPT(l,r,18); /* 10 */
++              D_ENCRYPT(r,l,16); /*  9 */
++              D_ENCRYPT(l,r,14); /*  8 */
++              D_ENCRYPT(r,l,12); /*  7 */
++              D_ENCRYPT(l,r,10); /*  6 */
++              D_ENCRYPT(r,l, 8); /*  5 */
++              D_ENCRYPT(l,r, 6); /*  4 */
++              D_ENCRYPT(r,l, 4); /*  3 */
++              D_ENCRYPT(l,r, 2); /*  2 */
++              D_ENCRYPT(r,l, 0); /*  1 */
++#else
++              for (i=30; i>0; i-=8)
++                      {
++                      D_ENCRYPT(l,r,i-0); /* 16 */
++                      D_ENCRYPT(r,l,i-2); /* 15 */
++                      D_ENCRYPT(l,r,i-4); /* 14 */
++                      D_ENCRYPT(r,l,i-6); /* 13 */
++                      }
++#endif
++              }
++
++      /* rotate and clear the top bits on machines with 8byte longs */
++      l=ROTATE(l,3)&0xffffffffL;
++      r=ROTATE(r,3)&0xffffffffL;
++
++      FP(r,l);
++      data[0]=l;
++      data[1]=r;
++      l=r=t=u=0;
++      }
++
++void des_encrypt2(data, ks, enc)
++DES_LONG *data;
++des_key_schedule ks;
++int enc;
++      {
++      register DES_LONG l,r,t,u;
++#ifdef DES_PTR
++      register unsigned char *des_SP=(unsigned char *)des_SPtrans;
++#endif
++#ifndef DES_UNROLL
++      register int i;
++#endif
++      register DES_LONG *s;
++
++      r=data[0];
++      l=data[1];
++
++      /* Things have been modified so that the initial rotate is
++       * done outside the loop.  This required the
++       * des_SPtrans values in sp.h to be rotated 1 bit to the right.
++       * One perl script later and things have a 5% speed up on a sparc2.
++       * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
++       * for pointing this out. */
++      /* clear the top bits on machines with 8byte longs */
++      r=ROTATE(r,29)&0xffffffffL;
++      l=ROTATE(l,29)&0xffffffffL;
++
++      s=(DES_LONG *)ks;
++      /* I don't know if it is worth the effort of loop unrolling the
++       * inner loop */
++      if (enc)
++              {
++#ifdef DES_UNROLL
++              D_ENCRYPT(l,r, 0); /*  1 */
++              D_ENCRYPT(r,l, 2); /*  2 */
++              D_ENCRYPT(l,r, 4); /*  3 */
++              D_ENCRYPT(r,l, 6); /*  4 */
++              D_ENCRYPT(l,r, 8); /*  5 */
++              D_ENCRYPT(r,l,10); /*  6 */
++              D_ENCRYPT(l,r,12); /*  7 */
++              D_ENCRYPT(r,l,14); /*  8 */
++              D_ENCRYPT(l,r,16); /*  9 */
++              D_ENCRYPT(r,l,18); /*  10 */
++              D_ENCRYPT(l,r,20); /*  11 */
++              D_ENCRYPT(r,l,22); /*  12 */
++              D_ENCRYPT(l,r,24); /*  13 */
++              D_ENCRYPT(r,l,26); /*  14 */
++              D_ENCRYPT(l,r,28); /*  15 */
++              D_ENCRYPT(r,l,30); /*  16 */
++#else
++              for (i=0; i<32; i+=8)
++                      {
++                      D_ENCRYPT(l,r,i+0); /*  1 */
++                      D_ENCRYPT(r,l,i+2); /*  2 */
++                      D_ENCRYPT(l,r,i+4); /*  3 */
++                      D_ENCRYPT(r,l,i+6); /*  4 */
++                      }
++#endif
++              }
++      else
++              {
++#ifdef DES_UNROLL
++              D_ENCRYPT(l,r,30); /* 16 */
++              D_ENCRYPT(r,l,28); /* 15 */
++              D_ENCRYPT(l,r,26); /* 14 */
++              D_ENCRYPT(r,l,24); /* 13 */
++              D_ENCRYPT(l,r,22); /* 12 */
++              D_ENCRYPT(r,l,20); /* 11 */
++              D_ENCRYPT(l,r,18); /* 10 */
++              D_ENCRYPT(r,l,16); /*  9 */
++              D_ENCRYPT(l,r,14); /*  8 */
++              D_ENCRYPT(r,l,12); /*  7 */
++              D_ENCRYPT(l,r,10); /*  6 */
++              D_ENCRYPT(r,l, 8); /*  5 */
++              D_ENCRYPT(l,r, 6); /*  4 */
++              D_ENCRYPT(r,l, 4); /*  3 */
++              D_ENCRYPT(l,r, 2); /*  2 */
++              D_ENCRYPT(r,l, 0); /*  1 */
++#else
++              for (i=30; i>0; i-=8)
++                      {
++                      D_ENCRYPT(l,r,i-0); /* 16 */
++                      D_ENCRYPT(r,l,i-2); /* 15 */
++                      D_ENCRYPT(l,r,i-4); /* 14 */
++                      D_ENCRYPT(r,l,i-6); /* 13 */
++                      }
++#endif
++              }
++      /* rotate and clear the top bits on machines with 8byte longs */
++      data[0]=ROTATE(l,3)&0xffffffffL;
++      data[1]=ROTATE(r,3)&0xffffffffL;
++      l=r=t=u=0;
++      }
++
++void des_encrypt3(data,ks1,ks2,ks3)
++DES_LONG *data;
++des_key_schedule ks1;
++des_key_schedule ks2;
++des_key_schedule ks3;
++      {
++      register DES_LONG l,r;
++
++      l=data[0];
++      r=data[1];
++      IP(l,r);
++      data[0]=l;
++      data[1]=r;
++      des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT);
++      des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT);
++      des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT);
++      l=data[0];
++      r=data[1];
++      FP(r,l);
++      data[0]=l;
++      data[1]=r;
++      }
++
++void des_decrypt3(data,ks1,ks2,ks3)
++DES_LONG *data;
++des_key_schedule ks1;
++des_key_schedule ks2;
++des_key_schedule ks3;
++      {
++      register DES_LONG l,r;
++
++      l=data[0];
++      r=data[1];
++      IP(l,r);
++      data[0]=l;
++      data[1]=r;
++      des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT);
++      des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT);
++      des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT);
++      l=data[0];
++      r=data[1];
++      FP(r,l);
++      data[0]=l;
++      data[1]=r;
++      }
++
++#ifndef DES_DEFAULT_OPTIONS
++
++void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
++des_cblock (*input);
++des_cblock (*output);
++long length;
++des_key_schedule schedule;
++des_cblock (*ivec);
++int enc;
++      {
++      register DES_LONG tin0,tin1;
++      register DES_LONG tout0,tout1,xor0,xor1;
++      register unsigned char *in,*out;
++      register long l=length;
++      DES_LONG tin[2];
++      unsigned char *iv;
++
++      in=(unsigned char *)input;
++      out=(unsigned char *)output;
++      iv=(unsigned char *)ivec;
++
++      if (enc)
++              {
++              c2l(iv,tout0);
++              c2l(iv,tout1);
++              for (l-=8; l>=0; l-=8)
++                      {
++                      c2l(in,tin0);
++                      c2l(in,tin1);
++                      tin0^=tout0; tin[0]=tin0;
++                      tin1^=tout1; tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
++                      tout0=tin[0]; l2c(tout0,out);
++                      tout1=tin[1]; l2c(tout1,out);
++                      }
++              if (l != -8)
++                      {
++                      c2ln(in,tin0,tin1,l+8);
++                      tin0^=tout0; tin[0]=tin0;
++                      tin1^=tout1; tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
++                      tout0=tin[0]; l2c(tout0,out);
++                      tout1=tin[1]; l2c(tout1,out);
++                      }
++              iv=(unsigned char *)ivec;
++              l2c(tout0,iv);
++              l2c(tout1,iv);
++              }
++      else
++              {
++              c2l(iv,xor0);
++              c2l(iv,xor1);
++              for (l-=8; l>=0; l-=8)
++                      {
++                      c2l(in,tin0); tin[0]=tin0;
++                      c2l(in,tin1); tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
++                      tout0=tin[0]^xor0;
++                      tout1=tin[1]^xor1;
++                      l2c(tout0,out);
++                      l2c(tout1,out);
++                      xor0=tin0;
++                      xor1=tin1;
++                      }
++              if (l != -8)
++                      {
++                      c2l(in,tin0); tin[0]=tin0;
++                      c2l(in,tin1); tin[1]=tin1;
++                      des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT);
++                      tout0=tin[0]^xor0;
++                      tout1=tin[1]^xor1;
++                      l2cn(tout0,tout1,out,l+8);
++                      xor0=tin0;
++                      xor1=tin1;
++                      }
++
++              iv=(unsigned char *)ivec;
++              l2c(xor0,iv);
++              l2c(xor1,iv);
++              }
++      tin0=tin1=tout0=tout1=xor0=xor1=0;
++      tin[0]=tin[1]=0;
++      }
++
++void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc)
++des_cblock (*input);
++des_cblock (*output);
++long length;
++des_key_schedule ks1;
++des_key_schedule ks2;
++des_key_schedule ks3;
++des_cblock (*ivec);
++int enc;
++      {
++      register DES_LONG tin0,tin1;
++      register DES_LONG tout0,tout1,xor0,xor1;
++      register unsigned char *in,*out;
++      register long l=length;
++      DES_LONG tin[2];
++      unsigned char *iv;
++
++      in=(unsigned char *)input;
++      out=(unsigned char *)output;
++      iv=(unsigned char *)ivec;
++
++      if (enc)
++              {
++              c2l(iv,tout0);
++              c2l(iv,tout1);
++              for (l-=8; l>=0; l-=8)
++                      {
++                      c2l(in,tin0);
++                      c2l(in,tin1);
++                      tin0^=tout0;
++                      tin1^=tout1;
++
++                      tin[0]=tin0;
++                      tin[1]=tin1;
++                      des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3);
++                      tout0=tin[0];
++                      tout1=tin[1];
++
++                      l2c(tout0,out);
++                      l2c(tout1,out);
++                      }
++              if (l != -8)
++                      {
++                      c2ln(in,tin0,tin1,l+8);
++                      tin0^=tout0;
++                      tin1^=tout1;
++
++                      tin[0]=tin0;
++                      tin[1]=tin1;
++                      des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3);
++                      tout0=tin[0];
++                      tout1=tin[1];
++
++                      l2c(tout0,out);
++                      l2c(tout1,out);
++                      }
++              iv=(unsigned char *)ivec;
++              l2c(tout0,iv);
++              l2c(tout1,iv);
++              }
++      else
++              {
++              register DES_LONG t0,t1;
++
++              c2l(iv,xor0);
++              c2l(iv,xor1);
++              for (l-=8; l>=0; l-=8)
++                      {
++                      c2l(in,tin0);
++                      c2l(in,tin1);
++
++                      t0=tin0;
++                      t1=tin1;
++
++                      tin[0]=tin0;
++                      tin[1]=tin1;
++                      des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3);
++                      tout0=tin[0];
++                      tout1=tin[1];
++
++                      tout0^=xor0;
++                      tout1^=xor1;
++                      l2c(tout0,out);
++                      l2c(tout1,out);
++                      xor0=t0;
++                      xor1=t1;
++                      }
++              if (l != -8)
++                      {
++                      c2l(in,tin0);
++                      c2l(in,tin1);
++                      
++                      t0=tin0;
++                      t1=tin1;
++
++                      tin[0]=tin0;
++                      tin[1]=tin1;
++                      des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3);
++                      tout0=tin[0];
++                      tout1=tin[1];
++              
++                      tout0^=xor0;
++                      tout1^=xor1;
++                      l2cn(tout0,tout1,out,l+8);
++                      xor0=t0;
++                      xor1=t1;
++                      }
++
++              iv=(unsigned char *)ivec;
++              l2c(xor0,iv);
++              l2c(xor1,iv);
++              }
++      tin0=tin1=tout0=tout1=xor0=xor1=0;
++      tin[0]=tin[1]=0;
++      }
++
++#endif /* DES_DEFAULT_OPTIONS */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/des_opts.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,620 @@
++/* crypto/des/des_opts.c */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++/* define PART1, PART2, PART3 or PART4 to build only with a few of the options.
++ * This is for machines with 64k code segment size restrictions. */
++
++#ifndef MSDOS
++#define TIMES
++#endif
++
++#include <stdio.h>
++#ifndef MSDOS
++#include <unistd.h>
++#else
++#include <io.h>
++extern void exit();
++#endif
++#include <signal.h>
++#ifndef VMS
++#ifndef _IRIX
++#include <time.h>
++#endif
++#ifdef TIMES
++#include <sys/types.h>
++#include <sys/times.h>
++#endif
++#else /* VMS */
++#include <types.h>
++struct tms {
++      time_t tms_utime;
++      time_t tms_stime;
++      time_t tms_uchild;      /* I dunno...  */
++      time_t tms_uchildsys;   /* so these names are a guess :-) */
++      }
++#endif
++#ifndef TIMES
++#include <sys/timeb.h>
++#endif
++
++#ifdef sun
++#include <limits.h>
++#include <sys/param.h>
++#endif
++
++#include "des/des_locl.h"
++#include "des/spr.h"
++
++#define DES_DEFAULT_OPTIONS
++
++#if !defined(PART1) && !defined(PART2) && !defined(PART3) && !defined(PART4)
++#define PART1
++#define PART2
++#define PART3
++#define PART4
++#endif
++
++#ifdef PART1
++
++#undef DES_UNROLL
++#undef DES_RISC1
++#undef DES_RISC2
++#undef DES_PTR
++#undef D_ENCRYPT
++#define des_encrypt  des_encrypt_u4_cisc_idx
++#define des_encrypt2 des_encrypt2_u4_cisc_idx
++#define des_encrypt3 des_encrypt3_u4_cisc_idx
++#define des_decrypt3 des_decrypt3_u4_cisc_idx
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#define DES_UNROLL
++#undef DES_RISC1
++#undef DES_RISC2
++#undef DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u16_cisc_idx
++#define des_encrypt2 des_encrypt2_u16_cisc_idx
++#define des_encrypt3 des_encrypt3_u16_cisc_idx
++#define des_decrypt3 des_decrypt3_u16_cisc_idx
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#undef DES_UNROLL
++#define DES_RISC1
++#undef DES_RISC2
++#undef DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u4_risc1_idx
++#define des_encrypt2 des_encrypt2_u4_risc1_idx
++#define des_encrypt3 des_encrypt3_u4_risc1_idx
++#define des_decrypt3 des_decrypt3_u4_risc1_idx
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#endif
++
++#ifdef PART2
++
++#undef DES_UNROLL
++#undef DES_RISC1
++#define DES_RISC2
++#undef DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u4_risc2_idx
++#define des_encrypt2 des_encrypt2_u4_risc2_idx
++#define des_encrypt3 des_encrypt3_u4_risc2_idx
++#define des_decrypt3 des_decrypt3_u4_risc2_idx
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#define DES_UNROLL
++#define DES_RISC1
++#undef DES_RISC2
++#undef DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u16_risc1_idx
++#define des_encrypt2 des_encrypt2_u16_risc1_idx
++#define des_encrypt3 des_encrypt3_u16_risc1_idx
++#define des_decrypt3 des_decrypt3_u16_risc1_idx
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#define DES_UNROLL
++#undef DES_RISC1
++#define DES_RISC2
++#undef DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u16_risc2_idx
++#define des_encrypt2 des_encrypt2_u16_risc2_idx
++#define des_encrypt3 des_encrypt3_u16_risc2_idx
++#define des_decrypt3 des_decrypt3_u16_risc2_idx
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#endif
++
++#ifdef PART3
++
++#undef DES_UNROLL
++#undef DES_RISC1
++#undef DES_RISC2
++#define DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u4_cisc_ptr
++#define des_encrypt2 des_encrypt2_u4_cisc_ptr
++#define des_encrypt3 des_encrypt3_u4_cisc_ptr
++#define des_decrypt3 des_decrypt3_u4_cisc_ptr
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#define DES_UNROLL
++#undef DES_RISC1
++#undef DES_RISC2
++#define DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u16_cisc_ptr
++#define des_encrypt2 des_encrypt2_u16_cisc_ptr
++#define des_encrypt3 des_encrypt3_u16_cisc_ptr
++#define des_decrypt3 des_decrypt3_u16_cisc_ptr
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#undef DES_UNROLL
++#define DES_RISC1
++#undef DES_RISC2
++#define DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u4_risc1_ptr
++#define des_encrypt2 des_encrypt2_u4_risc1_ptr
++#define des_encrypt3 des_encrypt3_u4_risc1_ptr
++#define des_decrypt3 des_decrypt3_u4_risc1_ptr
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#endif
++
++#ifdef PART4
++
++#undef DES_UNROLL
++#undef DES_RISC1
++#define DES_RISC2
++#define DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u4_risc2_ptr
++#define des_encrypt2 des_encrypt2_u4_risc2_ptr
++#define des_encrypt3 des_encrypt3_u4_risc2_ptr
++#define des_decrypt3 des_decrypt3_u4_risc2_ptr
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#define DES_UNROLL
++#define DES_RISC1
++#undef DES_RISC2
++#define DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u16_risc1_ptr
++#define des_encrypt2 des_encrypt2_u16_risc1_ptr
++#define des_encrypt3 des_encrypt3_u16_risc1_ptr
++#define des_decrypt3 des_decrypt3_u16_risc1_ptr
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#define DES_UNROLL
++#undef DES_RISC1
++#define DES_RISC2
++#define DES_PTR
++#undef D_ENCRYPT
++#undef des_encrypt
++#undef des_encrypt2
++#undef des_encrypt3
++#undef des_decrypt3
++#define des_encrypt  des_encrypt_u16_risc2_ptr
++#define des_encrypt2 des_encrypt2_u16_risc2_ptr
++#define des_encrypt3 des_encrypt3_u16_risc2_ptr
++#define des_decrypt3 des_decrypt3_u16_risc2_ptr
++#undef HEADER_DES_LOCL_H
++#include "des_enc.c"
++
++#endif
++
++/* The following if from times(3) man page.  It may need to be changed */
++#ifndef HZ
++# ifndef CLK_TCK
++#  ifndef _BSD_CLK_TCK_ /* FreeBSD fix */
++#   ifndef VMS
++#    define HZ        100.0
++#   else /* VMS */
++#    define HZ        100.0
++#   endif
++#  else /* _BSD_CLK_TCK_ */
++#   define HZ ((double)_BSD_CLK_TCK_)
++#  endif
++# else /* CLK_TCK */
++#  define HZ ((double)CLK_TCK)
++# endif
++#endif
++
++#define BUFSIZE       ((long)1024)
++long run=0;
++
++#ifndef NOPROTO
++double Time_F(int s);
++#else
++double Time_F();
++#endif
++
++#ifdef SIGALRM
++#if defined(__STDC__) || defined(sgi)
++#define SIGRETTYPE void
++#else
++#define SIGRETTYPE int
++#endif
++
++#ifndef NOPROTO
++SIGRETTYPE sig_done(int sig);
++#else
++SIGRETTYPE sig_done();
++#endif
++
++SIGRETTYPE sig_done(sig)
++int sig;
++      {
++      signal(SIGALRM,sig_done);
++      run=0;
++#ifdef LINT
++      sig=sig;
++#endif
++      }
++#endif
++
++#define START 0
++#define STOP  1
++
++double Time_F(s)
++int s;
++      {
++      double ret;
++#ifdef TIMES
++      static struct tms tstart,tend;
++
++      if (s == START)
++              {
++              times(&tstart);
++              return(0);
++              }
++      else
++              {
++              times(&tend);
++              ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ;
++              return((ret == 0.0)?1e-6:ret);
++              }
++#else /* !times() */
++      static struct timeb tstart,tend;
++      long i;
++
++      if (s == START)
++              {
++              ftime(&tstart);
++              return(0);
++              }
++      else
++              {
++              ftime(&tend);
++              i=(long)tend.millitm-(long)tstart.millitm;
++              ret=((double)(tend.time-tstart.time))+((double)i)/1000.0;
++              return((ret == 0.0)?1e-6:ret);
++              }
++#endif
++      }
++
++#ifdef SIGALRM
++#define print_name(name) fprintf(stderr,"Doing %s's for 10 seconds\n",name); alarm(10);
++#else
++#define print_name(name) fprintf(stderr,"Doing %s %ld times\n",name,cb);
++#endif
++      
++#define time_it(func,name,index) \
++      print_name(name); \
++      Time_F(START); \
++      for (count=0,run=1; COND(cb); count++) \
++              { \
++              unsigned long d[2]; \
++              func(d,&(sch[0]),DES_ENCRYPT); \
++              } \
++      tm[index]=Time_F(STOP); \
++      fprintf(stderr,"%ld %s's in %.2f second\n",count,name,tm[index]); \
++      tm[index]=((double)COUNT(cb))/tm[index];
++
++#define print_it(name,index) \
++      fprintf(stderr,"%s bytes per sec = %12.2f (%5.1fuS)\n",name, \
++              tm[index]*8,1.0e6/tm[index]);
++
++int main(argc,argv)
++int argc;
++char **argv;
++      {
++      long count;
++      static unsigned char buf[BUFSIZE];
++      static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0};
++      static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
++      static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
++      des_key_schedule sch,sch2,sch3;
++      double d,tm[16],max=0;
++      int rank[16];
++      char *str[16];
++      int max_idx=0,i,num=0,j;
++#ifndef SIGALARM
++      long ca,cb,cc,cd,ce;
++#endif
++
++      for (i=0; i<12; i++)
++              {
++              tm[i]=0.0;
++              rank[i]=0;
++              }
++
++#ifndef TIMES
++      fprintf(stderr,"To get the most acurate results, try to run this\n");
++      fprintf(stderr,"program when this computer is idle.\n");
++#endif
++
++      des_set_key((C_Block *)key,sch);
++      des_set_key((C_Block *)key2,sch2);
++      des_set_key((C_Block *)key3,sch3);
++
++#ifndef SIGALRM
++      fprintf(stderr,"First we calculate the approximate speed ...\n");
++      des_set_key((C_Block *)key,sch);
++      count=10;
++      do      {
++              long i;
++              unsigned long data[2];
++
++              count*=2;
++              Time_F(START);
++              for (i=count; i; i--)
++                      des_encrypt(data,&(sch[0]),DES_ENCRYPT);
++              d=Time_F(STOP);
++              } while (d < 3.0);
++      ca=count;
++      cb=count*3;
++      cc=count*3*8/BUFSIZE+1;
++      cd=count*8/BUFSIZE+1;
++
++      ce=count/20+1;
++#define COND(d) (count != (d))
++#define COUNT(d) (d)
++#else
++#define COND(c) (run)
++#define COUNT(d) (count)
++        signal(SIGALRM,sig_done);
++        alarm(10);
++#endif
++
++#ifdef PART1
++      time_it(des_encrypt_u4_cisc_idx,  "des_encrypt_u4_cisc_idx  ", 0);
++      time_it(des_encrypt_u16_cisc_idx, "des_encrypt_u16_cisc_idx ", 1);
++      time_it(des_encrypt_u4_risc1_idx, "des_encrypt_u4_risc1_idx ", 2);
++      num+=3;
++#endif
++#ifdef PART2
++      time_it(des_encrypt_u16_risc1_idx,"des_encrypt_u16_risc1_idx", 3);
++      time_it(des_encrypt_u4_risc2_idx, "des_encrypt_u4_risc2_idx ", 4);
++      time_it(des_encrypt_u16_risc2_idx,"des_encrypt_u16_risc2_idx", 5);
++      num+=3;
++#endif
++#ifdef PART3
++      time_it(des_encrypt_u4_cisc_ptr,  "des_encrypt_u4_cisc_ptr  ", 6);
++      time_it(des_encrypt_u16_cisc_ptr, "des_encrypt_u16_cisc_ptr ", 7);
++      time_it(des_encrypt_u4_risc1_ptr, "des_encrypt_u4_risc1_ptr ", 8);
++      num+=3;
++#endif
++#ifdef PART4
++      time_it(des_encrypt_u16_risc1_ptr,"des_encrypt_u16_risc1_ptr", 9);
++      time_it(des_encrypt_u4_risc2_ptr, "des_encrypt_u4_risc2_ptr ",10);
++      time_it(des_encrypt_u16_risc2_ptr,"des_encrypt_u16_risc2_ptr",11);
++      num+=3;
++#endif
++
++#ifdef PART1
++      str[0]=" 4  c i";
++      print_it("des_encrypt_u4_cisc_idx  ",0);
++      max=tm[0];
++      max_idx=0;
++      str[1]="16  c i";
++      print_it("des_encrypt_u16_cisc_idx ",1);
++      if (max < tm[1]) { max=tm[1]; max_idx=1; }
++      str[2]=" 4 r1 i";
++      print_it("des_encrypt_u4_risc1_idx ",2);
++      if (max < tm[2]) { max=tm[2]; max_idx=2; }
++#endif
++#ifdef PART2
++      str[3]="16 r1 i";
++      print_it("des_encrypt_u16_risc1_idx",3);
++      if (max < tm[3]) { max=tm[3]; max_idx=3; }
++      str[4]=" 4 r2 i";
++      print_it("des_encrypt_u4_risc2_idx ",4);
++      if (max < tm[4]) { max=tm[4]; max_idx=4; }
++      str[5]="16 r2 i";
++      print_it("des_encrypt_u16_risc2_idx",5);
++      if (max < tm[5]) { max=tm[5]; max_idx=5; }
++#endif
++#ifdef PART3
++      str[6]=" 4  c p";
++      print_it("des_encrypt_u4_cisc_ptr  ",6);
++      if (max < tm[6]) { max=tm[6]; max_idx=6; }
++      str[7]="16  c p";
++      print_it("des_encrypt_u16_cisc_ptr ",7);
++      if (max < tm[7]) { max=tm[7]; max_idx=7; }
++      str[8]=" 4 r1 p";
++      print_it("des_encrypt_u4_risc1_ptr ",8);
++      if (max < tm[8]) { max=tm[8]; max_idx=8; }
++#endif
++#ifdef PART4
++      str[9]="16 r1 p";
++      print_it("des_encrypt_u16_risc1_ptr",9);
++      if (max < tm[9]) { max=tm[9]; max_idx=9; }
++      str[10]=" 4 r2 p";
++      print_it("des_encrypt_u4_risc2_ptr ",10);
++      if (max < tm[10]) { max=tm[10]; max_idx=10; }
++      str[11]="16 r2 p";
++      print_it("des_encrypt_u16_risc2_ptr",11);
++      if (max < tm[11]) { max=tm[11]; max_idx=11; }
++#endif
++      printf("options    des ecb/s\n");
++      printf("%s %12.2f 100.0%%\n",str[max_idx],tm[max_idx]);
++      d=tm[max_idx];
++      tm[max_idx]= -2.0;
++      max= -1.0;
++      for (;;)
++              {
++              for (i=0; i<12; i++)
++                      {
++                      if (max < tm[i]) { max=tm[i]; j=i; }
++                      }
++              if (max < 0.0) break;
++              printf("%s %12.2f  %4.1f%%\n",str[j],tm[j],tm[j]/d*100.0);
++              tm[j]= -2.0;
++              max= -1.0;
++              }
++
++      switch (max_idx)
++              {
++      case 0:
++              printf("-DDES_DEFAULT_OPTIONS\n");
++              break;
++      case 1:
++              printf("-DDES_UNROLL\n");
++              break;
++      case 2:
++              printf("-DDES_RISC1\n");
++              break;
++      case 3:
++              printf("-DDES_UNROLL -DDES_RISC1\n");
++              break;
++      case 4:
++              printf("-DDES_RISC2\n");
++              break;
++      case 5:
++              printf("-DDES_UNROLL -DDES_RISC2\n");
++              break;
++      case 6:
++              printf("-DDES_PTR\n");
++              break;
++      case 7:
++              printf("-DDES_UNROLL -DDES_PTR\n");
++              break;
++      case 8:
++              printf("-DDES_RISC1 -DDES_PTR\n");
++              break;
++      case 9:
++              printf("-DDES_UNROLL -DDES_RISC1 -DDES_PTR\n");
++              break;
++      case 10:
++              printf("-DDES_RISC2 -DDES_PTR\n");
++              break;
++      case 11:
++              printf("-DDES_UNROLL -DDES_RISC2 -DDES_PTR\n");
++              break;
++              }
++      exit(0);
++#if defined(LINT) || defined(MSDOS)
++      return(0);
++#endif
++      }
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/dx86unix.S     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,3160 @@
++/* 
++ * This file was originally generated by Michael Richardson <mcr@freeswan.org>
++ * via the perl scripts found in the ASM subdir. It remains copyright of
++ * Eric Young, see the file COPYRIGHT.
++ *
++ * This was last done on October 9, 2002.
++ *
++ * While this file does not need to go through cpp, we pass it through
++ * CPP by naming it dx86unix.S instead of dx86unix.s because there is
++ * a bug in Rules.make for .s builds - specifically it references EXTRA_CFLAGS
++ * which may contain stuff that AS doesn't understand instead of
++ * referencing EXTRA_AFLAGS.
++ */    
++
++      .file   "dx86unix.S"
++      .version        "01.01"
++.text
++      .align 16 
++.globl des_encrypt
++      .type    des_encrypt , @function  
++des_encrypt:
++      pushl   %esi
++      pushl   %edi
++
++       
++      movl    12(%esp),       %esi
++      xorl    %ecx,           %ecx
++      pushl   %ebx
++      pushl   %ebp
++      movl    (%esi),         %eax
++      movl    28(%esp),       %ebx
++      movl    4(%esi),        %edi
++
++       
++      roll    $4,             %eax
++      movl    %eax,           %esi
++      xorl    %edi,           %eax
++      andl    $0xf0f0f0f0,    %eax
++      xorl    %eax,           %esi
++      xorl    %eax,           %edi
++
++      roll    $20,            %edi
++      movl    %edi,           %eax
++      xorl    %esi,           %edi
++      andl    $0xfff0000f,    %edi
++      xorl    %edi,           %eax
++      xorl    %edi,           %esi
++
++      roll    $14,            %eax
++      movl    %eax,           %edi
++      xorl    %esi,           %eax
++      andl    $0x33333333,    %eax
++      xorl    %eax,           %edi
++      xorl    %eax,           %esi
++
++      roll    $22,            %esi
++      movl    %esi,           %eax
++      xorl    %edi,           %esi
++      andl    $0x03fc03fc,    %esi
++      xorl    %esi,           %eax
++      xorl    %esi,           %edi
++
++      roll    $9,             %eax
++      movl    %eax,           %esi
++      xorl    %edi,           %eax
++      andl    $0xaaaaaaaa,    %eax
++      xorl    %eax,           %esi
++      xorl    %eax,           %edi
++
++.byte 209
++.byte 199              
++      movl    24(%esp),       %ebp
++      cmpl    $0,             %ebx
++      je      .L000start_decrypt
++
++       
++      movl    (%ebp),         %eax
++      xorl    %ebx,           %ebx
++      movl    4(%ebp),        %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    8(%ebp),        %eax
++      xorl    %ebx,           %ebx
++      movl    12(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    16(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    20(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    24(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    28(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    32(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    36(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    40(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    44(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    48(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    52(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    56(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    60(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    64(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    68(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    72(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    76(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    80(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    84(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    88(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    92(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    96(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    100(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    104(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    108(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    112(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    116(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    120(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    124(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++      jmp     .L001end
++.L000start_decrypt:
++
++       
++      movl    120(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    124(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    112(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    116(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    104(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    108(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    96(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    100(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    88(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    92(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    80(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    84(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    72(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    76(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    64(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    68(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    56(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    60(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    48(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    52(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    40(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    44(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    32(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    36(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    24(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    28(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    16(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    20(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    8(%ebp),        %eax
++      xorl    %ebx,           %ebx
++      movl    12(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    (%ebp),         %eax
++      xorl    %ebx,           %ebx
++      movl    4(%ebp),        %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++.L001end:
++
++       
++      movl    20(%esp),       %edx
++.byte 209
++.byte 206              
++      movl    %edi,           %eax
++      xorl    %esi,           %edi
++      andl    $0xaaaaaaaa,    %edi
++      xorl    %edi,           %eax
++      xorl    %edi,           %esi
++
++      roll    $23,            %eax
++      movl    %eax,           %edi
++      xorl    %esi,           %eax
++      andl    $0x03fc03fc,    %eax
++      xorl    %eax,           %edi
++      xorl    %eax,           %esi
++
++      roll    $10,            %edi
++      movl    %edi,           %eax
++      xorl    %esi,           %edi
++      andl    $0x33333333,    %edi
++      xorl    %edi,           %eax
++      xorl    %edi,           %esi
++
++      roll    $18,            %esi
++      movl    %esi,           %edi
++      xorl    %eax,           %esi
++      andl    $0xfff0000f,    %esi
++      xorl    %esi,           %edi
++      xorl    %esi,           %eax
++
++      roll    $12,            %edi
++      movl    %edi,           %esi
++      xorl    %eax,           %edi
++      andl    $0xf0f0f0f0,    %edi
++      xorl    %edi,           %esi
++      xorl    %edi,           %eax
++
++      rorl    $4,             %eax
++      movl    %eax,           (%edx)
++      movl    %esi,           4(%edx)
++      popl    %ebp
++      popl    %ebx
++      popl    %edi
++      popl    %esi
++      ret
++.des_encrypt_end:
++      .size    des_encrypt , .des_encrypt_end-des_encrypt  
++.ident        "desasm.pl"
++.text
++      .align 16 
++.globl des_encrypt2
++      .type    des_encrypt2 , @function  
++des_encrypt2:
++      pushl   %esi
++      pushl   %edi
++
++       
++      movl    12(%esp),       %eax
++      xorl    %ecx,           %ecx
++      pushl   %ebx
++      pushl   %ebp
++      movl    (%eax),         %esi
++      movl    28(%esp),       %ebx
++      roll    $3,             %esi
++      movl    4(%eax),        %edi
++      roll    $3,             %edi
++      movl    24(%esp),       %ebp
++      cmpl    $0,             %ebx
++      je      .L002start_decrypt
++
++       
++      movl    (%ebp),         %eax
++      xorl    %ebx,           %ebx
++      movl    4(%ebp),        %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    8(%ebp),        %eax
++      xorl    %ebx,           %ebx
++      movl    12(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    16(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    20(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    24(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    28(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    32(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    36(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    40(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    44(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    48(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    52(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    56(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    60(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    64(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    68(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    72(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    76(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    80(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    84(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    88(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    92(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    96(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    100(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    104(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    108(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    112(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    116(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    120(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    124(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++      jmp     .L003end
++.L002start_decrypt:
++
++       
++      movl    120(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    124(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    112(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    116(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    104(%ebp),      %eax
++      xorl    %ebx,           %ebx
++      movl    108(%ebp),      %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    96(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    100(%ebp),      %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    88(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    92(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    80(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    84(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    72(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    76(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    64(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    68(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    56(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    60(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    48(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    52(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    40(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    44(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    32(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    36(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    24(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    28(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    16(%ebp),       %eax
++      xorl    %ebx,           %ebx
++      movl    20(%ebp),       %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++
++       
++      movl    8(%ebp),        %eax
++      xorl    %ebx,           %ebx
++      movl    12(%ebp),       %edx
++      xorl    %esi,           %eax
++      xorl    %esi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %edi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %edi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %edi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %edi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %edi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %edi
++
++       
++      movl    (%ebp),         %eax
++      xorl    %ebx,           %ebx
++      movl    4(%ebp),        %edx
++      xorl    %edi,           %eax
++      xorl    %edi,           %edx
++      andl    $0xfcfcfcfc,    %eax
++      andl    $0xcfcfcfcf,    %edx
++      movb    %al,            %bl
++      movb    %ah,            %cl
++      rorl    $4,             %edx
++      movl          des_SPtrans(%ebx),%ebp
++      movb    %dl,            %bl
++      xorl    %ebp,           %esi
++      movl    0x200+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movb    %dh,            %cl
++      shrl    $16,            %eax
++      movl    0x100+des_SPtrans(%ebx),%ebp
++      xorl    %ebp,           %esi
++      movb    %ah,            %bl
++      shrl    $16,            %edx
++      movl    0x300+des_SPtrans(%ecx),%ebp
++      xorl    %ebp,           %esi
++      movl    24(%esp),       %ebp
++      movb    %dh,            %cl
++      andl    $0xff,          %eax
++      andl    $0xff,          %edx
++      movl    0x600+des_SPtrans(%ebx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x700+des_SPtrans(%ecx),%ebx
++      xorl    %ebx,           %esi
++      movl    0x400+des_SPtrans(%eax),%ebx
++      xorl    %ebx,           %esi
++      movl    0x500+des_SPtrans(%edx),%ebx
++      xorl    %ebx,           %esi
++.L003end:
++
++       
++      rorl    $3,             %edi
++      movl    20(%esp),       %eax
++      rorl    $3,             %esi
++      movl    %edi,           (%eax)
++      movl    %esi,           4(%eax)
++      popl    %ebp
++      popl    %ebx
++      popl    %edi
++      popl    %esi
++      ret
++.des_encrypt2_end:
++      .size    des_encrypt2 , .des_encrypt2_end-des_encrypt2  
++.ident        "desasm.pl"
++.text
++      .align 16 
++.globl des_encrypt3
++      .type    des_encrypt3 , @function  
++des_encrypt3:
++      pushl   %ebx
++      movl    8(%esp),        %ebx
++      pushl   %ebp
++      pushl   %esi
++      pushl   %edi
++
++       
++      movl    (%ebx),         %edi
++      movl    4(%ebx),        %esi
++      subl    $12,            %esp
++
++       
++      roll    $4,             %edi
++      movl    %edi,           %edx
++      xorl    %esi,           %edi
++      andl    $0xf0f0f0f0,    %edi
++      xorl    %edi,           %edx
++      xorl    %edi,           %esi
++
++      roll    $20,            %esi
++      movl    %esi,           %edi
++      xorl    %edx,           %esi
++      andl    $0xfff0000f,    %esi
++      xorl    %esi,           %edi
++      xorl    %esi,           %edx
++
++      roll    $14,            %edi
++      movl    %edi,           %esi
++      xorl    %edx,           %edi
++      andl    $0x33333333,    %edi
++      xorl    %edi,           %esi
++      xorl    %edi,           %edx
++
++      roll    $22,            %edx
++      movl    %edx,           %edi
++      xorl    %esi,           %edx
++      andl    $0x03fc03fc,    %edx
++      xorl    %edx,           %edi
++      xorl    %edx,           %esi
++
++      roll    $9,             %edi
++      movl    %edi,           %edx
++      xorl    %esi,           %edi
++      andl    $0xaaaaaaaa,    %edi
++      xorl    %edi,           %edx
++      xorl    %edi,           %esi
++
++      rorl    $3,             %edx
++      rorl    $2,             %esi
++      movl    %esi,           4(%ebx)
++      movl    36(%esp),       %eax
++      movl    %edx,           (%ebx)
++      movl    40(%esp),       %edi
++      movl    44(%esp),       %esi
++      movl    $1,             8(%esp)
++      movl    %eax,           4(%esp)
++      movl    %ebx,           (%esp)
++      call    des_encrypt2
++      movl    $0,             8(%esp)
++      movl    %edi,           4(%esp)
++      movl    %ebx,           (%esp)
++      call    des_encrypt2
++      movl    $1,             8(%esp)
++      movl    %esi,           4(%esp)
++      movl    %ebx,           (%esp)
++      call    des_encrypt2
++      addl    $12,            %esp
++      movl    (%ebx),         %edi
++      movl    4(%ebx),        %esi
++
++       
++      roll    $2,             %esi
++      roll    $3,             %edi
++      movl    %edi,           %eax
++      xorl    %esi,           %edi
++      andl    $0xaaaaaaaa,    %edi
++      xorl    %edi,           %eax
++      xorl    %edi,           %esi
++
++      roll    $23,            %eax
++      movl    %eax,           %edi
++      xorl    %esi,           %eax
++      andl    $0x03fc03fc,    %eax
++      xorl    %eax,           %edi
++      xorl    %eax,           %esi
++
++      roll    $10,            %edi
++      movl    %edi,           %eax
++      xorl    %esi,           %edi
++      andl    $0x33333333,    %edi
++      xorl    %edi,           %eax
++      xorl    %edi,           %esi
++
++      roll    $18,            %esi
++      movl    %esi,           %edi
++      xorl    %eax,           %esi
++      andl    $0xfff0000f,    %esi
++      xorl    %esi,           %edi
++      xorl    %esi,           %eax
++
++      roll    $12,            %edi
++      movl    %edi,           %esi
++      xorl    %eax,           %edi
++      andl    $0xf0f0f0f0,    %edi
++      xorl    %edi,           %esi
++      xorl    %edi,           %eax
++
++      rorl    $4,             %eax
++      movl    %eax,           (%ebx)
++      movl    %esi,           4(%ebx)
++      popl    %edi
++      popl    %esi
++      popl    %ebp
++      popl    %ebx
++      ret
++.des_encrypt3_end:
++      .size    des_encrypt3 , .des_encrypt3_end-des_encrypt3  
++.ident        "desasm.pl"
++.text
++      .align 16 
++.globl des_decrypt3
++      .type    des_decrypt3 , @function  
++des_decrypt3:
++      pushl   %ebx
++      movl    8(%esp),        %ebx
++      pushl   %ebp
++      pushl   %esi
++      pushl   %edi
++
++       
++      movl    (%ebx),         %edi
++      movl    4(%ebx),        %esi
++      subl    $12,            %esp
++
++       
++      roll    $4,             %edi
++      movl    %edi,           %edx
++      xorl    %esi,           %edi
++      andl    $0xf0f0f0f0,    %edi
++      xorl    %edi,           %edx
++      xorl    %edi,           %esi
++
++      roll    $20,            %esi
++      movl    %esi,           %edi
++      xorl    %edx,           %esi
++      andl    $0xfff0000f,    %esi
++      xorl    %esi,           %edi
++      xorl    %esi,           %edx
++
++      roll    $14,            %edi
++      movl    %edi,           %esi
++      xorl    %edx,           %edi
++      andl    $0x33333333,    %edi
++      xorl    %edi,           %esi
++      xorl    %edi,           %edx
++
++      roll    $22,            %edx
++      movl    %edx,           %edi
++      xorl    %esi,           %edx
++      andl    $0x03fc03fc,    %edx
++      xorl    %edx,           %edi
++      xorl    %edx,           %esi
++
++      roll    $9,             %edi
++      movl    %edi,           %edx
++      xorl    %esi,           %edi
++      andl    $0xaaaaaaaa,    %edi
++      xorl    %edi,           %edx
++      xorl    %edi,           %esi
++
++      rorl    $3,             %edx
++      rorl    $2,             %esi
++      movl    %esi,           4(%ebx)
++      movl    36(%esp),       %esi
++      movl    %edx,           (%ebx)
++      movl    40(%esp),       %edi
++      movl    44(%esp),       %eax
++      movl    $0,             8(%esp)
++      movl    %eax,           4(%esp)
++      movl    %ebx,           (%esp)
++      call    des_encrypt2
++      movl    $1,             8(%esp)
++      movl    %edi,           4(%esp)
++      movl    %ebx,           (%esp)
++      call    des_encrypt2
++      movl    $0,             8(%esp)
++      movl    %esi,           4(%esp)
++      movl    %ebx,           (%esp)
++      call    des_encrypt2
++      addl    $12,            %esp
++      movl    (%ebx),         %edi
++      movl    4(%ebx),        %esi
++
++       
++      roll    $2,             %esi
++      roll    $3,             %edi
++      movl    %edi,           %eax
++      xorl    %esi,           %edi
++      andl    $0xaaaaaaaa,    %edi
++      xorl    %edi,           %eax
++      xorl    %edi,           %esi
++
++      roll    $23,            %eax
++      movl    %eax,           %edi
++      xorl    %esi,           %eax
++      andl    $0x03fc03fc,    %eax
++      xorl    %eax,           %edi
++      xorl    %eax,           %esi
++
++      roll    $10,            %edi
++      movl    %edi,           %eax
++      xorl    %esi,           %edi
++      andl    $0x33333333,    %edi
++      xorl    %edi,           %eax
++      xorl    %edi,           %esi
++
++      roll    $18,            %esi
++      movl    %esi,           %edi
++      xorl    %eax,           %esi
++      andl    $0xfff0000f,    %esi
++      xorl    %esi,           %edi
++      xorl    %esi,           %eax
++
++      roll    $12,            %edi
++      movl    %edi,           %esi
++      xorl    %eax,           %edi
++      andl    $0xf0f0f0f0,    %edi
++      xorl    %edi,           %esi
++      xorl    %edi,           %eax
++
++      rorl    $4,             %eax
++      movl    %eax,           (%ebx)
++      movl    %esi,           4(%ebx)
++      popl    %edi
++      popl    %esi
++      popl    %ebp
++      popl    %ebx
++      ret
++.des_decrypt3_end:
++      .size    des_decrypt3 , .des_decrypt3_end-des_decrypt3  
++.ident        "desasm.pl"
++.text
++      .align 16 
++.globl des_ncbc_encrypt
++      .type    des_ncbc_encrypt , @function  
++des_ncbc_encrypt:
++
++      pushl   %ebp
++      pushl   %ebx
++      pushl   %esi
++      pushl   %edi
++      movl    28(%esp),       %ebp
++       
++      movl    36(%esp),       %ebx
++      movl    (%ebx),         %esi
++      movl    4(%ebx),        %edi
++      pushl   %edi
++      pushl   %esi
++      pushl   %edi
++      pushl   %esi
++      movl    %esp,           %ebx
++      movl    36(%esp),       %esi
++      movl    40(%esp),       %edi
++       
++      movl    56(%esp),       %ecx
++       
++      pushl   %ecx
++       
++      movl    52(%esp),       %eax
++      pushl   %eax
++      pushl   %ebx
++      cmpl    $0,             %ecx
++      jz      .L004decrypt
++      andl    $4294967288,    %ebp
++      movl    12(%esp),       %eax
++      movl    16(%esp),       %ebx
++      jz      .L005encrypt_finish
++.L006encrypt_loop:
++      movl    (%esi),         %ecx
++      movl    4(%esi),        %edx
++      xorl    %ecx,           %eax
++      xorl    %edx,           %ebx
++      movl    %eax,           12(%esp)
++      movl    %ebx,           16(%esp)
++      call    des_encrypt
++      movl    12(%esp),       %eax
++      movl    16(%esp),       %ebx
++      movl    %eax,           (%edi)
++      movl    %ebx,           4(%edi)
++      addl    $8,             %esi
++      addl    $8,             %edi
++      subl    $8,             %ebp
++      jnz     .L006encrypt_loop
++.L005encrypt_finish:
++      movl    56(%esp),       %ebp
++      andl    $7,             %ebp
++      jz      .L007finish
++      xorl    %ecx,           %ecx
++      xorl    %edx,           %edx
++      movl    .L008cbc_enc_jmp_table(,%ebp,4),%ebp
++      jmp     *%ebp
++.L009ej7:
++      movb    6(%esi),        %dh
++      sall    $8,             %edx
++.L010ej6:
++      movb    5(%esi),        %dh
++.L011ej5:
++      movb    4(%esi),        %dl
++.L012ej4:
++      movl    (%esi),         %ecx
++      jmp     .L013ejend
++.L014ej3:
++      movb    2(%esi),        %ch
++      sall    $8,             %ecx
++.L015ej2:
++      movb    1(%esi),        %ch
++.L016ej1:
++      movb    (%esi),         %cl
++.L013ejend:
++      xorl    %ecx,           %eax
++      xorl    %edx,           %ebx
++      movl    %eax,           12(%esp)
++      movl    %ebx,           16(%esp)
++      call    des_encrypt
++      movl    12(%esp),       %eax
++      movl    16(%esp),       %ebx
++      movl    %eax,           (%edi)
++      movl    %ebx,           4(%edi)
++      jmp     .L007finish
++.align 16 
++.L004decrypt:
++      andl    $4294967288,    %ebp
++      movl    20(%esp),       %eax
++      movl    24(%esp),       %ebx
++      jz      .L017decrypt_finish
++.L018decrypt_loop:
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++      movl    %eax,           12(%esp)
++      movl    %ebx,           16(%esp)
++      call    des_encrypt
++      movl    12(%esp),       %eax
++      movl    16(%esp),       %ebx
++      movl    20(%esp),       %ecx
++      movl    24(%esp),       %edx
++      xorl    %eax,           %ecx
++      xorl    %ebx,           %edx
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++      movl    %ecx,           (%edi)
++      movl    %edx,           4(%edi)
++      movl    %eax,           20(%esp)
++      movl    %ebx,           24(%esp)
++      addl    $8,             %esi
++      addl    $8,             %edi
++      subl    $8,             %ebp
++      jnz     .L018decrypt_loop
++.L017decrypt_finish:
++      movl    56(%esp),       %ebp
++      andl    $7,             %ebp
++      jz      .L007finish
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++      movl    %eax,           12(%esp)
++      movl    %ebx,           16(%esp)
++      call    des_encrypt
++      movl    12(%esp),       %eax
++      movl    16(%esp),       %ebx
++      movl    20(%esp),       %ecx
++      movl    24(%esp),       %edx
++      xorl    %eax,           %ecx
++      xorl    %ebx,           %edx
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++.L019dj7:
++      rorl    $16,            %edx
++      movb    %dl,            6(%edi)
++      shrl    $16,            %edx
++.L020dj6:
++      movb    %dh,            5(%edi)
++.L021dj5:
++      movb    %dl,            4(%edi)
++.L022dj4:
++      movl    %ecx,           (%edi)
++      jmp     .L023djend
++.L024dj3:
++      rorl    $16,            %ecx
++      movb    %cl,            2(%edi)
++      sall    $16,            %ecx
++.L025dj2:
++      movb    %ch,            1(%esi)
++.L026dj1:
++      movb    %cl,            (%esi)
++.L023djend:
++      jmp     .L007finish
++.align 16 
++.L007finish:
++      movl    64(%esp),       %ecx
++      addl    $28,            %esp
++      movl    %eax,           (%ecx)
++      movl    %ebx,           4(%ecx)
++      popl    %edi
++      popl    %esi
++      popl    %ebx
++      popl    %ebp
++      ret
++.align 16 
++.L008cbc_enc_jmp_table:
++      .long 0
++      .long .L016ej1
++      .long .L015ej2
++      .long .L014ej3
++      .long .L012ej4
++      .long .L011ej5
++      .long .L010ej6
++      .long .L009ej7
++.align 16 
++.L027cbc_dec_jmp_table:
++      .long 0
++      .long .L026dj1
++      .long .L025dj2
++      .long .L024dj3
++      .long .L022dj4
++      .long .L021dj5
++      .long .L020dj6
++      .long .L019dj7
++.des_ncbc_encrypt_end:
++      .size    des_ncbc_encrypt , .des_ncbc_encrypt_end-des_ncbc_encrypt  
++.ident        "desasm.pl"
++.text
++      .align 16 
++.globl des_ede3_cbc_encrypt
++      .type    des_ede3_cbc_encrypt , @function  
++des_ede3_cbc_encrypt:
++
++      pushl   %ebp
++      pushl   %ebx
++      pushl   %esi
++      pushl   %edi
++      movl    28(%esp),       %ebp
++       
++      movl    44(%esp),       %ebx
++      movl    (%ebx),         %esi
++      movl    4(%ebx),        %edi
++      pushl   %edi
++      pushl   %esi
++      pushl   %edi
++      pushl   %esi
++      movl    %esp,           %ebx
++      movl    36(%esp),       %esi
++      movl    40(%esp),       %edi
++       
++      movl    64(%esp),       %ecx
++       
++      movl    56(%esp),       %eax
++      pushl   %eax
++       
++      movl    56(%esp),       %eax
++      pushl   %eax
++       
++      movl    56(%esp),       %eax
++      pushl   %eax
++      pushl   %ebx
++      cmpl    $0,             %ecx
++      jz      .L028decrypt
++      andl    $4294967288,    %ebp
++      movl    16(%esp),       %eax
++      movl    20(%esp),       %ebx
++      jz      .L029encrypt_finish
++.L030encrypt_loop:
++      movl    (%esi),         %ecx
++      movl    4(%esi),        %edx
++      xorl    %ecx,           %eax
++      xorl    %edx,           %ebx
++      movl    %eax,           16(%esp)
++      movl    %ebx,           20(%esp)
++      call    des_encrypt3
++      movl    16(%esp),       %eax
++      movl    20(%esp),       %ebx
++      movl    %eax,           (%edi)
++      movl    %ebx,           4(%edi)
++      addl    $8,             %esi
++      addl    $8,             %edi
++      subl    $8,             %ebp
++      jnz     .L030encrypt_loop
++.L029encrypt_finish:
++      movl    60(%esp),       %ebp
++      andl    $7,             %ebp
++      jz      .L031finish
++      xorl    %ecx,           %ecx
++      xorl    %edx,           %edx
++      movl    .L032cbc_enc_jmp_table(,%ebp,4),%ebp
++      jmp     *%ebp
++.L033ej7:
++      movb    6(%esi),        %dh
++      sall    $8,             %edx
++.L034ej6:
++      movb    5(%esi),        %dh
++.L035ej5:
++      movb    4(%esi),        %dl
++.L036ej4:
++      movl    (%esi),         %ecx
++      jmp     .L037ejend
++.L038ej3:
++      movb    2(%esi),        %ch
++      sall    $8,             %ecx
++.L039ej2:
++      movb    1(%esi),        %ch
++.L040ej1:
++      movb    (%esi),         %cl
++.L037ejend:
++      xorl    %ecx,           %eax
++      xorl    %edx,           %ebx
++      movl    %eax,           16(%esp)
++      movl    %ebx,           20(%esp)
++      call    des_encrypt3
++      movl    16(%esp),       %eax
++      movl    20(%esp),       %ebx
++      movl    %eax,           (%edi)
++      movl    %ebx,           4(%edi)
++      jmp     .L031finish
++.align 16 
++.L028decrypt:
++      andl    $4294967288,    %ebp
++      movl    24(%esp),       %eax
++      movl    28(%esp),       %ebx
++      jz      .L041decrypt_finish
++.L042decrypt_loop:
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++      movl    %eax,           16(%esp)
++      movl    %ebx,           20(%esp)
++      call    des_decrypt3
++      movl    16(%esp),       %eax
++      movl    20(%esp),       %ebx
++      movl    24(%esp),       %ecx
++      movl    28(%esp),       %edx
++      xorl    %eax,           %ecx
++      xorl    %ebx,           %edx
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++      movl    %ecx,           (%edi)
++      movl    %edx,           4(%edi)
++      movl    %eax,           24(%esp)
++      movl    %ebx,           28(%esp)
++      addl    $8,             %esi
++      addl    $8,             %edi
++      subl    $8,             %ebp
++      jnz     .L042decrypt_loop
++.L041decrypt_finish:
++      movl    60(%esp),       %ebp
++      andl    $7,             %ebp
++      jz      .L031finish
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++      movl    %eax,           16(%esp)
++      movl    %ebx,           20(%esp)
++      call    des_decrypt3
++      movl    16(%esp),       %eax
++      movl    20(%esp),       %ebx
++      movl    24(%esp),       %ecx
++      movl    28(%esp),       %edx
++      xorl    %eax,           %ecx
++      xorl    %ebx,           %edx
++      movl    (%esi),         %eax
++      movl    4(%esi),        %ebx
++.L043dj7:
++      rorl    $16,            %edx
++      movb    %dl,            6(%edi)
++      shrl    $16,            %edx
++.L044dj6:
++      movb    %dh,            5(%edi)
++.L045dj5:
++      movb    %dl,            4(%edi)
++.L046dj4:
++      movl    %ecx,           (%edi)
++      jmp     .L047djend
++.L048dj3:
++      rorl    $16,            %ecx
++      movb    %cl,            2(%edi)
++      sall    $16,            %ecx
++.L049dj2:
++      movb    %ch,            1(%esi)
++.L050dj1:
++      movb    %cl,            (%esi)
++.L047djend:
++      jmp     .L031finish
++.align 16 
++.L031finish:
++      movl    76(%esp),       %ecx
++      addl    $32,            %esp
++      movl    %eax,           (%ecx)
++      movl    %ebx,           4(%ecx)
++      popl    %edi
++      popl    %esi
++      popl    %ebx
++      popl    %ebp
++      ret
++.align 16 
++.L032cbc_enc_jmp_table:
++      .long 0
++      .long .L040ej1
++      .long .L039ej2
++      .long .L038ej3
++      .long .L036ej4
++      .long .L035ej5
++      .long .L034ej6
++      .long .L033ej7
++.align 16 
++.L051cbc_dec_jmp_table:
++      .long 0
++      .long .L050dj1
++      .long .L049dj2
++      .long .L048dj3
++      .long .L046dj4
++      .long .L045dj5
++      .long .L044dj6
++      .long .L043dj7
++.des_ede3_cbc_encrypt_end:
++      .size    des_ede3_cbc_encrypt , .des_ede3_cbc_encrypt_end-des_ede3_cbc_encrypt  
++.ident        "desasm.pl"
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/ecb_enc.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,128 @@
++/* crypto/des/ecb_enc.c */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++#include "des/des_locl.h"
++#include "des/spr.h"
++
++char *libdes_version="libdes v 3.24 - 20-Apr-1996 - eay";
++char *DES_version="DES part of SSLeay 0.8.2b 08-Jan-1998";
++
++/* RCSID $Id: ecb_enc.c,v 1.8 2004/08/04 15:57:22 mcr Exp $ */
++/* This function ifdef'ed out for FreeS/WAN project. */
++#ifdef notdef
++char *des_options()
++      {
++      static int init=1;
++      static char buf[32];
++
++      if (init)
++              {
++              char *ptr,*unroll,*risc,*size;
++
++              init=0;
++#ifdef DES_PTR
++              ptr="ptr";
++#else
++              ptr="idx";
++#endif
++#if defined(DES_RISC1) || defined(DES_RISC2)
++#ifdef DES_RISC1
++              risc="risc1";
++#endif
++#ifdef DES_RISC2
++              risc="risc2";
++#endif
++#else
++              risc="cisc";
++#endif
++#ifdef DES_UNROLL
++              unroll="16";
++#else
++              unroll="4";
++#endif
++              if (sizeof(DES_LONG) != sizeof(long))
++                      size="int";
++              else
++                      size="long";
++              sprintf(buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,size);
++              }
++      return(buf);
++      }
++#endif
++              
++
++void des_ecb_encrypt(input, output, ks, enc)
++des_cblock (*input);
++des_cblock (*output);
++des_key_schedule ks;
++int enc;
++      {
++      register DES_LONG l;
++      register unsigned char *in,*out;
++      DES_LONG ll[2];
++
++      in=(unsigned char *)input;
++      out=(unsigned char *)output;
++      c2l(in,l); ll[0]=l;
++      c2l(in,l); ll[1]=l;
++      des_encrypt(ll,ks,enc);
++      l=ll[0]; l2c(l,out);
++      l=ll[1]; l2c(l,out);
++      l=ll[0]=ll[1]=0;
++      }
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/ipsec_alg_3des.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,181 @@
++/*
++ * ipsec_alg 3DES cipher stubs
++ *
++ * Copyright (C) 2005 Michael Richardson <mcr@xelerance.com> 
++ *
++ * Adapted from ipsec_alg_aes.c by JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ * 
++ * ipsec_alg_aes.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ */
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++/*    
++ *    special case: ipsec core modular with this static algo inside:
++ *    must avoid MODULE magic for this file
++ */
++#if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_3DES)
++#undef MODULE
++#endif
++
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/string.h>
++
++/*    Low freeswan header coupling    */
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_alg.h"
++#include "crypto/des.h"
++#include "openswan/ipsec_alg_3des.h"
++
++#define AES_CONTEXT_T aes_context
++static int debug_3des=0;
++static int test_3des=0;
++static int excl_3des=0;
++
++#if defined(CONFIG_KLIPS_ENC_3DES_MODULE)
++MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
++#ifdef module_param
++module_param(debug_3des,int,0600)
++module_param(test_des,int,0600)
++module_param(excl_des,int,0600)
++#else
++MODULE_PARM(debug_3des, "i");
++MODULE_PARM(test_des, "i");
++MODULE_PARM(excl_des, "i");
++#endif
++#endif
++
++#define ESP_AES_MAC_KEY_SZ    16      /* 128 bit MAC key */
++#define ESP_AES_MAC_BLK_LEN   16      /* 128 bit block */
++
++static int _3des_set_key(struct ipsec_alg_enc *alg,
++                       __u8 * key_e, const __u8 * key,
++                       size_t keysize)
++{
++      int ret = 0;
++      TripleDES_context *ctx = (TripleDES_context*)key_e;
++
++      if(keysize != 192/8) {
++        return EINVAL;
++      }
++      
++      des_set_key((des_cblock *)(key + DES_KEY_SZ*0), ctx->s1);
++      des_set_key((des_cblock *)(key + DES_KEY_SZ*1), ctx->s2);
++      des_set_key((des_cblock *)(key + DES_KEY_SZ*2), ctx->s3);
++      
++      if (debug_3des > 0)
++              printk(KERN_DEBUG "klips_debug:_3des_set_key:"
++                              "ret=%d key_e=%p key=%p keysize=%ld\n",
++                                ret, key_e, key, (unsigned long int) keysize);
++      return ret;
++}
++
++static int _3des_cbc_encrypt(struct ipsec_alg_enc *alg,
++                           __u8 * key_e,
++                           __u8 * in,
++                           int ilen, const __u8 * iv,
++                           int encrypt)
++{
++      TripleDES_context *ctx=(TripleDES_context*)key_e;
++      des_cblock miv;
++
++      memcpy(&miv, iv, sizeof(miv));
++
++      if (debug_3des > 0)
++              printk(KERN_DEBUG "klips_debug:_aes_cbc_encrypt:"
++                              "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
++                              key_e, in, ilen, iv, encrypt);
++
++      des_ede3_cbc_encrypt((des_cblock *)in,
++                           (des_cblock *)in,
++                           ilen,
++                           ctx->s1,
++                           ctx->s2,
++                           ctx->s3,
++                           &miv, encrypt);
++      return 1;
++}
++
++static struct ipsec_alg_enc ipsec_alg_3DES = {
++      ixt_common: {   ixt_version:    IPSEC_ALG_VERSION,
++                      ixt_refcnt:     ATOMIC_INIT(0),
++                      ixt_name:       "3des",
++                      ixt_blocksize:  ESP_3DES_CBC_BLK_LEN, 
++                      ixt_support: {
++                        ias_exttype:    IPSEC_ALG_TYPE_ENCRYPT,
++                        ias_id:         ESP_3DES,
++                        ias_keyminbits: ESP_3DES_KEY_SZ*8,
++                        ias_keymaxbits: ESP_3DES_KEY_SZ*8,
++              },
++      },
++#if defined(MODULE_KLIPS_ENC_3DES_MODULE)
++      ixt_module:     THIS_MODULE,
++#endif
++      ixt_e_keylen:   ESP_3DES_KEY_SZ*8,
++      ixt_e_ctx_size: sizeof(TripleDES_context),
++      ixt_e_set_key:  _3des_set_key,
++      ixt_e_cbc_encrypt:_3des_cbc_encrypt,
++};
++
++#if defined(CONFIG_KLIPS_ENC_3DES_MODULE)
++IPSEC_ALG_MODULE_INIT_MOD( ipsec_3des_init )
++#else
++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_3des_init )
++#endif
++{
++      int ret, test_ret;
++
++      if (excl_3des) ipsec_alg_3DES.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL;
++      ret=register_ipsec_alg_enc(&ipsec_alg_3DES);
++      printk("ipsec_3des_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
++                      ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, 
++                      ipsec_alg_3DES.ixt_common.ixt_support.ias_id, 
++                      ipsec_alg_3DES.ixt_common.ixt_name, 
++                      ret);
++      if (ret==0 && test_3des) {
++              test_ret=ipsec_alg_test(
++                              ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype,
++                              ipsec_alg_3DES.ixt_common.ixt_support.ias_id, 
++                              test_3des);
++              printk("ipsec_aes_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
++                              ipsec_alg_3DES.ixt_common.ixt_support.ias_exttype, 
++                              ipsec_alg_3DES.ixt_common.ixt_support.ias_id, 
++                              test_ret);
++      }
++      return ret;
++}
++
++#if defined(CONFIG_KLIPS_ENC_3DES_MODULE)
++IPSEC_ALG_MODULE_EXIT_MOD( ipsec_3des_fini )
++#else
++IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_3des_fini )
++#endif
++{
++      unregister_ipsec_alg_enc(&ipsec_alg_3DES);
++      return;
++}
++
++/* Dual, because 3des code is 4-clause BSD licensed */
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
++
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/des/set_key.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,246 @@
++/* crypto/des/set_key.c */
++/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ * 
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to.  The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ * 
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    "This product includes cryptographic software written by
++ *     Eric Young (eay@cryptsoft.com)"
++ *    The word 'cryptographic' can be left out if the rouines from the library
++ *    being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from 
++ *    the apps directory (application code) you must include an acknowledgement:
++ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ * 
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * 
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed.  i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++
++/* set_key.c v 1.4 eay 24/9/91
++ * 1.4 Speed up by 400% :-)
++ * 1.3 added register declarations.
++ * 1.2 unrolled make_key_sched a bit more
++ * 1.1 added norm_expand_bits
++ * 1.0 First working version
++ */
++#include "des/des_locl.h"
++#include "des/podd.h"
++#include "des/sk.h"
++
++#ifndef NOPROTO
++static int check_parity(des_cblock (*key));
++#else
++static int check_parity();
++#endif
++
++int des_check_key=0;
++
++void des_set_odd_parity(key)
++des_cblock (*key);
++      {
++      int i;
++
++      for (i=0; i<DES_KEY_SZ; i++)
++              (*key)[i]=odd_parity[(*key)[i]];
++      }
++
++static int check_parity(key)
++des_cblock (*key);
++      {
++      int i;
++
++      for (i=0; i<DES_KEY_SZ; i++)
++              {
++              if ((*key)[i] != odd_parity[(*key)[i]])
++                      return(0);
++              }
++      return(1);
++      }
++
++/* Weak and semi week keys as take from
++ * %A D.W. Davies
++ * %A W.L. Price
++ * %T Security for Computer Networks
++ * %I John Wiley & Sons
++ * %D 1984
++ * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference
++ * (and actual cblock values).
++ */
++#define NUM_WEAK_KEY  16
++static des_cblock weak_keys[NUM_WEAK_KEY]={
++      /* weak keys */
++      {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
++      {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},
++      {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},
++      {0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0},
++      /* semi-weak keys */
++      {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE},
++      {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},
++      {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},
++      {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},
++      {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},
++      {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},
++      {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},
++      {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},
++      {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},
++      {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},
++      {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
++      {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}};
++
++int des_is_weak_key(key)
++des_cblock (*key);
++      {
++      int i;
++
++      for (i=0; i<NUM_WEAK_KEY; i++)
++              /* Added == 0 to comparision, I obviously don't run
++               * this section very often :-(, thanks to
++               * engineering@MorningStar.Com for the fix
++               * eay 93/06/29
++               * Another problem, I was comparing only the first 4
++               * bytes, 97/03/18 */
++              if (memcmp(weak_keys[i],key,sizeof(des_cblock)) == 0) return(1);
++      return(0);
++      }
++
++/* NOW DEFINED IN des_local.h
++ * See ecb_encrypt.c for a pseudo description of these macros. 
++ * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
++ *    (b)^=(t),\
++ *    (a)=((a)^((t)<<(n))))
++ */
++
++#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
++      (a)=(a)^(t)^(t>>(16-(n))))
++
++/* return 0 if key parity is odd (correct),
++ * return -1 if key parity error,
++ * return -2 if illegal weak key.
++ */
++int des_set_key(key, schedule)
++des_cblock (*key);
++des_key_schedule schedule;
++      {
++      static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0};
++      register DES_LONG c,d,t,s,t2;
++      register unsigned char *in;
++      register DES_LONG *k;
++      register int i;
++
++      if (des_check_key)
++              {
++              if (!check_parity(key))
++                      return(-1);
++
++              if (des_is_weak_key(key))
++                      return(-2);
++              }
++
++      k=(DES_LONG *)schedule;
++      in=(unsigned char *)key;
++
++      c2l(in,c);
++      c2l(in,d);
++
++      /* do PC1 in 60 simple operations */ 
++/*    PERM_OP(d,c,t,4,0x0f0f0f0fL);
++      HPERM_OP(c,t,-2, 0xcccc0000L);
++      HPERM_OP(c,t,-1, 0xaaaa0000L);
++      HPERM_OP(c,t, 8, 0x00ff0000L);
++      HPERM_OP(c,t,-1, 0xaaaa0000L);
++      HPERM_OP(d,t,-8, 0xff000000L);
++      HPERM_OP(d,t, 8, 0x00ff0000L);
++      HPERM_OP(d,t, 2, 0x33330000L);
++      d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L);
++      d=(d>>8)|((c&0xf0000000L)>>4);
++      c&=0x0fffffffL; */
++
++      /* I now do it in 47 simple operations :-)
++       * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
++       * for the inspiration. :-) */
++      PERM_OP (d,c,t,4,0x0f0f0f0fL);
++      HPERM_OP(c,t,-2,0xcccc0000L);
++      HPERM_OP(d,t,-2,0xcccc0000L);
++      PERM_OP (d,c,t,1,0x55555555L);
++      PERM_OP (c,d,t,8,0x00ff00ffL);
++      PERM_OP (d,c,t,1,0x55555555L);
++      d=      (((d&0x000000ffL)<<16L)| (d&0x0000ff00L)     |
++               ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L));
++      c&=0x0fffffffL;
++
++      for (i=0; i<ITERATIONS; i++)
++              {
++              if (shifts2[i])
++                      { c=((c>>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); }
++              else
++                      { c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); }
++              c&=0x0fffffffL;
++              d&=0x0fffffffL;
++              /* could be a few less shifts but I am to lazy at this
++               * point in time to investigate */
++              s=      des_skb[0][ (c    )&0x3f                ]|
++                      des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]|
++                      des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]|
++                      des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) |
++                                                ((c>>22L)&0x38)];
++              t=      des_skb[4][ (d    )&0x3f                ]|
++                      des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]|
++                      des_skb[6][ (d>>15L)&0x3f                ]|
++                      des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)];
++
++              /* table contained 0213 4657 */
++              t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL;
++              *(k++)=ROTATE(t2,30)&0xffffffffL;
++
++              t2=((s>>16L)|(t&0xffff0000L));
++              *(k++)=ROTATE(t2,26)&0xffffffffL;
++              }
++      return(0);
++      }
++
++int des_key_sched(key, schedule)
++des_cblock (*key);
++des_key_schedule schedule;
++      {
++      return(des_set_key(key,schedule));
++      }
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/goodmask.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,100 @@
++/*
++ * minor utilities for subnet-mask manipulation
++ * Copyright (C) 1998, 1999  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: goodmask.c,v 1.12 2004/07/10 07:43:47 mcr Exp $
++ */
++#include "openswan.h"
++
++#ifndef ABITS
++#define       ABITS   32      /* bits in an IPv4 address */
++#endif
++
++/*
++ - goodmask - is this a good (^1*0*$) subnet mask?
++ * You are not expected to understand this.  See Henry S. Warren Jr, 
++ * "Functions realizable with word-parallel logical and two's-complement
++ * addition instructions", CACM 20.6 (June 1977), p.439.
++ */
++int                           /* predicate */
++goodmask(mask)
++struct in_addr mask;
++{
++      unsigned long x = ntohl(mask.s_addr);
++      /* clear rightmost contiguous string of 1-bits */
++#     define  CRCS1B(x)       (((x|(x-1))+1)&x)
++#     define  TOPBIT          (1UL << 31)
++
++      /* either zero, or has one string of 1-bits which is left-justified */
++      if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT)))
++              return 1;
++      return 0;
++}
++
++/*
++ - masktobits - how many bits in this mask?
++ * The algorithm is essentially a binary search, but highly optimized
++ * for this particular task.
++ */
++int                           /* -1 means !goodmask() */
++masktobits(mask)
++struct in_addr mask;
++{
++      unsigned long m = ntohl(mask.s_addr);
++      int masklen;
++
++      if (!goodmask(mask))
++              return -1;
++
++      if (m&0x00000001UL)
++              return 32;
++      masklen = 0;
++      if (m&(0x0000ffffUL<<1)) {      /* <<1 for 1-origin numbering */
++              masklen |= 0x10;
++              m <<= 16;
++      }
++      if (m&(0x00ff0000UL<<1)) {
++              masklen |= 0x08;
++              m <<= 8;
++      }
++      if (m&(0x0f000000UL<<1)) {
++              masklen |= 0x04;
++              m <<= 4;
++      }
++      if (m&(0x30000000UL<<1)) {
++              masklen |= 0x02;
++              m <<= 2;
++      }
++      if (m&(0x40000000UL<<1))
++              masklen |= 0x01;
++
++      return masklen;
++}
++
++/*
++ - bitstomask - return a mask with this many high bits on
++ */
++struct in_addr
++bitstomask(n)
++int n;
++{
++      struct in_addr result;
++
++      if (n > 0 && n <= ABITS)
++              result.s_addr = htonl(~((1UL << (ABITS - n)) - 1));
++      else if (n == 0)
++              result.s_addr = 0;
++      else
++              result.s_addr = 0;      /* best error report we can do */
++      return result;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/infblock.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,403 @@
++/* infblock.c -- interpret and process block types to last block
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++#include <zlib/zutil.h>
++#include "infblock.h"
++#include "inftrees.h"
++#include "infcodes.h"
++#include "infutil.h"
++
++struct inflate_codes_state {int dummy;}; /* for buggy compilers */
++
++/* simplify the use of the inflate_huft type with some defines */
++#define exop word.what.Exop
++#define bits word.what.Bits
++
++/* Table for deflate from PKZIP's appnote.txt. */
++local const uInt border[] = { /* Order of the bit length code lengths */
++        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
++
++/*
++   Notes beyond the 1.93a appnote.txt:
++
++   1. Distance pointers never point before the beginning of the output
++      stream.
++   2. Distance pointers can point back across blocks, up to 32k away.
++   3. There is an implied maximum of 7 bits for the bit length table and
++      15 bits for the actual data.
++   4. If only one code exists, then it is encoded using one bit.  (Zero
++      would be more efficient, but perhaps a little confusing.)  If two
++      codes exist, they are coded using one bit each (0 and 1).
++   5. There is no way of sending zero distance codes--a dummy must be
++      sent if there are none.  (History: a pre 2.0 version of PKZIP would
++      store blocks with no distance codes, but this was discovered to be
++      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
++      zero distance codes, which is sent as one code of zero bits in
++      length.
++   6. There are up to 286 literal/length codes.  Code 256 represents the
++      end-of-block.  Note however that the static length tree defines
++      288 codes just to fill out the Huffman codes.  Codes 286 and 287
++      cannot be used though, since there is no length base or extra bits
++      defined for them.  Similarily, there are up to 30 distance codes.
++      However, static trees define 32 codes (all 5 bits) to fill out the
++      Huffman codes, but the last two had better not show up in the data.
++   7. Unzip can check dynamic Huffman blocks for complete code sets.
++      The exception is that a single code would not be complete (see #4).
++   8. The five bits following the block type is really the number of
++      literal codes sent minus 257.
++   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
++      (1+6+6).  Therefore, to output three times the length, you output
++      three codes (1+1+1), whereas to output four times the same length,
++      you only need two codes (1+3).  Hmm.
++  10. In the tree reconstruction algorithm, Code = Code + Increment
++      only if BitLength(i) is not zero.  (Pretty obvious.)
++  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
++  12. Note: length code 284 can represent 227-258, but length code 285
++      really is 258.  The last length deserves its own, short code
++      since it gets used a lot in very redundant files.  The length
++      258 is special since 258 - 3 (the min match length) is 255.
++  13. The literal/length and distance code bit lengths are read as a
++      single stream of lengths.  It is possible (and advantageous) for
++      a repeat code (16, 17, or 18) to go across the boundary between
++      the two sets of lengths.
++ */
++
++
++void inflate_blocks_reset(s, z, c)
++inflate_blocks_statef *s;
++z_streamp z;
++uLongf *c;
++{
++  if (c != Z_NULL)
++    *c = s->check;
++  if (s->mode == BTREE || s->mode == DTREE)
++    ZFREE(z, s->sub.trees.blens);
++  if (s->mode == CODES)
++    inflate_codes_free(s->sub.decode.codes, z);
++  s->mode = TYPE;
++  s->bitk = 0;
++  s->bitb = 0;
++  s->read = s->write = s->window;
++  if (s->checkfn != Z_NULL)
++    z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
++  Tracev((stderr, "inflate:   blocks reset\n"));
++}
++
++
++inflate_blocks_statef *inflate_blocks_new(z, c, w)
++z_streamp z;
++check_func c;
++uInt w;
++{
++  inflate_blocks_statef *s;
++
++  if ((s = (inflate_blocks_statef *)ZALLOC
++       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
++    return s;
++  if ((s->hufts =
++       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
++  {
++    ZFREE(z, s);
++    return Z_NULL;
++  }
++  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
++  {
++    ZFREE(z, s->hufts);
++    ZFREE(z, s);
++    return Z_NULL;
++  }
++  s->end = s->window + w;
++  s->checkfn = c;
++  s->mode = TYPE;
++  Tracev((stderr, "inflate:   blocks allocated\n"));
++  inflate_blocks_reset(s, z, Z_NULL);
++  return s;
++}
++
++
++int inflate_blocks(s, z, r)
++inflate_blocks_statef *s;
++z_streamp z;
++int r;
++{
++  uInt t;               /* temporary storage */
++  uLong b;              /* bit buffer */
++  uInt k;               /* bits in bit buffer */
++  Bytef *p;             /* input data pointer */
++  uInt n;               /* bytes available there */
++  Bytef *q;             /* output window write pointer */
++  uInt m;               /* bytes to end of window or read pointer */
++
++  /* copy input/output information to locals (UPDATE macro restores) */
++  LOAD
++
++  /* process input based on current state */
++  while (1) switch (s->mode)
++  {
++    case TYPE:
++      NEEDBITS(3)
++      t = (uInt)b & 7;
++      s->last = t & 1;
++      switch (t >> 1)
++      {
++        case 0:                         /* stored */
++          Tracev((stderr, "inflate:     stored block%s\n",
++                 s->last ? " (last)" : ""));
++          DUMPBITS(3)
++          t = k & 7;                    /* go to byte boundary */
++          DUMPBITS(t)
++          s->mode = LENS;               /* get length of stored block */
++          break;
++        case 1:                         /* fixed */
++          Tracev((stderr, "inflate:     fixed codes block%s\n",
++                 s->last ? " (last)" : ""));
++          {
++            uInt bl, bd;
++            inflate_huft *tl, *td;
++
++            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
++            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
++            if (s->sub.decode.codes == Z_NULL)
++            {
++              r = Z_MEM_ERROR;
++              LEAVE
++            }
++          }
++          DUMPBITS(3)
++          s->mode = CODES;
++          break;
++        case 2:                         /* dynamic */
++          Tracev((stderr, "inflate:     dynamic codes block%s\n",
++                 s->last ? " (last)" : ""));
++          DUMPBITS(3)
++          s->mode = TABLE;
++          break;
++        case 3:                         /* illegal */
++          DUMPBITS(3)
++          s->mode = BAD;
++          z->msg = (char*)"invalid block type";
++          r = Z_DATA_ERROR;
++          LEAVE
++      }
++      break;
++    case LENS:
++      NEEDBITS(32)
++      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
++      {
++        s->mode = BAD;
++        z->msg = (char*)"invalid stored block lengths";
++        r = Z_DATA_ERROR;
++        LEAVE
++      }
++      s->sub.left = (uInt)b & 0xffff;
++      b = k = 0;                      /* dump bits */
++      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
++      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
++      break;
++    case STORED:
++      if (n == 0)
++        LEAVE
++      NEEDOUT
++      t = s->sub.left;
++      if (t > n) t = n;
++      if (t > m) t = m;
++      zmemcpy(q, p, t);
++      p += t;  n -= t;
++      q += t;  m -= t;
++      if ((s->sub.left -= t) != 0)
++        break;
++      Tracev((stderr, "inflate:       stored end, %lu total out\n",
++              z->total_out + (q >= s->read ? q - s->read :
++              (s->end - s->read) + (q - s->window))));
++      s->mode = s->last ? DRY : TYPE;
++      break;
++    case TABLE:
++      NEEDBITS(14)
++      s->sub.trees.table = t = (uInt)b & 0x3fff;
++#ifndef PKZIP_BUG_WORKAROUND
++      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
++      {
++        s->mode = BAD;
++        z->msg = (char*)"too many length or distance symbols";
++        r = Z_DATA_ERROR;
++        LEAVE
++      }
++#endif
++      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
++      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
++      {
++        r = Z_MEM_ERROR;
++        LEAVE
++      }
++      DUMPBITS(14)
++      s->sub.trees.index = 0;
++      Tracev((stderr, "inflate:       table sizes ok\n"));
++      s->mode = BTREE;
++    case BTREE:
++      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
++      {
++        NEEDBITS(3)
++        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
++        DUMPBITS(3)
++      }
++      while (s->sub.trees.index < 19)
++        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
++      s->sub.trees.bb = 7;
++      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
++                             &s->sub.trees.tb, s->hufts, z);
++      if (t != Z_OK)
++      {
++        r = t;
++        if (r == Z_DATA_ERROR)
++        {
++          ZFREE(z, s->sub.trees.blens);
++          s->mode = BAD;
++        }
++        LEAVE
++      }
++      s->sub.trees.index = 0;
++      Tracev((stderr, "inflate:       bits tree ok\n"));
++      s->mode = DTREE;
++    case DTREE:
++      while (t = s->sub.trees.table,
++             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
++      {
++        inflate_huft *h;
++        uInt i, j, c;
++
++        t = s->sub.trees.bb;
++        NEEDBITS(t)
++        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
++        t = h->bits;
++        c = h->base;
++        if (c < 16)
++        {
++          DUMPBITS(t)
++          s->sub.trees.blens[s->sub.trees.index++] = c;
++        }
++        else /* c == 16..18 */
++        {
++          i = c == 18 ? 7 : c - 14;
++          j = c == 18 ? 11 : 3;
++          NEEDBITS(t + i)
++          DUMPBITS(t)
++          j += (uInt)b & inflate_mask[i];
++          DUMPBITS(i)
++          i = s->sub.trees.index;
++          t = s->sub.trees.table;
++          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
++              (c == 16 && i < 1))
++          {
++            ZFREE(z, s->sub.trees.blens);
++            s->mode = BAD;
++            z->msg = (char*)"invalid bit length repeat";
++            r = Z_DATA_ERROR;
++            LEAVE
++          }
++          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
++          do {
++            s->sub.trees.blens[i++] = c;
++          } while (--j);
++          s->sub.trees.index = i;
++        }
++      }
++      s->sub.trees.tb = Z_NULL;
++      {
++        uInt bl, bd;
++        inflate_huft *tl, *td;
++        inflate_codes_statef *c;
++
++        bl = 9;         /* must be <= 9 for lookahead assumptions */
++        bd = 6;         /* must be <= 9 for lookahead assumptions */
++        t = s->sub.trees.table;
++        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
++                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
++                                  s->hufts, z);
++        if (t != Z_OK)
++        {
++          if (t == (uInt)Z_DATA_ERROR)
++          {
++            ZFREE(z, s->sub.trees.blens);
++            s->mode = BAD;
++          }
++          r = t;
++          LEAVE
++        }
++        Tracev((stderr, "inflate:       trees ok\n"));
++        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
++        {
++          r = Z_MEM_ERROR;
++          LEAVE
++        }
++        s->sub.decode.codes = c;
++      }
++      ZFREE(z, s->sub.trees.blens);
++      s->mode = CODES;
++    case CODES:
++      UPDATE
++      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
++        return inflate_flush(s, z, r);
++      r = Z_OK;
++      inflate_codes_free(s->sub.decode.codes, z);
++      LOAD
++      Tracev((stderr, "inflate:       codes end, %lu total out\n",
++              z->total_out + (q >= s->read ? q - s->read :
++              (s->end - s->read) + (q - s->window))));
++      if (!s->last)
++      {
++        s->mode = TYPE;
++        break;
++      }
++      s->mode = DRY;
++    case DRY:
++      FLUSH
++      if (s->read != s->write)
++        LEAVE
++      s->mode = DONE;
++    case DONE:
++      r = Z_STREAM_END;
++      LEAVE
++    case BAD:
++      r = Z_DATA_ERROR;
++      LEAVE
++    default:
++      r = Z_STREAM_ERROR;
++      LEAVE
++  }
++}
++
++
++int inflate_blocks_free(s, z)
++inflate_blocks_statef *s;
++z_streamp z;
++{
++  inflate_blocks_reset(s, z, Z_NULL);
++  ZFREE(z, s->window);
++  ZFREE(z, s->hufts);
++  ZFREE(z, s);
++  Tracev((stderr, "inflate:   blocks freed\n"));
++  return Z_OK;
++}
++
++
++void inflate_set_dictionary(s, d, n)
++inflate_blocks_statef *s;
++const Bytef *d;
++uInt  n;
++{
++  zmemcpy(s->window, d, n);
++  s->read = s->write = s->window + n;
++}
++
++
++/* Returns true if inflate is currently at the end of a block generated
++ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
++ * IN assertion: s != Z_NULL
++ */
++int inflate_blocks_sync_point(s)
++inflate_blocks_statef *s;
++{
++  return s->mode == LENS;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/infblock.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,39 @@
++/* infblock.h -- header to use infblock.c
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++struct inflate_blocks_state;
++typedef struct inflate_blocks_state FAR inflate_blocks_statef;
++
++extern inflate_blocks_statef * inflate_blocks_new OF((
++    z_streamp z,
++    check_func c,               /* check function */
++    uInt w));                   /* window size */
++
++extern int inflate_blocks OF((
++    inflate_blocks_statef *,
++    z_streamp ,
++    int));                      /* initial return code */
++
++extern void inflate_blocks_reset OF((
++    inflate_blocks_statef *,
++    z_streamp ,
++    uLongf *));                  /* check value on output */
++
++extern int inflate_blocks_free OF((
++    inflate_blocks_statef *,
++    z_streamp));
++
++extern void inflate_set_dictionary OF((
++    inflate_blocks_statef *s,
++    const Bytef *d,  /* dictionary */
++    uInt  n));       /* dictionary length */
++
++extern int inflate_blocks_sync_point OF((
++    inflate_blocks_statef *s));
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/infcodes.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,251 @@
++/* infcodes.c -- process literals and length/distance pairs
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++#include <zlib/zutil.h>
++#include "inftrees.h"
++#include "infblock.h"
++#include "infcodes.h"
++#include "infutil.h"
++#include "inffast.h"
++
++/* simplify the use of the inflate_huft type with some defines */
++#define exop word.what.Exop
++#define bits word.what.Bits
++
++typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
++      START,    /* x: set up for LEN */
++      LEN,      /* i: get length/literal/eob next */
++      LENEXT,   /* i: getting length extra (have base) */
++      DIST,     /* i: get distance next */
++      DISTEXT,  /* i: getting distance extra */
++      COPY,     /* o: copying bytes in window, waiting for space */
++      LIT,      /* o: got literal, waiting for output space */
++      WASH,     /* o: got eob, possibly still output waiting */
++      END,      /* x: got eob and all data flushed */
++      BADCODE}  /* x: got error */
++inflate_codes_mode;
++
++/* inflate codes private state */
++struct inflate_codes_state {
++
++  /* mode */
++  inflate_codes_mode mode;      /* current inflate_codes mode */
++
++  /* mode dependent information */
++  uInt len;
++  union {
++    struct {
++      inflate_huft *tree;       /* pointer into tree */
++      uInt need;                /* bits needed */
++    } code;             /* if LEN or DIST, where in tree */
++    uInt lit;           /* if LIT, literal */
++    struct {
++      uInt get;                 /* bits to get for extra */
++      uInt dist;                /* distance back to copy from */
++    } copy;             /* if EXT or COPY, where and how much */
++  } sub;                /* submode */
++
++  /* mode independent information */
++  Byte lbits;           /* ltree bits decoded per branch */
++  Byte dbits;           /* dtree bits decoder per branch */
++  inflate_huft *ltree;          /* literal/length/eob tree */
++  inflate_huft *dtree;          /* distance tree */
++
++};
++
++
++inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
++uInt bl, bd;
++inflate_huft *tl;
++inflate_huft *td; /* need separate declaration for Borland C++ */
++z_streamp z;
++{
++  inflate_codes_statef *c;
++
++  if ((c = (inflate_codes_statef *)
++       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
++  {
++    c->mode = START;
++    c->lbits = (Byte)bl;
++    c->dbits = (Byte)bd;
++    c->ltree = tl;
++    c->dtree = td;
++    Tracev((stderr, "inflate:       codes new\n"));
++  }
++  return c;
++}
++
++
++int inflate_codes(s, z, r)
++inflate_blocks_statef *s;
++z_streamp z;
++int r;
++{
++  uInt j;               /* temporary storage */
++  inflate_huft *t;      /* temporary pointer */
++  uInt e;               /* extra bits or operation */
++  uLong b;              /* bit buffer */
++  uInt k;               /* bits in bit buffer */
++  Bytef *p;             /* input data pointer */
++  uInt n;               /* bytes available there */
++  Bytef *q;             /* output window write pointer */
++  uInt m;               /* bytes to end of window or read pointer */
++  Bytef *f;             /* pointer to copy strings from */
++  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
++
++  /* copy input/output information to locals (UPDATE macro restores) */
++  LOAD
++
++  /* process input and output based on current state */
++  while (1) switch (c->mode)
++  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
++    case START:         /* x: set up for LEN */
++#ifndef SLOW
++      if (m >= 258 && n >= 10)
++      {
++        UPDATE
++        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
++        LOAD
++        if (r != Z_OK)
++        {
++          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
++          break;
++        }
++      }
++#endif /* !SLOW */
++      c->sub.code.need = c->lbits;
++      c->sub.code.tree = c->ltree;
++      c->mode = LEN;
++    case LEN:           /* i: get length/literal/eob next */
++      j = c->sub.code.need;
++      NEEDBITS(j)
++      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
++      DUMPBITS(t->bits)
++      e = (uInt)(t->exop);
++      if (e == 0)               /* literal */
++      {
++        c->sub.lit = t->base;
++        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
++                 "inflate:         literal '%c'\n" :
++                 "inflate:         literal 0x%02x\n", t->base));
++        c->mode = LIT;
++        break;
++      }
++      if (e & 16)               /* length */
++      {
++        c->sub.copy.get = e & 15;
++        c->len = t->base;
++        c->mode = LENEXT;
++        break;
++      }
++      if ((e & 64) == 0)        /* next table */
++      {
++        c->sub.code.need = e;
++        c->sub.code.tree = t + t->base;
++        break;
++      }
++      if (e & 32)               /* end of block */
++      {
++        Tracevv((stderr, "inflate:         end of block\n"));
++        c->mode = WASH;
++        break;
++      }
++      c->mode = BADCODE;        /* invalid code */
++      z->msg = (char*)"invalid literal/length code";
++      r = Z_DATA_ERROR;
++      LEAVE
++    case LENEXT:        /* i: getting length extra (have base) */
++      j = c->sub.copy.get;
++      NEEDBITS(j)
++      c->len += (uInt)b & inflate_mask[j];
++      DUMPBITS(j)
++      c->sub.code.need = c->dbits;
++      c->sub.code.tree = c->dtree;
++      Tracevv((stderr, "inflate:         length %u\n", c->len));
++      c->mode = DIST;
++    case DIST:          /* i: get distance next */
++      j = c->sub.code.need;
++      NEEDBITS(j)
++      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
++      DUMPBITS(t->bits)
++      e = (uInt)(t->exop);
++      if (e & 16)               /* distance */
++      {
++        c->sub.copy.get = e & 15;
++        c->sub.copy.dist = t->base;
++        c->mode = DISTEXT;
++        break;
++      }
++      if ((e & 64) == 0)        /* next table */
++      {
++        c->sub.code.need = e;
++        c->sub.code.tree = t + t->base;
++        break;
++      }
++      c->mode = BADCODE;        /* invalid code */
++      z->msg = (char*)"invalid distance code";
++      r = Z_DATA_ERROR;
++      LEAVE
++    case DISTEXT:       /* i: getting distance extra */
++      j = c->sub.copy.get;
++      NEEDBITS(j)
++      c->sub.copy.dist += (uInt)b & inflate_mask[j];
++      DUMPBITS(j)
++      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
++      c->mode = COPY;
++    case COPY:          /* o: copying bytes in window, waiting for space */
++      f = q - c->sub.copy.dist;
++      while (f < s->window)             /* modulo window size-"while" instead */
++        f += s->end - s->window;        /* of "if" handles invalid distances */
++      while (c->len)
++      {
++        NEEDOUT
++        OUTBYTE(*f++)
++        if (f == s->end)
++          f = s->window;
++        c->len--;
++      }
++      c->mode = START;
++      break;
++    case LIT:           /* o: got literal, waiting for output space */
++      NEEDOUT
++      OUTBYTE(c->sub.lit)
++      c->mode = START;
++      break;
++    case WASH:          /* o: got eob, possibly more output */
++      if (k > 7)        /* return unused byte, if any */
++      {
++        Assert(k < 16, "inflate_codes grabbed too many bytes")
++        k -= 8;
++        n++;
++        p--;            /* can always return one */
++      }
++      FLUSH
++      if (s->read != s->write)
++        LEAVE
++      c->mode = END;
++    case END:
++      r = Z_STREAM_END;
++      LEAVE
++    case BADCODE:       /* x: got error */
++      r = Z_DATA_ERROR;
++      LEAVE
++    default:
++      r = Z_STREAM_ERROR;
++      LEAVE
++  }
++#ifdef NEED_DUMMY_RETURN
++  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
++#endif
++}
++
++
++void inflate_codes_free(c, z)
++inflate_codes_statef *c;
++z_streamp z;
++{
++  ZFREE(z, c);
++  Tracev((stderr, "inflate:       codes free\n"));
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/infcodes.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,31 @@
++/* infcodes.h -- header to use infcodes.c
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++#ifndef _INFCODES_H
++#define _INFCODES_H
++
++struct inflate_codes_state;
++typedef struct inflate_codes_state FAR inflate_codes_statef;
++
++extern inflate_codes_statef *inflate_codes_new OF((
++    uInt, uInt,
++    inflate_huft *, inflate_huft *,
++    z_streamp ));
++
++extern int inflate_codes OF((
++    inflate_blocks_statef *,
++    z_streamp ,
++    int));
++
++extern void inflate_codes_free OF((
++    inflate_codes_statef *,
++    z_streamp ));
++
++#endif /* _INFCODES_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/inffast.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,183 @@
++/* inffast.c -- process literals and length/distance pairs fast
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++#include <zlib/zutil.h>
++#include "inftrees.h"
++#include "infblock.h"
++#include "infcodes.h"
++#include "infutil.h"
++#include "inffast.h"
++
++struct inflate_codes_state {int dummy;}; /* for buggy compilers */
++
++/* simplify the use of the inflate_huft type with some defines */
++#define exop word.what.Exop
++#define bits word.what.Bits
++
++/* macros for bit input with no checking and for returning unused bytes */
++#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
++#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
++
++/* Called with number of bytes left to write in window at least 258
++   (the maximum string length) and number of input bytes available
++   at least ten.  The ten bytes are six bytes for the longest length/
++   distance pair plus four bytes for overloading the bit buffer. */
++
++int inflate_fast(bl, bd, tl, td, s, z)
++uInt bl, bd;
++inflate_huft *tl;
++inflate_huft *td; /* need separate declaration for Borland C++ */
++inflate_blocks_statef *s;
++z_streamp z;
++{
++  inflate_huft *t;      /* temporary pointer */
++  uInt e;               /* extra bits or operation */
++  uLong b;              /* bit buffer */
++  uInt k;               /* bits in bit buffer */
++  Bytef *p;             /* input data pointer */
++  uInt n;               /* bytes available there */
++  Bytef *q;             /* output window write pointer */
++  uInt m;               /* bytes to end of window or read pointer */
++  uInt ml;              /* mask for literal/length tree */
++  uInt md;              /* mask for distance tree */
++  uInt c;               /* bytes to copy */
++  uInt d;               /* distance back to copy from */
++  Bytef *r;             /* copy source pointer */
++
++  /* load input, output, bit values */
++  LOAD
++
++  /* initialize masks */
++  ml = inflate_mask[bl];
++  md = inflate_mask[bd];
++
++  /* do until not enough input or output space for fast loop */
++  do {                          /* assume called with m >= 258 && n >= 10 */
++    /* get literal/length code */
++    GRABBITS(20)                /* max bits for literal/length code */
++    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
++    {
++      DUMPBITS(t->bits)
++      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
++                "inflate:         * literal '%c'\n" :
++                "inflate:         * literal 0x%02x\n", t->base));
++      *q++ = (Byte)t->base;
++      m--;
++      continue;
++    }
++    do {
++      DUMPBITS(t->bits)
++      if (e & 16)
++      {
++        /* get extra bits for length */
++        e &= 15;
++        c = t->base + ((uInt)b & inflate_mask[e]);
++        DUMPBITS(e)
++        Tracevv((stderr, "inflate:         * length %u\n", c));
++
++        /* decode distance base of block to copy */
++        GRABBITS(15);           /* max bits for distance code */
++        e = (t = td + ((uInt)b & md))->exop;
++        do {
++          DUMPBITS(t->bits)
++          if (e & 16)
++          {
++            /* get extra bits to add to distance base */
++            e &= 15;
++            GRABBITS(e)         /* get extra bits (up to 13) */
++            d = t->base + ((uInt)b & inflate_mask[e]);
++            DUMPBITS(e)
++            Tracevv((stderr, "inflate:         * distance %u\n", d));
++
++            /* do the copy */
++            m -= c;
++            r = q - d;
++            if (r < s->window)                  /* wrap if needed */
++            {
++              do {
++                r += s->end - s->window;        /* force pointer in window */
++              } while (r < s->window);          /* covers invalid distances */
++              e = s->end - r;
++              if (c > e)
++              {
++                c -= e;                         /* wrapped copy */
++                do {
++                    *q++ = *r++;
++                } while (--e);
++                r = s->window;
++                do {
++                    *q++ = *r++;
++                } while (--c);
++              }
++              else                              /* normal copy */
++              {
++                *q++ = *r++;  c--;
++                *q++ = *r++;  c--;
++                do {
++                    *q++ = *r++;
++                } while (--c);
++              }
++            }
++            else                                /* normal copy */
++            {
++              *q++ = *r++;  c--;
++              *q++ = *r++;  c--;
++              do {
++                *q++ = *r++;
++              } while (--c);
++            }
++            break;
++          }
++          else if ((e & 64) == 0)
++          {
++            t += t->base;
++            e = (t += ((uInt)b & inflate_mask[e]))->exop;
++          }
++          else
++          {
++            z->msg = (char*)"invalid distance code";
++            UNGRAB
++            UPDATE
++            return Z_DATA_ERROR;
++          }
++        } while (1);
++        break;
++      }
++      if ((e & 64) == 0)
++      {
++        t += t->base;
++        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
++        {
++          DUMPBITS(t->bits)
++          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
++                    "inflate:         * literal '%c'\n" :
++                    "inflate:         * literal 0x%02x\n", t->base));
++          *q++ = (Byte)t->base;
++          m--;
++          break;
++        }
++      }
++      else if (e & 32)
++      {
++        Tracevv((stderr, "inflate:         * end of block\n"));
++        UNGRAB
++        UPDATE
++        return Z_STREAM_END;
++      }
++      else
++      {
++        z->msg = (char*)"invalid literal/length code";
++        UNGRAB
++        UPDATE
++        return Z_DATA_ERROR;
++      }
++    } while (1);
++  } while (m >= 258 && n >= 10);
++
++  /* not enough input or output--restore pointers and return */
++  UNGRAB
++  UPDATE
++  return Z_OK;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/inffast.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,22 @@
++/* inffast.h -- header to use inffast.c
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++#ifndef _INFFAST_H
++#define _INFFAST_H
++
++extern int inflate_fast OF((
++    uInt,
++    uInt,
++    inflate_huft *,
++    inflate_huft *,
++    inflate_blocks_statef *,
++    z_streamp ));
++
++#endif /* _INFFAST_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/inffixed.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,151 @@
++/* inffixed.h -- table for decoding fixed codes
++ * Generated automatically by the maketree.c program
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++local uInt fixed_bl = 9;
++local uInt fixed_bd = 5;
++local inflate_huft fixed_tl[] = {
++    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
++    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
++    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
++    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
++    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
++    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
++    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
++    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
++    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
++    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
++    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
++    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
++    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
++    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
++    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
++    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
++    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
++    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
++    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
++    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
++    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
++    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
++    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
++    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
++    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
++    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
++    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
++    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
++    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
++    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
++    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
++    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
++    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
++    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
++    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
++    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
++    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
++    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
++    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
++    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
++    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
++    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
++    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
++    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
++    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
++    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
++    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
++    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
++    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
++    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
++    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
++    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
++    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
++    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
++    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
++    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
++    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
++    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
++    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
++    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
++    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
++    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
++    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
++    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
++    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
++    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
++    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
++    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
++    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
++    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
++    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
++    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
++    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
++    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
++    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
++    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
++    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
++    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
++    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
++    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
++    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
++    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
++    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
++    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
++    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
++    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
++    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
++    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
++    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
++    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
++    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
++    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
++    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
++    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
++    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
++    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
++    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
++    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
++    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
++    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
++    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
++    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
++    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
++    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
++    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
++    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
++    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
++    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
++    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
++    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
++    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
++    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
++    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
++    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
++    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
++    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
++    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
++    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
++    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
++    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
++    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
++    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
++    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
++    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
++    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
++    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
++    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
++    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
++  };
++local inflate_huft fixed_td[] = {
++    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
++    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
++    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
++    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
++    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
++    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
++    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
++    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
++  };
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/inflate.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,368 @@
++/* inflate.c -- zlib interface to inflate modules
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++#include <zlib/zutil.h>
++#include "infblock.h"
++
++struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
++
++typedef enum {
++      METHOD,   /* waiting for method byte */
++      FLAG,     /* waiting for flag byte */
++      DICT4,    /* four dictionary check bytes to go */
++      DICT3,    /* three dictionary check bytes to go */
++      DICT2,    /* two dictionary check bytes to go */
++      DICT1,    /* one dictionary check byte to go */
++      DICT0,    /* waiting for inflateSetDictionary */
++      BLOCKS,   /* decompressing blocks */
++      CHECK4,   /* four check bytes to go */
++      CHECK3,   /* three check bytes to go */
++      CHECK2,   /* two check bytes to go */
++      CHECK1,   /* one check byte to go */
++      DONE,     /* finished check, done */
++      BAD}      /* got an error--stay here */
++inflate_mode;
++
++/* inflate private state */
++struct internal_state {
++
++  /* mode */
++  inflate_mode  mode;   /* current inflate mode */
++
++  /* mode dependent information */
++  union {
++    uInt method;        /* if FLAGS, method byte */
++    struct {
++      uLong was;                /* computed check value */
++      uLong need;               /* stream check value */
++    } check;            /* if CHECK, check values to compare */
++    uInt marker;        /* if BAD, inflateSync's marker bytes count */
++  } sub;        /* submode */
++
++  /* mode independent information */
++  int  nowrap;          /* flag for no wrapper */
++  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
++  inflate_blocks_statef 
++    *blocks;            /* current inflate_blocks state */
++
++};
++
++
++int ZEXPORT inflateReset(z)
++z_streamp z;
++{
++  if (z == Z_NULL || z->state == Z_NULL)
++    return Z_STREAM_ERROR;
++  z->total_in = z->total_out = 0;
++  z->msg = Z_NULL;
++  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
++  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
++  Tracev((stderr, "inflate: reset\n"));
++  return Z_OK;
++}
++
++
++int ZEXPORT inflateEnd(z)
++z_streamp z;
++{
++  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
++    return Z_STREAM_ERROR;
++  if (z->state->blocks != Z_NULL)
++    inflate_blocks_free(z->state->blocks, z);
++  ZFREE(z, z->state);
++  z->state = Z_NULL;
++  Tracev((stderr, "inflate: end\n"));
++  return Z_OK;
++}
++
++
++int ZEXPORT inflateInit2_(z, w, version, stream_size)
++z_streamp z;
++int w;
++const char *version;
++int stream_size;
++{
++  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
++      stream_size != sizeof(z_stream))
++      return Z_VERSION_ERROR;
++
++  /* initialize state */
++  if (z == Z_NULL)
++    return Z_STREAM_ERROR;
++  z->msg = Z_NULL;
++  if (z->zalloc == Z_NULL)
++  {
++    return Z_STREAM_ERROR;
++/*    z->zalloc = zcalloc;
++    z->opaque = (voidpf)0;
++*/
++  }
++  if (z->zfree == Z_NULL) return Z_STREAM_ERROR; /* z->zfree = zcfree; */
++  if ((z->state = (struct internal_state FAR *)
++       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
++    return Z_MEM_ERROR;
++  z->state->blocks = Z_NULL;
++
++  /* handle undocumented nowrap option (no zlib header or check) */
++  z->state->nowrap = 0;
++  if (w < 0)
++  {
++    w = - w;
++    z->state->nowrap = 1;
++  }
++
++  /* set window size */
++  if (w < 8 || w > 15)
++  {
++    inflateEnd(z);
++    return Z_STREAM_ERROR;
++  }
++  z->state->wbits = (uInt)w;
++
++  /* create inflate_blocks state */
++  if ((z->state->blocks =
++      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
++      == Z_NULL)
++  {
++    inflateEnd(z);
++    return Z_MEM_ERROR;
++  }
++  Tracev((stderr, "inflate: allocated\n"));
++
++  /* reset state */
++  inflateReset(z);
++  return Z_OK;
++}
++
++
++int ZEXPORT inflateInit_(z, version, stream_size)
++z_streamp z;
++const char *version;
++int stream_size;
++{
++  return inflateInit2_(z, DEF_WBITS, version, stream_size);
++}
++
++
++#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
++#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
++
++int ZEXPORT inflate(z, f)
++z_streamp z;
++int f;
++{
++  int r;
++  uInt b;
++
++  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
++    return Z_STREAM_ERROR;
++  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
++  r = Z_BUF_ERROR;
++  while (1) switch (z->state->mode)
++  {
++    case METHOD:
++      NEEDBYTE
++      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
++      {
++        z->state->mode = BAD;
++        z->msg = (char*)"unknown compression method";
++        z->state->sub.marker = 5;       /* can't try inflateSync */
++        break;
++      }
++      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
++      {
++        z->state->mode = BAD;
++        z->msg = (char*)"invalid window size";
++        z->state->sub.marker = 5;       /* can't try inflateSync */
++        break;
++      }
++      z->state->mode = FLAG;
++    case FLAG:
++      NEEDBYTE
++      b = NEXTBYTE;
++      if (((z->state->sub.method << 8) + b) % 31)
++      {
++        z->state->mode = BAD;
++        z->msg = (char*)"incorrect header check";
++        z->state->sub.marker = 5;       /* can't try inflateSync */
++        break;
++      }
++      Tracev((stderr, "inflate: zlib header ok\n"));
++      if (!(b & PRESET_DICT))
++      {
++        z->state->mode = BLOCKS;
++        break;
++      }
++      z->state->mode = DICT4;
++    case DICT4:
++      NEEDBYTE
++      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
++      z->state->mode = DICT3;
++    case DICT3:
++      NEEDBYTE
++      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
++      z->state->mode = DICT2;
++    case DICT2:
++      NEEDBYTE
++      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
++      z->state->mode = DICT1;
++    case DICT1:
++      NEEDBYTE
++      z->state->sub.check.need += (uLong)NEXTBYTE;
++      z->adler = z->state->sub.check.need;
++      z->state->mode = DICT0;
++      return Z_NEED_DICT;
++    case DICT0:
++      z->state->mode = BAD;
++      z->msg = (char*)"need dictionary";
++      z->state->sub.marker = 0;       /* can try inflateSync */
++      return Z_STREAM_ERROR;
++    case BLOCKS:
++      r = inflate_blocks(z->state->blocks, z, r);
++      if (r == Z_DATA_ERROR)
++      {
++        z->state->mode = BAD;
++        z->state->sub.marker = 0;       /* can try inflateSync */
++        break;
++      }
++      if (r == Z_OK)
++        r = f;
++      if (r != Z_STREAM_END)
++        return r;
++      r = f;
++      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
++      if (z->state->nowrap)
++      {
++        z->state->mode = DONE;
++        break;
++      }
++      z->state->mode = CHECK4;
++    case CHECK4:
++      NEEDBYTE
++      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
++      z->state->mode = CHECK3;
++    case CHECK3:
++      NEEDBYTE
++      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
++      z->state->mode = CHECK2;
++    case CHECK2:
++      NEEDBYTE
++      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
++      z->state->mode = CHECK1;
++    case CHECK1:
++      NEEDBYTE
++      z->state->sub.check.need += (uLong)NEXTBYTE;
++
++      if (z->state->sub.check.was != z->state->sub.check.need)
++      {
++        z->state->mode = BAD;
++        z->msg = (char*)"incorrect data check";
++        z->state->sub.marker = 5;       /* can't try inflateSync */
++        break;
++      }
++      Tracev((stderr, "inflate: zlib check ok\n"));
++      z->state->mode = DONE;
++    case DONE:
++      return Z_STREAM_END;
++    case BAD:
++      return Z_DATA_ERROR;
++    default:
++      return Z_STREAM_ERROR;
++  }
++#ifdef NEED_DUMMY_RETURN
++  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
++#endif
++}
++
++
++int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
++z_streamp z;
++const Bytef *dictionary;
++uInt  dictLength;
++{
++  uInt length = dictLength;
++
++  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
++    return Z_STREAM_ERROR;
++
++  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
++  z->adler = 1L;
++
++  if (length >= ((uInt)1<<z->state->wbits))
++  {
++    length = (1<<z->state->wbits)-1;
++    dictionary += dictLength - length;
++  }
++  inflate_set_dictionary(z->state->blocks, dictionary, length);
++  z->state->mode = BLOCKS;
++  return Z_OK;
++}
++
++
++int ZEXPORT inflateSync(z)
++z_streamp z;
++{
++  uInt n;       /* number of bytes to look at */
++  Bytef *p;     /* pointer to bytes */
++  uInt m;       /* number of marker bytes found in a row */
++  uLong r, w;   /* temporaries to save total_in and total_out */
++
++  /* set up */
++  if (z == Z_NULL || z->state == Z_NULL)
++    return Z_STREAM_ERROR;
++  if (z->state->mode != BAD)
++  {
++    z->state->mode = BAD;
++    z->state->sub.marker = 0;
++  }
++  if ((n = z->avail_in) == 0)
++    return Z_BUF_ERROR;
++  p = z->next_in;
++  m = z->state->sub.marker;
++
++  /* search */
++  while (n && m < 4)
++  {
++    static const Byte mark[4] = {0, 0, 0xff, 0xff};
++    if (*p == mark[m])
++      m++;
++    else if (*p)
++      m = 0;
++    else
++      m = 4 - m;
++    p++, n--;
++  }
++
++  /* restore */
++  z->total_in += p - z->next_in;
++  z->next_in = p;
++  z->avail_in = n;
++  z->state->sub.marker = m;
++
++  /* return no joy or set up to restart on a new block */
++  if (m != 4)
++    return Z_DATA_ERROR;
++  r = z->total_in;  w = z->total_out;
++  inflateReset(z);
++  z->total_in = r;  z->total_out = w;
++  z->state->mode = BLOCKS;
++  return Z_OK;
++}
++
++
++/* Returns true if inflate is currently at the end of a block generated
++ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
++ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
++ * but removes the length bytes of the resulting empty stored block. When
++ * decompressing, PPP checks that at the end of input packet, inflate is
++ * waiting for these length bytes.
++ */
++int ZEXPORT inflateSyncPoint(z)
++z_streamp z;
++{
++  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
++    return Z_STREAM_ERROR;
++  return inflate_blocks_sync_point(z->state->blocks);
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/inftrees.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,454 @@
++/* inftrees.c -- generate Huffman trees for efficient decoding
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++#include <zlib/zutil.h>
++#include "inftrees.h"
++
++#if !defined(BUILDFIXED) && !defined(STDC)
++#  define BUILDFIXED   /* non ANSI compilers may not accept inffixed.h */
++#endif
++
++local const char inflate_copyright[] =
++   " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
++/*
++  If you use the zlib library in a product, an acknowledgment is welcome
++  in the documentation of your product. If for some reason you cannot
++  include such an acknowledgment, I would appreciate that you keep this
++  copyright string in the executable of your product.
++ */
++struct internal_state  {int dummy;}; /* for buggy compilers */
++
++/* simplify the use of the inflate_huft type with some defines */
++#define exop word.what.Exop
++#define bits word.what.Bits
++
++
++local int huft_build OF((
++    uIntf *,            /* code lengths in bits */
++    uInt,               /* number of codes */
++    uInt,               /* number of "simple" codes */
++    const uIntf *,      /* list of base values for non-simple codes */
++    const uIntf *,      /* list of extra bits for non-simple codes */
++    inflate_huft * FAR*,/* result: starting table */
++    uIntf *,            /* maximum lookup bits (returns actual) */
++    inflate_huft *,     /* space for trees */
++    uInt *,             /* hufts used in space */
++    uIntf * ));         /* space for values */
++
++/* Tables for deflate from PKZIP's appnote.txt. */
++local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
++        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
++        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
++        /* see note #13 above about 258 */
++local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
++        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
++        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
++local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
++        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
++        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
++        8193, 12289, 16385, 24577};
++local const uInt cpdext[30] = { /* Extra bits for distance codes */
++        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
++        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
++        12, 12, 13, 13};
++
++/*
++   Huffman code decoding is performed using a multi-level table lookup.
++   The fastest way to decode is to simply build a lookup table whose
++   size is determined by the longest code.  However, the time it takes
++   to build this table can also be a factor if the data being decoded
++   is not very long.  The most common codes are necessarily the
++   shortest codes, so those codes dominate the decoding time, and hence
++   the speed.  The idea is you can have a shorter table that decodes the
++   shorter, more probable codes, and then point to subsidiary tables for
++   the longer codes.  The time it costs to decode the longer codes is
++   then traded against the time it takes to make longer tables.
++
++   This results of this trade are in the variables lbits and dbits
++   below.  lbits is the number of bits the first level table for literal/
++   length codes can decode in one step, and dbits is the same thing for
++   the distance codes.  Subsequent tables are also less than or equal to
++   those sizes.  These values may be adjusted either when all of the
++   codes are shorter than that, in which case the longest code length in
++   bits is used, or when the shortest code is *longer* than the requested
++   table size, in which case the length of the shortest code in bits is
++   used.
++
++   There are two different values for the two tables, since they code a
++   different number of possibilities each.  The literal/length table
++   codes 286 possible values, or in a flat code, a little over eight
++   bits.  The distance table codes 30 possible values, or a little less
++   than five bits, flat.  The optimum values for speed end up being
++   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
++   The optimum values may differ though from machine to machine, and
++   possibly even between compilers.  Your mileage may vary.
++ */
++
++
++/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
++#define BMAX 15         /* maximum bit length of any code */
++
++local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
++uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
++uInt n;                 /* number of codes (assumed <= 288) */
++uInt s;                 /* number of simple-valued codes (0..s-1) */
++const uIntf *d;         /* list of base values for non-simple codes */
++const uIntf *e;         /* list of extra bits for non-simple codes */
++inflate_huft * FAR *t;  /* result: starting table */
++uIntf *m;               /* maximum lookup bits, returns actual */
++inflate_huft *hp;       /* space for trees */
++uInt *hn;               /* hufts used in space */
++uIntf *v;               /* working area: values in order of bit length */
++/* Given a list of code lengths and a maximum table size, make a set of
++   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
++   if the given code set is incomplete (the tables are still built in this
++   case), or Z_DATA_ERROR if the input is invalid. */
++{
++
++  uInt a;                       /* counter for codes of length k */
++  uInt c[BMAX+1];               /* bit length count table */
++  uInt f;                       /* i repeats in table every f entries */
++  int g;                        /* maximum code length */
++  int h;                        /* table level */
++  register uInt i;              /* counter, current code */
++  register uInt j;              /* counter */
++  register int k;               /* number of bits in current code */
++  int l;                        /* bits per table (returned in m) */
++  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
++  register uIntf *p;            /* pointer into c[], b[], or v[] */
++  inflate_huft *q;              /* points to current table */
++  struct inflate_huft_s r;      /* table entry for structure assignment */
++  inflate_huft *u[BMAX];        /* table stack */
++  register int w;               /* bits before this table == (l * h) */
++  uInt x[BMAX+1];               /* bit offsets, then code stack */
++  uIntf *xp;                    /* pointer into x */
++  int y;                        /* number of dummy codes added */
++  uInt z;                       /* number of entries in current table */
++
++
++  /* Generate counts for each bit length */
++  p = c;
++#define C0 *p++ = 0;
++#define C2 C0 C0 C0 C0
++#define C4 C2 C2 C2 C2
++  C4                            /* clear c[]--assume BMAX+1 is 16 */
++  p = b;  i = n;
++  do {
++    c[*p++]++;                  /* assume all entries <= BMAX */
++  } while (--i);
++  if (c[0] == n)                /* null input--all zero length codes */
++  {
++    *t = (inflate_huft *)Z_NULL;
++    *m = 0;
++    return Z_OK;
++  }
++
++
++  /* Find minimum and maximum length, bound *m by those */
++  l = *m;
++  for (j = 1; j <= BMAX; j++)
++    if (c[j])
++      break;
++  k = j;                        /* minimum code length */
++  if ((uInt)l < j)
++    l = j;
++  for (i = BMAX; i; i--)
++    if (c[i])
++      break;
++  g = i;                        /* maximum code length */
++  if ((uInt)l > i)
++    l = i;
++  *m = l;
++
++
++  /* Adjust last length count to fill out codes, if needed */
++  for (y = 1 << j; j < i; j++, y <<= 1)
++    if ((y -= c[j]) < 0)
++      return Z_DATA_ERROR;
++  if ((y -= c[i]) < 0)
++    return Z_DATA_ERROR;
++  c[i] += y;
++
++
++  /* Generate starting offsets into the value table for each length */
++  x[1] = j = 0;
++  p = c + 1;  xp = x + 2;
++  while (--i) {                 /* note that i == g from above */
++    *xp++ = (j += *p++);
++  }
++
++
++  /* Make a table of values in order of bit lengths */
++  p = b;  i = 0;
++  do {
++    if ((j = *p++) != 0)
++      v[x[j]++] = i;
++  } while (++i < n);
++  n = x[g];                     /* set n to length of v */
++
++
++  /* Generate the Huffman codes and for each, make the table entries */
++  x[0] = i = 0;                 /* first Huffman code is zero */
++  p = v;                        /* grab values in bit order */
++  h = -1;                       /* no tables yet--level -1 */
++  w = -l;                       /* bits decoded == (l * h) */
++  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
++  q = (inflate_huft *)Z_NULL;   /* ditto */
++  z = 0;                        /* ditto */
++
++  /* go through the bit lengths (k already is bits in shortest code) */
++  for (; k <= g; k++)
++  {
++    a = c[k];
++    while (a--)
++    {
++      /* here i is the Huffman code of length k bits for value *p */
++      /* make tables up to required level */
++      while (k > w + l)
++      {
++        h++;
++        w += l;                 /* previous table always l bits */
++
++        /* compute minimum size table less than or equal to l bits */
++        z = g - w;
++        z = z > (uInt)l ? l : z;        /* table size upper limit */
++        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
++        {                       /* too few codes for k-w bit table */
++          f -= a + 1;           /* deduct codes from patterns left */
++          xp = c + k;
++          if (j < z)
++            while (++j < z)     /* try smaller tables up to z bits */
++            {
++              if ((f <<= 1) <= *++xp)
++                break;          /* enough codes to use up j bits */
++              f -= *xp;         /* else deduct codes from patterns */
++            }
++        }
++        z = 1 << j;             /* table entries for j-bit table */
++
++        /* allocate new table */
++        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
++          return Z_DATA_ERROR;  /* overflow of MANY */
++        u[h] = q = hp + *hn;
++        *hn += z;
++
++        /* connect to last table, if there is one */
++        if (h)
++        {
++          x[h] = i;             /* save pattern for backing up */
++          r.bits = (Byte)l;     /* bits to dump before this table */
++          r.exop = (Byte)j;     /* bits in this table */
++          j = i >> (w - l);
++          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
++          u[h-1][j] = r;        /* connect to last table */
++        }
++        else
++          *t = q;               /* first table is returned result */
++      }
++
++      /* set up table entry in r */
++      r.bits = (Byte)(k - w);
++      if (p >= v + n)
++        r.exop = 128 + 64;      /* out of values--invalid code */
++      else if (*p < s)
++      {
++        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
++        r.base = *p++;          /* simple code is just the value */
++      }
++      else
++      {
++        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
++        r.base = d[*p++ - s];
++      }
++
++      /* fill code-like entries with r */
++      f = 1 << (k - w);
++      for (j = i >> w; j < z; j += f)
++        q[j] = r;
++
++      /* backwards increment the k-bit code i */
++      for (j = 1 << (k - 1); i & j; j >>= 1)
++        i ^= j;
++      i ^= j;
++
++      /* backup over finished tables */
++      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
++      while ((i & mask) != x[h])
++      {
++        h--;                    /* don't need to update q */
++        w -= l;
++        mask = (1 << w) - 1;
++      }
++    }
++  }
++
++
++  /* Return Z_BUF_ERROR if we were given an incomplete table */
++  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
++}
++
++
++int inflate_trees_bits(c, bb, tb, hp, z)
++uIntf *c;               /* 19 code lengths */
++uIntf *bb;              /* bits tree desired/actual depth */
++inflate_huft * FAR *tb; /* bits tree result */
++inflate_huft *hp;       /* space for trees */
++z_streamp z;            /* for messages */
++{
++  int r;
++  uInt hn = 0;          /* hufts used in space */
++  uIntf *v;             /* work area for huft_build */
++
++  if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
++    return Z_MEM_ERROR;
++  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
++                 tb, bb, hp, &hn, v);
++  if (r == Z_DATA_ERROR)
++    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
++  else if (r == Z_BUF_ERROR || *bb == 0)
++  {
++    z->msg = (char*)"incomplete dynamic bit lengths tree";
++    r = Z_DATA_ERROR;
++  }
++  ZFREE(z, v);
++  return r;
++}
++
++
++int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
++uInt nl;                /* number of literal/length codes */
++uInt nd;                /* number of distance codes */
++uIntf *c;               /* that many (total) code lengths */
++uIntf *bl;              /* literal desired/actual bit depth */
++uIntf *bd;              /* distance desired/actual bit depth */
++inflate_huft * FAR *tl; /* literal/length tree result */
++inflate_huft * FAR *td; /* distance tree result */
++inflate_huft *hp;       /* space for trees */
++z_streamp z;            /* for messages */
++{
++  int r;
++  uInt hn = 0;          /* hufts used in space */
++  uIntf *v;             /* work area for huft_build */
++
++  /* allocate work area */
++  if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
++    return Z_MEM_ERROR;
++
++  /* build literal/length tree */
++  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
++  if (r != Z_OK || *bl == 0)
++  {
++    if (r == Z_DATA_ERROR)
++      z->msg = (char*)"oversubscribed literal/length tree";
++    else if (r != Z_MEM_ERROR)
++    {
++      z->msg = (char*)"incomplete literal/length tree";
++      r = Z_DATA_ERROR;
++    }
++    ZFREE(z, v);
++    return r;
++  }
++
++  /* build distance tree */
++  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
++  if (r != Z_OK || (*bd == 0 && nl > 257))
++  {
++    if (r == Z_DATA_ERROR)
++      z->msg = (char*)"oversubscribed distance tree";
++    else if (r == Z_BUF_ERROR) {
++#ifdef PKZIP_BUG_WORKAROUND
++      r = Z_OK;
++    }
++#else
++      z->msg = (char*)"incomplete distance tree";
++      r = Z_DATA_ERROR;
++    }
++    else if (r != Z_MEM_ERROR)
++    {
++      z->msg = (char*)"empty distance tree with lengths";
++      r = Z_DATA_ERROR;
++    }
++    ZFREE(z, v);
++    return r;
++#endif
++  }
++
++  /* done */
++  ZFREE(z, v);
++  return Z_OK;
++}
++
++
++/* build fixed tables only once--keep them here */
++#ifdef BUILDFIXED
++local int fixed_built = 0;
++#define FIXEDH 544      /* number of hufts used by fixed tables */
++local inflate_huft fixed_mem[FIXEDH];
++local uInt fixed_bl;
++local uInt fixed_bd;
++local inflate_huft *fixed_tl;
++local inflate_huft *fixed_td;
++#else
++#include "inffixed.h"
++#endif
++
++
++int inflate_trees_fixed(bl, bd, tl, td, z)
++uIntf *bl;               /* literal desired/actual bit depth */
++uIntf *bd;               /* distance desired/actual bit depth */
++inflate_huft * FAR *tl;  /* literal/length tree result */
++inflate_huft * FAR *td;  /* distance tree result */
++z_streamp z;             /* for memory allocation */
++{
++#ifdef BUILDFIXED
++  /* build fixed tables if not already */
++  if (!fixed_built)
++  {
++    int k;              /* temporary variable */
++    uInt f = 0;         /* number of hufts used in fixed_mem */
++    uIntf *c;           /* length list for huft_build */
++    uIntf *v;           /* work area for huft_build */
++
++    /* allocate memory */
++    if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
++      return Z_MEM_ERROR;
++    if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
++    {
++      ZFREE(z, c);
++      return Z_MEM_ERROR;
++    }
++
++    /* literal table */
++    for (k = 0; k < 144; k++)
++      c[k] = 8;
++    for (; k < 256; k++)
++      c[k] = 9;
++    for (; k < 280; k++)
++      c[k] = 7;
++    for (; k < 288; k++)
++      c[k] = 8;
++    fixed_bl = 9;
++    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
++               fixed_mem, &f, v);
++
++    /* distance table */
++    for (k = 0; k < 30; k++)
++      c[k] = 5;
++    fixed_bd = 5;
++    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
++               fixed_mem, &f, v);
++
++    /* done */
++    ZFREE(z, v);
++    ZFREE(z, c);
++    fixed_built = 1;
++  }
++#endif
++  *bl = fixed_bl;
++  *bd = fixed_bd;
++  *tl = fixed_tl;
++  *td = fixed_td;
++  return Z_OK;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/inftrees.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,63 @@
++/* inftrees.h -- header to use inftrees.c
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++/* Huffman code lookup table entry--this entry is four bytes for machines
++   that have 16-bit pointers (e.g. PC's in the small or medium model). */
++
++#ifndef _INFTREES_H
++#define _INFTREES_H
++
++typedef struct inflate_huft_s FAR inflate_huft;
++
++struct inflate_huft_s {
++  union {
++    struct {
++      Byte Exop;        /* number of extra bits or operation */
++      Byte Bits;        /* number of bits in this code or subcode */
++    } what;
++    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
++  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
++  uInt base;            /* literal, length base, distance base,
++                           or table offset */
++};
++
++/* Maximum size of dynamic tree.  The maximum found in a long but non-
++   exhaustive search was 1004 huft structures (850 for length/literals
++   and 154 for distances, the latter actually the result of an
++   exhaustive search).  The actual maximum is not known, but the
++   value below is more than safe. */
++#define MANY 1440
++
++extern int inflate_trees_bits OF((
++    uIntf *,                    /* 19 code lengths */
++    uIntf *,                    /* bits tree desired/actual depth */
++    inflate_huft * FAR *,       /* bits tree result */
++    inflate_huft *,             /* space for trees */
++    z_streamp));                /* for messages */
++
++extern int inflate_trees_dynamic OF((
++    uInt,                       /* number of literal/length codes */
++    uInt,                       /* number of distance codes */
++    uIntf *,                    /* that many (total) code lengths */
++    uIntf *,                    /* literal desired/actual bit depth */
++    uIntf *,                    /* distance desired/actual bit depth */
++    inflate_huft * FAR *,       /* literal/length tree result */
++    inflate_huft * FAR *,       /* distance tree result */
++    inflate_huft *,             /* space for trees */
++    z_streamp));                /* for messages */
++
++extern int inflate_trees_fixed OF((
++    uIntf *,                    /* literal desired/actual bit depth */
++    uIntf *,                    /* distance desired/actual bit depth */
++    inflate_huft * FAR *,       /* literal/length tree result */
++    inflate_huft * FAR *,       /* distance tree result */
++    z_streamp));                /* for memory allocation */
++
++#endif /* _INFTREES_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/infutil.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,87 @@
++/* inflate_util.c -- data and routines common to blocks and codes
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++#include <zlib/zutil.h>
++#include "infblock.h"
++#include "inftrees.h"
++#include "infcodes.h"
++#include "infutil.h"
++
++struct inflate_codes_state {int dummy;}; /* for buggy compilers */
++
++/* And'ing with mask[n] masks the lower n bits */
++uInt inflate_mask[17] = {
++    0x0000,
++    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
++    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
++};
++
++
++/* copy as much as possible from the sliding window to the output area */
++int inflate_flush(s, z, r)
++inflate_blocks_statef *s;
++z_streamp z;
++int r;
++{
++  uInt n;
++  Bytef *p;
++  Bytef *q;
++
++  /* local copies of source and destination pointers */
++  p = z->next_out;
++  q = s->read;
++
++  /* compute number of bytes to copy as far as end of window */
++  n = (uInt)((q <= s->write ? s->write : s->end) - q);
++  if (n > z->avail_out) n = z->avail_out;
++  if (n && r == Z_BUF_ERROR) r = Z_OK;
++
++  /* update counters */
++  z->avail_out -= n;
++  z->total_out += n;
++
++  /* update check information */
++  if (s->checkfn != Z_NULL)
++    z->adler = s->check = (*s->checkfn)(s->check, q, n);
++
++  /* copy as far as end of window */
++  zmemcpy(p, q, n);
++  p += n;
++  q += n;
++
++  /* see if more to copy at beginning of window */
++  if (q == s->end)
++  {
++    /* wrap pointers */
++    q = s->window;
++    if (s->write == s->end)
++      s->write = s->window;
++
++    /* compute bytes to copy */
++    n = (uInt)(s->write - q);
++    if (n > z->avail_out) n = z->avail_out;
++    if (n && r == Z_BUF_ERROR) r = Z_OK;
++
++    /* update counters */
++    z->avail_out -= n;
++    z->total_out += n;
++
++    /* update check information */
++    if (s->checkfn != Z_NULL)
++      z->adler = s->check = (*s->checkfn)(s->check, q, n);
++
++    /* copy */
++    zmemcpy(p, q, n);
++    p += n;
++    q += n;
++  }
++
++  /* update pointers */
++  z->next_out = p;
++  s->read = q;
++
++  /* done */
++  return r;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/infutil.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,98 @@
++/* infutil.h -- types and macros common to blocks and codes
++ * Copyright (C) 1995-2002 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++   part of the implementation of the compression library and is
++   subject to change. Applications should only use zlib.h.
++ */
++
++#ifndef _INFUTIL_H
++#define _INFUTIL_H
++
++typedef enum {
++      TYPE,     /* get type bits (3, including end bit) */
++      LENS,     /* get lengths for stored */
++      STORED,   /* processing stored block */
++      TABLE,    /* get table lengths */
++      BTREE,    /* get bit lengths tree for a dynamic block */
++      DTREE,    /* get length, distance trees for a dynamic block */
++      CODES,    /* processing fixed or dynamic block */
++      DRY,      /* output remaining window bytes */
++      DONE,     /* finished last block, done */
++      BAD}      /* got a data error--stuck here */
++inflate_block_mode;
++
++/* inflate blocks semi-private state */
++struct inflate_blocks_state {
++
++  /* mode */
++  inflate_block_mode  mode;     /* current inflate_block mode */
++
++  /* mode dependent information */
++  union {
++    uInt left;          /* if STORED, bytes left to copy */
++    struct {
++      uInt table;               /* table lengths (14 bits) */
++      uInt index;               /* index into blens (or border) */
++      uIntf *blens;             /* bit lengths of codes */
++      uInt bb;                  /* bit length tree depth */
++      inflate_huft *tb;         /* bit length decoding tree */
++    } trees;            /* if DTREE, decoding info for trees */
++    struct {
++      inflate_codes_statef 
++         *codes;
++    } decode;           /* if CODES, current state */
++  } sub;                /* submode */
++  uInt last;            /* true if this block is the last block */
++
++  /* mode independent information */
++  uInt bitk;            /* bits in bit buffer */
++  uLong bitb;           /* bit buffer */
++  inflate_huft *hufts;  /* single malloc for tree space */
++  Bytef *window;        /* sliding window */
++  Bytef *end;           /* one byte after sliding window */
++  Bytef *read;          /* window read pointer */
++  Bytef *write;         /* window write pointer */
++  check_func checkfn;   /* check function */
++  uLong check;          /* check on output */
++
++};
++
++
++/* defines for inflate input/output */
++/*   update pointers and return */
++#define UPDBITS {s->bitb=b;s->bitk=k;}
++#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
++#define UPDOUT {s->write=q;}
++#define UPDATE {UPDBITS UPDIN UPDOUT}
++#define LEAVE {UPDATE return inflate_flush(s,z,r);}
++/*   get bytes and bits */
++#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
++#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
++#define NEXTBYTE (n--,*p++)
++#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
++#define DUMPBITS(j) {b>>=(j);k-=(j);}
++/*   output bytes */
++#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
++#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
++#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
++#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
++#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
++#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
++/*   load local pointers */
++#define LOAD {LOADIN LOADOUT}
++
++/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
++extern uInt inflate_mask[17];
++
++/* copy as much as possible from the sliding window to the output area */
++extern int inflate_flush OF((
++    inflate_blocks_statef *,
++    z_streamp ,
++    int));
++
++struct internal_state      {int dummy;}; /* for buggy compilers */
++
++#endif /* _INFUTIL_H */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/initaddr.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,50 @@
++/*
++ * initialize address structure
++ * Copyright (C) 2000  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: initaddr.c,v 1.6 2004/07/10 07:43:47 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - initaddr - initialize ip_address from bytes
++ */
++err_t                         /* NULL for success, else string literal */
++initaddr(src, srclen, af, dst)
++const unsigned char *src;
++size_t srclen;
++int af;                               /* address family */
++ip_address *dst;
++{
++      switch (af) {
++      case AF_INET:
++              if (srclen != 4)
++                      return "IPv4 address must be exactly 4 bytes";
++              dst->u.v4.sin_family = af;
++              dst->u.v4.sin_port = 0;         /* unused */
++              memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen);
++              break;
++      case AF_INET6:
++              if (srclen != 16)
++                      return "IPv6 address must be exactly 16 bytes";
++              dst->u.v6.sin6_family = af;
++              dst->u.v6.sin6_flowinfo = 0;            /* unused */
++              dst->u.v6.sin6_port = 0;                /* unused */
++              memcpy((char *)&dst->u.v6.sin6_addr, src, srclen);
++              break;
++      default:
++              return "unknown address family in initaddr";
++              break;
++      }
++      return NULL;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipcomp.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,701 @@
++/*
++ * IPCOMP zlib interface code.
++ * Copyright (C) 2000  Svenning Soerensen <svenning@post5.tele.dk>
++ * Copyright (C) 2000, 2001  Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.41.2.5 2006/10/06 21:39:26 paul Exp $";
++
++/* SSS */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++#include <asm/uaccess.h>
++#include <asm/checksum.h>
++
++#include <openswan.h>
++
++#include <net/ip.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipcomp.h"
++#include "zlib/zlib.h"
++#include "zlib/zutil.h"
++
++#include <pfkeyv2.h> /* SADB_X_CALG_DEFLATE */
++
++#ifdef CONFIG_KLIPS_DEBUG
++int sysctl_ipsec_debug_ipcomp = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++static
++struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask);
++
++static
++voidpf my_zcalloc(voidpf opaque, uInt items, uInt size)
++{
++      return (voidpf) kmalloc(items*size, GFP_ATOMIC);
++}
++
++static
++void my_zfree(voidpf opaque, voidpf address)
++{
++      kfree(address);
++}
++
++/* 
++ * We use this function because sometimes we want to pass a negative offset
++ * into skb_put(), this does not work on 64bit platforms because long to
++ * unsigned int casting.
++ */
++static inline unsigned char *
++safe_skb_put(struct sk_buff *skb, int extend)
++{
++        unsigned char *ptr;
++
++        if (extend>0) {
++                // increase the size of the packet
++                ptr = skb_put(skb, extend);
++        } else {
++                // shrink the size of the packet
++                ptr = skb->tail;
++                skb_trim (skb, skb->len + extend);
++        }
++
++        return ptr;
++}
++
++struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags)
++{
++      struct iphdr *iph;
++      unsigned int iphlen, pyldsz, cpyldsz;
++      unsigned char *buffer;
++      z_stream zs;
++      int zresult;
++      
++      KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                  "klips_debug:skb_compress: .\n");
++
++      if(skb == NULL) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_compress: "
++                          "passed in NULL skb, returning ERROR.\n");
++              if(flags != NULL) {
++                      *flags |= IPCOMP_PARMERROR;
++              }
++              return skb;
++      }
++
++      if(ips == NULL) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_compress: "
++                          "passed in NULL ipsec_sa needed for cpi, returning ERROR.\n");
++              if(flags) {
++                      *flags |= IPCOMP_PARMERROR;
++              }
++              return skb;
++      }
++
++      if (flags == NULL) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_compress: "
++                          "passed in NULL flags, returning ERROR.\n");
++              ipsec_kfree_skb(skb);
++              return NULL;
++      }
++      
++#ifdef NET_21
++      iph = skb->nh.iph;
++#else /* NET_21 */
++      iph = skb->ip_hdr;
++#endif /* NET_21 */
++
++      switch (iph->protocol) {
++      case IPPROTO_COMP:
++      case IPPROTO_AH:
++      case IPPROTO_ESP:
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_compress: "
++                          "skipping compression of packet with ip protocol %d.\n",
++                          iph->protocol);
++              *flags |= IPCOMP_UNCOMPRESSABLE;
++              return skb;
++      }
++      
++      /* Don't compress packets already fragmented */
++      if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_compress: "
++                          "skipping compression of fragmented packet.\n");
++              *flags |= IPCOMP_UNCOMPRESSABLE;
++              return skb;
++      }
++      
++      iphlen = iph->ihl << 2;
++      pyldsz = ntohs(iph->tot_len) - iphlen;
++
++      /* Don't compress less than 90 bytes (rfc 2394) */
++      if (pyldsz < 90) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_compress: "
++                          "skipping compression of tiny packet, len=%d.\n",
++                          pyldsz);
++              *flags |= IPCOMP_UNCOMPRESSABLE;
++              return skb;
++      }
++      
++      /* Adaptive decision */
++      if (ips->ips_comp_adapt_skip) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_compress: "
++                          "skipping compression: ips_comp_adapt_skip=%d.\n",
++                          ips->ips_comp_adapt_skip);
++              ips->ips_comp_adapt_skip--;
++              *flags |= IPCOMP_UNCOMPRESSABLE;
++              return skb;
++      }
++
++      zs.zalloc = my_zcalloc;
++      zs.zfree = my_zfree;
++      zs.opaque = 0;
++      
++      /* We want to use deflateInit2 because we don't want the adler
++         header. */
++      zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11,
++                             DEF_MEM_LEVEL,  Z_DEFAULT_STRATEGY);
++      if (zresult != Z_OK) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_compress: "
++                          "deflateInit2() returned error %d (%s), "
++                          "skipping compression.\n",
++                          zresult,
++                          zs.msg ? zs.msg : zError(zresult));
++              *flags |= IPCOMP_COMPRESSIONERROR;
++              return skb;
++      }
++      
++
++      /* Max output size. Result should be max this size.
++       * Implementation specific tweak:
++       * If it's not at least 32 bytes and 6.25% smaller than
++       * the original packet, it's probably not worth wasting
++       * the receiver's CPU cycles decompressing it.
++       * Your mileage may vary.
++       */
++      cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4);
++
++      buffer = kmalloc(cpyldsz, GFP_ATOMIC);
++      if (!buffer) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_compress: "
++                          "unable to kmalloc(%d, GFP_ATOMIC), "
++                          "skipping compression.\n",
++                          cpyldsz);
++              *flags |= IPCOMP_COMPRESSIONERROR;
++              deflateEnd(&zs);
++              return skb;
++      }
++      
++#ifdef CONFIG_KLIPS_DEBUG
++      if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
++              __u8 *c;
++
++              c = (__u8*)iph + iphlen;
++              ipsec_dmp_block("compress before", c, pyldsz);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      zs.next_in = (char *) iph + iphlen; /* start of payload */
++      zs.avail_in = pyldsz;
++      zs.next_out = buffer;     /* start of compressed payload */
++      zs.avail_out = cpyldsz;
++      
++      /* Finish compression in one step */
++      zresult = deflate(&zs, Z_FINISH);
++
++      /* Free all dynamically allocated buffers */
++      deflateEnd(&zs);
++      if (zresult != Z_STREAM_END) {
++              *flags |= IPCOMP_UNCOMPRESSABLE;
++              kfree(buffer);
++
++              /* Adjust adaptive counters */
++              if (++(ips->ips_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) {
++                      KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                                  "klips_debug:skb_compress: "
++                                  "first %d packets didn't compress, "
++                                  "skipping next %d\n",
++                                  IPCOMP_ADAPT_INITIAL_TRIES,
++                                  IPCOMP_ADAPT_INITIAL_SKIP);
++                      ips->ips_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP;
++              }
++              else if (ips->ips_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) {
++                      KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                                  "klips_debug:skb_compress: "
++                                  "next %d packets didn't compress, "
++                                  "skipping next %d\n",
++                                  IPCOMP_ADAPT_SUBSEQ_TRIES,
++                                  IPCOMP_ADAPT_SUBSEQ_SKIP);
++                      ips->ips_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP;
++                      ips->ips_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES;
++              }
++
++              return skb;
++      }
++      
++      /* resulting compressed size */
++      cpyldsz -= zs.avail_out;
++      
++      /* Insert IPCOMP header */
++      ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol;
++      ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0;
++      /* use the bottom 16 bits of the spi for the cpi.  The top 16 bits are
++         for internal reference only. */
++      ((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(ips->ips_said.spi) & 0x0000ffff));
++      KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                  "klips_debug:skb_compress: "
++                  "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n",
++                  ntohl(ips->ips_said.spi),
++                  ntohl(ips->ips_said.spi) & 0x0000ffff,
++                  ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi),
++                  pyldsz,
++                  cpyldsz);
++      
++      /* Update IP header */
++      iph->protocol = IPPROTO_COMP;
++      iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz);
++#if 1 /* XXX checksum is done by ipsec_tunnel ? */
++      iph->check = 0;
++      iph->check = ip_fast_csum((char *) iph, iph->ihl);
++#endif
++      
++      /* Copy compressed payload */
++      memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr),
++             buffer,
++             cpyldsz);
++      kfree(buffer);
++      
++      /* Update skb length/tail by "unputting" the shrinkage */
++        safe_skb_put (skb, cpyldsz + sizeof(struct ipcomphdr) - pyldsz);
++
++#ifdef CONFIG_KLIPS_DEBUG
++      if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
++              __u8 *c;
++              
++              c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr);
++              ipsec_dmp_block("compress result", c, cpyldsz);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++      
++      ips->ips_comp_adapt_skip = 0;
++      ips->ips_comp_adapt_tries = 0;
++      
++      return skb;
++}
++
++struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags)
++{
++      struct sk_buff *nskb = NULL;
++
++      /* original ip header */
++      struct iphdr *oiph, *iph;
++      unsigned int iphlen, pyldsz, cpyldsz;
++      z_stream zs;
++      int zresult;
++
++      KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                  "klips_debug:skb_decompress: .\n");
++
++      if(!skb) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "passed in NULL skb, returning ERROR.\n");
++              if (flags) *flags |= IPCOMP_PARMERROR;
++              return skb;
++      }
++
++      if(!ips && sysctl_ipsec_inbound_policy_check) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "passed in NULL ipsec_sa needed for comp alg, returning ERROR.\n");
++              if (flags) *flags |= IPCOMP_PARMERROR;
++              return skb;
++      }
++
++      if (!flags) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "passed in NULL flags, returning ERROR.\n");
++              ipsec_kfree_skb(skb);
++              return NULL;
++      }
++      
++#ifdef NET_21
++      oiph = skb->nh.iph;
++#else /* NET_21 */
++      oiph = skb->ip_hdr;
++#endif /* NET_21 */
++      
++      iphlen = oiph->ihl << 2;
++      
++      if (oiph->protocol != IPPROTO_COMP) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "called with non-IPCOMP packet (protocol=%d),"
++                          "skipping decompression.\n",
++                          oiph->protocol);
++              *flags |= IPCOMP_PARMERROR;
++              return skb;
++      }
++      
++      if ( (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0)
++           || ((((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi
++              != htons(SADB_X_CALG_DEFLATE))
++               && sysctl_ipsec_inbound_policy_check
++               && (!ips || (ips && (ips->ips_encalg != SADB_X_CALG_DEFLATE)))) ) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "called with incompatible IPCOMP packet (flags=%d, "
++                          "cpi=%d), ips-compalg=%d, skipping decompression.\n",
++                          ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags),
++                          ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi),
++                          ips ? ips->ips_encalg : 0);
++              *flags |= IPCOMP_PARMERROR;
++              
++              return skb;
++      }
++      
++      if (ntohs(oiph->frag_off) & ~0x4000) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "called with fragmented IPCOMP packet, "
++                          "skipping decompression.\n");
++              *flags |= IPCOMP_PARMERROR;
++              return skb;
++      }
++      
++      /* original compressed payload size */
++      cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr);
++
++      zs.zalloc = my_zcalloc;
++      zs.zfree = my_zfree;
++      zs.opaque = 0;
++      
++      zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr);
++      zs.avail_in = cpyldsz;
++      
++      /* Maybe we should be a bit conservative about memory
++         requirements and use inflateInit2 */
++      /* Beware, that this might make us unable to decompress packets
++         from other implementations - HINT: check PGPnet source code */
++      /* We want to use inflateInit2 because we don't want the adler
++         header. */
++      zresult = inflateInit2(&zs, -15); 
++      if (zresult != Z_OK) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "inflateInit2() returned error %d (%s), "
++                          "skipping decompression.\n",
++                          zresult,
++                          zs.msg ? zs.msg : zError(zresult));
++              *flags |= IPCOMP_DECOMPRESSIONERROR;
++
++              return skb;
++      }
++      
++      /* We have no way of knowing the exact length of the resulting
++         decompressed output before we have actually done the decompression.
++         For now, we guess that the packet will not be bigger than the
++         attached ipsec device's mtu or 16260, whichever is biggest.
++         This may be wrong, since the sender's mtu may be bigger yet.
++         XXX This must be dealt with later XXX
++      */
++      
++      /* max payload size */
++      pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu)
++                        : (65520 - iphlen);
++      KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                  "klips_debug:skb_decompress: "
++                  "max payload size: %d\n", pyldsz);
++      
++      while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) && 
++             (nskb = skb_copy_ipcomp(skb,
++                                     pyldsz - cpyldsz - sizeof(struct ipcomphdr),
++                                     GFP_ATOMIC)) == NULL) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "unable to skb_copy_ipcomp(skb, %d, GFP_ATOMIC), "
++                          "trying with less payload size.\n",
++                          (int)(pyldsz - cpyldsz - sizeof(struct ipcomphdr)));
++              pyldsz >>=1;
++      }
++      
++      if (!nskb) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "unable to allocate memory, dropping packet.\n");
++              *flags |= IPCOMP_DECOMPRESSIONERROR;
++              inflateEnd(&zs);
++
++              return skb;
++      }
++      
++#ifdef CONFIG_KLIPS_DEBUG
++      if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
++              __u8 *c;
++              
++              c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr);
++              ipsec_dmp_block("decompress before", c, cpyldsz);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#ifdef NET_21
++      iph = nskb->nh.iph;
++#else /* NET_21 */
++      iph = nskb->ip_hdr;
++#endif /* NET_21 */
++      zs.next_out = (char *)iph + iphlen;
++      zs.avail_out = pyldsz;
++
++      zresult = inflate(&zs, Z_SYNC_FLUSH);
++
++      /* work around a bug in zlib, which sometimes wants to taste an extra
++       * byte when being used in the (undocumented) raw deflate mode.
++       */
++      if (zresult == Z_OK && !zs.avail_in && zs.avail_out) {
++              __u8 zerostuff = 0;
++              
++              zs.next_in = &zerostuff;
++              zs.avail_in = 1;
++              zresult = inflate(&zs, Z_FINISH);
++      }
++
++      inflateEnd(&zs);
++      if (zresult != Z_STREAM_END) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_error:skb_decompress: "
++                          "inflate() returned error %d (%s), "
++                          "skipping decompression.\n",
++                          zresult,
++                          zs.msg ? zs.msg : zError(zresult));
++              *flags |= IPCOMP_DECOMPRESSIONERROR;
++              ipsec_kfree_skb(nskb);
++
++              return skb;
++      }
++      
++      /* Update IP header */
++      /* resulting decompressed size */
++      pyldsz -= zs.avail_out;
++      iph->tot_len = htons(iphlen + pyldsz);
++      iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh;
++      KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                  "klips_debug:skb_decompress: "
++                  "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n",
++                  ips ? ntohl(ips->ips_said.spi) : 0,
++                  ips ? ntohl(ips->ips_said.spi) & 0x0000ffff : 0,
++                  ntohs(((struct ipcomphdr*)(((char*)oiph)+iphlen))->ipcomp_cpi),
++                  cpyldsz,
++                  pyldsz,
++                  iph->protocol);
++      
++#if 1 /* XXX checksum is done by ipsec_rcv ? */
++      iph->check = 0;
++      iph->check = ip_fast_csum((char*) iph, iph->ihl);
++#endif
++      
++      /* Update skb length/tail by "unputting" the unused data area */
++      safe_skb_put(nskb, -zs.avail_out);
++      
++      ipsec_kfree_skb(skb);
++      
++      if (iph->protocol == IPPROTO_COMP)
++      {
++#ifdef CONFIG_KLIPS_DEBUG
++              if(sysctl_ipsec_debug_ipcomp)
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_decompress: "
++                          "Eh? inner packet is also compressed, dropping.\n");
++#endif /* CONFIG_KLIPS_DEBUG */
++              
++              ipsec_kfree_skb(nskb);
++              return NULL;
++      }
++      
++#ifdef CONFIG_KLIPS_DEBUG
++      if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
++              __u8 *c;
++              
++              c = (__u8*)iph + iphlen;
++              ipsec_dmp_block("decompress result", c, pyldsz);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++      
++      return nskb;
++}
++
++
++/* this is derived from skb_copy() in linux 2.2.14 */
++/* May be incompatible with other kernel versions!! */
++static
++struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask)
++{
++        struct sk_buff *n;
++      struct iphdr *iph;
++        unsigned long offset;
++        unsigned int iphlen;
++      
++      if(!skb) {
++              KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
++                          "klips_debug:skb_copy_ipcomp: "
++                          "passed in NULL skb, returning NULL.\n");
++              return NULL;
++      }
++
++        /*
++         *      Allocate the copy buffer
++         */
++      
++#ifdef NET_21
++      iph = skb->nh.iph;
++#else /* NET_21 */
++      iph = skb->ip_hdr;
++#endif /* NET_21 */
++        if (!iph) return NULL;
++        iphlen = iph->ihl << 2;
++      
++        n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask);
++        if(n==NULL)
++                return NULL;
++      
++        /*
++         *      Shift between the two data areas in bytes
++         */
++      
++        offset=n->head-skb->head;
++
++        /* Set the data pointer */
++        skb_reserve(n,skb->data-skb->head);
++        /* Set the tail pointer and length */
++        safe_skb_put(n,skb->len+data_growth);
++        /* Copy the bytes up to and including the ip header */
++        memcpy(n->head,
++             skb->head,
++             ((char *)iph - (char *)skb->head) + iphlen);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
++        n->list=NULL;
++#endif
++      n->next=NULL;
++      n->prev=NULL;
++        n->sk=NULL;
++        n->dev=skb->dev;
++      if (skb->h.raw)
++              n->h.raw=skb->h.raw+offset;
++      else
++              n->h.raw=NULL;
++        n->protocol=skb->protocol;
++#ifdef NET_21
++        n->csum = 0;
++        n->priority=skb->priority;
++        n->dst=dst_clone(skb->dst);
++        n->nh.raw=skb->nh.raw+offset;
++#ifndef NETDEV_23
++        n->is_clone=0;
++#endif /* NETDEV_23 */
++        atomic_set(&n->users, 1);
++        n->destructor = NULL;
++#ifdef HAVE_SOCK_SECURITY
++        n->security=skb->security;
++#endif
++        memcpy(n->cb, skb->cb, sizeof(skb->cb));
++#ifdef CONFIG_IP_FIREWALL
++        n->fwmark = skb->fwmark;
++#endif
++#else /* NET_21 */
++      n->link3=NULL;
++      n->when=skb->when;
++      n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
++      n->saddr=skb->saddr;
++      n->daddr=skb->daddr;
++      n->raddr=skb->raddr;
++      n->seq=skb->seq;
++      n->end_seq=skb->end_seq;
++      n->ack_seq=skb->ack_seq;
++      n->acked=skb->acked;
++      n->free=1;
++      n->arp=skb->arp;
++      n->tries=0;
++      n->lock=0;
++      n->users=0;
++      memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
++#endif /* NET_21 */
++      if (skb->mac.raw)
++              n->mac.raw=skb->mac.raw+offset;
++      else
++              n->mac.raw=NULL;
++#ifndef NETDEV_23
++      n->used=skb->used;
++#endif /* !NETDEV_23 */
++        n->pkt_type=skb->pkt_type;
++#ifndef NETDEV_23
++      n->pkt_bridged=skb->pkt_bridged;
++#endif /* NETDEV_23 */
++      n->ip_summed=0;
++#ifdef HAVE_TSTAMP
++        n->tstamp = skb->tstamp;
++#else
++        n->stamp=skb->stamp;
++#endif
++#ifndef NETDEV_23 /* this seems to have been removed in 2.4 */
++#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
++        n->shapelatency=skb->shapelatency;       /* Latency on frame */
++        n->shapeclock=skb->shapeclock;           /* Time it should go out */
++        n->shapelen=skb->shapelen;               /* Frame length in clocks */
++        n->shapestamp=skb->shapestamp;           /* Stamp for shaper    */
++        n->shapepend=skb->shapepend;             /* Pending */
++#endif /* defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) */
++#endif /* NETDEV_23 */
++
++        return n;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_ah.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,407 @@
++/*
++ * processing code for AH
++ * Copyright (C) 2003-2004   Michael Richardson <mcr@xelerance.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_ah_c_version[] = "RCSID $Id: ipsec_ah.c,v 1.12.2.2 2006/10/06 21:39:26 paul Exp $";
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>  /* struct device, and other headers */
++#include <linux/etherdevice.h>        /* eth_type_trans */
++#include <linux/ip.h>         /* struct iphdr */
++#include <linux/skbuff.h>
++#include <openswan.h>
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++#include <net/protocol.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h" 
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipsec_xmit.h"
++
++#include "openswan/ipsec_auth.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_proto.h"
++
++__u32 zeroes[AH_AMAX];
++
++enum ipsec_rcv_value
++ipsec_rcv_ah_checks(struct ipsec_rcv_state *irs,
++                  struct sk_buff *skb)
++{
++      int ahminlen;
++
++      ahminlen = irs->hard_header_len + sizeof(struct iphdr);
++
++      /* take care not to deref this pointer until we check the minlen though */
++      irs->protostuff.ahstuff.ahp = (struct ahhdr *)skb->h.raw;
++
++      if((skb->len < ahminlen+sizeof(struct ahhdr)) ||
++         (skb->len < ahminlen+(irs->protostuff.ahstuff.ahp->ah_hl << 2))) {
++              KLIPS_PRINT(debug_rcv & DB_RX_INAU,
++                          "klips_debug:ipsec_rcv: "
++                          "runt ah packet of skb->len=%d received from %s, dropped.\n",
++                          skb->len,
++                          irs->ipsaddr_txt);
++              if(irs->stats) {
++                      irs->stats->rx_errors++;
++              }
++              return IPSEC_RCV_BADLEN;
++      }
++
++      irs->said.spi = irs->protostuff.ahstuff.ahp->ah_spi;
++
++      /* XXX we only support the one 12-byte authenticator for now */
++      if(irs->protostuff.ahstuff.ahp->ah_hl != ((AHHMAC_HASHLEN+AHHMAC_RPLLEN) >> 2)) {
++              KLIPS_PRINT(debug_rcv & DB_RX_INAU,
++                          "klips_debug:ipsec_rcv: "
++                          "bad authenticator length %ld, expected %lu from %s.\n",
++                          (long)(irs->protostuff.ahstuff.ahp->ah_hl << 2),
++                          (unsigned long) sizeof(struct ahhdr),
++                          irs->ipsaddr_txt);
++              if(irs->stats) {
++                      irs->stats->rx_errors++;
++              }
++              return IPSEC_RCV_BADLEN;
++      }
++
++      return IPSEC_RCV_OK;
++}
++
++
++enum ipsec_rcv_value
++ipsec_rcv_ah_setup_auth(struct ipsec_rcv_state *irs,
++                      struct sk_buff *skb,
++                      __u32          *replay,
++                      unsigned char **authenticator)
++{
++      struct ahhdr *ahp = irs->protostuff.ahstuff.ahp;
++
++      *replay = ntohl(ahp->ah_rpl);
++      *authenticator = ahp->ah_data;
++
++      return IPSEC_RCV_OK;
++}
++
++enum ipsec_rcv_value
++ipsec_rcv_ah_authcalc(struct ipsec_rcv_state *irs,
++                    struct sk_buff *skb)
++{
++      struct auth_alg *aa;
++      struct ahhdr *ahp = irs->protostuff.ahstuff.ahp;
++      union {
++              MD5_CTX         md5;
++              SHA1_CTX        sha1;
++      } tctx;
++      struct iphdr ipo;
++      int ahhlen;
++
++      aa = irs->authfuncs;
++
++      /* copy the initialized keying material */
++      memcpy(&tctx, irs->ictx, irs->ictx_len);
++
++      ipo = *irs->ipp;
++      ipo.tos = 0;    /* mutable RFC 2402 3.3.3.1.1.1 */
++      ipo.frag_off = 0;
++      ipo.ttl = 0;
++      ipo.check = 0;
++
++
++      /* do the sanitized header */
++      (*aa->update)((void*)&tctx, (caddr_t)&ipo, sizeof(struct iphdr));
++
++      /* XXX we didn't do the options here! */
++
++      /* now do the AH header itself */
++      ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2);
++      (*aa->update)((void*)&tctx, (caddr_t)ahp,  ahhlen - AHHMAC_HASHLEN);
++
++      /* now, do some zeroes */
++      (*aa->update)((void*)&tctx, (caddr_t)zeroes,  AHHMAC_HASHLEN);
++
++      /* finally, do the packet contents themselves */
++      (*aa->update)((void*)&tctx,
++                    (caddr_t)skb->h.raw + ahhlen,
++                    skb->len - ahhlen);
++
++      (*aa->final)(irs->hash, (void *)&tctx);
++
++      memcpy(&tctx, irs->octx, irs->octx_len);
++
++      (*aa->update)((void *)&tctx, irs->hash, aa->hashlen);
++      (*aa->final)(irs->hash, (void *)&tctx);
++
++      return IPSEC_RCV_OK;
++}
++
++enum ipsec_rcv_value
++ipsec_rcv_ah_decap(struct ipsec_rcv_state *irs)
++{
++      struct ahhdr *ahp = irs->protostuff.ahstuff.ahp;
++      struct sk_buff *skb;
++      int ahhlen;
++
++      skb=irs->skb;
++
++      ahhlen = AH_BASIC_LEN + (ahp->ah_hl << 2);
++
++      irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - ahhlen);
++      irs->next_header  = ahp->ah_nh;
++
++      /*
++       * move the IP header forward by the size of the AH header, which
++       * will remove the the AH header from the packet.
++       */
++      memmove((void *)(skb->nh.raw + ahhlen),
++              (void *)(skb->nh.raw), irs->iphlen);
++
++      ipsec_rcv_dmp("ah postmove", skb->data, skb->len);
++
++      /* skb_pull below, will move up by ahhlen */
++
++      /* XXX not clear how this can happen, as the message indicates */
++      if(skb->len < ahhlen) {
++              printk(KERN_WARNING
++                     "klips_error:ipsec_rcv: "
++                     "tried to skb_pull ahhlen=%d, %d available.  This should never happen, please report.\n",
++                     ahhlen,
++                     (int)(skb->len));
++              return IPSEC_RCV_DECAPFAIL;
++      }
++      skb_pull(skb, ahhlen);
++
++      skb->nh.raw = skb->nh.raw + ahhlen;
++      irs->ipp = skb->nh.iph;
++
++      ipsec_rcv_dmp("ah postpull", (void *)skb->nh.iph, skb->len);
++
++      return IPSEC_RCV_OK;
++}
++
++enum ipsec_xmit_value
++ipsec_xmit_ah_setup(struct ipsec_xmit_state *ixs)
++{
++  struct iphdr ipo;
++  struct ahhdr *ahp;
++  __u8 hash[AH_AMAX];
++  union {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++    MD5_CTX md5;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++    SHA1_CTX sha1;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++  } tctx;
++  unsigned char *dat = (unsigned char *)ixs->iph;
++
++  ahp = (struct ahhdr *)(dat + ixs->iphlen);
++  ahp->ah_spi = ixs->ipsp->ips_said.spi;
++  ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq));
++  ahp->ah_rv = 0;
++  ahp->ah_nh = ixs->iph->protocol;
++  ahp->ah_hl = (sizeof(struct ahhdr) >> 2) - sizeof(__u64)/sizeof(__u32);
++  ixs->iph->protocol = IPPROTO_AH;
++  ipsec_xmit_dmp("ahp", (char*)ahp, sizeof(*ahp));
++  
++  ipo = *ixs->iph;
++  ipo.tos = 0;
++  ipo.frag_off = 0;
++  ipo.ttl = 0;
++  ipo.check = 0;
++  ipsec_xmit_dmp("ipo", (char*)&ipo, sizeof(ipo));
++  
++  switch(ixs->ipsp->ips_authalg) {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++  case AH_MD5:
++    tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++    ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr));
++    ipsec_xmit_dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Update(&tctx.md5, (unsigned char *)ahp,
++            sizeof(struct ahhdr) - sizeof(ahp->ah_data));
++    ipsec_xmit_dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN);
++    ipsec_xmit_dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Update(&tctx.md5,  dat + ixs->iphlen + sizeof(struct ahhdr),
++            ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr));
++    ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Final(hash, &tctx.md5);
++    ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash));
++    tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx;
++    ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Update(&tctx.md5, hash, AHMD596_ALEN);
++    ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Final(hash, &tctx.md5);
++    ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash));
++    
++    memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);
++    
++    /* paranoid */
++    memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));
++    memset((caddr_t)hash, 0, sizeof(*hash));
++    break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++  case AH_SHA:
++    tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++    SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr));
++    SHA1Update(&tctx.sha1, (unsigned char *)ahp, sizeof(struct ahhdr) - sizeof(ahp->ah_data));
++    SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN);
++    SHA1Update(&tctx.sha1, dat + ixs->iphlen + sizeof(struct ahhdr),
++             ixs->skb->len - ixs->iphlen - sizeof(struct ahhdr));
++    SHA1Final(hash, &tctx.sha1);
++    tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx;
++    SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);
++    SHA1Final(hash, &tctx.sha1);
++    
++    memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);
++    
++    /* paranoid */
++    memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));
++    memset((caddr_t)hash, 0, sizeof(*hash));
++    break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++  default:
++    ixs->stats->tx_errors++;
++    return IPSEC_XMIT_AH_BADALG;
++  }
++#ifdef NET_21
++  ixs->skb->h.raw = (unsigned char*)ahp;
++#endif /* NET_21 */
++
++  return IPSEC_XMIT_OK;
++}
++
++struct xform_functions ah_xform_funcs[]={
++      {       rcv_checks:         ipsec_rcv_ah_checks,
++              rcv_setup_auth:     ipsec_rcv_ah_setup_auth,
++              rcv_calc_auth:      ipsec_rcv_ah_authcalc,
++              rcv_decrypt:        ipsec_rcv_ah_decap,
++
++              xmit_setup:         ipsec_xmit_ah_setup,
++              xmit_headroom:      sizeof(struct ahhdr),
++              xmit_needtailroom:  0,
++      },
++};
++
++
++#ifdef NET_26
++struct inet_protocol ah_protocol = {
++  .handler = ipsec_rcv,
++  .no_policy = 1,
++};
++#else
++struct inet_protocol ah_protocol =
++{
++      ipsec_rcv,                              /* AH handler */
++      NULL,                           /* TUNNEL error control */
++#ifdef NETDEV_25
++      1,                              /* no policy */
++#else
++      0,                              /* next */
++      IPPROTO_AH,                     /* protocol ID */
++      0,                              /* copy */
++      NULL,                           /* data */
++      "AH"                            /* name */
++#endif
++};
++#endif /* NET_26 */
++
++/*
++ * $Log: ipsec_ah.c,v $
++ * Revision 1.12.2.2  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.12.2.1  2006/02/15 05:35:14  paul
++ * Patch by  David McCullough <davidm@snapgear.com>
++ * If you setup a tunnel without ESP it doesn't work.  It used to work in
++ * an older openswan version but stopped when klips was modified to deal
++ * with the pulled IP header on the received SKB's.
++ *
++ * The code in ipsec_ah.c still thinks the IP header is there and runs the
++ * hash on the incorrect data.
++ *
++ * Revision 1.12  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.11  2005/04/15 19:50:55  mcr
++ *    adjustments to use proper skb fields for data.
++ *
++ * Revision 1.10  2004/09/14 00:22:57  mcr
++ *    adjustment of MD5* functions.
++ *
++ * Revision 1.9  2004/09/13 02:22:47  mcr
++ *    #define inet_protocol if necessary.
++ *
++ * Revision 1.8  2004/09/06 18:35:48  mcr
++ *    2.6.8.1 gets rid of inet_protocol->net_protocol compatibility,
++ *    so adjust for that.
++ *
++ * Revision 1.7  2004/08/22 05:00:48  mcr
++ *    if we choose to compile the file, we want the contents,
++ *    so don't pull any punches.
++ *
++ * Revision 1.6  2004/08/17 03:27:23  mcr
++ *    klips 2.6 edits.
++ *
++ * Revision 1.5  2004/08/14 03:28:24  mcr
++ *    fixed log comment to remove warning about embedded comment.
++ *
++ * Revision 1.4  2004/08/04 15:57:07  mcr
++ *    moved des .h files to include/des/ *
++ *    included 2.6 protocol specific things
++ *    started at NAT-T support, but it will require a kernel patch.
++ *
++ * Revision 1.3  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.2  2004/04/06 02:49:25  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_alg.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1057 @@
++/*
++ * Modular extensions service and registration functions
++ *
++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ * 
++ * Version: 0.8.1
++ *
++ * ipsec_alg.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ */
++#define __NO_VERSION__
++
++#if defined (MODULE)
++#include <linux/module.h>
++#endif
++
++#include <linux/kernel.h> /* printk() */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++#include <linux/socket.h>
++#include <linux/in.h>
++#include <linux/types.h>
++#include <linux/string.h>     /* memcmp() */
++#include <linux/random.h>     /* get_random_bytes() */
++#include <linux/errno.h>  /* error codes */
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include "openswan/ipsec_param.h"
++#include <openswan.h>
++#include "openswan/ipsec_sa.h"
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h"
++#if defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH)
++# include "openswan/ipsec_ah.h"
++#endif /* defined(CONFIG_KLIPS_ESP) || defined(CONFIG_KLIPS_AH) */
++#ifdef CONFIG_KLIPS_ESP
++# include "openswan/ipsec_esp.h"
++#endif /* !CONFIG_KLIPS_ESP */
++#ifdef CONFIG_KLIPS_IPCOMP
++# include "openswan/ipcomp.h"
++#endif /* CONFIG_KLIPS_COMP */
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_alg.h"
++#include "openswan/ipsec_proto.h"
++
++#if SADB_EALG_MAX < 255
++#warning Compiling with limited ESP support ( SADB_EALG_MAX < 256 )
++#endif
++
++static rwlock_t ipsec_alg_lock = RW_LOCK_UNLOCKED;
++#define IPSEC_ALG_HASHSZ      16      /* must be power of 2, even 2^0=1 */
++static struct list_head ipsec_alg_hash_table[IPSEC_ALG_HASHSZ];
++
++/*    Old gcc's will fail here        */
++#define barf_out(fmt, args...)  do { struct ipsec_alg *ixtc = (struct ipsec_alg *)ixt; printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixtc->ixt_name , ## args) \
++      ; goto out; } while(0)
++
++#ifdef NET_26
++/* 
++ *    Must be already protected by lock 
++ */
++static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt)
++{
++#ifdef MODULE
++      if (ixt->ixt_module)
++              try_module_get(ixt->ixt_module);
++#endif
++      atomic_inc(&ixt->ixt_refcnt);
++}
++static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) {
++      atomic_dec(&ixt->ixt_refcnt);
++#ifdef MODULE
++      if (ixt->ixt_module)
++              module_put(ixt->ixt_module);
++#endif
++}
++
++#else
++
++/* 
++ *    Must be already protected by lock 
++ */
++static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) {
++#ifdef MODULE
++      if (ixt->ixt_module) {
++              __MOD_INC_USE_COUNT(ixt->ixt_module);
++      }
++#endif
++      atomic_inc(&ixt->ixt_refcnt);
++}
++static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) {
++      atomic_dec(&ixt->ixt_refcnt);
++#ifdef MODULE
++      if (ixt->ixt_module)
++              __MOD_DEC_USE_COUNT(ixt->ixt_module);
++#endif
++}
++#endif
++
++/*
++ *    simple hash function, optimized for 0-hash (1 list) special
++ *    case
++ */
++#if IPSEC_ALG_HASHSZ > 1
++static inline unsigned ipsec_alg_hashfn(int alg_type, int alg_id) {
++      return ((alg_type^alg_id)&(IPSEC_ALG_HASHSZ-1));
++}
++#else
++#define ipsec_alg_hashfn(x,y) (0)
++#endif
++
++/*****************************************************************
++ *
++ *    INTERNAL table handling: insert, delete, find
++ *
++ *****************************************************************/
++
++/*    
++ *    hash table initialization, called from ipsec_alg_init()
++ */
++static void ipsec_alg_hash_init(void) {
++      struct list_head *head = ipsec_alg_hash_table;
++      int i = IPSEC_ALG_HASHSZ;
++      do {
++              INIT_LIST_HEAD(head);
++              head++;
++              i--;
++      } while (i);
++}
++/*
++ *    hash list lookup by {alg_type, alg_id} and table head,
++ *    must be already protected by lock
++ */
++static struct ipsec_alg *__ipsec_alg_find(unsigned alg_type, unsigned alg_id, struct list_head * head) {
++      struct list_head *p;
++      struct ipsec_alg *ixt=NULL;
++      for (p=head->next; p!=head; p=p->next) {
++              ixt = list_entry(p, struct ipsec_alg, ixt_list);
++              if (ixt->ixt_alg_type == alg_type && ixt->ixt_alg_id==alg_id) {
++                      goto out;
++              }
++      }
++      ixt=NULL;
++out:
++      return ixt;
++}
++/*
++ *    inserts (in front) a new entry in hash table, 
++ *    called from ipsec_alg_register() when new algorithm is registered.
++ */
++static int ipsec_alg_insert(struct ipsec_alg *ixt) {
++      int ret=-EINVAL;
++      unsigned hashval=ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id);
++      struct list_head *head= ipsec_alg_hash_table + hashval;
++      struct ipsec_alg *ixt_cur;
++
++      /*      new element must be virgin ... */
++      if (ixt->ixt_list.next != &ixt->ixt_list || 
++              ixt->ixt_list.prev != &ixt->ixt_list) {
++              printk(KERN_ERR "ipsec_alg_insert: ixt object \"%s\" "
++                              "list head not initialized\n",
++                              ixt->ixt_name);
++              return ret;
++      }
++      write_lock_bh(&ipsec_alg_lock);
++
++      ixt_cur = __ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head);
++
++      /* if previous (current) ipsec_alg found check excl flag of _anyone_ */
++      if (ixt_cur
++          && ((ixt->ixt_state|ixt_cur->ixt_state) & IPSEC_ALG_ST_EXCL)) {
++        barf_out("ipsec_alg for alg_type=%d, alg_id=%d already exist. "
++                 "Not loaded (ret=%d).\n",
++                 ixt->ixt_alg_type,
++                 ixt->ixt_alg_id, ret=-EEXIST);
++      }
++      list_add(&ixt->ixt_list, head);
++      ixt->ixt_state |= IPSEC_ALG_ST_REGISTERED;
++      ret=0;
++out:
++      write_unlock_bh(&ipsec_alg_lock);
++      return ret;
++}
++
++/*
++ *    deletes an existing entry in hash table, 
++ *    called from ipsec_alg_unregister() when algorithm is unregistered.
++ */
++static int ipsec_alg_delete(struct ipsec_alg *ixt) {
++      write_lock_bh(&ipsec_alg_lock);
++      list_del(&ixt->ixt_list);
++      write_unlock_bh(&ipsec_alg_lock);
++      return 0;
++}
++
++/*
++ *    here @user context (read-only when @kernel bh context) 
++ *    -> no bh disabling
++ *
++ *    called from ipsec_sa_init() -> ipsec_alg_sa_init()
++ */
++static struct ipsec_alg *ipsec_alg_get(int alg_type, int alg_id)
++{
++      unsigned hashval=ipsec_alg_hashfn(alg_type, alg_id);
++      struct list_head *head= ipsec_alg_hash_table + hashval;
++      struct ipsec_alg *ixt;
++
++      read_lock(&ipsec_alg_lock);
++      ixt=__ipsec_alg_find(alg_type, alg_id, head);
++      if (ixt) __ipsec_alg_usage_inc(ixt);
++      read_unlock(&ipsec_alg_lock);
++
++      return ixt;
++}
++
++static void ipsec_alg_put(struct ipsec_alg *ixt) {
++      __ipsec_alg_usage_dec((struct ipsec_alg *)ixt);
++}
++
++/*****************************************************************
++ *
++ *    INTERFACE for ENC services: key creation, encrypt function
++ *
++ *****************************************************************/
++
++/*
++ *    main encrypt service entry point
++ *    called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and
++ *    ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT
++ */
++int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat,
++                        int ilen, const __u8 * iv, int encrypt)
++{
++      int ret;
++      struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;
++#ifdef CONFIG_KLIPS_DEBUG
++      int debug_flag = (encrypt==IPSEC_ALG_ENCRYPT ?
++                        debug_tunnel : debug_rcv);
++#endif
++
++      KLIPS_PRINT(debug_flag,
++                  "klips_debug:ipsec_alg_esp_encrypt: "
++                  "entering with encalg=%d, ixt_e=%p\n",
++                  sa_p->ips_encalg, ixt_e);
++      if (ixt_e == NULL) {
++#ifdef CONFIG_KLIPS_DEBUG
++        KLIPS_ERROR(debug_flag,
++                    "klips_debug:ipsec_alg_esp_encrypt: "
++                    "NULL ipsec_alg_enc object\n");
++#endif
++              return -1;
++      }
++      KLIPS_PRINT(debug_flag,
++                  "klips_debug:ipsec_alg_esp_encrypt: "
++                  "calling cbc_encrypt encalg=%d "
++                  "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n",
++                      sa_p->ips_encalg, 
++                      sa_p->ips_key_e, idat, ilen, iv, encrypt);
++      ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, sa_p->ips_key_e, idat,
++                                   ilen, iv, encrypt);
++      KLIPS_PRINT(debug_flag,
++                  "klips_debug:ipsec_alg_esp_encrypt: "
++                  "returned ret=%d\n",
++                  ret);
++      return ret;
++}
++
++/*
++ *    encryption key context creation function
++ *    called from pfkey_v2_parser.c:pfkey_ips_init() 
++ */
++int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) {
++      int ret=-EINVAL;
++      int keyminbits, keymaxbits;
++      caddr_t ekp;
++      struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:ipsec_alg_enc_key_create: "
++                  "entering with encalg=%d ixt_e=%p\n",
++                  sa_p->ips_encalg, ixt_e);
++      if (!ixt_e) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_alg_enc_key_create: "
++                          "NULL ipsec_alg_enc object\n");
++              return -EPROTO;
++      }
++
++      /* 
++       * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo 
++       */
++      switch(ixt_e->ixt_common.ixt_support.ias_id) {
++              case ESP_3DES:
++                      keyminbits=keymaxbits=192;break;
++              case ESP_DES:
++                      keyminbits=keymaxbits=64;break;
++              default:
++                      keyminbits=ixt_e->ixt_common.ixt_support.ias_keyminbits;
++                      keymaxbits=ixt_e->ixt_common.ixt_support.ias_keymaxbits;
++      }
++      if(sa_p->ips_key_bits_e<keyminbits || 
++                      sa_p->ips_key_bits_e>keymaxbits) {
++              KLIPS_PRINT(debug_pfkey,
++                              "klips_debug:ipsec_alg_enc_key_create: "
++                              "incorrect encryption key size for id=%d: %d bits -- "
++                              "must be between %d,%d bits\n" /*octets (bytes)\n"*/,
++                              ixt_e->ixt_common.ixt_support.ias_id,
++                              sa_p->ips_key_bits_e, keyminbits, keymaxbits);
++              ret=-EINVAL;
++              goto ixt_out;
++      }
++      /* save encryption key pointer */
++      ekp = sa_p->ips_key_e;
++
++
++      if (ixt_e->ixt_e_new_key) {
++              sa_p->ips_key_e = ixt_e->ixt_e_new_key(ixt_e,
++                              ekp, sa_p->ips_key_bits_e/8);
++              ret =  (sa_p->ips_key_e)? 0 : -EINVAL;
++      } else {
++              if((sa_p->ips_key_e = (caddr_t)
++                  kmalloc((sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size),
++                          GFP_ATOMIC)) == NULL) {
++                      ret=-ENOMEM;
++                      goto ixt_out;
++              }
++              /* zero-out key_e */
++              memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size);
++
++              /* I cast here to allow more decoupling in alg module */
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_alg_enc_key_create: about to call:"
++                                  "set_key(key_e=%p, ekp=%p, key_size=%d)\n",
++                                  (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
++              ret = ixt_e->ixt_e_set_key(ixt_e, (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
++      }
++      /* paranoid */
++      memset(ekp, 0, sa_p->ips_key_bits_e/8);
++      kfree(ekp);
++ixt_out:
++      return ret;
++}
++
++/***************************************************************
++ *
++ *    INTERFACE for AUTH services: key creation, hash functions
++ *
++ ***************************************************************/
++
++/*
++ *    auth key context creation function
++ *    called from pfkey_v2_parser.c:pfkey_ips_init() 
++ */
++int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) {
++      int ret=-EINVAL;
++      struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth;
++      int keyminbits, keymaxbits;
++      unsigned char *akp;
++      unsigned int aks;
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:ipsec_alg_auth_key_create: "
++                  "entering with authalg=%d ixt_a=%p\n",
++                  sa_p->ips_authalg, ixt_a);
++      if (!ixt_a) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_alg_auth_key_create: "
++                          "NULL ipsec_alg_auth object\n");
++              return -EPROTO;
++      }
++      keyminbits=ixt_a->ixt_common.ixt_support.ias_keyminbits;
++      keymaxbits=ixt_a->ixt_common.ixt_support.ias_keymaxbits;
++      if(sa_p->ips_key_bits_a<keyminbits || sa_p->ips_key_bits_a>keymaxbits) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_alg_auth_key_create: incorrect auth"
++                          "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/,
++                          sa_p->ips_key_bits_a, keyminbits, keymaxbits);
++              ret=-EINVAL;
++              goto ixt_out;
++      }
++      /* save auth key pointer */
++      sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */
++      akp = sa_p->ips_key_a;
++      aks = sa_p->ips_key_a_size;
++
++      /* will hold: 2 ctx and a blocksize buffer: kb */
++      sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size;
++      if((sa_p->ips_key_a = 
++              (caddr_t) kmalloc(sa_p->ips_key_a_size, GFP_ATOMIC)) == NULL) {
++              ret=-ENOMEM;
++              goto ixt_out;
++      }
++      ixt_a->ixt_a_hmac_set_key(ixt_a, sa_p->ips_key_a, akp, sa_p->ips_key_bits_a/8); /* XXX XXX */
++      ret=0;
++      memset(akp, 0, aks);
++      kfree(akp);
++                      
++ixt_out:
++      return ret;
++}
++
++
++int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp,
++                        int len, __u8 *hash, int hashlen)
++{
++      struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth;
++      if (!ixt_a) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_sa_esp_hash: "
++                          "NULL ipsec_alg_auth object\n");
++              return -EPROTO;
++      }
++      KLIPS_PRINT(debug_tunnel|debug_rcv,
++                      "klips_debug:ipsec_sa_esp_hash: "
++                      "hashing %p (%d bytes) to %p (%d bytes)\n",
++                      espp, len,
++                      hash, hashlen);
++      ixt_a->ixt_a_hmac_hash(ixt_a,
++                      sa_p->ips_key_a, 
++                      espp, len,
++                      hash, hashlen);
++      return 0;
++}
++
++/***************************************************************
++ *
++ *    INTERFACE for module loading,testing, and unloading
++ *
++ ***************************************************************/
++
++/* validation for registering (enc) module */
++static int check_enc(struct ipsec_alg_enc *ixt)
++{
++      int ret=-EINVAL;
++      if (ixt->ixt_common.ixt_blocksize==0) /*  || ixt->ixt_common.ixt_blocksize%2) need for ESP_NULL */
++              barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_common.ixt_blocksize);
++      if (ixt->ixt_common.ixt_support.ias_keyminbits==0
++          && ixt->ixt_common.ixt_support.ias_keymaxbits==0
++          && ixt->ixt_e_keylen==0)
++              goto zero_key_ok;
++      
++      if (ixt->ixt_common.ixt_support.ias_keyminbits==0)
++              barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits);
++      
++      if (ixt->ixt_common.ixt_support.ias_keymaxbits==0)
++              barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits);
++      
++      if (ixt->ixt_e_keylen==0)
++              barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen);
++      
++zero_key_ok:
++      if (ixt->ixt_e_ctx_size==0 && ixt->ixt_e_new_key == NULL)
++              barf_out(KERN_ERR "invalid key_e_size=%d and ixt_e_new_key=NULL\n", ixt->ixt_e_ctx_size);
++      if (ixt->ixt_e_cbc_encrypt==NULL)
++              barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n");
++      ret=0;
++out:
++      return ret;
++}
++
++/* validation for registering (auth) module */
++static int check_auth(struct ipsec_alg_auth *ixt)
++{
++      int ret=-EINVAL;
++      if (ixt->ixt_common.ixt_support.ias_id==0 || ixt->ixt_common.ixt_support.ias_id > SADB_AALG_MAX)
++              barf_out("invalid alg_id=%d > %d (SADB_AALG_MAX)\n",
++                       ixt->ixt_common.ixt_support.ias_id, SADB_AALG_MAX);
++
++      if (ixt->ixt_common.ixt_blocksize==0
++          || ixt->ixt_common.ixt_blocksize%2)
++              barf_out(KERN_ERR "invalid blocksize=%d\n",
++                       ixt->ixt_common.ixt_blocksize);
++
++      if (ixt->ixt_common.ixt_blocksize>AH_BLKLEN_MAX)
++              barf_out(KERN_ERR "sorry blocksize=%d > %d. "
++                      "Please increase AH_BLKLEN_MAX and recompile\n", 
++                      ixt->ixt_common.ixt_blocksize,
++                      AH_BLKLEN_MAX);
++      if (ixt->ixt_common.ixt_support.ias_keyminbits==0 && ixt->ixt_common.ixt_support.ias_keymaxbits==0 && ixt->ixt_a_keylen==0)
++              goto zero_key_ok;
++      if (ixt->ixt_common.ixt_support.ias_keyminbits==0)
++              barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits);
++      if (ixt->ixt_common.ixt_support.ias_keymaxbits==0)
++              barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits);
++      if (ixt->ixt_common.ixt_support.ias_keymaxbits!=ixt->ixt_common.ixt_support.ias_keyminbits)
++              barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n");
++      if (ixt->ixt_a_keylen==0)
++              barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen);
++zero_key_ok:
++      if (ixt->ixt_a_ctx_size==0)
++              barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size);
++      if (ixt->ixt_a_hmac_set_key==NULL)
++              barf_out(KERN_ERR "a_hmac_set_key() must be not NULL\n");
++      if (ixt->ixt_a_hmac_hash==NULL)
++              barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n");
++      ret=0;
++out:
++      return ret;
++}
++
++/* 
++ * Generic (enc, auth) registration entry point 
++ */
++int register_ipsec_alg(struct ipsec_alg *ixt)
++{
++      int ret=-EINVAL;
++      /*      Validation      */
++      if (ixt==NULL)
++              barf_out("NULL ipsec_alg object passed\n");
++      if ((ixt->ixt_version&0xffffff00) != (IPSEC_ALG_VERSION&0xffffff00))
++              barf_out("incorrect version: %d.%d.%d-%d, "
++                      "must be %d.%d.%d[-%d]\n",
++                              IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), 
++                              IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION));
++
++      switch(ixt->ixt_alg_type) {
++              case IPSEC_ALG_TYPE_AUTH:
++                      if ((ret=check_auth((struct ipsec_alg_auth *)ixt)<0))
++                              goto out;
++                      break;
++              case IPSEC_ALG_TYPE_ENCRYPT: 
++                      if ((ret=check_enc((struct ipsec_alg_enc *)ixt)<0))
++                              goto out;
++                      /* 
++                       * Adapted two lines below: 
++                       *      ivlen == 0 is possible (NULL enc has blocksize==1)
++                       *
++                       * fixed NULL support by David De Reu <DeReu@tComLabs.com>
++                       */
++                      if (ixt->ixt_support.ias_ivlen == 0
++                          && ixt->ixt_blocksize > 1) {
++                              ixt->ixt_support.ias_ivlen = ixt->ixt_blocksize*8;
++                      }
++                      break;
++              default:
++                      barf_out("alg_type=%d not supported\n", ixt->ixt_alg_type);
++      }
++      INIT_LIST_HEAD(&ixt->ixt_list);
++      ret = ipsec_alg_insert(ixt);
++      if (ret<0) 
++              barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed."
++                              "Not loaded (ret=%d).\n",
++                              ixt->ixt_support.ias_id, ret);
++
++
++      ret = pfkey_list_insert_supported((struct ipsec_alg_supported *)&ixt->ixt_support
++                                        , &(pfkey_supported_list[SADB_SATYPE_ESP]));
++
++      if (ret==0) {
++              ixt->ixt_state |= IPSEC_ALG_ST_SUPP;
++              /*      send register event to userspace        */
++              pfkey_register_reply(SADB_SATYPE_ESP, NULL);
++      } else
++              printk(KERN_ERR "pfkey_list_insert_supported returned %d. "
++                              "Loading anyway.\n", ret);
++      ret=0;
++out:
++      return ret;
++}
++
++/* 
++ *    unregister ipsec_alg object from own tables, if 
++ *    success => calls pfkey_list_remove_supported()
++ */
++int unregister_ipsec_alg(struct ipsec_alg *ixt) {
++      int ret= -EINVAL;
++      switch(ixt->ixt_alg_type) {
++              case IPSEC_ALG_TYPE_AUTH:
++              case IPSEC_ALG_TYPE_ENCRYPT: 
++                      break;
++              default:
++                      /*      this is not a typo :) */
++                      barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", 
++                              ixt->ixt_name);
++      }
++
++      ret=ipsec_alg_delete(ixt);
++      if (ixt->ixt_state&IPSEC_ALG_ST_SUPP) {
++              ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP;
++              pfkey_list_remove_supported((struct ipsec_alg_supported *)&ixt->ixt_support
++                                          , &(pfkey_supported_list[SADB_SATYPE_ESP]));
++
++              /*      send register event to userspace        */
++              pfkey_register_reply(SADB_SATYPE_ESP, NULL);
++      }
++
++out:
++      return ret;
++}
++
++/*
++ *    Must be called from user context
++ *    used at module load type for testing algo implementation
++ */
++static int ipsec_alg_test_encrypt(int enc_alg, int test) {
++      int ret;
++      caddr_t buf = NULL;
++      int iv_size, keysize, key_e_size;
++      struct ipsec_alg_enc *ixt_e;
++      void *tmp_key_e = NULL;
++      #define BUFSZ   1024
++      #define MARGIN  0
++      #define test_enc   (buf+MARGIN)
++      #define test_dec   (test_enc+BUFSZ+MARGIN)
++      #define test_tmp   (test_dec+BUFSZ+MARGIN)
++      #define test_key_e (test_tmp+BUFSZ+MARGIN)
++      #define test_iv    (test_key_e+key_e_size+MARGIN)
++      #define test_key   (test_iv+iv_size+MARGIN)
++      #define test_size  (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7)
++      ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg);
++      if (ixt_e==NULL) {
++              KLIPS_PRINT(1, 
++                          "klips_debug: ipsec_alg_test_encrypt: "
++                          "encalg=%d object not found\n",
++                          enc_alg);
++              ret=-EINVAL;
++              goto out;
++      }
++      iv_size=ixt_e->ixt_common.ixt_support.ias_ivlen / 8;
++      key_e_size=ixt_e->ixt_e_ctx_size;
++      keysize=ixt_e->ixt_e_keylen;
++      KLIPS_PRINT(1, 
++                  "klips_debug: ipsec_alg_test_encrypt: "
++                  "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n",
++                  enc_alg, iv_size, key_e_size, keysize);
++      if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
++              ret= -ENOMEM;
++              goto out;
++      }
++      get_random_bytes(test_key, keysize);
++      get_random_bytes(test_iv, iv_size);
++      if (ixt_e->ixt_e_new_key) {
++              tmp_key_e = ixt_e->ixt_e_new_key(ixt_e, test_key, keysize);
++              ret = tmp_key_e ? 0 : -EINVAL;
++      } else {
++              tmp_key_e = test_key_e;
++              ret = ixt_e->ixt_e_set_key(ixt_e, test_key_e, test_key, keysize);
++      }
++      if (ret < 0)
++              goto out;
++      get_random_bytes(test_enc, BUFSZ);
++      memcpy(test_tmp, test_enc, BUFSZ);
++      ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_enc, BUFSZ, test_iv, 1);
++      printk(KERN_INFO
++                  "klips_info: ipsec_alg_test_encrypt: "
++                  "cbc_encrypt=1 ret=%d\n", 
++                      ret);
++      ret=memcmp(test_enc, test_tmp, BUFSZ);
++      printk(KERN_INFO
++                  "klips_info: ipsec_alg_test_encrypt: "
++                  "memcmp(enc, tmp) ret=%d: %s\n", ret,
++                      ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" );
++      memcpy(test_dec, test_enc, BUFSZ);
++      ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_dec, BUFSZ, test_iv, 0);
++      printk(KERN_INFO
++                  "klips_info: ipsec_alg_test_encrypt: "
++                  "cbc_encrypt=0 ret=%d\n", ret);
++      ret=memcmp(test_dec, test_tmp, BUFSZ);
++      printk(KERN_INFO
++                  "klips_info: ipsec_alg_test_encrypt: "
++                  "memcmp(dec,tmp) ret=%d: %s\n", ret,
++                      ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" );
++      {
++              /*      Shamelessly taken from drivers/md sources  O:)  */
++              unsigned long now;
++              int i, count, max=0;
++              int encrypt, speed;
++              for (encrypt=0; encrypt <2;encrypt ++) {
++                      for (i = 0; i < 5; i++) {
++                              now = jiffies;
++                              count = 0;
++                              while (jiffies == now) {
++                                      mb();
++                                      ixt_e->ixt_e_cbc_encrypt(ixt_e, 
++                                                      tmp_key_e, test_tmp, 
++                                                      BUFSZ, test_iv, encrypt);
++                                      mb();
++                                      count++;
++                                      mb();
++                              }
++                              if (count > max)
++                                      max = count;
++                      }
++                      speed = max * (HZ * BUFSZ / 1024);
++                      printk(KERN_INFO
++                                  "klips_info: ipsec_alg_test_encrypt: "
++                                  "%s %s speed=%d KB/s\n", 
++                                  ixt_e->ixt_common.ixt_name,
++                                  encrypt? "encrypt": "decrypt", speed);
++              }
++      }
++out:
++      if (tmp_key_e && ixt_e->ixt_e_destroy_key) ixt_e->ixt_e_destroy_key(ixt_e, tmp_key_e);
++      if (buf) kfree(buf);
++      if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e);
++      return ret;
++      #undef test_enc  
++      #undef test_dec  
++      #undef test_tmp  
++      #undef test_key_e
++      #undef test_iv   
++      #undef test_key  
++      #undef test_size 
++}
++
++/*
++ *    Must be called from user context
++ *    used at module load type for testing algo implementation
++ */
++static int ipsec_alg_test_auth(int auth_alg, int test) {
++      int ret;
++      caddr_t buf = NULL;
++      int blocksize, keysize, key_a_size;
++      struct ipsec_alg_auth *ixt_a;
++      #define BUFSZ   1024
++      #define MARGIN  0
++      #define test_auth  (buf+MARGIN)
++      #define test_key_a (test_auth+BUFSZ+MARGIN)
++      #define test_key   (test_key_a+key_a_size+MARGIN)
++      #define test_hash  (test_key+keysize+MARGIN)
++      #define test_size  (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4)
++      ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg);
++      if (ixt_a==NULL) {
++              KLIPS_PRINT(1, 
++                          "klips_debug: ipsec_alg_test_auth: "
++                          "encalg=%d object not found\n",
++                          auth_alg);
++              ret=-EINVAL;
++              goto out;
++      }
++      blocksize=ixt_a->ixt_common.ixt_blocksize;
++      key_a_size=ixt_a->ixt_a_ctx_size;
++      keysize=ixt_a->ixt_a_keylen;
++      KLIPS_PRINT(1, 
++                  "klips_debug: ipsec_alg_test_auth: "
++                  "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n",
++                  auth_alg, blocksize, key_a_size, keysize);
++      if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
++              ret= -ENOMEM;
++              goto out;
++      }
++      get_random_bytes(test_key, keysize);
++      ret = ixt_a->ixt_a_hmac_set_key(ixt_a, test_key_a, test_key, keysize);
++      if (ret < 0 )
++              goto out;
++      get_random_bytes(test_auth, BUFSZ);
++      ret=ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
++      printk(KERN_INFO
++                  "klips_info: ipsec_alg_test_auth: "
++                  "ret=%d\n", ret);
++      {
++              /*      Shamelessly taken from drivers/md sources  O:)  */
++              unsigned long now;
++              int i, count, max=0;
++              int speed;
++              for (i = 0; i < 5; i++) {
++                      now = jiffies;
++                      count = 0;
++                      while (jiffies == now) {
++                              mb();
++                              ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
++                              mb();
++                              count++;
++                              mb();
++                      }
++                      if (count > max)
++                              max = count;
++              }
++              speed = max * (HZ * BUFSZ / 1024);
++              printk(KERN_INFO
++                              "klips_info: ipsec_alg_test_auth: "
++                              "%s hash speed=%d KB/s\n", 
++                              ixt_a->ixt_common.ixt_name,
++                              speed);
++      }
++out:
++      if (buf) kfree(buf);
++      if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a);
++      return ret;
++      #undef test_auth 
++      #undef test_key_a
++      #undef test_key  
++      #undef test_hash 
++      #undef test_size 
++}
++
++int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) {
++      switch(alg_type) {
++              case IPSEC_ALG_TYPE_ENCRYPT:
++                      return ipsec_alg_test_encrypt(alg_id, test);
++                      break;
++              case IPSEC_ALG_TYPE_AUTH:
++                      return ipsec_alg_test_auth(alg_id, test);
++                      break;
++      }
++      printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: "
++                      "alg_type=%d alg_id=%d\n",
++                      alg_type, alg_id);
++      return -EINVAL;
++}
++
++int ipsec_alg_init(void) {
++      KLIPS_PRINT(1, "klips_info:ipsec_alg_init: "
++                      "KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n",
++                      IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION),
++                      SADB_EALG_MAX, SADB_AALG_MAX);
++      /*      Initialize tables */
++      write_lock_bh(&ipsec_alg_lock);
++      ipsec_alg_hash_init();
++      write_unlock_bh(&ipsec_alg_lock);
++
++      /*      Initialize static algos         */
++      KLIPS_PRINT(1, "klips_info:ipsec_alg_init: "
++              "calling ipsec_alg_static_init()\n");
++
++      /* If we are suppose to use our AES, and don't have
++       * CryptoAPI enabled...
++       */
++#if defined(CONFIG_KLIPS_ENC_AES) && CONFIG_KLIPS_ENC_AES && !defined(CONFIG_KLIPS_ENC_AES_MODULE) 
++#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI
++#warning "Using built-in AES rather than CryptoAPI AES"
++#endif        
++      {
++              extern int ipsec_aes_init(void);
++              ipsec_aes_init();
++      }
++#endif
++
++#if defined(CONFIG_KLIPS_ENC_3DES) && CONFIG_KLIPS_ENC_3DES && !defined(CONFIG_KLIPS_ENC_3DES_MODULE) 
++#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI
++#warning "Using built-in 3des rather than CryptoAPI 3des"
++#endif        
++      {
++              extern int ipsec_3des_init(void);
++              ipsec_3des_init();
++      }
++#endif
++#if defined(CONFIG_KLIPS_ENC_NULL) && CONFIG_KLIPS_ENC_NULL && !defined(CONFIG_KLIPS_ENC_NULL_MODULE) 
++#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI
++#warning "Using built-in null cipher rather than CryptoAPI null cipher"
++#endif        
++#warning "Building with null cipher (ESP_NULL), blame on you :-)"
++      {
++              extern int ipsec_null_init(void);
++              ipsec_null_init();
++      }
++#endif
++
++
++      /* If we are doing CryptoAPI, then init */
++#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI && !defined(CONFIG_KLIPS_ENC_CRYPTOAPI_MODULE)
++      {
++                extern int ipsec_cryptoapi_init(void);
++                ipsec_cryptoapi_init();
++        }
++#endif
++
++
++      return 0;
++}
++
++/**********************************************
++ *
++ *    INTERFACE for ipsec_sa init and wipe
++ *
++ **********************************************/
++
++/*    
++ *    Called from pluto -> pfkey_v2_parser.c:pfkey_ipsec_sa_init()    
++ */
++int ipsec_alg_sa_init(struct ipsec_sa *sa_p) {
++      struct ipsec_alg_enc *ixt_e;
++      struct ipsec_alg_auth *ixt_a;
++
++      /*      Only ESP for now ... */
++      if (sa_p->ips_said.proto != IPPROTO_ESP)
++              return -EPROTONOSUPPORT;
++
++      KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :"
++                      "entering for encalg=%d, authalg=%d\n",
++                          sa_p->ips_encalg, sa_p->ips_authalg);
++
++      if ((ixt_e=(struct ipsec_alg_enc *)
++              ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg))) {
++              KLIPS_PRINT(debug_pfkey,
++                  "klips_debug: ipsec_alg_sa_init() :"
++                  "found ipsec_alg (ixt_e=%p) for encalg=%d\n",
++                  ixt_e, sa_p->ips_encalg);
++              sa_p->ips_alg_enc=ixt_e;
++      }
++
++      if ((ixt_a=(struct ipsec_alg_auth *)
++              ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg))) {
++              KLIPS_PRINT(debug_pfkey,
++                  "klips_debug: ipsec_alg_sa_init() :"
++                  "found ipsec_alg (ixt_a=%p) for auth=%d\n",
++                  ixt_a, sa_p->ips_authalg);
++              sa_p->ips_alg_auth=ixt_a;
++      }
++      return 0;
++}
++
++/*    
++ *    Called from pluto -> ipsec_sa.c:ipsec_sa_delchain()
++ */
++int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) {
++      struct ipsec_alg *ixt;
++      if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_enc)) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :"
++                              "unlinking for encalg=%d\n",
++                              ixt->ixt_support.ias_id);
++              ipsec_alg_put(ixt);
++      }
++      if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_auth)) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :"
++                              "unlinking for authalg=%d\n",
++                              ixt->ixt_support.ias_id);
++              ipsec_alg_put(ixt);
++      }
++      return 0;
++}
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_xform_get_info(char *buffer,
++                   char **start,
++                   off_t offset,
++                   int length     IPSEC_PROC_LAST_ARG)
++{
++      int len = 0;
++      off_t begin = 0;
++      int i;
++      struct list_head *head;
++      struct ipsec_alg *ixt;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_tncfg_get_info: "
++                  "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
++                  buffer,
++                  *start,
++                  (int)offset,
++                  length);
++
++      for(i = 0, head = ipsec_alg_hash_table;
++          i<IPSEC_ALG_HASHSZ;
++          i++, head++)
++      {
++              struct list_head *p;
++              for (p=head->next; p!=head; p=p->next)
++              {
++                      ixt = list_entry(p, struct ipsec_alg, ixt_list);
++                      len += ipsec_snprintf(buffer+len, length-len,
++                                            "VERSION=%d TYPE=%d ID=%d NAME=%s REFCNT=%d ",
++                                            ixt->ixt_version, ixt->ixt_alg_type, ixt->ixt_support.ias_id,
++                                            ixt->ixt_name, ixt->ixt_refcnt);
++
++                      len += ipsec_snprintf(buffer+len, length-len,
++                                            "STATE=%08x BLOCKSIZE=%d IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ",
++                                            ixt->ixt_state, ixt->ixt_blocksize,
++                                            ixt->ixt_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_keymaxbits);
++
++                      len += ipsec_snprintf(buffer+len, length-len,
++                                            "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ",
++                                            ixt->ixt_support.ias_ivlen, ixt->ixt_support.ias_keyminbits, ixt->ixt_support.ias_keymaxbits);
++
++                      switch(ixt->ixt_alg_type)
++                      {
++                      case IPSEC_ALG_TYPE_AUTH:
++                      {
++                              struct ipsec_alg_auth *auth = (struct ipsec_alg_auth *)ixt;
++
++                              len += ipsec_snprintf(buffer+len, length-len,
++                                                    "KEYLEN=%d CTXSIZE=%d AUTHLEN=%d ",
++                                                    auth->ixt_a_keylen, auth->ixt_a_ctx_size,
++                                                    auth->ixt_a_authlen);
++                              break;
++                      }
++                      case IPSEC_ALG_TYPE_ENCRYPT:
++                      {
++                              struct ipsec_alg_enc *enc = (struct ipsec_alg_enc *)ixt;
++                              len += ipsec_snprintf(buffer+len, length-len,
++                                                    "KEYLEN=%d CTXSIZE=%d ",
++                                                    enc->ixt_e_keylen, enc->ixt_e_ctx_size);
++
++                              break;
++                      }
++                      }
++
++                      len += ipsec_snprintf(buffer+len, length-len, "\n");
++              }
++      } 
++
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      len -= (offset - begin);                        /* Start slop */
++      if (len > length)
++              len = length;
++      return len;
++}
++
++
++/*
++ *    As the author of this module, I ONLY ALLOW using it from
++ *    GPL (or same LICENSE TERMS as kernel source) modules.
++ *
++ *    In respect to hardware crypto engines this means:
++ *    * Closed-source device drivers ARE NOT ALLOWED to use 
++ *      this interface.
++ *    * Closed-source VHDL/Verilog firmware running on 
++ *      the crypto hardware device IS ALLOWED to use this interface
++ *      via a GPL (or same LICENSE TERMS as kernel source) device driver.
++ *    --Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording)
++ */
++
++/*    
++ *    These symbols can only be used from GPL modules 
++ *    for now, I'm disabling this because it creates false
++ *    symbol problems for old modutils.
++ */
++
++#ifdef CONFIG_MODULES
++#ifndef NET_26
++#if 0
++#ifndef EXPORT_SYMBOL_GPL 
++#undef EXPORT_SYMBOL_GPL
++#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL
++#endif 
++#endif
++EXPORT_SYMBOL(register_ipsec_alg);
++EXPORT_SYMBOL(unregister_ipsec_alg);
++EXPORT_SYMBOL(ipsec_alg_test);
++#endif
++#endif
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_alg_cryptoapi.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,455 @@
++/*
++ * ipsec_alg to linux cryptoapi GLUE
++ *
++ * Authors: CODE.ar TEAM
++ *    Harpo MAxx <harpo@linuxmendoza.org.ar>
++ *    JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ *    Luciano Ruete <docemeses@softhome.net>
++ * 
++ * ipsec_alg_cryptoapi.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * Example usage:
++ *   modinfo -p ipsec_cryptoapi   (quite useful info, including supported algos)
++ *   modprobe ipsec_cryptoapi
++ *   modprobe ipsec_cryptoapi test=1
++ *   modprobe ipsec_cryptoapi excl=1                     (exclusive cipher/algo)
++ *   modprobe ipsec_cryptoapi noauto=1  aes=1 twofish=1  (only these ciphers)
++ *   modprobe ipsec_cryptoapi aes=128,128                (force these keylens)
++ *   modprobe ipsec_cryptoapi des_ede3=0                 (everything but 3DES)
++ */
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++/*    
++ *    special case: ipsec core modular with this static algo inside:
++ *    must avoid MODULE magic for this file
++ */
++#if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_CRYPTOAPI)
++#undef MODULE
++#endif
++
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/string.h>
++
++/* Check if __exit is defined, if not null it */
++#ifndef __exit
++#define __exit
++#endif
++
++/* warn the innocent */
++#if !defined (CONFIG_CRYPTO) && !defined (CONFIG_CRYPTO_MODULE)
++#warning "No linux CryptoAPI found, install 2.4.22+ or 2.6.x"
++#define NO_CRYPTOAPI_SUPPORT
++#endif
++
++#include "openswan.h"
++#include "openswan/ipsec_alg.h"
++#include "openswan/ipsec_policy.h"
++
++#include <linux/crypto.h>
++#ifdef CRYPTO_API_VERSION_CODE
++#warning "Old CryptoAPI is not supported. Only linux-2.4.22+ or linux-2.6.x are supported"
++#define NO_CRYPTOAPI_SUPPORT
++#endif
++
++#ifdef NO_CRYPTOAPI_SUPPORT
++#warning "Building an unusable module :P"
++/* Catch old CryptoAPI by not allowing module to load */
++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init )
++{
++      printk(KERN_WARNING "ipsec_cryptoapi.o was not built on stock Linux CryptoAPI (2.4.22+ or 2.6.x), not loading.\n");
++      return -EINVAL;
++}
++#else
++#include <asm/scatterlist.h>
++#include <asm/pgtable.h>
++#include <linux/mm.h>
++
++#define CIPHERNAME_AES                "aes"
++#define CIPHERNAME_1DES               "des"
++#define CIPHERNAME_3DES               "des3_ede"
++#define CIPHERNAME_BLOWFISH   "blowfish"
++#define CIPHERNAME_CAST               "cast5"
++#define CIPHERNAME_SERPENT    "serpent"
++#define CIPHERNAME_TWOFISH    "twofish"
++
++#define ESP_SERPENT           252     /* from ipsec drafts */
++#define ESP_TWOFISH           253     /* from ipsec drafts */
++
++#define DIGESTNAME_MD5                "md5"
++#define DIGESTNAME_SHA1               "sha1"
++
++MODULE_AUTHOR("Juanjo Ciarlante, Harpo MAxx, Luciano Ruete");
++static int debug_crypto=0;
++static int test_crypto=0;
++static int excl_crypto=0;
++
++static int noauto = 0;
++
++#ifdef module_param
++module_param(debug_crypto,int,0600)
++module_param(test_crypto,int,0600)
++module_param(excl_crypto,int,0600)
++
++module_param(noauto,int,0600)
++#else
++MODULE_PARM(debug_crypto, "i");
++MODULE_PARM(test_crypto, "i");
++MODULE_PARM(excl_crypto, "i");
++
++MODULE_PARM(noauto,"i");
++#endif
++MODULE_PARM_DESC(noauto, "Dont try all known algos, just setup enabled ones");
++
++#ifdef CONFIG_KLIPS_ENC_1DES
++static int des_ede1[] = {-1, -1};
++#endif
++static int des_ede3[] = {-1, -1};
++static int aes[] = {-1, -1};
++static int blowfish[] = {-1, -1};
++static int cast[] = {-1, -1};
++static int serpent[] = {-1, -1};
++static int twofish[] = {-1, -1};
++
++#ifdef CONFIG_KLIPS_ENC_1DES
++#ifdef module_param
++module_param_array(des_ede1,int,NULL,0)
++#else
++MODULE_PARM(des_ede1,"1-2i");
++#endif
++#endif
++#ifdef module_param
++module_param_array(des_ede3,int,NULL,0)
++module_param_array(aes,int,NULL,0)
++module_param_array(blowfish,int,NULL,0)
++module_param_array(cast,int,NULL,0)
++module_param_array(serpent,int,NULL,0)
++module_param_array(twofish,int,NULL,0)
++#else
++MODULE_PARM(des_ede3,"1-2i");
++MODULE_PARM(aes,"1-2i");
++MODULE_PARM(blowfish,"1-2i");
++MODULE_PARM(cast,"1-2i");
++MODULE_PARM(serpent,"1-2i");
++MODULE_PARM(twofish,"1-2i");
++#endif
++MODULE_PARM_DESC(des_ede1, "0: disable | 1: force_enable | min,max: dontuse");
++MODULE_PARM_DESC(des_ede3, "0: disable | 1: force_enable | min,max: dontuse");
++MODULE_PARM_DESC(aes, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(blowfish, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(cast, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(serpent, "0: disable | 1: force_enable | min,max: keybitlens");
++MODULE_PARM_DESC(twofish, "0: disable | 1: force_enable | min,max: keybitlens");
++
++struct ipsec_alg_capi_cipher {
++      const char *ciphername; /* cryptoapi's ciphername */
++      unsigned blocksize;
++      unsigned short minbits;
++      unsigned short maxbits;
++      int *parm;              /* lkm param for this cipher */
++      struct ipsec_alg_enc alg;       /* note it's not a pointer */
++};
++
++static struct ipsec_alg_capi_cipher alg_capi_carray[] = {
++  { CIPHERNAME_AES,     16, 128, 256, aes,      { ixt_common:{ ixt_support:{ ias_id: ESP_AES}}}},
++  { CIPHERNAME_TWOFISH, 16, 128, 256, twofish,  { ixt_common:{ ixt_support:{ ias_id: ESP_TWOFISH,}}}},
++  { CIPHERNAME_SERPENT, 16, 128, 256, serpent,  { ixt_common:{ ixt_support:{ ias_id: ESP_SERPENT,}}}},
++  { CIPHERNAME_CAST,     8, 128, 128, cast   ,  { ixt_common:{ ixt_support:{ ias_id: ESP_CAST,}}}},
++  { CIPHERNAME_BLOWFISH, 8,  96, 448, blowfish, { ixt_common:{ ixt_support:{ ias_id: ESP_BLOWFISH,}}}},
++  { CIPHERNAME_3DES,     8, 192, 192, des_ede3, { ixt_common:{ ixt_support:{ ias_id: ESP_3DES,}}}},
++#ifdef CONFIG_KLIPS_ENC_1DES
++  { CIPHERNAME_1DES,     8,  64,  64, des_ede1, { ixt_common:{ ixt_support:{ ias_id: ESP_DES,}}}},
++#endif
++  { NULL, 0, 0, 0, NULL, {} }
++};
++
++#ifdef NOT_YET
++struct ipsec_alg_capi_digest {
++      const char *digestname; /* cryptoapi's digestname */
++      struct digest_implementation *di;
++      struct ipsec_alg_auth alg;      /* note it's not a pointer */
++};
++static struct ipsec_alg_capi_cipher alg_capi_darray[] = {
++      { DIGESTNAME_MD5,     NULL, { ixt_alg_id: AH_MD5, }},
++      { DIGESTNAME_SHA1,    NULL, { ixt_alg_id: AH_SHA, }},
++      { NULL, NULL, {} }
++};
++#endif
++/*
++ *    "generic" linux cryptoapi setup_cipher() function
++ */
++int setup_cipher(const char *ciphername)
++{
++      return crypto_alg_available(ciphername, 0);
++}
++
++/*
++ *    setups ipsec_alg_capi_cipher "hyper" struct components, calling
++ *    register_ipsec_alg for cointaned ipsec_alg object
++ */
++static void _capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e);
++static __u8 * _capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen);
++static int _capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt);
++
++static int
++setup_ipsec_alg_capi_cipher(struct ipsec_alg_capi_cipher *cptr)
++{
++      int ret;
++      cptr->alg.ixt_common.ixt_version = IPSEC_ALG_VERSION;
++      cptr->alg.ixt_common.ixt_module  = THIS_MODULE;
++      atomic_set (& cptr->alg.ixt_common.ixt_refcnt, 0);
++      strncpy (cptr->alg.ixt_common.ixt_name , cptr->ciphername, sizeof (cptr->alg.ixt_common.ixt_name));
++
++      cptr->alg.ixt_common.ixt_blocksize=cptr->blocksize;
++      cptr->alg.ixt_common.ixt_support.ias_keyminbits=cptr->minbits;
++      cptr->alg.ixt_common.ixt_support.ias_keymaxbits=cptr->maxbits;
++      cptr->alg.ixt_common.ixt_state = 0;
++      if (excl_crypto) cptr->alg.ixt_common.ixt_state |= IPSEC_ALG_ST_EXCL;
++      cptr->alg.ixt_e_keylen=cptr->alg.ixt_common.ixt_support.ias_keymaxbits/8;
++      cptr->alg.ixt_e_ctx_size = 0;
++      cptr->alg.ixt_common.ixt_support.ias_exttype = IPSEC_ALG_TYPE_ENCRYPT;
++      cptr->alg.ixt_e_new_key = _capi_new_key;
++      cptr->alg.ixt_e_destroy_key = _capi_destroy_key;
++      cptr->alg.ixt_e_cbc_encrypt = _capi_cbc_encrypt;
++      cptr->alg.ixt_common.ixt_data = cptr;
++
++      ret=register_ipsec_alg_enc(&cptr->alg);
++      printk(KERN_INFO "KLIPS cryptoapi interface: " 
++                      "alg_type=%d alg_id=%d name=%s "
++                      "keyminbits=%d keymaxbits=%d, %s(%d)\n", 
++                              cptr->alg.ixt_common.ixt_support.ias_exttype, 
++                              cptr->alg.ixt_common.ixt_support.ias_id, 
++                              cptr->alg.ixt_common.ixt_name, 
++                              cptr->alg.ixt_common.ixt_support.ias_keyminbits,
++                              cptr->alg.ixt_common.ixt_support.ias_keymaxbits,
++             ret ? "not found" : "found", ret);
++      return ret;
++}
++/*
++ *    called in ipsec_sa_wipe() time, will destroy key contexts
++ *    and do 1 unbind()
++ */
++static void 
++_capi_destroy_key (struct ipsec_alg_enc *alg, __u8 *key_e)
++{
++      struct crypto_tfm *tfm=(struct crypto_tfm*)key_e;
++      
++      if (debug_crypto > 0)
++              printk(KERN_DEBUG "klips_debug: _capi_destroy_key:"
++                              "name=%s key_e=%p \n",
++                              alg->ixt_common.ixt_name, key_e);
++      if (!key_e) {
++              printk(KERN_ERR "klips_debug: _capi_destroy_key:"
++                              "name=%s NULL key_e!\n",
++                              alg->ixt_common.ixt_name);
++              return;
++      }
++      crypto_free_tfm(tfm);
++}
++      
++/*
++ *    create new key context, need alg->ixt_data to know which
++ *    (of many) cipher inside this module is the target
++ */
++static __u8 *
++_capi_new_key (struct ipsec_alg_enc *alg, const __u8 *key, size_t keylen)
++{
++      struct ipsec_alg_capi_cipher *cptr;
++      struct crypto_tfm *tfm=NULL;
++
++      cptr = alg->ixt_common.ixt_data;
++      if (!cptr) {
++              printk(KERN_ERR "_capi_new_key(): "
++                              "NULL ixt_data (?!) for \"%s\" algo\n" 
++                              , alg->ixt_common.ixt_name);
++              goto err;
++      }
++      if (debug_crypto > 0)
++              printk(KERN_DEBUG "klips_debug:_capi_new_key:"
++                              "name=%s cptr=%p key=%p keysize=%d\n",
++                              alg->ixt_common.ixt_name, cptr, key, keylen);
++      
++      /*      
++       *      alloc tfm
++       */
++      tfm = crypto_alloc_tfm(cptr->ciphername, CRYPTO_TFM_MODE_CBC);
++      if (!tfm) {
++              printk(KERN_ERR "_capi_new_key(): "
++                              "NULL tfm for \"%s\" cryptoapi (\"%s\") algo\n" 
++                      , alg->ixt_common.ixt_name, cptr->ciphername);
++              goto err;
++      }
++      if (crypto_cipher_setkey(tfm, key, keylen) < 0) {
++              printk(KERN_ERR "_capi_new_key(): "
++                              "failed new_key() for \"%s\" cryptoapi algo (keylen=%d)\n" 
++                      , alg->ixt_common.ixt_name, keylen);
++              crypto_free_tfm(tfm);
++              tfm=NULL;
++      }
++err:
++      if (debug_crypto > 0)
++              printk(KERN_DEBUG "klips_debug:_capi_new_key:"
++                              "name=%s key=%p keylen=%d tfm=%p\n",
++                              alg->ixt_common.ixt_name, key, keylen, tfm);
++      return (__u8 *) tfm;
++}
++/*
++ *    core encryption function: will use cx->ci to call actual cipher's
++ *    cbc function
++ */
++static int 
++_capi_cbc_encrypt(struct ipsec_alg_enc *alg, __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, int encrypt) {
++      int error =0;
++      struct crypto_tfm *tfm=(struct crypto_tfm *)key_e;
++      struct scatterlist sg = { 
++              .page = virt_to_page(in),
++              .offset = (unsigned long)(in) % PAGE_SIZE,
++              .length=ilen,
++      };
++      if (debug_crypto > 1)
++              printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:"
++                              "key_e=%p "
++                              "in=%p out=%p ilen=%d iv=%p encrypt=%d\n"
++                              , key_e
++                              , in, in, ilen, iv, encrypt);
++      crypto_cipher_set_iv(tfm, iv, crypto_tfm_alg_ivsize(tfm));
++      if (encrypt)
++              error = crypto_cipher_encrypt (tfm, &sg, &sg, ilen);
++      else
++              error = crypto_cipher_decrypt (tfm, &sg, &sg, ilen);
++      if (debug_crypto > 1)
++              printk(KERN_DEBUG "klips_debug:_capi_cbc_encrypt:"
++                              "error=%d\n"
++                              , error);
++      return (error<0)? error : ilen;
++}
++/*
++ *    main initialization loop: for each cipher in list, do
++ *    1) setup cryptoapi cipher else continue
++ *    2) register ipsec_alg object
++ */
++static int
++setup_cipher_list (struct ipsec_alg_capi_cipher* clist) 
++{
++      struct ipsec_alg_capi_cipher *cptr;
++      /* foreach cipher in list ... */
++      for (cptr=clist;cptr->ciphername;cptr++) {
++              /* 
++               * see if cipher has been disabled (0) or
++               * if noauto set and not enabled (1)
++               */
++              if (cptr->parm[0] == 0 || (noauto && cptr->parm[0] < 0)) {
++                      if (debug_crypto>0)
++                              printk(KERN_INFO "setup_cipher_list(): "
++                                      "ciphername=%s skipped at user request: "
++                                      "noauto=%d parm[0]=%d parm[1]=%d\n"
++                                      , cptr->ciphername
++                                      , noauto
++                                      , cptr->parm[0]
++                                      , cptr->parm[1]);
++                      continue;
++              }
++              /* 
++               *      use a local ci to avoid touching cptr->ci,
++               *      if register ipsec_alg success then bind cipher
++               */
++              if(cptr->alg.ixt_common.ixt_support.ias_name == NULL) {
++                cptr->alg.ixt_common.ixt_support.ias_name = cptr->ciphername;
++              }
++
++              if( setup_cipher(cptr->ciphername) ) {
++                      if (debug_crypto > 0)
++                              printk(KERN_DEBUG "klips_debug:"
++                                              "setup_cipher_list():"
++                                              "ciphername=%s found\n"
++                              , cptr->ciphername);
++
++                      if (setup_ipsec_alg_capi_cipher(cptr) != 0) {
++                              printk(KERN_ERR "klips_debug:"
++                                     "setup_cipher_list():"
++                                     "ciphername=%s failed ipsec_alg_register\n"
++                                     , cptr->ciphername);
++                      }
++              } else {
++                      printk(KERN_INFO "KLIPS: lookup for ciphername=%s: not found \n",
++                             cptr->ciphername);
++              }
++      }
++      return 0;
++}
++/*
++ *    deregister ipsec_alg objects and unbind ciphers
++ */
++static int
++unsetup_cipher_list (struct ipsec_alg_capi_cipher* clist) 
++{
++      struct ipsec_alg_capi_cipher *cptr;
++      /* foreach cipher in list ... */
++      for (cptr=clist;cptr->ciphername;cptr++) {
++              if (cptr->alg.ixt_common.ixt_state & IPSEC_ALG_ST_REGISTERED) {
++                      unregister_ipsec_alg_enc(&cptr->alg);
++              }
++      }
++      return 0;
++}
++/*
++ *    test loop for registered algos
++ */
++static int
++test_cipher_list (struct ipsec_alg_capi_cipher* clist) 
++{
++      int test_ret;
++      struct ipsec_alg_capi_cipher *cptr;
++      /* foreach cipher in list ... */
++      for (cptr=clist;cptr->ciphername;cptr++) {
++              if (cptr->alg.ixt_common.ixt_state & IPSEC_ALG_ST_REGISTERED) {
++                      test_ret=ipsec_alg_test(
++                                      cptr->alg.ixt_common.ixt_support.ias_exttype,
++                                      cptr->alg.ixt_common.ixt_support.ias_id, 
++                                      test_crypto);
++                      printk("test_cipher_list(alg_type=%d alg_id=%d): test_ret=%d\n", 
++                             cptr->alg.ixt_common.ixt_support.ias_exttype, 
++                             cptr->alg.ixt_common.ixt_support.ias_id,
++                             test_ret);
++              }
++      }
++      return 0;
++}
++
++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_cryptoapi_init )
++{
++      int ret, test_ret;
++      if ((ret=setup_cipher_list(alg_capi_carray)) < 0)
++              return  -EPROTONOSUPPORT;
++      if (ret==0 && test_crypto) {
++              test_ret=test_cipher_list(alg_capi_carray);
++      }
++      return ret;
++}
++IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_cryptoapi_fini )
++{
++      unsetup_cipher_list(alg_capi_carray);
++      return;
++}
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++
++#endif /* NO_CRYPTOAPI_SUPPORT */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_esp.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,607 @@
++/*
++ * processing code for ESP
++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_esp_c_version[] = "RCSID $Id: ipsec_esp.c,v 1.13.2.6 2006/10/06 21:39:26 paul Exp $";
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>  /* struct device, and other headers */
++#include <linux/etherdevice.h>        /* eth_type_trans */
++#include <linux/ip.h>         /* struct iphdr */
++#include <linux/skbuff.h>
++#include <openswan.h>
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++#include <net/protocol.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipsec_xmit.h"
++
++#include "openswan/ipsec_auth.h"
++
++#ifdef CONFIG_KLIPS_ESP
++#include "openswan/ipsec_esp.h"
++#endif /* CONFIG_KLIPS_ESP */
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_alg.h"
++
++#ifdef CONFIG_KLIPS_DEBUG
++#define ESP_DMP(_x,_y,_z) if(debug_rcv && sysctl_ipsec_debug_verbose) ipsec_dmp_block(_x,_y,_z)
++#else
++#define ESP_DMP(_x,_y,_z)
++#endif
++
++#ifdef CONFIG_KLIPS_ESP
++enum ipsec_rcv_value
++ipsec_rcv_esp_checks(struct ipsec_rcv_state *irs,
++                   struct sk_buff *skb)
++{
++      __u8 proto;
++      int len;        /* packet length */
++
++      len = skb->len;
++      proto = irs->ipp->protocol;
++
++      /* XXX this will need to be 8 for IPv6 */
++      if ((proto == IPPROTO_ESP) && ((len - irs->iphlen) % 4)) {
++              printk("klips_error:ipsec_rcv: "
++                     "got packet with content length = %d from %s -- should be on 4 octet boundary, packet dropped\n",
++                     len - irs->iphlen,
++                     irs->ipsaddr_txt);
++              if(irs->stats) {
++                      irs->stats->rx_errors++;
++              }
++              return IPSEC_RCV_BADLEN;
++      }
++
++      if(skb->len < (irs->hard_header_len + sizeof(struct iphdr) + sizeof(struct esphdr))) {
++              KLIPS_PRINT(debug_rcv & DB_RX_INAU,
++                          "klips_debug:ipsec_rcv: "
++                          "runt esp packet of skb->len=%d received from %s, dropped.\n",
++                          skb->len,
++                          irs->ipsaddr_txt);
++              if(irs->stats) {
++                      irs->stats->rx_errors++;
++              }
++              return IPSEC_RCV_BADLEN;
++      }
++
++      irs->protostuff.espstuff.espp = (struct esphdr *)skb->h.raw;
++      irs->said.spi = irs->protostuff.espstuff.espp->esp_spi;
++
++      return IPSEC_RCV_OK;
++}
++
++enum ipsec_rcv_value
++ipsec_rcv_esp_decrypt_setup(struct ipsec_rcv_state *irs,
++                          struct sk_buff *skb,
++                          __u32          *replay,
++                          unsigned char **authenticator)
++{
++      struct esphdr *espp = irs->protostuff.espstuff.espp;
++      //unsigned char *idat = (unsigned char *)espp;
++
++      KLIPS_PRINT(debug_rcv,
++                  "klips_debug:ipsec_rcv: "
++                  "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n",
++                  irs->ipsaddr_txt,
++                  (__u32)ntohl(espp->esp_rpl),
++                  (__u32)ntohl(*((__u32 *)(espp->esp_iv)    )),
++                  (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)),
++                  irs->len,
++                  irs->ilen,
++                  irs->sa_len ? irs->sa : " (error)");
++
++      *replay = ntohl(espp->esp_rpl);
++      *authenticator = &(skb->h.raw[irs->ilen]);
++
++      return IPSEC_RCV_OK;
++}
++
++enum ipsec_rcv_value
++ipsec_rcv_esp_authcalc(struct ipsec_rcv_state *irs,
++                     struct sk_buff *skb)
++{
++      struct auth_alg *aa;
++      struct esphdr *espp = irs->protostuff.espstuff.espp;
++      union {
++              MD5_CTX         md5;
++              SHA1_CTX        sha1;
++      } tctx;
++
++      if (irs->ipsp->ips_alg_auth) {
++              KLIPS_PRINT(debug_rcv,
++                              "klips_debug:ipsec_rcv: "
++                              "ipsec_alg hashing proto=%d... ",
++                              irs->said.proto);
++              if(irs->said.proto == IPPROTO_ESP) {
++                      ipsec_alg_sa_esp_hash(irs->ipsp,
++                                      (caddr_t)espp, irs->ilen,
++                                      irs->hash, AHHMAC_HASHLEN);
++                      return IPSEC_RCV_OK;
++              }
++              return IPSEC_RCV_BADPROTO;
++      }
++      aa = irs->authfuncs;
++
++      /* copy the initialized keying material */
++      memcpy(&tctx, irs->ictx, irs->ictx_len);
++
++#ifdef HASH_DEBUG
++      ESP_DMP("ictx", irs->ictx, irs->ictx_len);
++
++      ESP_DMP("mac_esp", (caddr_t)espp, irs->ilen);
++#endif
++      (*aa->update)((void *)&tctx, (caddr_t)espp, irs->ilen);
++
++      (*aa->final)(irs->hash, (void *)&tctx);
++
++#ifdef HASH_DEBUG
++      ESP_DMP("hash1", irs->hash, aa->hashlen);
++#endif
++
++      memcpy(&tctx, irs->octx, irs->octx_len);
++
++#ifdef HASH_DEBUG
++      ESP_DMP("octx", irs->octx, irs->octx_len);
++#endif
++
++      (*aa->update)((void *)&tctx, irs->hash, aa->hashlen);
++      (*aa->final)(irs->hash, (void *)&tctx);
++
++      return IPSEC_RCV_OK;
++}
++
++
++enum ipsec_rcv_value
++ipsec_rcv_esp_decrypt(struct ipsec_rcv_state *irs)
++{
++      struct ipsec_sa *ipsp = irs->ipsp;
++      struct esphdr *espp = irs->protostuff.espstuff.espp;
++      int i;
++      int pad = 0, padlen;
++      int badpad = 0;
++      int esphlen = 0;
++      __u8 *idat;     /* pointer to content to be decrypted/authenticated */
++      int encaplen = 0;
++      struct sk_buff *skb;
++      struct ipsec_alg_enc *ixt_e=NULL;
++
++      skb=irs->skb;
++
++      idat = skb->h.raw;
++
++      /* encaplen is the distance between the end of the IP
++       * header and the beginning of the ESP header.
++       * on ESP headers it is zero, but on UDP-encap ESP
++       * it includes the space for the UDP header.
++       *
++       * Note: UDP-encap code has already moved the
++       *       skb->data forward to accomodate this.
++       */
++      encaplen = idat - (skb->nh.raw + irs->iphlen);
++
++      ixt_e=ipsp->ips_alg_enc;
++      esphlen = ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8;
++      KLIPS_PRINT(debug_rcv,
++                  "klips_debug:ipsec_rcv: "
++                  "encalg=%d esphlen=%d\n",
++                  ipsp->ips_encalg, esphlen);
++
++      idat += esphlen;
++      irs->ilen -= esphlen;
++
++      if (ipsec_alg_esp_encrypt(ipsp, 
++                                idat, irs->ilen, espp->esp_iv, 
++                                IPSEC_ALG_DECRYPT) <= 0) {
++#ifdef CONFIG_KLIPS_DEBUG
++              KLIPS_ERROR(debug_rcv, "klips_error:ipsec_rcv: "
++                          "got packet with esplen = %d "
++                          "from %s -- should be on "
++                          "ENC(%d) octet boundary, "
++                          "packet dropped\n",
++                          irs->ilen,
++                          irs->ipsaddr_txt,
++                          ipsp->ips_encalg);
++#endif
++              if(irs->stats) {
++                      irs->stats->rx_errors++;
++              }
++              return IPSEC_RCV_BAD_DECRYPT;
++      } 
++
++      ESP_DMP("postdecrypt", idat, irs->ilen);
++
++      irs->next_header = idat[irs->ilen - 1];
++      padlen = idat[irs->ilen - 2];
++      pad = padlen + 2 + irs->authlen;
++
++      KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
++                  "klips_debug:ipsec_rcv: "
++                  "padlen=%d, contents: 0x<offset>: 0x<value> 0x<value> ...\n",
++                  padlen);
++
++      for (i = 1; i <= padlen; i++) {
++              if((i % 16) == 1) {
++                      KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
++                                  "klips_debug:           %02x:",
++                                  i - 1);
++              }
++              KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,
++                              " %02x",
++                              idat[irs->ilen - 2 - padlen + i - 1]);
++              if(i != idat[irs->ilen - 2 - padlen + i - 1]) {
++                      badpad = 1;
++              }
++              if((i % 16) == 0) {
++                      KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,
++                                      "\n");
++              }
++      }
++      if((i % 16) != 1) {
++              KLIPS_PRINTMORE(debug_rcv & DB_RX_IPAD,
++                                              "\n");
++      }
++      if(badpad) {
++              KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
++                          "klips_debug:ipsec_rcv: "
++                          "warning, decrypted packet from %s has bad padding\n",
++                          irs->ipsaddr_txt);
++              KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
++                          "klips_debug:ipsec_rcv: "
++                          "...may be bad decryption -- not dropped\n");
++              ipsp->ips_errs.ips_encpad_errs += 1;
++      }
++
++      KLIPS_PRINT(debug_rcv & DB_RX_IPAD,
++                  "klips_debug:ipsec_rcv: "
++                  "packet decrypted from %s: next_header = %d, padding = %d\n",
++                  irs->ipsaddr_txt,
++                  irs->next_header,
++                  pad - 2 - irs->authlen);
++
++      irs->ipp->tot_len = htons(ntohs(irs->ipp->tot_len) - (esphlen + pad));
++
++      /*
++       * move the IP header forward by the size of the ESP header, which
++       * will remove the the ESP header from the packet.
++       *
++       * XXX this is really unnecessary, since odds we are in tunnel
++       *     mode, and we will be *removing* this IP header.
++       *
++       */
++      memmove((void *)(idat - irs->iphlen),
++              (void *)(skb->nh.raw), irs->iphlen);
++
++      ESP_DMP("esp postmove", (idat - irs->iphlen),
++              irs->iphlen + irs->ilen);
++
++      /* skb_pull below, will move up by esphlen */
++
++      /* XXX not clear how this can happen, as the message indicates */
++      if(skb->len < esphlen) {
++              printk(KERN_WARNING
++                     "klips_error:ipsec_rcv: "
++                     "tried to skb_pull esphlen=%d, %d available.  This should never happen, please report.\n",
++                     esphlen, (int)(skb->len));
++              return IPSEC_RCV_ESP_DECAPFAIL;
++      }
++      skb_pull(skb, esphlen);
++      skb->nh.raw = idat - irs->iphlen;
++      irs->ipp = skb->nh.iph;
++
++      ESP_DMP("esp postpull", skb->data, skb->len);
++
++      /* now, trip off the padding from the end */
++      KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                  "klips_debug:ipsec_rcv: "
++                  "trimming to %d.\n",
++                  irs->len - esphlen - pad);
++      if(pad + esphlen <= irs->len) {
++              skb_trim(skb, irs->len - esphlen - pad);
++      } else {
++              KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                          "klips_debug:ipsec_rcv: "
++                          "bogus packet, size is zero or negative, dropping.\n");
++              return IPSEC_RCV_DECAPFAIL;
++      }
++
++      return IPSEC_RCV_OK;
++}
++
++/*
++ *
++ */
++enum ipsec_xmit_value
++ipsec_xmit_esp_setup(struct ipsec_xmit_state *ixs)
++{
++#ifdef CONFIG_KLIPS_ENC_3DES
++  __u32 iv[2];
++#endif
++  struct esphdr *espp;
++  int ilen = 0;
++  int padlen = 0, i;
++  unsigned char *dat;
++  unsigned char *idat, *pad;
++  __u8 hash[AH_AMAX];
++  union {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++    MD5_CTX md5;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++    SHA1_CTX sha1;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++  } tctx;
++
++  dat = (unsigned char *)ixs->iph;
++
++  espp = (struct esphdr *)(dat + ixs->iphlen);
++  espp->esp_spi = ixs->ipsp->ips_said.spi;
++  espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq));
++  
++  switch(ixs->ipsp->ips_encalg) {
++#if defined(CONFIG_KLIPS_ENC_3DES)
++#ifdef CONFIG_KLIPS_ENC_3DES
++  case ESP_3DES:
++#endif /* CONFIG_KLIPS_ENC_3DES */
++    iv[0] = *((__u32*)&(espp->esp_iv)    ) =
++      ((__u32*)(ixs->ipsp->ips_iv))[0];
++    iv[1] = *((__u32*)&(espp->esp_iv) + 1) =
++      ((__u32*)(ixs->ipsp->ips_iv))[1];
++    break;
++#endif /* defined(CONFIG_KLIPS_ENC_3DES) */
++  default:
++    ixs->stats->tx_errors++;
++    return IPSEC_XMIT_ESP_BADALG;
++  }
++              
++  idat = dat + ixs->iphlen + sizeof(struct esphdr);
++  ilen = ixs->skb->len - (ixs->iphlen + sizeof(struct esphdr) + ixs->authlen);
++  
++  /* Self-describing padding */
++  pad = &dat[ixs->skb->len - ixs->tailroom];
++  padlen = ixs->tailroom - 2 - ixs->authlen;
++  for (i = 0; i < padlen; i++) {
++    pad[i] = i + 1; 
++  }
++  dat[ixs->skb->len - ixs->authlen - 2] = padlen;
++  
++  dat[ixs->skb->len - ixs->authlen - 1] = ixs->iph->protocol;
++  ixs->iph->protocol = IPPROTO_ESP;
++  
++  switch(ixs->ipsp->ips_encalg) {
++#ifdef CONFIG_KLIPS_ENC_3DES
++  case ESP_3DES:
++    des_ede3_cbc_encrypt((des_cblock *)idat,
++                       (des_cblock *)idat,
++                       ilen,
++                       ((struct des_eks *)(ixs->ipsp->ips_key_e))[0].ks,
++                       ((struct des_eks *)(ixs->ipsp->ips_key_e))[1].ks,
++                       ((struct des_eks *)(ixs->ipsp->ips_key_e))[2].ks,
++                       (des_cblock *)iv, 1);
++    break;
++#endif /* CONFIG_KLIPS_ENC_3DES */
++  default:
++    ixs->stats->tx_errors++;
++    return IPSEC_XMIT_ESP_BADALG;
++  }
++  
++  switch(ixs->ipsp->ips_encalg) {
++#if defined(CONFIG_KLIPS_ENC_3DES)
++#ifdef CONFIG_KLIPS_ENC_3DES
++  case ESP_3DES:
++#endif /* CONFIG_KLIPS_ENC_3DES */
++    /* XXX update IV with the last 8 octets of the encryption */
++#if KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK
++    ((__u32*)(ixs->ipsp->ips_iv))[0] =
++      ((__u32 *)(idat))[(ilen >> 2) - 2];
++    ((__u32*)(ixs->ipsp->ips_iv))[1] =
++      ((__u32 *)(idat))[(ilen >> 2) - 1];
++#else /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */
++    prng_bytes(&ipsec_prng, (char *)ixs->ipsp->ips_iv, EMT_ESPDES_IV_SZ); 
++#endif /* KLIPS_IMPAIRMENT_ESPIV_CBC_ATTACK */
++    break;
++#endif /* defined(CONFIG_KLIPS_ENC_3DES) */
++  default:
++    ixs->stats->tx_errors++;
++    return IPSEC_XMIT_ESP_BADALG;
++  }
++  
++  switch(ixs->ipsp->ips_authalg) {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++  case AH_MD5:
++    ipsec_xmit_dmp("espp", (char*)espp, ixs->skb->len - ixs->iphlen - ixs->authlen);
++    tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++    ipsec_xmit_dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Update(&tctx.md5, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen);
++    ipsec_xmit_dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Final(hash, &tctx.md5);
++    ipsec_xmit_dmp("ictx hash", (char*)&hash, sizeof(hash));
++    tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx;
++    ipsec_xmit_dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Update(&tctx.md5, hash, AHMD596_ALEN);
++    ipsec_xmit_dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));
++    osMD5Final(hash, &tctx.md5);
++    ipsec_xmit_dmp("octx hash", (char*)&hash, sizeof(hash));
++    memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen);
++    
++    /* paranoid */
++    memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));
++    memset((caddr_t)hash, 0, sizeof(*hash));
++    break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++  case AH_SHA:
++    tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++    SHA1Update(&tctx.sha1, (caddr_t)espp, ixs->skb->len - ixs->iphlen - ixs->authlen);
++    SHA1Final(hash, &tctx.sha1);
++    tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx;
++    SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);
++    SHA1Final(hash, &tctx.sha1);
++    memcpy(&(dat[ixs->skb->len - ixs->authlen]), hash, ixs->authlen);
++    
++    /* paranoid */
++    memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));
++    memset((caddr_t)hash, 0, sizeof(*hash));
++    break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++  case AH_NONE:
++    break;
++  default:
++    ixs->stats->tx_errors++;
++    return IPSEC_XMIT_AH_BADALG;
++  }
++
++  ixs->skb->h.raw = (unsigned char*)espp;
++
++  return IPSEC_XMIT_OK;
++}
++
++
++struct xform_functions esp_xform_funcs[]={
++      {       rcv_checks:         ipsec_rcv_esp_checks,
++              rcv_setup_auth:     ipsec_rcv_esp_decrypt_setup,
++              rcv_calc_auth:      ipsec_rcv_esp_authcalc,
++              rcv_decrypt:        ipsec_rcv_esp_decrypt,
++
++              xmit_setup:         ipsec_xmit_esp_setup,
++              xmit_headroom:      sizeof(struct esphdr),
++              xmit_needtailroom:  1,
++      },
++};
++
++#ifdef NET_26
++struct inet_protocol esp_protocol = {
++  .handler = ipsec_rcv,
++  .no_policy = 1,
++};
++#else
++struct inet_protocol esp_protocol =
++{
++      ipsec_rcv,                      /* ESP handler          */
++      NULL,                           /* TUNNEL error control */
++#ifdef NETDEV_25
++      1,                              /* no policy */
++#else
++      0,                              /* next */
++      IPPROTO_ESP,                    /* protocol ID */
++      0,                              /* copy */
++      NULL,                           /* data */
++      "ESP"                           /* name */
++#endif
++};
++#endif /* NET_26 */
++
++#endif /* !CONFIG_KLIPS_ESP */
++
++
++/*
++ * $Log: ipsec_esp.c,v $
++ * Revision 1.13.2.6  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.13.2.5  2006/08/24 03:02:01  paul
++ * Compile fixes for when CONFIG_KLIPS_DEBUG is not set. (bug #642)
++ *
++ * Revision 1.13.2.4  2006/05/06 03:07:38  ken
++ * Pull in proper padsize->tailroom fix from #public
++ * Need to do correct math on padlen since padsize is not equal to tailroom
++ *
++ * Revision 1.13.2.3  2006/05/05 03:58:04  ken
++ * ixs->padsize becomes ixs->tailroom
++ *
++ * Revision 1.13.2.2  2006/05/01 14:36:03  mcr
++ * use KLIPS_ERROR for fatal things.
++ *
++ * Revision 1.13.2.1  2006/04/20 16:33:06  mcr
++ * remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++ * Fix in-kernel module compilation. Sub-makefiles do not work.
++ *
++ * Revision 1.13  2005/05/21 03:19:57  mcr
++ *    hash ctx is not really that interesting most of the time.
++ *
++ * Revision 1.12  2005/05/11 01:28:49  mcr
++ *    removed "poor-man"s OOP in favour of proper C structures.
++ *
++ * Revision 1.11  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.10  2005/04/17 04:36:14  mcr
++ *    code now deals with ESP and UDP-ESP code.
++ *
++ * Revision 1.9  2005/04/15 19:52:30  mcr
++ *    adjustments to use proper skb fields for data.
++ *
++ * Revision 1.8  2004/09/14 00:22:57  mcr
++ *    adjustment of MD5* functions.
++ *
++ * Revision 1.7  2004/09/13 02:23:01  mcr
++ *    #define inet_protocol if necessary.
++ *
++ * Revision 1.6  2004/09/06 18:35:49  mcr
++ *    2.6.8.1 gets rid of inet_protocol->net_protocol compatibility,
++ *    so adjust for that.
++ *
++ * Revision 1.5  2004/08/17 03:27:23  mcr
++ *    klips 2.6 edits.
++ *
++ * Revision 1.4  2004/08/04 15:57:07  mcr
++ *    moved des .h files to include/des/ *
++ *    included 2.6 protocol specific things
++ *    started at NAT-T support, but it will require a kernel patch.
++ *
++ * Revision 1.3  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.2  2004/04/06 02:49:25  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_init.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,614 @@
++/*
++ * @(#) Initialization code.
++ * Copyright (C) 1996, 1997   John Ioannidis.
++ * Copyright (C) 1998 - 2002  Richard Guy Briggs <rgb@freeswan.org>
++ *               2001 - 2004  Michael Richardson <mcr@xelerance.com>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * /proc system code was split out into ipsec_proc.c after rev. 1.70.
++ *
++ */
++
++char ipsec_init_c_version[] = "RCSID $Id: ipsec_init.c,v 1.104.2.4 2006/10/06 21:39:26 paul Exp $";
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/in.h>          /* struct sockaddr_in */
++#include <linux/skbuff.h>
++#include <linux/random.h>       /* get_random_bytes() */
++#include <net/protocol.h>
++
++#include <openswan.h>
++
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* 23_SPINLOCK */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* 23_SPINLOCK */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++
++#ifdef CONFIG_PROC_FS
++# include <linux/proc_fs.h>
++#endif /* CONFIG_PROC_FS */
++
++#ifdef NETLINK_SOCK
++# include <linux/netlink.h>
++#else
++# include <net/netlink.h>
++#endif
++
++#include "openswan/radij.h"
++
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_stats.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++
++#ifdef CONFIG_KLIPS_IPCOMP
++# include "openswan/ipcomp.h"
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_alg.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++#include <net/xfrmudp.h>
++#endif
++
++#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(HAVE_XFRM4_UDP_REGISTER)
++#warning "You are trying to build KLIPS2.6 with NAT-T support, but you did not"
++#error   "properly apply the NAT-T patch to your 2.6 kernel source tree."
++#endif
++
++#if !defined(CONFIG_KLIPS_ESP) && !defined(CONFIG_KLIPS_AH)
++#error "kernel configuration must include ESP or AH"
++#endif
++
++/*
++ * seems to be present in 2.4.10 (Linus), but also in some RH and other
++ * distro kernels of a lower number.
++ */
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_eroute = 0;
++int debug_spi = 0;
++int debug_netlink = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++struct prng ipsec_prng;
++
++
++#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++xfrm4_rcv_encap_t klips_old_encap = NULL;
++#endif
++
++extern int ipsec_device_event(struct notifier_block *dnot, unsigned long event, void *ptr);
++/*
++ * the following structure is required so that we receive
++ * event notifications when network devices are enabled and
++ * disabled (ifconfig up and down).
++ */
++static struct notifier_block ipsec_dev_notifier={
++      ipsec_device_event,
++      NULL,
++      0
++};
++
++#ifdef CONFIG_SYSCTL
++extern int ipsec_sysctl_register(void);
++extern void ipsec_sysctl_unregister(void);
++#endif
++
++#if defined(NET_26) || defined(IPSKB_XFRM_TUNNEL_SIZE)
++static inline int
++openswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol)
++{
++      return inet_add_protocol(prot, protocol);
++}
++
++static inline int
++openswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol)
++{
++      return inet_del_protocol(prot, protocol);
++}
++
++#else
++static inline int
++openswan_inet_add_protocol(struct inet_protocol *prot, unsigned protocol)
++{
++      inet_add_protocol(prot);
++      return 0;
++}
++
++static inline int
++openswan_inet_del_protocol(struct inet_protocol *prot, unsigned protocol)
++{
++      inet_del_protocol(prot);
++      return 0;
++}
++
++#endif
++
++/* void */
++int
++ipsec_klips_init(void)
++{
++      int error = 0;
++      unsigned char seed[256];
++#ifdef CONFIG_KLIPS_ENC_3DES
++      extern int des_check_key;
++
++      /* turn off checking of keys */
++      des_check_key=0;
++#endif /* CONFIG_KLIPS_ENC_3DES */
++
++      KLIPS_PRINT(1, "klips_info:ipsec_init: "
++                  "KLIPS startup, Openswan KLIPS IPsec stack version: %s\n",
++                  ipsec_version_code());
++
++      error |= ipsec_proc_init();
++
++#ifdef SPINLOCK
++      ipsec_sadb.sadb_lock = SPIN_LOCK_UNLOCKED;
++#else /* SPINLOCK */
++      ipsec_sadb.sadb_lock = 0;
++#endif /* SPINLOCK */
++
++#ifndef SPINLOCK
++      tdb_lock.lock = 0;
++      eroute_lock.lock = 0;
++#endif /* !SPINLOCK */
++
++      error |= ipsec_sadb_init();
++      error |= ipsec_radijinit();
++
++      error |= pfkey_init();
++
++      error |= register_netdevice_notifier(&ipsec_dev_notifier);
++
++#ifdef CONFIG_KLIPS_ESP
++      openswan_inet_add_protocol(&esp_protocol, IPPROTO_ESP);
++#endif /* CONFIG_KLIPS_ESP */
++
++#ifdef CONFIG_KLIPS_AH
++      openswan_inet_add_protocol(&ah_protocol, IPPROTO_AH);
++#endif /* CONFIG_KLIPS_AH */
++
++/* we never actually link IPCOMP to the stack */
++#ifdef IPCOMP_USED_ALONE
++#ifdef CONFIG_KLIPS_IPCOMP
++      openswan_inet_add_protocol(&comp_protocol, IPPROTO_COMP);
++#endif /* CONFIG_KLIPS_IPCOMP */
++#endif
++
++      error |= ipsec_tunnel_init_devices();
++
++#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++      /* register our ESP-UDP handler */
++      if(udp4_register_esp_rcvencap(klips26_rcv_encap
++                                    , &klips_old_encap)!=0) {
++         printk(KERN_ERR "KLIPS: can not register klips_rcv_encap function\n");
++      }
++#endif        
++
++
++#ifdef CONFIG_SYSCTL
++        error |= ipsec_sysctl_register();
++#endif                                                                          
++
++      ipsec_alg_init();
++
++      get_random_bytes((void *)seed, sizeof(seed));
++      prng_init(&ipsec_prng, seed, sizeof(seed));
++
++      return error;
++}     
++
++
++/* void */
++int
++ipsec_cleanup(void)
++{
++      int error = 0;
++
++#ifdef CONFIG_SYSCTL
++        ipsec_sysctl_unregister();
++#endif                                                                          
++#if defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++      if(udp4_unregister_esp_rcvencap(klips_old_encap) < 0) {
++              printk(KERN_ERR "KLIPS: can not unregister klips_rcv_encap function\n");
++      }
++#endif
++
++      KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
++                  "klips_debug:ipsec_cleanup: "
++                  "calling ipsec_tunnel_cleanup_devices.\n");
++      error |= ipsec_tunnel_cleanup_devices();
++
++      KLIPS_PRINT(debug_netlink, "called ipsec_tunnel_cleanup_devices");
++
++/* we never actually link IPCOMP to the stack */
++#ifdef IPCOMP_USED_ALONE
++#ifdef CONFIG_KLIPS_IPCOMP
++      if (openswan_inet_del_protocol(&comp_protocol, IPPROTO_COMP) < 0)
++              printk(KERN_INFO "klips_debug:ipsec_cleanup: "
++                     "comp close: can't remove protocol\n");
++#endif /* CONFIG_KLIPS_IPCOMP */
++#endif /* IPCOMP_USED_ALONE */
++
++#ifdef CONFIG_KLIPS_AH
++      if (openswan_inet_del_protocol(&ah_protocol, IPPROTO_AH) < 0)
++              printk(KERN_INFO "klips_debug:ipsec_cleanup: "
++                     "ah close: can't remove protocol\n");
++#endif /* CONFIG_KLIPS_AH */
++
++#ifdef CONFIG_KLIPS_ESP
++      if (openswan_inet_del_protocol(&esp_protocol, IPPROTO_ESP) < 0)
++              printk(KERN_INFO "klips_debug:ipsec_cleanup: "
++                     "esp close: can't remove protocol\n");
++#endif /* CONFIG_KLIPS_ESP */
++
++      error |= unregister_netdevice_notifier(&ipsec_dev_notifier);
++
++      KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
++                  "klips_debug:ipsec_cleanup: "
++                  "calling ipsec_sadb_cleanup.\n");
++      error |= ipsec_sadb_cleanup(0);
++      error |= ipsec_sadb_free();
++
++      KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
++                  "klips_debug:ipsec_cleanup: "
++                  "calling ipsec_radijcleanup.\n");
++      error |= ipsec_radijcleanup();
++      
++      KLIPS_PRINT(debug_pfkey, /* debug_tunnel & DB_TN_INIT, */
++                  "klips_debug:ipsec_cleanup: "
++                  "calling pfkey_cleanup.\n");
++      error |= pfkey_cleanup();
++
++      ipsec_proc_cleanup();
++
++      prng_final(&ipsec_prng);
++
++      return error;
++}
++
++#ifdef MODULE
++int
++init_module(void)
++{
++      int error = 0;
++
++      error |= ipsec_klips_init();
++
++      return error;
++}
++
++void
++cleanup_module(void)
++{
++      KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
++                  "klips_debug:cleanup_module: "
++                  "calling ipsec_cleanup.\n");
++
++      ipsec_cleanup();
++
++      KLIPS_PRINT(1, "klips_info:cleanup_module: "
++                  "ipsec module unloaded.\n");
++}
++#endif /* MODULE */
++
++/*
++ * $Log: ipsec_init.c,v $
++ * Revision 1.104.2.4  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.104.2.3  2006/07/31 15:25:20  paul
++ * Check for NETKEY backport in Debian using IPSKB_XFRM_TUNNEL_SIZE to
++ * determine wether inet_add_protocol needs the protocol argument.
++ *
++ * Revision 1.104.2.2  2006/04/20 16:33:06  mcr
++ * remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++ * Fix in-kernel module compilation. Sub-makefiles do not work.
++ *
++ * Revision 1.104.2.1  2005/08/12 01:18:20  ken
++ * Warn people who don't have NAT-T patch applied, but try and compile NAT-T code
++ *
++ * Revision 1.105  2005/08/12 00:56:33  mcr
++ *    add warning for people who didn't apply nat-t patch.
++ *
++ * Revision 1.104  2005/07/08 15:51:41  mcr
++ *    removed duplicate NAT-T code.
++ *    if CONFIG_IPSEC_NAT_TRAVERSAL isn't defined, then there is no issue.
++ *
++ * Revision 1.103  2005/07/08 03:02:05  paul
++ * Fixed garbled define that accidentally got commited to the real tree.
++ *
++ * Revision 1.102  2005/07/08 02:56:37  paul
++ * gcc4 fixes that were not commited because vault was down
++ *
++ * Revision 1.101  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.100  2005/04/10 22:56:09  mcr
++ *    change to udp.c registration API.
++ *
++ * Revision 1.99  2005/04/08 18:26:13  mcr
++ *    register with udp.c, the klips26 encap receive function
++ *
++ * Revision 1.98  2004/09/13 02:23:18  mcr
++ *    #define inet_protocol if necessary.
++ *
++ * Revision 1.97  2004/09/06 18:35:49  mcr
++ *    2.6.8.1 gets rid of inet_protocol->net_protocol compatibility,
++ *    so adjust for that.
++ *
++ * Revision 1.96  2004/08/17 03:27:23  mcr
++ *    klips 2.6 edits.
++ *
++ * Revision 1.95  2004/08/03 18:19:08  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.94  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.93  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.92  2004/03/30 15:30:39  ken
++ * Proper Capitalization
++ *
++ * Revision 1.91  2004/03/22 01:51:51  ken
++ * We are open
++ *
++ * Revision 1.90.4.2  2004/04/05 04:30:46  mcr
++ *    patches for alg-branch to compile/work with 2.x openswan
++ *
++ * Revision 1.90.4.1  2003/12/22 15:25:52  jjo
++ *      Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.90  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.89.4.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.89  2003/07/31 22:47:16  mcr
++ *    preliminary (untested by FS-team) 2.5 patches.
++ *
++ * Revision 1.88  2003/06/22 20:05:36  mcr
++ *    clarified why IPCOMP was not being registered, and put a new
++ *    #ifdef in rather than #if 0.
++ *
++ * Revision 1.87  2002/09/20 15:40:51  rgb
++ * Added a lock to the global ipsec_sadb struct for future use.
++ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem
++ * of freeing newly created structures when clearing the reftable upon startup
++ * to start from a known state.
++ *
++ * Revision 1.86  2002/08/15 18:39:15  rgb
++ * Move ipsec_prng outside debug code.
++ *
++ * Revision 1.85  2002/05/14 02:35:29  rgb
++ * Change reference to tdb to ipsa.
++ *
++ * Revision 1.84  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.83  2002/04/24 07:36:28  mcr
++ * Moved from ./klips/net/ipsec/ipsec_init.c,v
++ *
++ * Revision 1.82  2002/04/20 00:12:25  rgb
++ * Added esp IV CBC attack fix, disabled.
++ *
++ * Revision 1.81  2002/04/09 16:13:32  mcr
++ *    switch license to straight GPL.
++ *
++ * Revision 1.80  2002/03/24 07:34:08  rgb
++ * Sanity check for at least one of AH or ESP configured.
++ *
++ * Revision 1.79  2002/02/05 22:55:15  mcr
++ *    added MODULE_LICENSE declaration.
++ *    This macro does not appear in all kernel versions (see comment).
++ *
++ * Revision 1.78  2002/01/29 17:17:55  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.77  2002/01/29 04:00:51  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.76  2002/01/29 02:13:17  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.75  2001/11/26 09:23:48  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.74  2001/11/22 05:44:11  henry
++ * new version stuff
++ *
++ * Revision 1.71.2.2  2001/10/22 20:51:00  mcr
++ *    explicitely set des_check_key.
++ *
++ * Revision 1.71.2.1  2001/09/25 02:19:39  mcr
++ *    /proc manipulation code moved to new ipsec_proc.c
++ *
++ * Revision 1.73  2001/11/06 19:47:17  rgb
++ * Changed lifetime_packets to uint32 from uint64.
++ *
++ * Revision 1.72  2001/10/18 04:45:19  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.71  2001/09/20 15:32:45  rgb
++ * Minor pfkey lifetime fixes.
++ *
++ * Revision 1.70  2001/07/06 19:51:21  rgb
++ * Added inbound policy checking code for IPIP SAs.
++ *
++ * Revision 1.69  2001/06/14 19:33:26  rgb
++ * Silence startup message for console, but allow it to be logged.
++ * Update copyright date.
++ *
++ * Revision 1.68  2001/05/29 05:14:36  rgb
++ * Added PMTU to /proc/net/ipsec_tncfg output.  See 'man 5 ipsec_tncfg'.
++ *
++ * Revision 1.67  2001/05/04 16:34:52  rgb
++ * Rremove erroneous checking of return codes for proc_net_* in 2.4.
++ *
++ * Revision 1.66  2001/05/03 19:40:34  rgb
++ * Check error return codes in startup and shutdown.
++ *
++ * Revision 1.65  2001/02/28 05:03:27  rgb
++ * Clean up and rationalise startup messages.
++ *
++ * Revision 1.64  2001/02/27 22:24:53  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.63  2000/11/29 20:14:06  rgb
++ * Add src= to the output of /proc/net/ipsec_spi and delete dst from IPIP.
++ *
++ * Revision 1.62  2000/11/06 04:31:24  rgb
++ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
++ * Fixed longlong for pre-2.4 kernels (Svenning).
++ * Add Svenning's adaptive content compression.
++ * Disabled registration of ipcomp handler.
++ *
++ * Revision 1.61  2000/10/11 13:37:54  rgb
++ * #ifdef out debug print that causes proc/net/ipsec_version to oops.
++ *
++ * Revision 1.60  2000/09/20 03:59:01  rgb
++ * Change static info functions to DEBUG_NO_STATIC to reveal function names
++ * in oopsen.
++ *
++ * Revision 1.59  2000/09/16 01:06:26  rgb
++ * Added cast of var to silence compiler warning about long fed to int
++ * format.
++ *
++ * Revision 1.58  2000/09/15 11:37:01  rgb
++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++ * IPCOMP zlib deflate code.
++ *
++ * Revision 1.57  2000/09/12 03:21:50  rgb
++ * Moved radij_c_version printing to ipsec_version_get_info().
++ * Reformatted ipsec_version_get_info().
++ * Added sysctl_{,un}register() calls.
++ *
++ * Revision 1.56  2000/09/08 19:16:50  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ * Removed all references to CONFIG_IPSEC_PFKEYv2.
++ *
++ * Revision 1.55  2000/08/30 05:19:03  rgb
++ * Cleaned up no longer used spi_next, netlink register/unregister, other
++ * minor cleanup.
++ * Removed cruft replaced by TDB_XFORM_NAME.
++ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst.
++ * Moved debug version strings to printk when /proc/net/ipsec_version is
++ * called.
++ *
++ * Revision 1.54  2000/08/20 18:31:05  rgb
++ * Changed cosmetic alignment in spi_info.
++ * Changed addtime and usetime to use actual value which is relative
++ * anyways, as intended. (Momchil)
++ *
++ * Revision 1.53  2000/08/18 17:37:03  rgb
++ * Added an (int) cast to shut up the compiler...
++ *
++ * Revision 1.52  2000/08/01 14:51:50  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.51  2000/07/25 20:41:22  rgb
++ * Removed duplicate parameter in spi_getinfo.
++ *
++ * Revision 1.50  2000/07/17 03:21:45  rgb
++ * Removed /proc/net/ipsec_spinew.
++ *
++ * Revision 1.49  2000/06/28 05:46:51  rgb
++ * Renamed ivlen to iv_bits for consistency.
++ * Changed output of add and use times to be relative to now.
++ *
++ * Revision 1.48  2000/05/11 18:26:10  rgb
++ * Commented out calls to netlink_attach/detach to avoid activating netlink
++ * in the kenrel config.
++ *
++ * Revision 1.47  2000/05/10 22:35:26  rgb
++ * Comment out most of the startup version information.
++ *
++ * Revision 1.46  2000/03/22 16:15:36  rgb
++ * Fixed renaming of dev_get (MB).
++ *
++ * Revision 1.45  2000/03/16 06:40:48  rgb
++ * Hardcode PF_KEYv2 support.
++ *
++ * Revision 1.44  2000/01/22 23:19:20  rgb
++ * Simplified code to use existing macro TDB_XFORM_NAME().
++ *
++ * Revision 1.43  2000/01/21 06:14:04  rgb
++ * Print individual stats only if non-zero.
++ * Removed 'bits' from each keylength for brevity.
++ * Shortened lifetimes legend for brevity.
++ * Changed wording from 'last_used' to the clearer 'idle'.
++ *
++ * Revision 1.42  1999/12/31 14:57:19  rgb
++ * MB fix for new dummy-less proc_get_info in 2.3.35.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_ipcomp.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,256 @@
++/*
++ * processing code for IPCOMP
++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_ipcomp_c_version[] = "RCSID $Id: ipsec_ipcomp.c,v 1.5.2.2 2006/10/06 21:39:26 paul Exp $";
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>  /* struct device, and other headers */
++#include <linux/etherdevice.h>        /* eth_type_trans */
++#include <linux/ip.h>         /* struct iphdr */
++#include <linux/skbuff.h>
++#include <openswan.h>
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipsec_xmit.h"
++
++#include "openswan/ipsec_auth.h"
++
++#ifdef CONFIG_KLIPS_IPCOMP
++#include "openswan/ipsec_ipcomp.h"
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#include "openswan/ipsec_proto.h"
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_ipcomp = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++
++#ifdef CONFIG_KLIPS_IPCOMP
++enum ipsec_rcv_value
++ipsec_rcv_ipcomp_checks(struct ipsec_rcv_state *irs,
++                      struct sk_buff *skb)
++{
++      int ipcompminlen;
++
++      ipcompminlen = sizeof(struct iphdr);
++
++      if(skb->len < (ipcompminlen + sizeof(struct ipcomphdr))) {
++              KLIPS_PRINT(debug_rcv & DB_RX_INAU,
++                          "klips_debug:ipsec_rcv: "
++                          "runt comp packet of skb->len=%d received from %s, dropped.\n",
++                          skb->len,
++                          irs->ipsaddr_txt);
++              if(irs->stats) {
++                      irs->stats->rx_errors++;
++              }
++              return IPSEC_RCV_BADLEN;
++      }
++
++      irs->protostuff.ipcompstuff.compp = (struct ipcomphdr *)skb->h.raw;
++      irs->said.spi = htonl((__u32)ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi));
++      return IPSEC_RCV_OK;
++}
++
++enum ipsec_rcv_value
++ipsec_rcv_ipcomp_decomp(struct ipsec_rcv_state *irs)
++{
++      unsigned int flags = 0;
++      struct ipsec_sa *ipsp = irs->ipsp;
++      struct sk_buff *skb;
++
++      skb=irs->skb;
++
++      ipsec_xmit_dmp("ipcomp", skb->h.raw, skb->len);
++
++      if(ipsp == NULL) {
++              return IPSEC_RCV_SAIDNOTFOUND;
++      }
++
++      if(sysctl_ipsec_inbound_policy_check &&
++         ((((ntohl(ipsp->ips_said.spi) & 0x0000ffff) != ntohl(irs->said.spi)) &&
++           (ipsp->ips_encalg != ntohl(irs->said.spi))   /* this is a workaround for peer non-compliance with rfc2393 */
++                  ))) {
++              char sa2[SATOT_BUF];
++              size_t sa_len2 = 0;
++
++              sa_len2 = satot(&ipsp->ips_said, 0, sa2, sizeof(sa2));
++
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n",
++                          irs->sa_len ? irs->sa : " (error)",
++                          ipsp != NULL ? (sa_len2 ? sa2 : " (error)") : "NULL",
++                          ntohs(irs->protostuff.ipcompstuff.compp->ipcomp_cpi),
++                          (__u32)ntohl(irs->said.spi),
++                          ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0,
++                          ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0);
++              if(irs->stats) {
++                      irs->stats->rx_dropped++;
++              }
++              return IPSEC_RCV_SAIDNOTFOUND;
++      }
++
++      ipsp->ips_comp_ratio_cbytes += ntohs(irs->ipp->tot_len);
++      irs->next_header = irs->protostuff.ipcompstuff.compp->ipcomp_nh;
++
++      skb = skb_decompress(skb, ipsp, &flags);
++      if (!skb || flags) {
++              spin_unlock(&tdb_lock);
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "skb_decompress() returned error flags=%x, dropped.\n",
++                          flags);
++              if (irs->stats) {
++                      if (flags)
++                              irs->stats->rx_errors++;
++                      else
++                              irs->stats->rx_dropped++;
++              }
++              return IPSEC_RCV_IPCOMPFAILED;
++      }
++
++      /* make sure we update the pointer */
++      irs->skb = skb;
++      
++#ifdef NET_21
++      irs->ipp = skb->nh.iph;
++#else /* NET_21 */
++      irs->ipp = skb->ip_hdr;
++#endif /* NET_21 */
++
++      ipsp->ips_comp_ratio_dbytes += ntohs(irs->ipp->tot_len);
++
++      KLIPS_PRINT(debug_rcv,
++                  "klips_debug:ipsec_rcv: "
++                  "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n",
++                  irs->sa_len ? irs->sa : " (error)",
++                  (__u32)ntohl(irs->said.spi),
++                  ipsp != NULL ? (__u32)ntohl((ipsp->ips_said.spi)) : 0,
++                  ipsp != NULL ? (__u16)(ntohl(ipsp->ips_said.spi) & 0x0000ffff) : 0,
++                  irs->next_header);
++      KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, irs->ipp);
++
++      return IPSEC_RCV_OK;
++}
++
++enum ipsec_xmit_value
++ipsec_xmit_ipcomp_setup(struct ipsec_xmit_state *ixs)
++{
++  unsigned int flags = 0;
++#ifdef CONFIG_KLIPS_DEBUG
++  unsigned int old_tot_len = ntohs(ixs->iph->tot_len);
++#endif /* CONFIG_KLIPS_DEBUG */
++
++  ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len);
++
++  ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags);
++
++#ifdef NET_21
++  ixs->iph = ixs->skb->nh.iph;
++#else /* NET_21 */
++  ixs->iph = ixs->skb->ip_hdr;
++#endif /* NET_21 */
++  
++  ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len);
++  
++#ifdef CONFIG_KLIPS_DEBUG
++  if (debug_tunnel & DB_TN_CROUT)
++    {
++      if (old_tot_len > ntohs(ixs->iph->tot_len))
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_encap_once: "
++                  "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n",
++                  old_tot_len, ntohs(ixs->iph->tot_len),
++                  ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi),
++                  ntohl(ixs->ipsp->ips_said.spi),
++                  (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff));
++      else
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_encap_once: "
++                  "packet did not compress (flags = %d).\n",
++                  flags);
++    }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++  return IPSEC_XMIT_OK;
++}
++
++struct xform_functions ipcomp_xform_funcs[]={
++      {rcv_checks:  ipsec_rcv_ipcomp_checks,
++       rcv_decrypt: ipsec_rcv_ipcomp_decomp,
++       xmit_setup:  ipsec_xmit_ipcomp_setup,
++       xmit_headroom: 0,
++       xmit_needtailroom: 0,
++      },
++};
++
++#if 0
++/* We probably don't want to install a pure IPCOMP protocol handler, but
++   only want to handle IPCOMP if it is encapsulated inside an ESP payload
++   (which is already handled) */
++#ifdef CONFIG_KLIPS_IPCOMP
++struct inet_protocol comp_protocol =
++{
++      ipsec_rcv,                      /* COMP handler         */
++      NULL,                           /* COMP error control   */
++#ifdef NETDEV_25
++      1,                              /* no policy */
++#else
++      0,                              /* next */
++      IPPROTO_COMP,                   /* protocol ID */
++      0,                              /* copy */
++      NULL,                           /* data */
++      "COMP"                          /* name */
++#endif
++};
++#endif /* CONFIG_KLIPS_IPCOMP */
++#endif
++
++#endif /* CONFIG_KLIPS_IPCOMP */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_ipip.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,122 @@
++/*
++ * processing code for IPIP
++ * Copyright (C) 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_ipip_c_version[] = "RCSID $Id: ipsec_ipip.c,v 1.3.2.3 2006/10/06 21:39:26 paul Exp $";
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>  /* struct device, and other headers */
++#include <linux/etherdevice.h>        /* eth_type_trans */
++#include <linux/ip.h>         /* struct iphdr */
++#include <linux/skbuff.h>
++#include <openswan.h>
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipsec_xmit.h"
++
++#include "openswan/ipsec_auth.h"
++#include "openswan/ipsec_ipip.h"
++#include "openswan/ipsec_param.h"
++
++#include "openswan/ipsec_proto.h"
++
++enum ipsec_xmit_value
++ipsec_xmit_ipip_setup(struct ipsec_xmit_state *ixs)
++{
++  ixs->iph->version  = 4;
++
++  switch(sysctl_ipsec_tos) {
++  case 0:
++#ifdef NET_21
++    ixs->iph->tos = ixs->skb->nh.iph->tos;
++#else /* NET_21 */
++    ixs->iph->tos = ixs->skb->ip_hdr->tos;
++#endif /* NET_21 */
++    break;
++  case 1:
++    ixs->iph->tos = 0;
++    break;
++  default:
++    break;
++  }
++  ixs->iph->ttl      = SYSCTL_IPSEC_DEFAULT_TTL;
++  ixs->iph->frag_off = 0;
++  ixs->iph->saddr    = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr;
++  ixs->iph->daddr    = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr;
++  ixs->iph->protocol = IPPROTO_IPIP;
++  ixs->iph->ihl      = sizeof(struct iphdr) >> 2;
++  
++  KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb);
++  
++  ixs->newdst = (__u32)ixs->iph->daddr;
++  ixs->newsrc = (__u32)ixs->iph->saddr;
++  
++#ifdef NET_21
++  ixs->skb->h.ipiph = ixs->skb->nh.iph;
++#endif /* NET_21 */
++  return IPSEC_XMIT_OK;
++}
++
++struct xform_functions ipip_xform_funcs[]={
++  {   rcv_checks:         NULL,
++      rcv_setup_auth:     NULL,
++      rcv_calc_auth:      NULL,
++      rcv_decrypt:        NULL,
++
++      xmit_setup:         ipsec_xmit_ipip_setup,
++      xmit_headroom:      sizeof(struct iphdr),
++      xmit_needtailroom:  0,
++  },
++};
++
++
++
++
++
++
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_kern24.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,74 @@
++/*
++ * Copyright 2005 (C) Michael Richardson <mcr@xelerance.com>
++ *
++ * This is a file of functions which are present in 2.6 kernels,
++ * but are not available by default in the 2.4 series.
++ *
++ * As such this code is usually from the Linux kernel, and is covered by
++ * GPL.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * $Id: ipsec_kern24.c,v 1.2 2005/05/20 03:19:18 mcr Exp $
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/spinlock.h>
++
++/*
++ * printk rate limiting, lifted from the networking subsystem.
++ *
++ * This enforces a rate limit: not more than one kernel message
++ * every printk_ratelimit_jiffies to make a denial-of-service
++ * attack impossible.
++ */
++static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED;
++
++int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
++{
++      static unsigned long toks = 10*5*HZ;
++      static unsigned long last_msg;
++      static int missed;
++      unsigned long flags;
++      unsigned long now = jiffies;
++
++      spin_lock_irqsave(&ratelimit_lock, flags);
++      toks += now - last_msg;
++      last_msg = now;
++      if (toks > (ratelimit_burst * ratelimit_jiffies))
++              toks = ratelimit_burst * ratelimit_jiffies;
++      if (toks >= ratelimit_jiffies) {
++              int lost = missed;
++              missed = 0;
++              toks -= ratelimit_jiffies;
++              spin_unlock_irqrestore(&ratelimit_lock, flags);
++              if (lost)
++                      printk(KERN_WARNING "printk: %d messages suppressed.\n", lost);
++              return 1;
++      }
++      missed++;
++      spin_unlock_irqrestore(&ratelimit_lock, flags);
++      return 0;
++}
++
++/* minimum time in jiffies between messages */
++int printk_ratelimit_jiffies = 5*HZ;
++
++/* number of messages we send before ratelimiting */
++int printk_ratelimit_burst = 10;
++
++int printk_ratelimit(void)
++{
++      return __printk_ratelimit(printk_ratelimit_jiffies,
++                              printk_ratelimit_burst);
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_life.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,273 @@
++/*
++ * @(#) lifetime structure utilities
++ *
++ * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
++ *                 and Michael Richardson  <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_life.c,v 1.13.10.1 2006/10/06 21:39:26 paul Exp $
++ *
++ */
++
++/* 
++ * This provides series of utility functions for dealing with lifetime
++ * structures.
++ *
++ * ipsec_check_lifetime - returns -1    hard lifetime exceeded
++ *                                 0    soft lifetime exceeded
++ *                                 1    everything is okay
++ *                        based upon whether or not the count exceeds hard/soft
++ *
++ */
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif        /* for CONFIG_IP_FORWARD */
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#include <linux/netdevice.h>   /* struct device, struct net_device_stats and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/skbuff.h>
++#include <openswan.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_eroute.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++
++#include "openswan/ipsec_sa.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_ipe4.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++
++#ifdef CONFIG_KLIPS_IPCOMP
++#include "openswan/ipcomp.h"
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++
++
++enum ipsec_life_alive
++ipsec_lifetime_check(struct ipsec_lifetime64 *il64,
++                   const char *lifename,
++                   const char *saname,
++                   enum ipsec_life_type ilt,
++                   enum ipsec_direction idir,
++                   struct ipsec_sa *ips)
++{
++      __u64 count;
++      const char *dir;
++
++      if(saname == NULL) {
++              saname = "unknown-SA";
++      }
++
++      if(idir == ipsec_incoming) {
++              dir = "incoming";
++      } else {
++              dir = "outgoing";
++      }
++              
++
++      if(ilt == ipsec_life_timebased) {
++              count = jiffies/HZ - il64->ipl_count;
++      } else {
++              count = il64->ipl_count;
++      }
++
++      if(il64->ipl_hard &&
++         (count > il64->ipl_hard)) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_lifetime_check: "
++                          "hard %s lifetime of SA:<%s%s%s> %s has been reached, SA expired, "
++                          "%s packet dropped.\n",
++                          lifename,
++                          IPS_XFORM_NAME(ips),
++                          saname,
++                          dir);
++
++              pfkey_expire(ips, 1);
++              return ipsec_life_harddied;
++      }
++
++      if(il64->ipl_soft &&
++         (count > il64->ipl_soft)) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_lifetime_check: "
++                          "soft %s lifetime of SA:<%s%s%s> %s has been reached, SA expiring, "
++                          "soft expire message sent up, %s packet still processed.\n",
++                          lifename,
++                          IPS_XFORM_NAME(ips),
++                          saname,
++                          dir);
++
++              if(ips->ips_state != SADB_SASTATE_DYING) {
++                      pfkey_expire(ips, 0);
++              }
++              ips->ips_state = SADB_SASTATE_DYING;
++
++              return ipsec_life_softdied;
++      }
++      return ipsec_life_okay;
++}
++
++
++/*
++ * This function takes a buffer (with length), a lifetime name and type,
++ * and formats a string to represent the current values of the lifetime.
++ * 
++ * It returns the number of bytes that the format took (or would take,
++ * if the buffer were large enough: snprintf semantics).
++ * This is used in /proc routines and in debug output.
++ */
++int
++ipsec_lifetime_format(char *buffer,
++                    int   buflen,
++                    char *lifename,
++                    enum ipsec_life_type timebaselife,
++                    struct ipsec_lifetime64 *lifetime)
++{
++      int len = 0;
++      __u64 count;
++
++      if(timebaselife == ipsec_life_timebased) {
++              count = jiffies/HZ - lifetime->ipl_count;
++      } else {
++              count = lifetime->ipl_count;
++      }
++
++      if(lifetime->ipl_count > 1 || 
++         lifetime->ipl_soft      ||
++         lifetime->ipl_hard) {
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) 
++              len = ipsec_snprintf(buffer, buflen,
++                             "%s(%Lu,%Lu,%Lu)",
++                             lifename,
++                             count,
++                             lifetime->ipl_soft,
++                             lifetime->ipl_hard);
++#else /* XXX high 32 bits are not displayed */
++              len = ipsec_snprintf(buffer, buflen,
++                              "%s(%lu,%lu,%lu)",
++                              lifename,
++                              (unsigned long)count,
++                              (unsigned long)lifetime->ipl_soft,
++                              (unsigned long)lifetime->ipl_hard);
++#endif
++      }
++
++      return len;
++}
++
++void
++ipsec_lifetime_update_hard(struct ipsec_lifetime64 *lifetime,
++                        __u64 newvalue)
++{
++      if(newvalue &&
++         (!lifetime->ipl_hard ||
++          (newvalue < lifetime->ipl_hard))) {
++              lifetime->ipl_hard = newvalue;
++
++              if(!lifetime->ipl_soft &&
++                 (lifetime->ipl_hard < lifetime->ipl_soft)) {
++                      lifetime->ipl_soft = lifetime->ipl_hard;
++              }
++      }
++}     
++
++void
++ipsec_lifetime_update_soft(struct ipsec_lifetime64 *lifetime,
++                        __u64 newvalue)
++{
++      if(newvalue &&
++         (!lifetime->ipl_soft ||
++          (newvalue < lifetime->ipl_soft))) {
++              lifetime->ipl_soft = newvalue;
++
++              if(lifetime->ipl_hard &&
++                 (lifetime->ipl_hard < lifetime->ipl_soft)) {
++                      lifetime->ipl_soft = lifetime->ipl_hard;
++              }
++      }
++}
++
++      
++/*
++ * $Log: ipsec_life.c,v $
++ * Revision 1.13.10.1  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.13  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.12  2004/04/23 20:44:35  ken
++ * Update comments
++ *
++ * Revision 1.11  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.10  2004/03/30 11:03:10  paul
++ * two more occurances of snprintf, found by Sam from a users oops msg.
++ *
++ * Revision 1.9  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.8.4.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.8  2003/02/06 02:00:10  rgb
++ * Fixed incorrect debugging text label
++ *
++ * Revision 1.7  2002/05/23 07:16:26  rgb
++ * Fixed absolute/relative reference to lifetime count printout.
++ *
++ * Revision 1.6  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.5  2002/04/24 07:36:28  mcr
++ * Moved from ./klips/net/ipsec/ipsec_life.c,v
++ *
++ * Revision 1.4  2002/01/29 17:17:55  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.3  2002/01/29 02:13:17  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.2  2001/11/26 09:16:14  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:25:57  mcr
++ *    lifetime structure created and common functions created.
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_mast.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1099 @@
++/*
++ * IPSEC MAST code.
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001, 2002  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_mast_c_version[] = "RCSID $Id: ipsec_mast.c,v 1.7.2.1 2006/10/06 21:39:26 paul Exp $";
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif        /* for CONFIG_IP_FORWARD */
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "freeswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/tcp.h>         /* struct tcphdr */
++#include <linux/udp.h>         /* struct udphdr */
++#include <linux/skbuff.h>
++#include <freeswan.h>
++#include <linux/in6.h>
++#include <net/dst.h>
++#undef dev_kfree_skb
++#define dev_kfree_skb(a,b) kfree_skb(a)
++#define PHYSDEV_TYPE
++#include <net/icmp.h>         /* icmp_send() */
++#include <net/ip.h>
++#include <linux/netfilter_ipv4.h>
++
++#include <linux/if_arp.h>
++
++#include "freeswan/radij.h"
++#include "freeswan/ipsec_life.h"
++#include "freeswan/ipsec_xform.h"
++#include "freeswan/ipsec_eroute.h"
++#include "freeswan/ipsec_encap.h"
++#include "freeswan/ipsec_radij.h"
++#include "freeswan/ipsec_sa.h"
++#include "freeswan/ipsec_tunnel.h"
++#include "freeswan/ipsec_mast.h"
++#include "freeswan/ipsec_ipe4.h"
++#include "freeswan/ipsec_ah.h"
++#include "freeswan/ipsec_esp.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "freeswan/ipsec_proto.h"
++
++int ipsec_maxdevice_count = -1;
++
++DEBUG_NO_STATIC int
++ipsec_mast_open(struct net_device *dev)
++{
++      struct ipsecpriv *prv = dev->priv;
++      
++      /*
++       * Can't open until attached.
++       */
++
++      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                  "klips_debug:ipsec_mast_open: "
++                  "dev = %s, prv->dev = %s\n",
++                  dev->name, prv->dev?prv->dev->name:"NONE");
++
++      if (prv->dev == NULL)
++              return -ENODEV;
++      
++      KLIPS_INC_USE;
++      return 0;
++}
++
++DEBUG_NO_STATIC int
++ipsec_mast_close(struct net_device *dev)
++{
++      KLIPS_DEC_USE;
++      return 0;
++}
++
++static inline int ipsec_mast_xmit2(struct sk_buff *skb)
++{
++      return ip_send(skb);
++}
++
++enum ipsec_xmit_value
++ipsec_mast_send(struct ipsec_xmit_state*ixs)
++{
++      /* new route/dst cache code from James Morris */
++      ixs->skb->dev = ixs->physdev;
++      /*skb_orphan(ixs->skb);*/
++      if((ixs->error = ip_route_output(&ixs->route,
++                                  ixs->skb->nh.iph->daddr,
++                                  ixs->pass ? 0 : ixs->skb->nh.iph->saddr,
++                                  RT_TOS(ixs->skb->nh.iph->tos),
++                                  ixs->physdev->iflink /* rgb: should this be 0? */))) {
++              ixs->stats->tx_errors++;
++              KLIPS_PRINT(debug_mast & DB_MAST_XMIT,
++                          "klips_debug:ipsec_xmit_send: "
++                          "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n",
++                          ixs->error,
++                          ixs->route->u.dst.dev->name);
++              return IPSEC_XMIT_ROUTEERR;
++      }
++      if(ixs->dev == ixs->route->u.dst.dev) {
++              ip_rt_put(ixs->route);
++              /* This is recursion, drop it. */
++              ixs->stats->tx_errors++;
++              KLIPS_PRINT(debug_mast & DB_MAST_XMIT,
++                          "klips_debug:ipsec_xmit_send: "
++                          "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n",
++                          ixs->dev->name);
++              return IPSEC_XMIT_RECURSDETECT;
++      }
++      dst_release(ixs->skb->dst);
++      ixs->skb->dst = &ixs->route->u.dst;
++      ixs->stats->tx_bytes += ixs->skb->len;
++      if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) {
++              ixs->stats->tx_errors++;
++              printk(KERN_WARNING
++                     "klips_error:ipsec_xmit_send: "
++                     "tried to __skb_pull nh-data=%ld, %d available.  This should never happen, please report.\n",
++                     (unsigned long)(ixs->skb->nh.raw - ixs->skb->data),
++                     ixs->skb->len);
++              return IPSEC_XMIT_PUSHPULLERR;
++      }
++      __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data);
++#ifdef SKB_RESET_NFCT
++      nf_conntrack_put(ixs->skb->nfct);
++      ixs->skb->nfct = NULL;
++#ifdef CONFIG_NETFILTER_DEBUG
++      ixs->skb->nf_debug = 0;
++#endif /* CONFIG_NETFILTER_DEBUG */
++#endif /* SKB_RESET_NFCT */
++      KLIPS_PRINT(debug_mast & DB_MAST_XMIT,
++                  "klips_debug:ipsec_xmit_send: "
++                  "...done, calling ip_send() on device:%s\n",
++                  ixs->skb->dev ? ixs->skb->dev->name : "NULL");
++      KLIPS_IP_PRINT(debug_mast & DB_MAST_XMIT, ixs->skb->nh.iph);
++      {
++              int err;
++
++              err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev,
++                            ipsec_mast_xmit2);
++              if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) {
++                      if(net_ratelimit())
++                              printk(KERN_ERR
++                                     "klips_error:ipsec_xmit_send: "
++                                     "ip_send() failed, err=%d\n", 
++                                     -err);
++                      ixs->stats->tx_errors++;
++                      ixs->stats->tx_aborted_errors++;
++                      ixs->skb = NULL;
++                      return IPSEC_XMIT_IPSENDFAILURE;
++              }
++      }
++      ixs->stats->tx_packets++;
++
++      ixs->skb = NULL;
++      
++      return IPSEC_XMIT_OK;
++}
++
++void
++ipsec_mast_cleanup(struct ipsec_xmit_state*ixs)
++{
++#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE)
++      netif_wake_queue(ixs->dev);
++#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
++      ixs->dev->tbusy = 0;
++#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
++      if(ixs->saved_header) {
++              kfree(ixs->saved_header);
++      }
++      if(ixs->skb) {
++              dev_kfree_skb(ixs->skb, FREE_WRITE);
++      }
++      if(ixs->oskb) {
++              dev_kfree_skb(ixs->oskb, FREE_WRITE);
++      }
++      if (ixs->ips.ips_ident_s.data) {
++              kfree(ixs->ips.ips_ident_s.data);
++      }
++      if (ixs->ips.ips_ident_d.data) {
++              kfree(ixs->ips.ips_ident_d.data);
++      }
++}
++
++#if 0
++/*
++ *    This function assumes it is being called from dev_queue_xmit()
++ *    and that skb is filled properly by that function.
++ */
++int
++ipsec_mast_start_xmit(struct sk_buff *skb, struct net_device *dev, IPsecSAref_t SAref)
++{
++      struct ipsec_xmit_state ixs_mem;
++      struct ipsec_xmit_state *ixs = &ixs_mem;
++      enum ipsec_xmit_value stat = IPSEC_XMIT_OK;
++
++      /* dev could be a mast device, but should be optional, I think... */
++      /* SAref is also optional, but one of the two must be present. */
++      /* I wonder if it could accept no device or saref and guess? */
++
++/*    ipsec_xmit_sanity_check_dev(ixs); */
++
++      ipsec_xmit_sanity_check_skb(ixs);
++
++      ipsec_xmit_adjust_hard_header(ixs);
++
++      stat = ipsec_xmit_encap_bundle(ixs);
++      if(stat != IPSEC_XMIT_OK) {
++              /* SA processing failed */
++      }
++
++      ipsec_xmit_hard_header_restore();
++}
++#endif
++
++DEBUG_NO_STATIC struct net_device_stats *
++ipsec_mast_get_stats(struct net_device *dev)
++{
++      return &(((struct ipsecpriv *)(dev->priv))->mystats);
++}
++
++/*
++ * Revectored calls.
++ * For each of these calls, a field exists in our private structure.
++ */
++
++DEBUG_NO_STATIC int
++ipsec_mast_hard_header(struct sk_buff *skb, struct net_device *dev,
++      unsigned short type, void *daddr, void *saddr, unsigned len)
++{
++      struct ipsecpriv *prv = dev->priv;
++      struct net_device *tmp;
++      int ret;
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(skb == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_hard_header: "
++                          "no skb...\n");
++              return -ENODATA;
++      }
++
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_hard_header: "
++                          "no device...\n");
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                  "klips_debug:ipsec_mast_hard_header: "
++                  "skb->dev=%s dev=%s.\n",
++                  skb->dev ? skb->dev->name : "NULL",
++                  dev->name);
++      
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_hard_header: "
++                          "no private space associated with dev=%s\n",
++                          dev->name ? dev->name : "NULL");
++              return -ENODEV;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_hard_header: "
++                          "no physical device associated with dev=%s\n",
++                          dev->name ? dev->name : "NULL");
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      /* check if we have to send a IPv6 packet. It might be a Router
++         Solicitation, where the building of the packet happens in
++         reverse order:
++         1. ll hdr,
++         2. IPv6 hdr,
++         3. ICMPv6 hdr
++         -> skb->nh.raw is still uninitialized when this function is
++         called!!  If this is no IPv6 packet, we can print debugging
++         messages, otherwise we skip all debugging messages and just
++         build the ll header */
++      if(type != ETH_P_IPV6) {
++              /* execute this only, if we don't have to build the
++                 header for a IPv6 packet */
++              if(!prv->hard_header) {
++                      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                                  "klips_debug:ipsec_mast_hard_header: "
++                                  "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ",
++                                  saddr,
++                                  daddr,
++                                  len,
++                                  type,
++                                  dev->name);
++                      KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC,
++                                      "ip=%08x->%08x\n",
++                                      (__u32)ntohl(skb->nh.iph->saddr),
++                                      (__u32)ntohl(skb->nh.iph->daddr) );
++                      stats->tx_dropped++;
++                      return -ENODEV;
++              }
++              
++#define da ((struct net_device *)(prv->dev))->dev_addr
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_hard_header: "
++                          "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ",
++                          saddr,
++                          daddr,
++                          len,
++                          type,
++                          dev->name,
++                          prv->dev->name,
++                          da[0], da[1], da[2], da[3], da[4], da[5]);
++              KLIPS_PRINTMORE(debug_mast & DB_MAST_REVEC,
++                          "ip=%08x->%08x\n",
++                          (__u32)ntohl(skb->nh.iph->saddr),
++                          (__u32)ntohl(skb->nh.iph->daddr) );
++      } else {
++              KLIPS_PRINT(debug_mast,
++                          "klips_debug:ipsec_mast_hard_header: "
++                          "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n");
++      }                                                                       
++      tmp = skb->dev;
++      skb->dev = prv->dev;
++      ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len);
++      skb->dev = tmp;
++      return ret;
++}
++
++DEBUG_NO_STATIC int
++ipsec_mast_rebuild_header(struct sk_buff *skb)
++{
++      struct ipsecpriv *prv = skb->dev->priv;
++      struct net_device *tmp;
++      int ret;
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(skb->dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_rebuild_header: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_rebuild_header: "
++                          "no private space associated with dev=%s",
++                          skb->dev->name ? skb->dev->name : "NULL");
++              return -ENODEV;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_rebuild_header: "
++                          "no physical device associated with dev=%s",
++                          skb->dev->name ? skb->dev->name : "NULL");
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      if(!prv->rebuild_header) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_rebuild_header: "
++                          "physical device has been detached, packet dropped skb->dev=%s->NULL ",
++                          skb->dev->name);
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "ip=%08x->%08x\n",
++                          (__u32)ntohl(skb->nh.iph->saddr),
++                          (__u32)ntohl(skb->nh.iph->daddr) );
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                  "klips_debug:ipsec_mast: "
++                  "Revectored rebuild_header dev=%s->%s ",
++                  skb->dev->name, prv->dev->name);
++      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                  "ip=%08x->%08x\n",
++                  (__u32)ntohl(skb->nh.iph->saddr),
++                  (__u32)ntohl(skb->nh.iph->daddr) );
++      tmp = skb->dev;
++      skb->dev = prv->dev;
++      
++      ret = prv->rebuild_header(skb);
++      skb->dev = tmp;
++      return ret;
++}
++
++DEBUG_NO_STATIC int
++ipsec_mast_set_mac_address(struct net_device *dev, void *addr)
++{
++      struct ipsecpriv *prv = dev->priv;
++      
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_set_mac_address: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_set_mac_address: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return -ENODEV;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_set_mac_address: "
++                          "no physical device associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      if(!prv->set_mac_address) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_set_mac_address: "
++                          "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
++                          dev->name);
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                  "klips_debug:ipsec_mast_set_mac_address: "
++                  "Revectored dev=%s->%s addr=0p%p\n",
++                  dev->name, prv->dev->name, addr);
++      return prv->set_mac_address(prv->dev, addr);
++
++}
++
++DEBUG_NO_STATIC void
++ipsec_mast_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char *  haddr)
++{
++      struct ipsecpriv *prv = dev->priv;
++      
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_cache_update: "
++                          "no device...");
++              return;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_cache_update: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_cache_update: "
++                          "no physical device associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              stats->tx_dropped++;
++              return;
++      }
++
++      if(!prv->header_cache_update) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_cache_update: "
++                          "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
++                          dev->name);
++              return;
++      }
++
++      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                  "klips_debug:ipsec_mast: "
++                  "Revectored cache_update\n");
++      prv->header_cache_update(hh, prv->dev, haddr);
++      return;
++}
++
++DEBUG_NO_STATIC int
++ipsec_mast_neigh_setup(struct neighbour *n)
++{
++      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                  "klips_debug:ipsec_mast_neigh_setup:\n");
++
++        if (n->nud_state == NUD_NONE) {
++                n->ops = &arp_broken_ops;
++                n->output = n->ops->output;
++        }
++        return 0;
++}
++
++DEBUG_NO_STATIC int
++ipsec_mast_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
++{
++      KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                  "klips_debug:ipsec_mast_neigh_setup_dev: "
++                  "setting up %s\n",
++                  dev ? dev->name : "NULL");
++
++        if (p->tbl->family == AF_INET) {
++                p->neigh_setup = ipsec_mast_neigh_setup;
++                p->ucast_probes = 0;
++                p->mcast_probes = 0;
++        }
++        return 0;
++}
++
++/*
++ * We call the attach routine to attach another device.
++ */
++
++DEBUG_NO_STATIC int
++ipsec_mast_attach(struct net_device *dev, struct net_device *physdev)
++{
++        int i;
++      struct ipsecpriv *prv = dev->priv;
++
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_attach: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_attach: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return -ENODATA;
++      }
++
++      prv->dev = physdev;
++      prv->hard_start_xmit = physdev->hard_start_xmit;
++      prv->get_stats = physdev->get_stats;
++
++      if (physdev->hard_header) {
++              prv->hard_header = physdev->hard_header;
++              dev->hard_header = ipsec_mast_hard_header;
++      } else
++              dev->hard_header = NULL;
++      
++      if (physdev->rebuild_header) {
++              prv->rebuild_header = physdev->rebuild_header;
++              dev->rebuild_header = ipsec_mast_rebuild_header;
++      } else
++              dev->rebuild_header = NULL;
++      
++      if (physdev->set_mac_address) {
++              prv->set_mac_address = physdev->set_mac_address;
++              dev->set_mac_address = ipsec_mast_set_mac_address;
++      } else
++              dev->set_mac_address = NULL;
++      
++      if (physdev->header_cache_update) {
++              prv->header_cache_update = physdev->header_cache_update;
++              dev->header_cache_update = ipsec_mast_cache_update;
++      } else
++              dev->header_cache_update = NULL;
++
++      dev->hard_header_len = physdev->hard_header_len;
++
++/*    prv->neigh_setup        = physdev->neigh_setup; */
++      dev->neigh_setup        = ipsec_mast_neigh_setup_dev;
++      dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */
++      prv->mtu = physdev->mtu;
++
++#ifdef PHYSDEV_TYPE
++      dev->type = physdev->type; /* ARPHRD_MAST; */
++#endif /*  PHYSDEV_TYPE */
++
++      dev->addr_len = physdev->addr_len;
++      for (i=0; i<dev->addr_len; i++) {
++              dev->dev_addr[i] = physdev->dev_addr[i];
++      }
++#ifdef CONFIG_KLIPS_DEBUG
++      if(debug_mast & DB_MAST_INIT) {
++              printk(KERN_INFO "klips_debug:ipsec_mast_attach: "
++                     "physical device %s being attached has HW address: %2x",
++                     physdev->name, physdev->dev_addr[0]);
++              for (i=1; i < physdev->addr_len; i++) {
++                      printk(":%02x", physdev->dev_addr[i]);
++              }
++              printk("\n");
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      return 0;
++}
++
++/*
++ * We call the detach routine to detach the ipsec mast from another device.
++ */
++
++DEBUG_NO_STATIC int
++ipsec_mast_detach(struct net_device *dev)
++{
++        int i;
++      struct ipsecpriv *prv = dev->priv;
++
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_detach: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_REVEC,
++                          "klips_debug:ipsec_mast_detach: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return -ENODATA;
++      }
++
++      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                  "klips_debug:ipsec_mast_detach: "
++                  "physical device %s being detached from virtual device %s\n",
++                  prv->dev ? prv->dev->name : "NULL",
++                  dev->name);
++
++      prv->dev = NULL;
++      prv->hard_start_xmit = NULL;
++      prv->get_stats = NULL;
++
++      prv->hard_header = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->hard_header = NULL;
++#endif /* DETACH_AND_DOWN */
++      
++      prv->rebuild_header = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->rebuild_header = NULL;
++#endif /* DETACH_AND_DOWN */
++      
++      prv->set_mac_address = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->set_mac_address = NULL;
++#endif /* DETACH_AND_DOWN */
++      
++      prv->header_cache_update = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->header_cache_update = NULL;
++#endif /* DETACH_AND_DOWN */
++
++#ifdef DETACH_AND_DOWN
++      dev->neigh_setup        = NULL;
++#endif /* DETACH_AND_DOWN */
++
++      dev->hard_header_len = 0;
++#ifdef DETACH_AND_DOWN
++      dev->mtu = 0;
++#endif /* DETACH_AND_DOWN */
++      prv->mtu = 0;
++      for (i=0; i<MAX_ADDR_LEN; i++) {
++              dev->dev_addr[i] = 0;
++      }
++      dev->addr_len = 0;
++#ifdef PHYSDEV_TYPE
++      dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */
++#endif /*  PHYSDEV_TYPE */
++      
++      return 0;
++}
++
++/*
++ * We call the clear routine to detach all ipsec masts from other devices.
++ */
++DEBUG_NO_STATIC int
++ipsec_mast_clear(void)
++{
++      int i;
++      struct net_device *ipsecdev = NULL, *prvdev;
++      struct ipsecpriv *prv;
++      char name[9];
++      int ret;
++
++      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                  "klips_debug:ipsec_mast_clear: .\n");
++
++      for(i = 0; i < IPSEC_NUM_IF; i++) {
++              sprintf(name, IPSEC_DEV_FORMAT, i);
++              if((ipsecdev = ipsec_dev_get(name)) != NULL) {
++                      if((prv = (struct ipsecpriv *)(ipsecdev->priv))) {
++                              prvdev = (struct net_device *)(prv->dev);
++                              if(prvdev) {
++                                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                                  "klips_debug:ipsec_mast_clear: "
++                                                  "physical device for device %s is %s\n",
++                                                  name, prvdev->name);
++                                      if((ret = ipsec_mast_detach(ipsecdev))) {
++                                              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                                          "klips_debug:ipsec_mast_clear: "
++                                                          "error %d detatching device %s from device %s.\n",
++                                                          ret, name, prvdev->name);
++                                              return ret;
++                                      }
++                              }
++                      }
++              }
++      }
++      return 0;
++}
++
++DEBUG_NO_STATIC int
++ipsec_mast_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++      struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data;
++      struct ipsecpriv *prv = dev->priv;
++      struct net_device *them; /* physical device */
++#ifdef CONFIG_IP_ALIAS
++      char *colon;
++      char realphysname[IFNAMSIZ];
++#endif /* CONFIG_IP_ALIAS */
++      
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_ioctl: "
++                          "device not supplied.\n");
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                  "klips_debug:ipsec_mast_ioctl: "
++                  "tncfg service call #%d for dev=%s\n",
++                  cmd,
++                  dev->name ? dev->name : "NULL");
++      switch (cmd) {
++      /* attach a virtual ipsec? device to a physical device */
++      case IPSEC_SET_DEV:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_ioctl: "
++                          "calling ipsec_mast_attatch...\n");
++#ifdef CONFIG_IP_ALIAS
++              /* If this is an IP alias interface, get its real physical name */
++              strncpy(realphysname, cf->cf_name, IFNAMSIZ);
++              realphysname[IFNAMSIZ-1] = 0;
++              colon = strchr(realphysname, ':');
++              if (colon) *colon = 0;
++              them = ipsec_dev_get(realphysname);
++#else /* CONFIG_IP_ALIAS */
++              them = ipsec_dev_get(cf->cf_name);
++#endif /* CONFIG_IP_ALIAS */
++
++              if (them == NULL) {
++                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                  "klips_debug:ipsec_mast_ioctl: "
++                                  "physical device %s requested is null\n",
++                                  cf->cf_name);
++                      return -ENXIO;
++              }
++              
++#if 0
++              if (them->flags & IFF_UP) {
++                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                  "klips_debug:ipsec_mast_ioctl: "
++                                  "physical device %s requested is not up.\n",
++                                  cf->cf_name);
++                      return -ENXIO;
++              }
++#endif
++              
++              if (prv && prv->dev) {
++                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                  "klips_debug:ipsec_mast_ioctl: "
++                                  "virtual device is already connected to %s.\n",
++                                  prv->dev->name ? prv->dev->name : "NULL");
++                      return -EBUSY;
++              }
++              return ipsec_mast_attach(dev, them);
++
++      case IPSEC_DEL_DEV:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_ioctl: "
++                          "calling ipsec_mast_detatch.\n");
++              if (! prv->dev) {
++                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                  "klips_debug:ipsec_mast_ioctl: "
++                                  "physical device not connected.\n");
++                      return -ENODEV;
++              }
++              return ipsec_mast_detach(dev);
++             
++      case IPSEC_CLR_DEV:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_ioctl: "
++                          "calling ipsec_mast_clear.\n");
++              return ipsec_mast_clear();
++
++      default:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_ioctl: "
++                          "unknown command %d.\n",
++                          cmd);
++              return -EOPNOTSUPP;
++      }
++}
++
++int
++ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
++{
++      struct net_device *dev = ptr;
++      struct net_device *ipsec_dev;
++      struct ipsecpriv *priv;
++      char name[9];
++      int i;
++
++      if (dev == NULL) {
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "dev=NULL for event type %ld.\n",
++                          event);
++              return(NOTIFY_DONE);
++      }
++
++      /* check for loopback devices */
++      if (dev && (dev->flags & IFF_LOOPBACK)) {
++              return(NOTIFY_DONE);
++      }
++
++      switch (event) {
++      case NETDEV_DOWN:
++              /* look very carefully at the scope of these compiler
++                 directives before changing anything... -- RGB */
++
++      case NETDEV_UNREGISTER:
++              switch (event) {
++              case NETDEV_DOWN:
++                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                  "klips_debug:ipsec_mast_device_event: "
++                                  "NETDEV_DOWN dev=%s flags=%x\n",
++                                  dev->name,
++                                  dev->flags);
++                      if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) {
++                              printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n",
++                                     dev->name);
++                      }
++                      break;
++              case NETDEV_UNREGISTER:
++                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                  "klips_debug:ipsec_mast_device_event: "
++                                  "NETDEV_UNREGISTER dev=%s flags=%x\n",
++                                  dev->name,
++                                  dev->flags);
++                      break;
++              }
++              
++              /* find the attached physical device and detach it. */
++              for(i = 0; i < IPSEC_NUM_IF; i++) {
++                      sprintf(name, IPSEC_DEV_FORMAT, i);
++                      ipsec_dev = ipsec_dev_get(name);
++                      if(ipsec_dev) {
++                              priv = (struct ipsecpriv *)(ipsec_dev->priv);
++                              if(priv) {
++                                      ;
++                                      if(((struct net_device *)(priv->dev)) == dev) {
++                                              /* dev_close(ipsec_dev); */
++                                              /* return */ ipsec_mast_detach(ipsec_dev);
++                                              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                                          "klips_debug:ipsec_mast_device_event: "
++                                                          "device '%s' has been detached.\n",
++                                                          ipsec_dev->name);
++                                              break;
++                                      }
++                              } else {
++                                      KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                                                  "klips_debug:ipsec_mast_device_event: "
++                                                  "device '%s' has no private data space!\n",
++                                                  ipsec_dev->name);
++                              }
++                      }
++              }
++              break;
++      case NETDEV_UP:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_UP dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_REBOOT:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_REBOOT dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_CHANGE:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_CHANGE dev=%s flags=%x\n",
++                          dev->name,
++                          dev->flags);
++              break;
++      case NETDEV_REGISTER:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_REGISTER dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_CHANGEMTU:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_CHANGEMTU dev=%s to mtu=%d\n",
++                          dev->name,
++                          dev->mtu);
++              break;
++      case NETDEV_CHANGEADDR:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_CHANGEADDR dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_GOING_DOWN:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_GOING_DOWN dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_CHANGENAME:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "NETDEV_CHANGENAME dev=%s\n",
++                          dev->name);
++              break;
++      default:
++              KLIPS_PRINT(debug_mast & DB_MAST_INIT,
++                          "klips_debug:ipsec_mast_device_event: "
++                          "event type %ld unrecognised for dev=%s\n",
++                          event,
++                          dev->name);
++              break;
++      }
++      return NOTIFY_DONE;
++}
++
++/*
++ *    Called when an ipsec mast device is initialized.
++ *    The ipsec mast device structure is passed to us.
++ */
++ 
++int
++ipsec_mast_init(struct net_device *dev)
++{
++      int i;
++
++      KLIPS_PRINT(debug_mast,
++                  "klips_debug:ipsec_mast_init: "
++                  "allocating %lu bytes initialising device: %s\n",
++                  (unsigned long) sizeof(struct ipsecpriv),
++                  dev->name ? dev->name : "NULL");
++
++      /* Add our mast functions to the device */
++      dev->open               = ipsec_mast_open;
++      dev->stop               = ipsec_mast_close;
++      dev->hard_start_xmit    = ipsec_mast_start_xmit;
++      dev->get_stats          = ipsec_mast_get_stats;
++
++      dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL);
++      if (dev->priv == NULL)
++              return -ENOMEM;
++      memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv));
++
++      for(i = 0; i < sizeof(zeroes); i++) {
++              ((__u8*)(zeroes))[i] = 0;
++      }
++      
++      dev->set_multicast_list = NULL;
++      dev->do_ioctl           = ipsec_mast_ioctl;
++      dev->hard_header        = NULL;
++      dev->rebuild_header     = NULL;
++      dev->set_mac_address    = NULL;
++      dev->header_cache_update= NULL;
++      dev->neigh_setup        = ipsec_mast_neigh_setup_dev;
++      dev->hard_header_len    = 0;
++      dev->mtu                = 0;
++      dev->addr_len           = 0;
++      dev->type               = ARPHRD_VOID; /* ARPHRD_MAST; */ /* ARPHRD_ETHER; */
++      dev->tx_queue_len       = 10;           /* Small queue */
++      memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN);       /* what if this is not attached to ethernet? */
++
++      /* New-style flags. */
++      dev->flags              = IFF_NOARP /* 0 */ /* Petr Novak */;
++      dev_init_buffers(dev);
++
++      /* We're done.  Have I forgotten anything? */
++      return 0;
++}
++
++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
++/*  Module specific interface (but it links with the rest of IPSEC)  */
++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
++
++int
++ipsec_mast_probe(struct net_device *dev)
++{
++      ipsec_mast_init(dev); 
++      return 0;
++}
++
++int 
++ipsec_mast_init_devices(void)
++{
++      return 0;
++}
++
++/* void */
++int
++ipsec_mast_cleanup_devices(void)
++{
++      int error = 0;
++      int i;
++      char name[10];
++      struct net_device *dev_mast;
++      
++      for(i = 0; i < ipsec_mastdevice_count; i++) {
++              sprintf(name, MAST_DEV_FORMAT, i);
++              if((dev_mast = ipsec_dev_get(name)) == NULL) {
++                      break;
++              }
++              unregister_netdev(dev_mast);
++              kfree(dev_mast->priv);
++              dev_mast->priv=NULL;
++      }
++      return error;
++}
++
++/*
++ * $Log: ipsec_mast.c,v $
++ * Revision 1.7.2.1  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.7  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.6  2004/12/03 21:25:57  mcr
++ *    compile time fixes for running on 2.6.
++ *    still experimental.
++ *
++ * Revision 1.5  2004/08/03 18:19:08  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.4  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.3  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.2.4.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.2  2003/06/22 20:06:17  mcr
++ *    refactored mast code still had lots of ipsecX junk in it.
++ *
++ * Revision 1.1  2003/02/12 19:31:12  rgb
++ * Refactored from ipsec_tunnel.c
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_md5c.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,453 @@
++/*
++ * RCSID $Id: ipsec_md5c.c,v 1.10 2005/04/15 01:25:57 mcr Exp $
++ */
++
++/*
++ * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic
++ * changes to accomodate it in the kernel by ji.
++ */
++
++#include <asm/byteorder.h>
++#include <linux/string.h>
++
++#include "openswan/ipsec_md5h.h"
++
++/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
++ */
++
++/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
++rights reserved.
++
++License to copy and use this software is granted provided that it
++is identified as the "RSA Data Security, Inc. MD5 Message-Digest
++Algorithm" in all material mentioning or referencing this software
++or this function.
++
++License is also granted to make and use derivative works provided
++that such works are identified as "derived from the RSA Data
++Security, Inc. MD5 Message-Digest Algorithm" in all material
++mentioning or referencing the derived work.
++
++RSA Data Security, Inc. makes no representations concerning either
++the merchantability of this software or the suitability of this
++software for any particular purpose. It is provided "as is"
++without express or implied warranty of any kind.
++
++These notices must be retained in any copies of any part of this
++documentation and/or software.
++ */
++
++/*
++ * Additions by JI
++ * 
++ * HAVEMEMCOPY is defined if mem* routines are available
++ *
++ * HAVEHTON is defined if htons() and htonl() can be used
++ * for big/little endian conversions
++ *
++ */
++
++#define HAVEMEMCOPY
++#ifdef __LITTLE_ENDIAN
++#define LITTLENDIAN
++#endif
++#ifdef __BIG_ENDIAN
++#define BIGENDIAN
++#endif
++
++/* Constants for MD5Transform routine.
++ */
++
++#define S11 7
++#define S12 12
++#define S13 17
++#define S14 22
++#define S21 5
++#define S22 9
++#define S23 14
++#define S24 20
++#define S31 4
++#define S32 11
++#define S33 16
++#define S34 23
++#define S41 6
++#define S42 10
++#define S43 15
++#define S44 21
++
++static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
++
++#ifdef LITTLEENDIAN
++#define Encode MD5_memcpy
++#define Decode MD5_memcpy
++#else
++static void Encode PROTO_LIST
++  ((unsigned char *, UINT4 *, unsigned int));
++static void Decode PROTO_LIST
++  ((UINT4 *, unsigned char *, unsigned int));
++#endif
++
++#ifdef HAVEMEMCOPY
++/* no need to include <memory.h> here; <linux/string.h> defines these */
++#define MD5_memcpy    memcpy
++#define MD5_memset    memset
++#else
++#ifdef HAVEBCOPY
++#define MD5_memcpy(_a,_b,_c) bcopy((_b),(_a),(_c))
++#define MD5_memset(_a,_b,_c) bzero((_a),(_c))
++#else
++static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
++static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
++#endif
++#endif
++static unsigned char PADDING[64] = {
++  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++};
++
++/* F, G, H and I are basic MD5 functions.
++ */
++#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
++#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
++#define H(x, y, z) ((x) ^ (y) ^ (z))
++#define I(x, y, z) ((y) ^ ((x) | (~z)))
++
++/* ROTATE_LEFT rotates x left n bits.
++ */
++#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
++
++/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
++Rotation is separate from addition to prevent recomputation.
++ */
++#define FF(a, b, c, d, x, s, ac) { \
++ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
++ (a) = ROTATE_LEFT ((a), (s)); \
++ (a) += (b); \
++  }
++#define GG(a, b, c, d, x, s, ac) { \
++ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
++ (a) = ROTATE_LEFT ((a), (s)); \
++ (a) += (b); \
++  }
++#define HH(a, b, c, d, x, s, ac) { \
++ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
++ (a) = ROTATE_LEFT ((a), (s)); \
++ (a) += (b); \
++  }
++#define II(a, b, c, d, x, s, ac) { \
++ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
++ (a) = ROTATE_LEFT ((a), (s)); \
++ (a) += (b); \
++  }
++
++/*
++ * MD5 initialization. Begins an MD5 operation, writing a new context.
++ */
++void osMD5Init(void *vcontext)
++{
++  MD5_CTX *context = vcontext;                                     
++
++  context->count[0] = context->count[1] = 0;
++  /* Load magic initialization constants.*/
++  context->state[0] = 0x67452301;
++  context->state[1] = 0xefcdab89;
++  context->state[2] = 0x98badcfe;
++  context->state[3] = 0x10325476;
++}
++
++/* MD5 block update operation. Continues an MD5 message-digest
++  operation, processing another message block, and updating the
++  context.
++ */
++void osMD5Update (vcontext, input, inputLen)
++     void *vcontext;
++     unsigned char *input;                                /* input block */
++     __u32 inputLen;                     /* length of input block */
++{
++  MD5_CTX *context = vcontext;                                     
++  __u32 i;
++  unsigned int index, partLen;
++
++  /* Compute number of bytes mod 64 */
++  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
++
++  /* Update number of bits */
++  if ((context->count[0] += ((UINT4)inputLen << 3))
++   < ((UINT4)inputLen << 3))
++ context->count[1]++;
++  context->count[1] += ((UINT4)inputLen >> 29);
++
++  partLen = 64 - index;
++
++  /* Transform as many times as possible.
++*/
++  if (inputLen >= partLen) {
++ MD5_memcpy
++   ((POINTER)&context->buffer[index], (POINTER)input, partLen);
++ MD5Transform (context->state, context->buffer);
++
++ for (i = partLen; i + 63 < inputLen; i += 64)
++   MD5Transform (context->state, &input[i]);
++
++ index = 0;
++  }
++  else
++ i = 0;
++
++  /* Buffer remaining input */
++  MD5_memcpy
++ ((POINTER)&context->buffer[index], (POINTER)&input[i],
++  inputLen-i);
++}
++
++/* MD5 finalization. Ends an MD5 message-digest operation, writing the
++  the message digest and zeroizing the context.
++ */
++void osMD5Final (digest, vcontext)
++unsigned char digest[16];                         /* message digest */
++void *vcontext;                                       /* context */
++{
++  MD5_CTX *context = vcontext;                                     
++  unsigned char bits[8];
++  unsigned int index, padLen;
++
++  /* Save number of bits */
++  Encode (bits, context->count, 8);
++
++  /* Pad out to 56 mod 64.
++*/
++  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
++  padLen = (index < 56) ? (56 - index) : (120 - index);
++  osMD5Update (context, PADDING, padLen);
++
++  /* Append length (before padding) */
++  osMD5Update (context, bits, 8);
++
++  if (digest != NULL)                 /* Bill Simpson's padding */
++  {
++        /* store state in digest */
++        Encode (digest, context->state, 16);
++
++        /* Zeroize sensitive information.
++         */
++        MD5_memset ((POINTER)context, 0, sizeof (*context));
++  }
++}
++
++/* MD5 basic transformation. Transforms state based on block.
++ */
++static void MD5Transform (state, block)
++UINT4 state[4];
++unsigned char block[64];
++{
++  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
++
++  Decode (x, block, 64);
++
++  /* Round 1 */
++  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
++  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
++  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
++  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
++  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
++  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
++  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
++  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
++  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
++  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
++  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
++  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
++  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
++  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
++  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
++  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
++
++ /* Round 2 */
++  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
++  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
++  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
++  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
++  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
++  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
++  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
++  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
++  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
++  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
++  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
++  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
++  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
++  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
++  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
++  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
++
++  /* Round 3 */
++  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
++  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
++  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
++  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
++  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
++  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
++  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
++  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
++  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
++  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
++  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
++  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
++  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
++  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
++  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
++  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
++
++  /* Round 4 */
++  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
++  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
++  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
++  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
++  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
++  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
++  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
++  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
++  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
++  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
++  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
++  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
++  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
++  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
++  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
++  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
++
++  state[0] += a;
++  state[1] += b;
++  state[2] += c;
++  state[3] += d;
++
++  /* Zeroize sensitive information.
++*/
++  MD5_memset ((POINTER)x, 0, sizeof (x));
++}
++
++#ifndef LITTLEENDIAN
++
++/* Encodes input (UINT4) into output (unsigned char). Assumes len is
++  a multiple of 4.
++ */
++static void Encode (output, input, len)
++unsigned char *output;
++UINT4 *input;
++unsigned int len;
++{
++  unsigned int i, j;
++
++  for (i = 0, j = 0; j < len; i++, j += 4) {
++ output[j] = (unsigned char)(input[i] & 0xff);
++ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
++ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
++ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
++  }
++}
++
++/* Decodes input (unsigned char) into output (UINT4). Assumes len is
++  a multiple of 4.
++ */
++static void Decode (output, input, len)
++UINT4 *output;
++unsigned char *input;
++unsigned int len;
++{
++  unsigned int i, j;
++
++  for (i = 0, j = 0; j < len; i++, j += 4)
++ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
++   (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
++}
++
++#endif
++
++#ifndef HAVEMEMCOPY
++#ifndef HAVEBCOPY
++/* Note: Replace "for loop" with standard memcpy if possible.
++ */
++
++static void MD5_memcpy (output, input, len)
++POINTER output;
++POINTER input;
++unsigned int len;
++{
++  unsigned int i;
++
++  for (i = 0; i < len; i++)
++
++ output[i] = input[i];
++}
++
++/* Note: Replace "for loop" with standard memset if possible.
++ */
++
++static void MD5_memset (output, value, len)
++POINTER output;
++int value;
++unsigned int len;
++{
++  unsigned int i;
++
++  for (i = 0; i < len; i++)
++ ((char *)output)[i] = (char)value;
++}
++#endif
++#endif
++
++/*
++ * $Log: ipsec_md5c.c,v $
++ * Revision 1.10  2005/04/15 01:25:57  mcr
++ *    minor fix to comments.
++ *
++ * Revision 1.9  2004/09/08 17:21:36  ken
++ * Rename MD5* -> osMD5 functions to prevent clashes with other symbols exported by kernel modules (CIFS in 2.6 initiated this)
++ *
++ * Revision 1.8  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.7  2002/09/10 01:45:14  mcr
++ *    changed type of MD5_CTX and SHA1_CTX to void * so that
++ *    the function prototypes would match, and could be placed
++ *    into a pointer to a function.
++ *
++ * Revision 1.6  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.5  2002/04/24 07:36:28  mcr
++ * Moved from ./klips/net/ipsec/ipsec_md5c.c,v
++ *
++ * Revision 1.4  1999/12/13 13:59:12  rgb
++ * Quick fix to argument size to Update bugs.
++ *
++ * Revision 1.3  1999/05/21 18:09:28  henry
++ * unnecessary <memory.h> include causes trouble in 2.2
++ *
++ * Revision 1.2  1999/04/06 04:54:26  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.1  1998/06/18 21:27:48  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.2  1998/04/23 20:54:02  rgb
++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
++ * verified.
++ *
++ * Revision 1.1  1998/04/09 03:06:08  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.3  1996/11/20 14:48:53  ji
++ * Release update only.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_proc.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1186 @@
++/*
++ * @(#) /proc file system interface code.
++ *
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
++ *                                 2001  Michael Richardson <mcr@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * Split out from ipsec_init.c version 1.70.
++ */
++
++char ipsec_proc_c_version[] = "RCSID $Id: ipsec_proc.c,v 1.39.2.4 2006/11/15 22:21:39 paul Exp $";
++
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_kversion.h"
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/in.h>          /* struct sockaddr_in */
++#include <linux/skbuff.h>
++#include <asm/uaccess.h>       /* copy_from_user */
++#include <openswan.h>
++#ifdef SPINLOCK
++#ifdef SPINLOCK_23
++#include <linux/spinlock.h> /* *lock* */
++#else /* SPINLOCK_23 */
++#include <asm/spinlock.h> /* *lock* */
++#endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++#ifdef CONFIG_PROC_FS
++#include <linux/proc_fs.h>
++#endif /* CONFIG_PROC_FS */
++#ifdef NETLINK_SOCK
++#include <linux/netlink.h>
++#else
++#include <net/netlink.h>
++#endif
++
++#include "openswan/radij.h"
++
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_stats.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_xmit.h"
++
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++#include "openswan/ipsec_kern24.h"
++
++#ifdef CONFIG_KLIPS_IPCOMP
++#include "openswan/ipcomp.h"
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#include "openswan/ipsec_proto.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#ifdef CONFIG_PROC_FS
++
++#ifdef IPSEC_PROC_SUBDIRS
++static struct proc_dir_entry *proc_net_ipsec_dir = NULL;
++static struct proc_dir_entry *proc_eroute_dir    = NULL;
++static struct proc_dir_entry *proc_spi_dir       = NULL;
++static struct proc_dir_entry *proc_spigrp_dir    = NULL;
++static struct proc_dir_entry *proc_birth_dir     = NULL;
++static struct proc_dir_entry *proc_stats_dir     = NULL;
++#endif
++
++struct ipsec_birth_reply ipsec_ipv4_birth_packet;
++struct ipsec_birth_reply ipsec_ipv6_birth_packet;
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_esp = 0;
++int debug_ah = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#define DECREMENT_UNSIGNED(X, amount) ((amount < (X)) ? (X)-amount : 0)
++
++extern int ipsec_xform_get_info(char *buffer, char **start,
++                              off_t offset, int length IPSEC_PROC_LAST_ARG);
++
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_eroute_get_info(char *buffer, 
++                    char **start, 
++                    off_t offset, 
++                    int length        IPSEC_PROC_LAST_ARG)
++{
++      struct wsbuf w = {buffer, length, offset, 0, 0};
++
++#ifdef CONFIG_KLIPS_DEBUG
++      if (debug_radij & DB_RJ_DUMPTREES)
++        rj_dumptrees();                       /* XXXXXXXXX */
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_eroute_get_info: "
++                  "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
++                  buffer,
++                  *start,
++                  (int)offset,
++                  length);
++
++      spin_lock_bh(&eroute_lock);
++
++      rj_walktree(rnh, ipsec_rj_walker_procprint, &w);
++/*    rj_walktree(mask_rjhead, ipsec_rj_walker_procprint, &w); */
++
++      spin_unlock_bh(&eroute_lock);
++
++      *start = buffer + (offset - w.begin);   /* Start of wanted data */
++      return w.len - (offset - w.begin);
++}
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_spi_get_info(char *buffer,
++                 char **start,
++                 off_t offset,
++                 int length    IPSEC_PROC_LAST_ARG)
++{
++      const int max_content = length > 0? length-1 : 0;
++      int len = 0;
++      off_t begin = 0;
++      int i;
++      struct ipsec_sa *sa_p;
++      char sa[SATOT_BUF];
++      char buf_s[SUBNETTOA_BUF];
++      char buf_d[SUBNETTOA_BUF];
++      size_t sa_len;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_spi_get_info: "
++                  "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
++                  buffer,
++                  *start,
++                  (int)offset,
++                  length);
++      
++      spin_lock_bh(&tdb_lock);
++
++      for (i = 0; i < SADB_HASHMOD; i++) {
++              for (sa_p = ipsec_sadb_hash[i];
++                   sa_p;
++                   sa_p = sa_p->ips_hnext) {
++                      atomic_inc(&sa_p->ips_refcount);
++                      sa_len = satot(&sa_p->ips_said, 'x', sa, sizeof(sa));
++                      len += ipsec_snprintf(buffer+len, length-len, "%s ",
++                                     sa_len ? sa : " (error)");
++
++                      len += ipsec_snprintf(buffer+len, length-len, "%s%s%s",
++                                     IPS_XFORM_NAME(sa_p));
++
++                      len += ipsec_snprintf(buffer+len, length-len, ": dir=%s",
++                                     (sa_p->ips_flags & EMT_INBOUND) ?
++                                     "in " : "out");
++
++                      if(sa_p->ips_addr_s) {
++                              addrtoa(((struct sockaddr_in*)(sa_p->ips_addr_s))->sin_addr,
++                                      0, buf_s, sizeof(buf_s));
++                              len += ipsec_snprintf(buffer+len, length-len, " src=%s",
++                                             buf_s);
++                      }
++
++                      if((sa_p->ips_said.proto == IPPROTO_IPIP)
++                         && (sa_p->ips_flags & SADB_X_SAFLAGS_INFLOW)) {
++                              subnettoa(sa_p->ips_flow_s.u.v4.sin_addr,
++                                        sa_p->ips_mask_s.u.v4.sin_addr,
++                                        0,
++                                        buf_s,
++                                        sizeof(buf_s));
++
++                              subnettoa(sa_p->ips_flow_d.u.v4.sin_addr,
++                                        sa_p->ips_mask_d.u.v4.sin_addr,
++                                        0,
++                                        buf_d,
++                                        sizeof(buf_d));
++
++                              len += ipsec_snprintf(buffer+len, length-len, " policy=%s->%s",
++                                             buf_s, buf_d);
++                      }
++                      
++                      if(sa_p->ips_iv_bits) {
++                              int j;
++                              len += ipsec_snprintf(buffer+len, length-len, " iv_bits=%dbits iv=0x",
++                                             sa_p->ips_iv_bits);
++
++                              for(j = 0; j < sa_p->ips_iv_bits / 8; j++) {
++                                      len += ipsec_snprintf(buffer+len, length-len, "%02x",
++                                                     (__u32)((__u8*)(sa_p->ips_iv))[j]);
++                              }
++                      }
++
++                      if(sa_p->ips_encalg || sa_p->ips_authalg) {
++                              if(sa_p->ips_replaywin) {
++                                      len += ipsec_snprintf(buffer+len, length-len, " ooowin=%d",
++                                                     sa_p->ips_replaywin);
++                              }
++                              if(sa_p->ips_errs.ips_replaywin_errs) {
++                                      len += ipsec_snprintf(buffer+len, length-len, " ooo_errs=%d",
++                                                     sa_p->ips_errs.ips_replaywin_errs);
++                              }
++                              if(sa_p->ips_replaywin_lastseq) {
++                                       len += ipsec_snprintf(buffer+len, length-len, " seq=%d",
++                                                    sa_p->ips_replaywin_lastseq);
++                              }
++                              if(sa_p->ips_replaywin_bitmap) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
++                                      len += ipsec_snprintf(buffer+len, length-len, " bit=0x%Lx",
++                                                     sa_p->ips_replaywin_bitmap);
++#else
++                                      len += ipsec_snprintf(buffer+len, length-len, " bit=0x%x%08x",
++                                                     (__u32)(sa_p->ips_replaywin_bitmap >> 32),
++                                                     (__u32)sa_p->ips_replaywin_bitmap);
++#endif
++                              }
++                              if(sa_p->ips_replaywin_maxdiff) {
++                                      len += ipsec_snprintf(buffer+len, length-len, " max_seq_diff=%d",
++                                                     sa_p->ips_replaywin_maxdiff);
++                              }
++                      }
++                      if(sa_p->ips_flags & ~EMT_INBOUND) {
++                              len += ipsec_snprintf(buffer+len, length-len, " flags=0x%x",
++                                             sa_p->ips_flags & ~EMT_INBOUND);
++                              len += ipsec_snprintf(buffer+len, length-len, "<");
++                              /* flag printing goes here */
++                              len += ipsec_snprintf(buffer+len, length-len, ">");
++                      }
++                      if(sa_p->ips_auth_bits) {
++                              len += ipsec_snprintf(buffer+len, length-len, " alen=%d",
++                                             sa_p->ips_auth_bits);
++                      }
++                      if(sa_p->ips_key_bits_a) {
++                              len += ipsec_snprintf(buffer+len, length-len, " aklen=%d",
++                                             sa_p->ips_key_bits_a);
++                      }
++                      if(sa_p->ips_errs.ips_auth_errs) {
++                              len += ipsec_snprintf(buffer+len, length-len, " auth_errs=%d",
++                                             sa_p->ips_errs.ips_auth_errs);
++                      }
++                      if(sa_p->ips_key_bits_e) {
++                              len += ipsec_snprintf(buffer+len, length-len, " eklen=%d",
++                                             sa_p->ips_key_bits_e);
++                      }
++                      if(sa_p->ips_errs.ips_encsize_errs) {
++                              len += ipsec_snprintf(buffer+len, length-len, " encr_size_errs=%d",
++                                             sa_p->ips_errs.ips_encsize_errs);
++                      }
++                      if(sa_p->ips_errs.ips_encpad_errs) {
++                              len += ipsec_snprintf(buffer+len, length-len, " encr_pad_errs=%d",
++                                             sa_p->ips_errs.ips_encpad_errs);
++                      }
++                      
++                      len += ipsec_snprintf(buffer+len, length-len, " life(c,s,h)=");
++
++                      len += ipsec_lifetime_format(buffer + len,
++                                                   length - len,
++                                                   "alloc", 
++                                                   ipsec_life_countbased,
++                                                   &sa_p->ips_life.ipl_allocations);
++
++                      len += ipsec_lifetime_format(buffer + len,
++                                                   length - len,
++                                                   "bytes",
++                                                   ipsec_life_countbased,
++                                                   &sa_p->ips_life.ipl_bytes);
++
++                      len += ipsec_lifetime_format(buffer + len,
++                                                   length - len,
++                                                   "addtime",
++                                                   ipsec_life_timebased,
++                                                   &sa_p->ips_life.ipl_addtime);
++
++                      len += ipsec_lifetime_format(buffer + len,
++                                                   length - len,
++                                                   "usetime",
++                                                   ipsec_life_timebased,
++                                                   &sa_p->ips_life.ipl_usetime);
++                      
++                      len += ipsec_lifetime_format(buffer + len,
++                                                   length - len,
++                                                   "packets",
++                                                   ipsec_life_countbased,
++                                                   &sa_p->ips_life.ipl_packets);
++                      
++                      if(sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
++                              len += ipsec_snprintf(buffer+len, length-len, " idle=%Ld",
++                                             jiffies / HZ - sa_p->ips_life.ipl_usetime.ipl_last);
++#else
++                              len += ipsec_snprintf(buffer+len, length-len, " idle=%lu",
++                                             jiffies / HZ - (unsigned long)sa_p->ips_life.ipl_usetime.ipl_last);
++#endif
++                      }
++
++#ifdef CONFIG_KLIPS_IPCOMP
++                      if(sa_p->ips_said.proto == IPPROTO_COMP &&
++                         (sa_p->ips_comp_ratio_dbytes ||
++                          sa_p->ips_comp_ratio_cbytes)) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
++                              len += ipsec_snprintf(buffer+len, length-len, " ratio=%Ld:%Ld",
++                                             sa_p->ips_comp_ratio_dbytes,
++                                             sa_p->ips_comp_ratio_cbytes);
++#else
++                              len += ipsec_snprintf(buffer+len, length-len, " ratio=%lu:%lu",
++                                             (unsigned long)sa_p->ips_comp_ratio_dbytes,
++                                             (unsigned long)sa_p->ips_comp_ratio_cbytes);
++#endif
++                      }
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++                      {
++                              char *natttype_name;
++
++                              switch(sa_p->ips_natt_type)
++                              {
++                              case 0:
++                                      natttype_name="none";
++                                      break;
++                              case ESPINUDP_WITH_NON_IKE:
++                                      natttype_name="nonike";
++                                      break;
++                              case ESPINUDP_WITH_NON_ESP:
++                                      natttype_name="nonesp";
++                                      break;
++                              default:
++                                      natttype_name = "unknown";
++                                      break;
++                              }
++
++                              len += ipsec_snprintf(buffer + len, length-len, " natencap=%s",
++                                             natttype_name);
++                              
++                              len += ipsec_snprintf(buffer + len, length-len, " natsport=%d",
++                                             sa_p->ips_natt_sport);
++                              
++                              len += ipsec_snprintf(buffer + len,length-len, " natdport=%d",
++                                             sa_p->ips_natt_dport);
++                      }
++#else
++                      len += ipsec_snprintf(buffer + len, length-len, " natencap=na");
++#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */
++                              
++                      len += ipsec_snprintf(buffer + len,length-len, " refcount=%d",
++                                     atomic_read(&sa_p->ips_refcount));
++
++                      len += ipsec_snprintf(buffer+len, length-len, " ref=%d",
++                                     sa_p->ips_ref);
++#ifdef CONFIG_KLIPS_DEBUG
++                      if(debug_xform) {
++                      len += ipsec_snprintf(buffer+len, length-len, " reftable=%lu refentry=%lu",
++                                     (unsigned long)IPsecSAref2table(sa_p->ips_ref),
++                                     (unsigned long)IPsecSAref2entry(sa_p->ips_ref));
++                      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++                      len += ipsec_snprintf(buffer+len, length-len, "\n");
++
++                        atomic_dec(&sa_p->ips_refcount);   
++                       
++                        if (len >= max_content) {
++                               /* we've done all that can fit -- stop loops */
++                               len = max_content;      /* truncate crap */
++                                goto done_spi_i;
++                        } else {
++                               const off_t pos = begin + len;  /* file position of end of what we've generated */
++
++                               if (pos <= offset) {
++                                       /* all is before first interesting character:
++                                        * discard, but note where we are.
++                                        */
++                                       len = 0;
++                                       begin = pos;
++                               }
++                        }
++                }
++        }
++
++done_spi_i:   
++      spin_unlock_bh(&tdb_lock);
++
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      return len - (offset - begin);
++}
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_spigrp_get_info(char *buffer,
++                    char **start,
++                    off_t offset,
++                    int length     IPSEC_PROC_LAST_ARG)
++{
++      /* Limit of useful snprintf output */
++      const int max_content = length > 0? length-1 : 0; 
++
++      int len = 0;
++      off_t begin = 0;
++      int i;
++      struct ipsec_sa *sa_p, *sa_p2;
++      char sa[SATOT_BUF];
++      size_t sa_len;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_spigrp_get_info: "
++                  "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
++                  buffer,
++                  *start,
++                  (int)offset,
++                  length);
++
++      spin_lock_bh(&tdb_lock);
++      
++      for (i = 0; i < SADB_HASHMOD; i++) {
++              for (sa_p = ipsec_sadb_hash[i];
++                   sa_p != NULL;
++                   sa_p = sa_p->ips_hnext)
++              {
++                      atomic_inc(&sa_p->ips_refcount);
++                      if(sa_p->ips_inext == NULL) {
++                              sa_p2 = sa_p;
++                              while(sa_p2 != NULL) {
++                                      atomic_inc(&sa_p2->ips_refcount);
++                                      sa_len = satot(&sa_p2->ips_said,
++                                                     'x', sa, sizeof(sa));
++                                      
++                                      len += ipsec_snprintf(buffer+len, length-len, "%s ",
++                                                     sa_len ? sa : " (error)");
++                                      atomic_dec(&sa_p2->ips_refcount);
++                                      sa_p2 = sa_p2->ips_onext;
++                              }
++                              len += ipsec_snprintf(buffer+len, length-len, "\n");
++                       }
++
++                       atomic_dec(&sa_p->ips_refcount);
++                                        
++                       if (len >= max_content) {
++                               /* we've done all that can fit -- stop loops */
++                               len = max_content;      /* truncate crap */
++                               goto done_spigrp_i;
++                       } else {
++                               const off_t pos = begin + len;
++
++                               if (pos <= offset) {
++                                       /* all is before first interesting character:
++                                        * discard, but note where we are.
++                                        */
++                                        len = 0;
++                                        begin = pos;
++                               }
++                       }
++              }
++      }
++
++done_spigrp_i:        
++      spin_unlock_bh(&tdb_lock);
++
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      return len - (offset - begin);
++}
++
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_tncfg_get_info(char *buffer,
++                   char **start,
++                   off_t offset,
++                   int length     IPSEC_PROC_LAST_ARG)
++{
++      /* limit of useful snprintf output */ 
++      const int max_content = length > 0? length-1 : 0;
++      int len = 0;
++      off_t begin = 0;
++      int i;
++      char name[9];
++      struct net_device *dev, *privdev;
++      struct ipsecpriv *priv;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_tncfg_get_info: "
++                  "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
++                  buffer,
++                  *start,
++                  (int)offset,
++                  length);
++
++      for(i = 0; i < IPSEC_NUM_IF; i++) {
++              ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i);
++              dev = __ipsec_dev_get(name);
++              if(dev) {
++                      priv = (struct ipsecpriv *)(dev->priv);
++                      len += ipsec_snprintf(buffer+len, length-len, "%s",
++                                     dev->name);
++                      if(priv) {
++                              privdev = (struct net_device *)(priv->dev);
++                              len += ipsec_snprintf(buffer+len, length-len, " -> %s",
++                                             privdev ? privdev->name : "NULL");
++                              len += ipsec_snprintf(buffer+len, length-len, " mtu=%d(%d) -> %d",
++                                             dev->mtu,
++                                             priv->mtu,
++                                             privdev ? privdev->mtu : 0);
++                      } else {
++                              KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                                          "klips_debug:ipsec_tncfg_get_info: device '%s' has no private data space!\n",
++                                          dev->name);
++                      }
++                      len += ipsec_snprintf(buffer+len, length-len, "\n");
++
++                        if (len >= max_content) {
++                                /* we've done all that can fit -- stop loop */
++                                len = max_content;      /* truncate crap */
++                                 break;
++                        } else {
++                                const off_t pos = begin + len;
++                                if (pos <= offset) {
++                                        len = 0;
++                                        begin = pos;
++                                }
++                      }
++              }
++      }
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      len -= (offset - begin);                        /* Start slop */
++      if (len > length)
++              len = length;
++      return len;
++}
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_version_get_info(char *buffer,
++                     char **start,
++                     off_t offset,
++                     int length  IPSEC_PROC_LAST_ARG)
++{
++      int len = 0;
++      off_t begin = 0;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_version_get_info: "
++                  "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
++                  buffer,
++                  *start,
++                  (int)offset,
++                  length);
++
++      len += ipsec_snprintf(buffer + len,length-len, "Openswan version: %s\n",
++                     ipsec_version_code());
++#if 0
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_version_get_info: "
++                  "ipsec_init version: %s\n",
++                  ipsec_init_c_version);
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_version_get_info: "
++                  "ipsec_tunnel version: %s\n",
++                  ipsec_tunnel_c_version);
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_version_get_info: "
++                  "ipsec_netlink version: %s\n",
++                  ipsec_netlink_c_version);
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_version_get_info: "
++                  "radij_c_version: %s\n",
++                  radij_c_version);
++#endif
++
++
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      len -= (offset - begin);                        /* Start slop */
++      if (len > length)
++              len = length;
++      return len;
++}
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++unsigned int natt_available = 1;
++#else
++unsigned int natt_available = 0;
++#endif
++module_param(natt_available, int, 0444);
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_natt_get_info(char *buffer,
++                    char **start,
++                    off_t offset,
++                    int length  IPSEC_PROC_LAST_ARG)
++{
++        int len = 0;
++        off_t begin = 0;
++
++        len += ipsec_snprintf(buffer + len,
++                              length-len, "%d\n",
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++                              1
++#else
++                              0
++#endif
++                );
++
++        *start = buffer + (offset - begin);     /* Start of wanted data */
++        len -= (offset - begin);                        /* Start slop */
++        if (len > length)
++                len = length;
++        return len;
++}
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_birth_info(char *page,
++               char **start,
++               off_t offset,
++               int count,
++               int *eof,
++               void *data)
++{
++      struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data;
++      int len;
++
++      if(offset >= ibr->packet_template_len) {
++              if(eof) {
++                      *eof=1;
++              }
++              return 0;
++      }
++
++      len = ibr->packet_template_len;
++      len -= offset;
++      if (len > count)
++              len = count;
++
++      memcpy(page + offset, ibr->packet_template+offset, len);
++
++      return len;
++}
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_birth_set(struct file *file, const char *buffer,
++              unsigned long count, void *data)
++{
++      struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data;
++      int len;
++
++      KLIPS_INC_USE;
++        if(count > IPSEC_BIRTH_TEMPLATE_MAXLEN) {
++                len = IPSEC_BIRTH_TEMPLATE_MAXLEN;
++      } else {
++                len = count;
++      }
++
++        if(copy_from_user(ibr->packet_template, buffer, len)) {
++                KLIPS_DEC_USE;
++                return -EFAULT;
++        }
++      ibr->packet_template_len = len;
++
++        KLIPS_DEC_USE;
++
++        return len;
++}
++
++
++#ifdef CONFIG_KLIPS_DEBUG
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_klipsdebug_get_info(char *buffer,
++                        char **start,
++                        off_t offset,
++                        int length      IPSEC_PROC_LAST_ARG)
++{
++      int len = 0;
++      off_t begin = 0;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
++                  "klips_debug:ipsec_klipsdebug_get_info: "
++                  "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
++                  buffer,
++                  *start,
++                  (int)offset,
++                  length);
++
++      len += ipsec_snprintf(buffer+len, length-len, "debug_tunnel=%08x.\n", debug_tunnel);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_xform=%08x.\n", debug_xform);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_eroute=%08x.\n", debug_eroute);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_spi=%08x.\n", debug_spi);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_radij=%08x.\n", debug_radij);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_esp=%08x.\n", debug_esp);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_ah=%08x.\n", debug_ah);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_rcv=%08x.\n", debug_rcv);
++      len += ipsec_snprintf(buffer+len, length-len, "debug_pfkey=%08x.\n", debug_pfkey);
++
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      len -= (offset - begin);                        /* Start slop */
++      if (len > length)
++              len = length;
++      return len;
++}
++#endif /* CONFIG_KLIPS_DEBUG */
++
++IPSEC_PROCFS_DEBUG_NO_STATIC
++int
++ipsec_stats_get_int_info(char *buffer,
++                       char **start,
++                       off_t offset,
++                       int   length,
++                       int   *eof,
++                       void  *data)
++{
++
++      const int max_content = length > 0? length-1 : 0;
++      int len = 0;
++      int *thing;
++
++      thing = (int *)data;
++      
++      len = ipsec_snprintf(buffer+len, length-len, "%08x\n", *thing);
++
++      if (len >= max_content)
++               len = max_content;      /* truncate crap */
++
++        *start = buffer + offset;       /* Start of wanted data */
++        return len > offset? len - offset : 0;
++
++}
++
++#ifndef PROC_FS_2325
++struct proc_dir_entry ipsec_eroute =
++{
++      0,
++      12, "ipsec_eroute",
++      S_IFREG | S_IRUGO, 1, 0, 0, 0,
++      &proc_net_inode_operations,
++      ipsec_eroute_get_info,
++      NULL, NULL, NULL, NULL, NULL
++};
++
++struct proc_dir_entry ipsec_spi =
++{
++      0,
++      9, "ipsec_spi",
++      S_IFREG | S_IRUGO, 1, 0, 0, 0,
++      &proc_net_inode_operations,
++      ipsec_spi_get_info,
++      NULL, NULL, NULL, NULL, NULL
++};
++
++struct proc_dir_entry ipsec_spigrp =
++{
++      0,
++      12, "ipsec_spigrp",
++      S_IFREG | S_IRUGO, 1, 0, 0, 0,
++      &proc_net_inode_operations,
++      ipsec_spigrp_get_info,
++      NULL, NULL, NULL, NULL, NULL
++};
++
++struct proc_dir_entry ipsec_tncfg =
++{
++      0,
++      11, "ipsec_tncfg",
++      S_IFREG | S_IRUGO, 1, 0, 0, 0,
++      &proc_net_inode_operations,
++      ipsec_tncfg_get_info,
++      NULL, NULL, NULL, NULL, NULL
++};
++
++struct proc_dir_entry ipsec_version =
++{
++      0,
++      13, "ipsec_version",
++      S_IFREG | S_IRUGO, 1, 0, 0, 0,
++      &proc_net_inode_operations,
++      ipsec_version_get_info,
++      NULL, NULL, NULL, NULL, NULL
++};
++
++#ifdef CONFIG_KLIPS_DEBUG
++struct proc_dir_entry ipsec_klipsdebug =
++{
++      0,
++      16, "ipsec_klipsdebug",
++      S_IFREG | S_IRUGO, 1, 0, 0, 0,
++      &proc_net_inode_operations,
++      ipsec_klipsdebug_get_info,
++      NULL, NULL, NULL, NULL, NULL
++};
++#endif /* CONFIG_KLIPS_DEBUG */
++#endif /* !PROC_FS_2325 */
++#endif /* CONFIG_PROC_FS */
++
++#if defined(PROC_FS_2325) 
++struct ipsec_proc_list {
++      char                   *name;
++      struct proc_dir_entry **parent;
++      struct proc_dir_entry **dir;
++      read_proc_t            *readthing;
++      write_proc_t           *writething;
++      void                   *data;
++};
++static struct ipsec_proc_list proc_items[]={
++#ifdef CONFIG_KLIPS_DEBUG
++      {"klipsdebug", &proc_net_ipsec_dir, NULL,             ipsec_klipsdebug_get_info, NULL, NULL},
++#endif
++      {"eroute",     &proc_net_ipsec_dir, &proc_eroute_dir, NULL, NULL, NULL},
++      {"all",        &proc_eroute_dir,    NULL,             ipsec_eroute_get_info,     NULL, NULL},
++      {"spi",        &proc_net_ipsec_dir, &proc_spi_dir,    NULL, NULL, NULL},
++      {"all",        &proc_spi_dir,       NULL,             ipsec_spi_get_info,        NULL, NULL},
++      {"spigrp",     &proc_net_ipsec_dir, &proc_spigrp_dir, NULL, NULL, NULL},
++      {"all",        &proc_spigrp_dir,    NULL,             ipsec_spigrp_get_info,     NULL, NULL},
++      {"birth",      &proc_net_ipsec_dir, &proc_birth_dir,  NULL,      NULL, NULL},
++      {"ipv4",       &proc_birth_dir,     NULL,             ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv4_birth_packet},
++      {"ipv6",       &proc_birth_dir,     NULL,             ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv6_birth_packet},
++      {"tncfg",      &proc_net_ipsec_dir, NULL,             ipsec_tncfg_get_info,      NULL, NULL},
++      {"xforms",     &proc_net_ipsec_dir, NULL,             ipsec_xform_get_info,      NULL, NULL},
++      {"stats",      &proc_net_ipsec_dir, &proc_stats_dir,  NULL,      NULL, NULL},
++      {"trap_count", &proc_stats_dir,     NULL,             ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_count},
++      {"trap_sendcount", &proc_stats_dir, NULL,             ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_sendcount},
++      {"version",    &proc_net_ipsec_dir, NULL,             ipsec_version_get_info,    NULL, NULL},
++      {NULL,         NULL,                NULL,             NULL,      NULL, NULL}
++};
++#endif
++              
++int
++ipsec_proc_init()
++{
++      int error = 0;
++#ifdef IPSEC_PROC_SUBDIRS
++      struct proc_dir_entry *item;
++#endif
++
++      /*
++       * just complain because pluto won't run without /proc!
++       */
++#ifndef CONFIG_PROC_FS 
++#error You must have PROC_FS built in to use KLIPS
++#endif
++
++        /* for 2.0 kernels */
++#if !defined(PROC_FS_2325) && !defined(PROC_FS_21)
++      error |= proc_register_dynamic(&proc_net, &ipsec_eroute);
++      error |= proc_register_dynamic(&proc_net, &ipsec_spi);
++      error |= proc_register_dynamic(&proc_net, &ipsec_spigrp);
++      error |= proc_register_dynamic(&proc_net, &ipsec_tncfg);
++      error |= proc_register_dynamic(&proc_net, &ipsec_version);
++#ifdef CONFIG_KLIPS_DEBUG
++      error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug);
++#endif /* CONFIG_KLIPS_DEBUG */
++#endif
++
++      /* for 2.2 kernels */
++#if !defined(PROC_FS_2325) && defined(PROC_FS_21)
++      error |= proc_register(proc_net, &ipsec_eroute);
++      error |= proc_register(proc_net, &ipsec_spi);
++      error |= proc_register(proc_net, &ipsec_spigrp);
++      error |= proc_register(proc_net, &ipsec_tncfg);
++      error |= proc_register(proc_net, &ipsec_version);
++#ifdef CONFIG_KLIPS_DEBUG
++      error |= proc_register(proc_net, &ipsec_klipsdebug);
++#endif /* CONFIG_KLIPS_DEBUG */
++#endif
++
++      /* for 2.4 kernels */
++#if defined(PROC_FS_2325)
++      /* create /proc/net/ipsec */
++
++      /* zero these out before we initialize /proc/net/ipsec/birth/stuff */
++      memset(&ipsec_ipv4_birth_packet, 0, sizeof(struct ipsec_birth_reply));
++      memset(&ipsec_ipv6_birth_packet, 0, sizeof(struct ipsec_birth_reply));
++
++      proc_net_ipsec_dir = proc_mkdir("ipsec", proc_net);
++      if(proc_net_ipsec_dir == NULL) {
++              /* no point in continuing */
++              return 1;
++      }       
++
++      {
++              struct ipsec_proc_list *it;
++
++              it=proc_items;
++              while(it->name!=NULL) {
++                      if(it->dir) {
++                              /* make a dir instead */
++                              item = proc_mkdir(it->name, *it->parent);
++                              *it->dir = item;
++                      } else {
++                              item = create_proc_entry(it->name, 0400, *it->parent);
++                      }
++                      if(item) {
++                              item->read_proc  = it->readthing;
++                              item->write_proc = it->writething;
++                              item->data       = it->data;
++#ifdef MODULE
++                              item->owner = THIS_MODULE;
++#endif
++                      } else {
++                              error |= 1;
++                      }
++                      it++;
++              }
++      }
++      
++      /* now create some symlinks to provide compatibility */
++      proc_symlink("ipsec_eroute", proc_net, "ipsec/eroute/all");
++      proc_symlink("ipsec_spi",    proc_net, "ipsec/spi/all");
++      proc_symlink("ipsec_spigrp", proc_net, "ipsec/spigrp/all");
++      proc_symlink("ipsec_tncfg",  proc_net, "ipsec/tncfg");
++      proc_symlink("ipsec_version",proc_net, "ipsec/version");
++      proc_symlink("ipsec_klipsdebug",proc_net,"ipsec/klipsdebug");
++
++#endif /* !PROC_FS_2325 */
++
++      return error;
++}
++
++void
++ipsec_proc_cleanup()
++{
++
++      /* for 2.0 and 2.2 kernels */
++#if !defined(PROC_FS_2325) 
++
++#ifdef CONFIG_KLIPS_DEBUG
++      if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0)
++              printk("klips_debug:ipsec_cleanup: "
++                     "cannot unregister /proc/net/ipsec_klipsdebug\n");
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      if (proc_net_unregister(ipsec_version.low_ino) != 0)
++              printk("klips_debug:ipsec_cleanup: "
++                     "cannot unregister /proc/net/ipsec_version\n");
++      if (proc_net_unregister(ipsec_eroute.low_ino) != 0)
++              printk("klips_debug:ipsec_cleanup: "
++                     "cannot unregister /proc/net/ipsec_eroute\n");
++      if (proc_net_unregister(ipsec_spi.low_ino) != 0)
++              printk("klips_debug:ipsec_cleanup: "
++                     "cannot unregister /proc/net/ipsec_spi\n");
++      if (proc_net_unregister(ipsec_spigrp.low_ino) != 0)
++              printk("klips_debug:ipsec_cleanup: "
++                     "cannot unregister /proc/net/ipsec_spigrp\n");
++      if (proc_net_unregister(ipsec_tncfg.low_ino) != 0)
++              printk("klips_debug:ipsec_cleanup: "
++                     "cannot unregister /proc/net/ipsec_tncfg\n");
++#endif
++
++      /* for 2.4 kernels */
++#if defined(PROC_FS_2325)
++      {
++              struct ipsec_proc_list *it;
++
++              /* find end of list */
++              it=proc_items;
++              while(it->name!=NULL) {
++                      it++;
++              }
++              it--;
++
++              do {
++                      remove_proc_entry(it->name, *it->parent);
++                      it--;
++              } while(it >= proc_items);
++      }
++
++
++#ifdef CONFIG_KLIPS_DEBUG
++      remove_proc_entry("ipsec_klipsdebug", proc_net);
++#endif /* CONFIG_KLIPS_DEBUG */
++      remove_proc_entry("ipsec_eroute",     proc_net);
++      remove_proc_entry("ipsec_spi",        proc_net);
++      remove_proc_entry("ipsec_spigrp",     proc_net);
++      remove_proc_entry("ipsec_tncfg",      proc_net);
++      remove_proc_entry("ipsec_version",    proc_net);
++      remove_proc_entry("ipsec",            proc_net);
++#endif /* 2.4 kernel */
++}
++
++/*
++ * $Log: ipsec_proc.c,v $
++ * Revision 1.39.2.4  2006/11/15 22:21:39  paul
++ * backport of creating a /sys/ file to test for nat-t capability in kernel.
++ *
++ * Revision 1.39.2.3  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.39.2.2  2006/02/13 18:48:12  paul
++ * Fix by  Ankit Desai <ankit@elitecore.com> for module unloading.
++ *
++ * Revision 1.39.2.1  2005/09/07 00:45:59  paul
++ * pull up of mcr's nat-t klips detection patch from head
++ *
++ * Revision 1.39  2005/05/20 03:19:18  mcr
++ *    modifications for use on 2.4.30 kernel, with backported
++ *    printk_ratelimit(). all warnings removed.
++ *
++ * Revision 1.38  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.37  2005/04/13 22:49:49  mcr
++ *    moved KLIPS specific snprintf() wrapper to seperate file.
++ *
++ * Revision 1.36  2005/04/06 17:44:36  mcr
++ *    when NAT-T is compiled out, show encap as "NA"
++ *
++ * Revision 1.35  2005/01/26 00:50:35  mcr
++ *    adjustment of confusion of CONFIG_IPSEC_NAT vs CONFIG_KLIPS_NAT,
++ *    and make sure that NAT_TRAVERSAL is set as well to match
++ *    userspace compiles of code.
++ *
++ * Revision 1.34  2004/12/03 21:25:57  mcr
++ *    compile time fixes for running on 2.6.
++ *    still experimental.
++ *
++ * Revision 1.33  2004/08/17 03:27:23  mcr
++ *    klips 2.6 edits.
++ *
++ * Revision 1.32  2004/08/03 18:19:08  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.31  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.30  2004/04/25 21:23:11  ken
++ * Pull in dhr's changes from FreeS/WAN 2.06
++ *
++ * Revision 1.29  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.28  2004/03/28 20:29:58  paul
++ *      <hugh_> ssize_t, not ssized_t
++ *
++ * Revision 1.27  2004/03/28 20:27:20  paul
++ * Included tested and confirmed fixes mcr made and dhr verified for
++ * snprint statements. Changed one other snprintf to use ipsec_snprintf
++ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with
++ * dhr. (thanks dhr!)
++ *
++ * Revision 1.26  2004/02/09 22:07:06  mcr
++ *    added information about nat-traversal setting to spi-output.
++ *
++ * Revision 1.25.4.1  2004/04/05 04:30:46  mcr
++ *    patches for alg-branch to compile/work with 2.x openswan
++ *
++ * Revision 1.25  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.24.4.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.24  2003/06/20 01:42:21  mcr
++ *    added counters to measure how many ACQUIREs we send to pluto,
++ *    and how many are successfully sent.
++ *
++ * Revision 1.23  2003/04/03 17:38:09  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ *
++ * Revision 1.22  2002/09/20 15:40:57  rgb
++ * Renamed saref macros for consistency and brevity.
++ *
++ * Revision 1.21  2002/09/20 05:01:35  rgb
++ * Print ref and  reftable, refentry seperately.
++ *
++ * Revision 1.20  2002/09/19 02:35:39  mcr
++ *    do not define structures needed by /proc/net/ipsec/ if we
++ *    aren't going create that directory.
++ *
++ * Revision 1.19  2002/09/10 01:43:25  mcr
++ *    fixed problem in /-* comment.
++ *
++ * Revision 1.18  2002/09/03 16:22:11  mcr
++ *    fixed initialization of birth/stuff values - some simple
++ *    screw ups in the code.
++ *    removed debugging that was left in by mistake.
++ *
++ * Revision 1.17  2002/09/02 17:54:53  mcr
++ *    changed how the table driven /proc entries are created so that
++ *    making subdirs is now explicit rather than implicit.
++ *
++ * Revision 1.16  2002/08/30 01:23:37  mcr
++ *    reorganized /proc creating code to clear up ifdefs,
++ *    make the 2.4 code table driven, and put things into
++ *    /proc/net/ipsec subdir. Symlinks are left for compatibility.
++ *
++ * Revision 1.15  2002/08/13 19:01:25  mcr
++ *    patches from kenb to permit compilation of FreeSWAN on ia64.
++ *    des library patched to use proper DES_LONG type for ia64.
++ *
++ * Revision 1.14  2002/07/26 08:48:31  rgb
++ * Added SA ref table code.
++ *
++ * Revision 1.13  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.12  2002/05/27 18:56:07  rgb
++ * Convert to dynamic ipsec device allocation.
++ *
++ * Revision 1.11  2002/05/23 07:14:50  rgb
++ * Added refcount code.
++ * Cleaned up %p variants to 0p%p for test suite cleanup.
++ * Convert "usecount" to "refcount" to remove ambiguity.
++ *
++ * Revision 1.10  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.9  2002/04/24 07:36:28  mcr
++ * Moved from ./klips/net/ipsec/ipsec_proc.c,v
++ *
++ * Revision 1.8  2002/01/29 17:17:55  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.7  2002/01/29 04:00:52  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.6  2002/01/29 02:13:17  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.5  2002/01/12 02:54:30  mcr
++ *    beginnings of /proc/net/ipsec dir.
++ *
++ * Revision 1.4  2001/12/11 02:21:05  rgb
++ * Don't include module version here, fixing 2.2 compile bug.
++ *
++ * Revision 1.3  2001/12/05 07:19:44  rgb
++ * Fixed extraneous #include "version.c" bug causing modular KLIPS failure.
++ *
++ * Revision 1.2  2001/11/26 09:16:14  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.74  2001/11/22 05:44:11  henry
++ * new version stuff
++ *
++ * Revision 1.1.2.1  2001/09/25 02:19:40  mcr
++ *    /proc manipulation code moved to new ipsec_proc.c
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_radij.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,889 @@
++/*
++ * Interface between the IPSEC code and the radix (radij) tree code
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_radij.c,v 1.73.2.1 2006/10/06 21:39:26 paul Exp $
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, struct net_device_stats and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++#include <openswan.h>
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* 23_SPINLOCK */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* 23_SPINLOCK */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++
++#include "openswan/ipsec_eroute.h"
++#include "openswan/ipsec_sa.h"
++ 
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_tunnel.h"    /* struct ipsecpriv */
++#include "openswan/ipsec_xform.h"
++ 
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_radij = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++struct radij_node_head *rnh = NULL;
++#ifdef SPINLOCK
++spinlock_t eroute_lock = SPIN_LOCK_UNLOCKED;
++#else /* SPINLOCK */
++spinlock_t eroute_lock;
++#endif /* SPINLOCK */
++
++int
++ipsec_radijinit(void)
++{
++      maj_keylen = sizeof (struct sockaddr_encap);
++
++      rj_init();
++      
++      if (rj_inithead((void **)&rnh, /*16*/offsetof(struct sockaddr_encap, sen_type) * sizeof(__u8)) == 0) /* 16 is bit offset of sen_type */
++              return -1;
++      return 0;
++}
++
++int
++ipsec_radijcleanup(void)
++{
++      int error;
++
++      spin_lock_bh(&eroute_lock);
++
++      error = radijcleanup();
++
++      spin_unlock_bh(&eroute_lock);
++
++      return error;
++}
++
++int
++ipsec_cleareroutes(void)
++{
++      int error;
++
++      spin_lock_bh(&eroute_lock);
++
++      error = radijcleartree();
++
++      spin_unlock_bh(&eroute_lock);
++
++      return error;
++}
++
++int
++ipsec_breakroute(struct sockaddr_encap *eaddr,
++               struct sockaddr_encap *emask,
++               struct sk_buff **first,
++               struct sk_buff **last)
++{
++      struct eroute *ro;
++      struct radij_node *rn;
++      int error;
++#ifdef CONFIG_KLIPS_DEBUG
++      
++      if (debug_eroute) {
++                char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF];
++              subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
++              subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
++              KLIPS_PRINT(debug_eroute,
++                          "klips_debug:ipsec_breakroute: "
++                          "attempting to delete eroute for %s:%d->%s:%d %d\n",
++                          buf1, ntohs(eaddr->sen_sport),
++                          buf2, ntohs(eaddr->sen_dport), eaddr->sen_proto);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      spin_lock_bh(&eroute_lock);
++
++      if ((error = rj_delete(eaddr, emask, rnh, &rn)) != 0) {
++              spin_unlock_bh(&eroute_lock);
++              KLIPS_PRINT(debug_eroute, 
++                          "klips_debug:ipsec_breakroute: "
++                          "node not found, eroute delete failed.\n");
++              return error;
++      }
++
++      spin_unlock_bh(&eroute_lock);
++      
++      ro = (struct eroute *)rn;
++      
++      KLIPS_PRINT(debug_eroute, 
++                  "klips_debug:ipsec_breakroute: "
++                  "deleted eroute=0p%p, ident=0p%p->0p%p, first=0p%p, last=0p%p\n",
++                  ro,
++                  ro->er_ident_s.data,
++                  ro->er_ident_d.data,
++                  ro->er_first,
++                  ro->er_last);
++      
++      if (ro->er_ident_s.data != NULL) {
++              kfree(ro->er_ident_s.data);
++      }
++      if (ro->er_ident_d.data != NULL) {
++              kfree(ro->er_ident_d.data);
++      }
++      if (ro->er_first != NULL) {
++#if 0
++              struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_first->dev->priv))->mystats);
++              stats->tx_dropped--;
++#endif
++              *first = ro->er_first;
++      }
++      if (ro->er_last != NULL) {
++#if 0
++              struct net_device_stats *stats = (struct net_device_stats *) &(((struct ipsecpriv *)(ro->er_last->dev->priv))->mystats);
++              stats->tx_dropped--;
++#endif
++              *last = ro->er_last;
++      }
++      
++      if (rn->rj_flags & (RJF_ACTIVE | RJF_ROOT))
++              panic ("ipsec_breakroute RMT_DELEROUTE root or active node\n");
++      memset((caddr_t)rn, 0, sizeof (struct eroute));
++      kfree(rn);
++      
++      return 0;
++}
++
++int
++ipsec_makeroute(struct sockaddr_encap *eaddr,
++              struct sockaddr_encap *emask,
++              ip_said said,
++              uint32_t pid,
++              struct sk_buff *skb,
++              struct ident *ident_s,
++              struct ident *ident_d)
++{
++      struct eroute *retrt;
++      int error;
++      char sa[SATOT_BUF];
++      size_t sa_len;
++
++#ifdef CONFIG_KLIPS_DEBUG
++      
++      if (debug_eroute) {
++
++              {
++                       char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF];
++
++                       subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
++                       subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
++                       sa_len = satot(&said, 0, sa, sizeof(sa));
++                       KLIPS_PRINT(debug_eroute,
++                                   "klips_debug:ipsec_makeroute: "
++                                   "attempting to allocate %lu bytes to insert eroute for %s->%s, SA: %s, PID:%d, skb=0p%p, ident:%s->%s\n",
++                                   (unsigned long) sizeof(struct eroute),
++                                   buf1,
++                                   buf2,
++                                   sa_len ? sa : " (error)",
++                                   pid,
++                                   skb,
++                                   (ident_s ? (ident_s->data ? ident_s->data : "NULL") : "NULL"),
++                                   (ident_d ? (ident_d->data ? ident_d->data : "NULL") : "NULL"));
++               }
++               {
++                       char buf1[sizeof(struct sockaddr_encap)*2 + 1],   
++                               buf2[sizeof(struct sockaddr_encap)*2 + 1];
++                       int i;
++                       unsigned char *b1 = buf1,
++                               *b2 = buf2,
++                               *ea = (unsigned char *)eaddr,
++                               *em = (unsigned char *)emask;
++                                   
++                                   
++                       for (i=0; i<sizeof(struct sockaddr_encap); i++) {
++                               sprintf(b1, "%02x", ea[i]);
++                               sprintf(b2, "%02x", em[i]);
++                               b1+=2;
++                               b2+=2;
++                       }
++                       KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_makeroute: %s / %s \n", buf1, buf2);
++                }
++
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      retrt = (struct eroute *)kmalloc(sizeof (struct eroute), GFP_ATOMIC);
++      if (retrt == NULL) {
++              printk("klips_error:ipsec_makeroute: "
++                     "not able to allocate kernel memory");
++              return -ENOMEM;
++      }
++      memset((caddr_t)retrt, 0, sizeof (struct eroute));
++
++      retrt->er_eaddr = *eaddr;
++      retrt->er_emask = *emask;
++      retrt->er_said = said;
++      retrt->er_pid = pid;
++      retrt->er_count = 0;
++      retrt->er_lasttime = jiffies/HZ;
++
++      {
++        /* this is because gcc 3. doesn't like cast's as lvalues */
++        struct rjtentry *rje = (struct rjtentry *)&(retrt->er_rjt);
++        caddr_t er = (caddr_t)&(retrt->er_eaddr);
++        
++        rje->rd_nodes->rj_key= er;
++      }
++      
++      if (ident_s && ident_s->type != SADB_IDENTTYPE_RESERVED) {
++              int data_len = ident_s->len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
++              
++              retrt->er_ident_s.type = ident_s->type;
++              retrt->er_ident_s.id = ident_s->id;
++              retrt->er_ident_s.len = ident_s->len;
++              if(data_len) {
++                      KLIPS_PRINT(debug_eroute, 
++                                  "klips_debug:ipsec_makeroute: "
++                                  "attempting to allocate %u bytes for ident_s.\n",
++                                  data_len);
++                      if(!(retrt->er_ident_s.data = kmalloc(data_len, GFP_KERNEL))) {
++                              kfree(retrt);
++                              printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len);
++                              return ENOMEM;
++                      }
++                      memcpy(retrt->er_ident_s.data, ident_s->data, data_len);
++              } else {
++                      retrt->er_ident_s.data = NULL;
++              }
++      }
++      
++      if (ident_d && ident_d->type != SADB_IDENTTYPE_RESERVED) {
++              int data_len = ident_d->len  * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
++              
++              retrt->er_ident_d.type = ident_d->type;
++              retrt->er_ident_d.id = ident_d->id;
++              retrt->er_ident_d.len = ident_d->len;
++              if(data_len) {
++                      KLIPS_PRINT(debug_eroute, 
++                                  "klips_debug:ipsec_makeroute: "
++                                  "attempting to allocate %u bytes for ident_d.\n",
++                                  data_len);
++                      if(!(retrt->er_ident_d.data = kmalloc(data_len, GFP_KERNEL))) {
++                              if (retrt->er_ident_s.data)
++                                      kfree(retrt->er_ident_s.data);
++                              kfree(retrt);
++                              printk("klips_error:ipsec_makeroute: not able to allocate kernel memory (%d)\n", data_len);
++                              return ENOMEM;
++                      }
++                      memcpy(retrt->er_ident_d.data, ident_d->data, data_len);
++              } else {
++                      retrt->er_ident_d.data = NULL;
++              }
++      }
++      retrt->er_first = skb;
++      retrt->er_last = NULL;
++      
++      KLIPS_PRINT(debug_eroute, 
++                  "klips_debug:ipsec_makeroute: "
++                  "calling rj_addroute now\n");
++
++      spin_lock_bh(&eroute_lock);
++      
++      error = rj_addroute(&(retrt->er_eaddr), &(retrt->er_emask), 
++                       rnh, retrt->er_rjt.rd_nodes);
++
++      spin_unlock_bh(&eroute_lock);
++      
++      if(error) {
++              sa_len = satot(&said, 0, sa, sizeof(sa));
++              KLIPS_PRINT(debug_eroute, 
++                          "klips_debug:ipsec_makeroute: "
++                          "rj_addroute not able to insert eroute for SA:%s (error:%d)\n",
++                          sa_len ? sa : " (error)", error);
++              if (retrt->er_ident_s.data)
++                      kfree(retrt->er_ident_s.data);
++              if (retrt->er_ident_d.data)
++                      kfree(retrt->er_ident_d.data);
++              
++              kfree(retrt);
++              
++              return error;
++      }
++
++#ifdef CONFIG_KLIPS_DEBUG
++      if (debug_eroute) {
++              char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF];
++/*
++              subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
++              subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
++*/
++              subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_src, rd_mask((&(retrt->er_rjt)))->sen_ip_src, 0, buf1, sizeof(buf1));
++              subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_dst, rd_mask((&(retrt->er_rjt)))->sen_ip_dst, 0, buf2, sizeof(buf2));
++              sa_len = satot(&retrt->er_said, 0, sa, sizeof(sa));
++              
++              KLIPS_PRINT(debug_eroute,
++                          "klips_debug:ipsec_makeroute: "
++                          "pid=%05d "
++                          "count=%10d "
++                          "lasttime=%6d "
++                          "%-18s -> %-18s => %s\n",
++                          retrt->er_pid,
++                          retrt->er_count,
++                          (int)(jiffies/HZ - retrt->er_lasttime),
++                          buf1,
++                          buf2,
++                          sa_len ? sa : " (error)");
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++      KLIPS_PRINT(debug_eroute,
++                  "klips_debug:ipsec_makeroute: "
++                  "succeeded.\n");
++      return 0;
++}
++
++struct eroute *
++ipsec_findroute(struct sockaddr_encap *eaddr)
++{
++      struct radij_node *rn;
++#ifdef CONFIG_KLIPS_DEBUG
++      char buf1[ADDRTOA_BUF], buf2[ADDRTOA_BUF];
++      
++      if (debug_radij & DB_RJ_FINDROUTE) {
++              addrtoa(eaddr->sen_ip_src, 0, buf1, sizeof(buf1));
++              addrtoa(eaddr->sen_ip_dst, 0, buf2, sizeof(buf2));
++              KLIPS_PRINT(debug_eroute,
++                          "klips_debug:ipsec_findroute: "
++                          "%s:%d->%s:%d %d\n",
++                          buf1, ntohs(eaddr->sen_sport),
++                          buf2, ntohs(eaddr->sen_dport),
++                          eaddr->sen_proto);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++      rn = rj_match((caddr_t)eaddr, rnh);
++      if(rn) {
++              KLIPS_PRINT(debug_eroute && sysctl_ipsec_debug_verbose,
++                          "klips_debug:ipsec_findroute: "
++                          "found, points to proto=%d, spi=%x, dst=%x.\n",
++                          ((struct eroute*)rn)->er_said.proto,
++                          ntohl(((struct eroute*)rn)->er_said.spi),
++                          ntohl(((struct eroute*)rn)->er_said.dst.u.v4.sin_addr.s_addr));
++      }
++      return (struct eroute *)rn;
++}
++              
++#ifdef CONFIG_PROC_FS
++/** ipsec_rj_walker_procprint: print one line of eroute table output.
++ *
++ * Theoretical BUG: if w->length is less than the length
++ * of some line we should produce, that line will never
++ * be finished.  In effect, the "file" will stop part way 
++ * through that line.
++ */
++int
++ipsec_rj_walker_procprint(struct radij_node *rn, void *w0)
++{
++      struct eroute *ro = (struct eroute *)rn;
++      struct rjtentry *rd = (struct rjtentry *)rn;
++      struct wsbuf *w = (struct wsbuf *)w0;
++      char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF];
++      char buf3[16];
++      char sa[SATOT_BUF];
++      size_t sa_len, buf_len;
++      struct sockaddr_encap *key, *mask;
++      
++      KLIPS_PRINT(debug_radij,
++                  "klips_debug:ipsec_rj_walker_procprint: "
++                  "rn=0p%p, w0=0p%p\n",
++                  rn,
++                  w0);
++      if (rn->rj_b >= 0) {
++              return 0;
++      }
++      
++      key = rd_key(rd);
++      mask = rd_mask(rd);
++
++      if (key == NULL || mask == NULL) {
++                return 0;
++        }
++
++      buf_len = subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1));
++      if(key->sen_sport != 0) {
++        sprintf(buf1+buf_len-1, ":%d", ntohs(key->sen_sport));
++      }
++
++      buf_len = subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2));
++      if(key->sen_dport != 0) {
++        sprintf(buf2+buf_len-1, ":%d", ntohs(key->sen_dport));
++      }
++
++      buf3[0]='\0';
++      if(key->sen_proto != 0) {
++        sprintf(buf3, ":%d", key->sen_proto);
++      }
++
++      sa_len = satot(&ro->er_said, 'x', sa, sizeof(sa));
++      w->len += ipsec_snprintf(w->buffer + w->len,
++                               w->length - w->len,
++                               "%-10d "
++                               "%-18s -> %-18s => %s%s\n",
++                               ro->er_count,
++                               buf1,
++                               buf2,
++                               sa_len ? sa : " (error)",
++                               buf3);
++      
++       {
++               /* snprintf can only fill the last character with NUL
++                * so the maximum useful character is w->length-1.
++                * However, if w->length == 0, we cannot go back.
++                * (w->length surely cannot be negative.)
++                */
++               int max_content = w->length > 0? w->length-1 : 0;
++
++               if (w->len >= max_content) {
++                       /* we've done all that can fit -- stop treewalking */
++                       w->len = max_content;   /* truncate crap */
++                       return -ENOBUFS;
++               } else {
++                       const off_t pos = w->begin + w->len;    /* file position of end of what we've generated */
++                
++                       if (pos <= w->offset) {
++                               /* all is before first interesting character:
++                                * discard, but note where we are.
++                                */
++                               w->len = 0;
++                               w->begin = pos;
++                       }
++                       return 0;
++               }
++        }        
++}
++#endif          /* CONFIG_PROC_FS */
++
++int
++ipsec_rj_walker_delete(struct radij_node *rn, void *w0)
++{
++      struct eroute *ro;
++      struct rjtentry *rd = (struct rjtentry *)rn;
++      struct radij_node *rn2;
++      int error;
++      struct sockaddr_encap *key, *mask;
++      
++      key = rd_key(rd);
++      mask = rd_mask(rd);
++      
++      if(!key || !mask) {
++              return -ENODATA;
++      }
++#ifdef CONFIG_KLIPS_DEBUG
++      if(debug_radij) {
++              char buf1[SUBNETTOA_BUF], buf2[SUBNETTOA_BUF];
++              subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1));
++              subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2));
++              KLIPS_PRINT(debug_radij, 
++                          "klips_debug:ipsec_rj_walker_delete: "
++                          "deleting: %s -> %s\n",
++                          buf1,
++                          buf2);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      if((error = rj_delete(key, mask, rnh, &rn2))) {
++              KLIPS_PRINT(debug_radij,
++                          "klips_debug:ipsec_rj_walker_delete: "
++                          "rj_delete failed with error=%d.\n", error);
++              return error;
++      }
++
++      if(rn2 != rn) {
++              printk("klips_debug:ipsec_rj_walker_delete: "
++                     "tried to delete a different node?!?  This should never happen!\n");
++      }
++ 
++      ro = (struct eroute *)rn;
++      
++      if (ro->er_ident_s.data)
++              kfree(ro->er_ident_s.data);
++      if (ro->er_ident_d.data)
++              kfree(ro->er_ident_d.data);
++      
++      memset((caddr_t)rn, 0, sizeof (struct eroute));
++      kfree(rn);
++      
++      return 0;
++}
++
++/*
++ * $Log: ipsec_radij.c,v $
++ * Revision 1.73.2.1  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.73  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.72  2004/12/03 21:25:57  mcr
++ *    compile time fixes for running on 2.6.
++ *    still experimental.
++ *
++ * Revision 1.71  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.70  2004/04/25 21:10:52  ken
++ * Pull in dhr's changes from FreeS/WAN 2.06
++ *
++ * Revision 1.69  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.68  2004/03/28 20:27:20  paul
++ * Included tested and confirmed fixes mcr made and dhr verified for
++ * snprint statements. Changed one other snprintf to use ipsec_snprintf
++ * so it wouldnt break compatibility with 2.0/2.2 kernels. Verified with
++ * dhr. (thanks dhr!)
++ *
++ * Revision 1.67.4.1  2004/04/05 04:30:46  mcr
++ *    patches for alg-branch to compile/work with 2.x openswan
++ *
++ * Revision 1.67  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.66.24.2  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.66.24.1  2003/09/21 13:59:56  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.66  2002/10/12 23:11:53  dhr
++ *
++ * [KenB + DHR] more 64-bit cleanup
++ *
++ * Revision 1.65  2002/09/20 05:01:40  rgb
++ * Added memory allocation debugging.
++ *
++ * Revision 1.64  2002/05/31 01:46:05  mcr
++ *    added && sysctl_ipsec_debug_verbose verbose to ipsec_findroute
++ *    as requested in PR#14.
++ *
++ * Revision 1.63  2002/05/23 07:14:11  rgb
++ * Cleaned up %p variants to 0p%p for test suite cleanup.
++ *
++ * Revision 1.62  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.61  2002/04/24 07:36:29  mcr
++ * Moved from ./klips/net/ipsec/ipsec_radij.c,v
++ *
++ * Revision 1.60  2002/02/19 23:59:45  rgb
++ * Removed redundant compiler directives.
++ *
++ * Revision 1.59  2002/02/06 04:13:47  mcr
++ *    missing #ifdef CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.58  2002/01/29 17:17:56  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.57  2002/01/29 04:00:52  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.56  2002/01/29 02:13:17  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.55  2001/11/26 09:23:48  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.53.2.1  2001/09/25 02:26:32  mcr
++ *    headers adjusted for new usage.
++ *
++ * Revision 1.54  2001/10/18 04:45:20  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.53  2001/09/19 17:19:40  rgb
++ * Debug output bugfix for NetCelo's PF_KEY ident patch.
++ *
++ * Revision 1.52  2001/09/19 16:33:37  rgb
++ * Temporarily disable ident fields to /proc/net/ipsec_eroute.
++ *
++ * Revision 1.51  2001/09/15 16:24:04  rgb
++ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
++ *
++ * Revision 1.50  2001/09/14 16:58:36  rgb
++ * Added support for storing the first and last packets through a HOLD.
++ *
++ * Revision 1.49  2001/09/08 21:13:32  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.48  2001/06/15 04:12:56  rgb
++ * Fixed kernel memory allocation error return code polarity bug.
++ *
++ * Revision 1.47  2001/06/14 19:35:09  rgb
++ * Update copyright date.
++ *
++ * Revision 1.46  2001/06/08 08:47:18  rgb
++ * Fixed for debug disabled.
++ *
++ * Revision 1.45  2001/05/27 06:12:11  rgb
++ * Added structures for pid, packet count and last access time to eroute.
++ * Added packet count to beginning of /proc/net/ipsec_eroute.
++ *
++ * Revision 1.44  2001/05/03 19:41:01  rgb
++ * Initialise error return variable.
++ * Use more appropriate return value for ipsec_rj_walker_delete().
++ *
++ * Revision 1.43  2001/02/27 22:24:54  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.42  2001/02/27 06:21:57  rgb
++ * Added findroute success instrumentation.
++ *
++ * Revision 1.41  2000/11/06 04:32:08  rgb
++ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
++ *
++ * Revision 1.40  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.39  2000/08/30 05:25:20  rgb
++ * Correct debug text in ipsec_breakroute() from incorrect
++ * "ipsec_callback".
++ *
++ * Revision 1.38  2000/07/28 14:58:31  rgb
++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
++ *
++ * Revision 1.37  2000/03/16 14:02:50  rgb
++ * Fixed debug scope to enable compilation with debug off.
++ *
++ * Revision 1.36  2000/01/21 06:14:46  rgb
++ * Added debugging text to ipsec_rj_walker_delete().
++ * Set return code to negative for consistency.
++ *
++ * Revision 1.35  1999/11/23 23:05:24  rgb
++ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
++ *
++ * Revision 1.34  1999/11/18 04:13:56  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
++ *
++ * Revision 1.33  1999/11/17 15:53:39  rgb
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ *
++ * Revision 1.32  1999/10/26 13:58:33  rgb
++ * Put spinlock flags variable declaration outside the debug compiler
++ * directive to enable compilation with debug shut off.
++ *
++ * Revision 1.31  1999/10/15 22:13:29  rgb
++ * Clean out cruft.
++ * Align /proc/net/ipsec_eroute output for easier readability.
++ * Fix double linefeed in radij debug output.
++ * Fix double locking bug that locks up 2.0.36 but not 2.0.38.
++ *
++ * Revision 1.30  1999/10/08 18:37:33  rgb
++ * Fix end-of-line spacing to sate whining PHMs.
++ *
++ * Revision 1.29  1999/10/03 18:52:45  rgb
++ * Spinlock support for 2.0.xx.
++ * Dumb return code spin_unlock fix.
++ *
++ * Revision 1.28  1999/10/01 16:22:24  rgb
++ * Switch from assignment init. to functional init. of spinlocks.
++ *
++ * Revision 1.27  1999/10/01 15:44:53  rgb
++ * Move spinlock header include to 2.1> scope.
++ *
++ * Revision 1.26  1999/10/01 00:01:23  rgb
++ * Added eroute structure locking.
++ *
++ * Revision 1.25  1999/06/10 16:07:30  rgb
++ * Silence delete eroute on no debug.
++ *
++ * Revision 1.24  1999/05/09 03:25:36  rgb
++ * Fix bug introduced by 2.2 quick-and-dirty patch.
++ *
++ * Revision 1.23  1999/05/05 22:02:31  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.22  1999/04/29 15:17:23  rgb
++ * Add return values to init and cleanup functions.
++ * Add sanity checking for null pointer arguments.
++ *
++ * Revision 1.21  1999/04/11 00:28:58  henry
++ * GPL boilerplate
++ *
++ * Revision 1.20  1999/04/06 04:54:26  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.19  1999/02/17 16:50:35  rgb
++ * Clean out unused cruft.
++ * Consolidate for space and speed efficiency.
++ * Convert DEBUG_IPSEC to KLIPS_PRINT
++ *
++ * Revision 1.18  1999/01/22 06:22:06  rgb
++ * Cruft clean-out.
++ * 64-bit clean-up.
++ *
++ * Revision 1.17  1998/12/02 03:09:39  rgb
++ * Clean up debug printing conditionals to compile with debugging off.
++ *
++ * Revision 1.16  1998/12/01 13:49:39  rgb
++ * Wrap version info printing in debug switches.
++ *
++ * Revision 1.15  1998/11/30 13:22:54  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.14  1998/10/31 06:48:17  rgb
++ * Fixed up comments in #endif directives.
++ *
++ * Revision 1.13  1998/10/27 13:48:09  rgb
++ * Cleaned up /proc/net/ipsec_* filesystem for easy parsing by scripts.
++ * Fixed less(1) truncated output bug.
++ * Code clean-up.
++ *
++ * Revision 1.12  1998/10/25 02:41:36  rgb
++ * Change return type on ipsec_breakroute and ipsec_makeroute and add an
++ * argument to be able to transmit more infomation about errors.
++ * Fix cut-and-paste debug statement identifier.
++ *
++ * Revision 1.11  1998/10/22 06:45:39  rgb
++ * Cleaned up cruft.
++ * Convert to use satoa for printk.
++ *
++ * Revision 1.10  1998/10/19 14:44:28  rgb
++ * Added inclusion of freeswan.h.
++ * sa_id structure implemented and used: now includes protocol.
++ *
++ * Revision 1.9  1998/10/09 04:30:52  rgb
++ * Added 'klips_debug' prefix to all klips printk debug statements.
++ * Deleted old commented out cruft.
++ *
++ * Revision 1.8  1998/08/06 17:24:23  rgb
++ * Fix addrtoa return code bug from stale manpage advice preventing packets
++ * from being erouted.
++ *
++ * Revision 1.7  1998/08/06 07:44:59  rgb
++ * Fixed /proc/net/ipsec_eroute subnettoa and addrtoa return value bug that
++ * ended up in nothing being printed.
++ *
++ * Revision 1.6  1998/08/05 22:16:41  rgb
++ * Cleanup to prevent cosmetic errors (ie. debug output) from being fatal.
++ *
++ * Revision 1.5  1998/07/29 20:38:44  rgb
++ * Debug and fix subnettoa and addrtoa output.
++ *
++ * Revision 1.4  1998/07/28 00:02:39  rgb
++ * Converting to exclusive use of addrtoa.
++ * Fix eroute delete.
++ *
++ * Revision 1.3  1998/07/14 18:21:26  rgb
++ * Add function to clear the eroute table.
++ *
++ * Revision 1.2  1998/06/23 02:59:14  rgb
++ * Added debugging output to eroute add/delete routines.
++ *
++ * Revision 1.9  1998/06/18 21:29:06  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid kernel
++ * build scripts happier in presence of symbolic links
++ *
++ * Revision 1.8  1998/06/05 02:32:26  rgb
++ * Fix spi ntoh kernel debug output.
++ *
++ * Revision 1.7  1998/05/25 20:30:37  rgb
++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
++ *
++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
++ * add ipsec_rj_walker_delete.
++ *
++ * Revision 1.6  1998/05/21 13:08:57  rgb
++ * Rewrote procinfo subroutines to avoid *bad things* when more that 3k of
++ * information is available for printout.
++ *
++ * Revision 1.5  1998/05/18 21:35:55  rgb
++ * Clean up output for numerical consistency and readability.  Zero freed
++ * eroute memory.
++ *
++ * Revision 1.4  1998/04/21 21:28:58  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.3  1998/04/14 17:30:39  rgb
++ * Fix up compiling errors for radij tree memory reclamation.
++ *
++ * Revision 1.2  1998/04/12 22:03:23  rgb
++ * Updated ESP-3DES-HMAC-MD5-96,
++ *    ESP-DES-HMAC-MD5-96,
++ *    AH-HMAC-MD5-96,
++ *    AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
++ *
++ * Fixed eroute references in /proc/net/ipsec*.
++ *
++ * Started to patch module unloading memory leaks in ipsec_netlink and
++ * radij tree unloading.
++ *
++ * Revision 1.1  1998/04/09 03:06:10  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:39:04  ji
++ * Minor cleanups.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_rcv.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,2317 @@
++/*
++ * receive code
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998-2003   Richard Guy Briggs.
++ * Copyright (C) 2004        Michael Richardson <mcr@xelerance.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_rcv_c_version[] = "RCSID $Id: ipsec_rcv.c,v 1.171.2.11 2007/04/28 20:46:40 paul Exp $";
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>  /* struct device, and other headers */
++#include <linux/etherdevice.h>        /* eth_type_trans */
++#include <linux/ip.h>         /* struct iphdr */
++
++#include <net/tcp.h>
++#include <net/udp.h>
++#include <linux/skbuff.h>
++#include <openswan.h>
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++
++#include "openswan/ipsec_kern24.h"
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h"
++
++#include "openswan/ipsec_auth.h"
++
++#include "openswan/ipsec_esp.h"
++
++#ifdef CONFIG_KLIPS_AH
++#include "openswan/ipsec_ah.h"
++#endif /* CONFIG_KLIPS_AH */
++
++#ifdef CONFIG_KLIPS_IPCOMP
++#include "openswan/ipsec_ipcomp.h"
++#endif /* CONFIG_KLIPS_COMP */
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_alg.h"
++#include "openswan/ipsec_kern24.h"
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_rcv = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++int sysctl_ipsec_inbound_policy_check = 1;
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++#include <linux/udp.h>
++#endif
++
++/* This is a private use protocol, and AT&T should be ashamed. They should have
++ * used protocol # 59, which is "no next header" instead of 0xFE.
++ */
++#ifndef IPPROTO_ATT_HEARTBEAT
++#define IPPROTO_ATT_HEARTBEAT 0xFE
++#endif
++
++/*
++ * Check-replay-window routine, adapted from the original
++ * by J. Hughes, from draft-ietf-ipsec-esp-des-md5-03.txt
++ *
++ *  This is a routine that implements a 64 packet window. This is intend-
++ *  ed on being an implementation sample.
++ */
++
++DEBUG_NO_STATIC int
++ipsec_checkreplaywindow(struct ipsec_sa*ipsp, __u32 seq)
++{
++      __u32 diff;
++
++      if (ipsp->ips_replaywin == 0)   /* replay shut off */
++              return 1;
++      if (seq == 0)
++              return 0;               /* first == 0 or wrapped */
++
++      /* new larger sequence number */
++      if (seq > ipsp->ips_replaywin_lastseq) {
++              return 1;               /* larger is good */
++      }
++      diff = ipsp->ips_replaywin_lastseq - seq;
++
++      /* too old or wrapped */ /* if wrapped, kill off SA? */
++      if (diff >= ipsp->ips_replaywin) {
++              return 0;
++      }
++      /* this packet already seen */
++      if (ipsp->ips_replaywin_bitmap & (1 << diff))
++              return 0;
++      return 1;                       /* out of order but good */
++}
++
++DEBUG_NO_STATIC int
++ipsec_updatereplaywindow(struct ipsec_sa*ipsp, __u32 seq)
++{
++      __u32 diff;
++
++      if (ipsp->ips_replaywin == 0)   /* replay shut off */
++              return 1;
++      if (seq == 0)
++              return 0;               /* first == 0 or wrapped */
++
++      /* new larger sequence number */
++      if (seq > ipsp->ips_replaywin_lastseq) {
++              diff = seq - ipsp->ips_replaywin_lastseq;
++
++              /* In win, set bit for this pkt */
++              if (diff < ipsp->ips_replaywin)
++                      ipsp->ips_replaywin_bitmap =
++                              (ipsp->ips_replaywin_bitmap << diff) | 1;
++              else
++                      /* This packet has way larger seq num */
++                      ipsp->ips_replaywin_bitmap = 1;
++
++              if(seq - ipsp->ips_replaywin_lastseq - 1 > ipsp->ips_replaywin_maxdiff) {
++                      ipsp->ips_replaywin_maxdiff = seq - ipsp->ips_replaywin_lastseq - 1;
++              }
++              ipsp->ips_replaywin_lastseq = seq;
++              return 1;               /* larger is good */
++      }
++      diff = ipsp->ips_replaywin_lastseq - seq;
++
++      /* too old or wrapped */ /* if wrapped, kill off SA? */
++      if (diff >= ipsp->ips_replaywin) {
++/*
++              if(seq < 0.25*max && ipsp->ips_replaywin_lastseq > 0.75*max) {
++                      ipsec_sa_delchain(ipsp);
++              }
++*/
++              return 0;
++      }
++      /* this packet already seen */
++      if (ipsp->ips_replaywin_bitmap & (1 << diff))
++              return 0;
++      ipsp->ips_replaywin_bitmap |= (1 << diff);      /* mark as seen */
++      return 1;                       /* out of order but good */
++}
++
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++struct auth_alg ipsec_rcv_md5[]={
++      {osMD5Init, osMD5Update, osMD5Final, AHMD596_ALEN}
++};
++
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++struct auth_alg ipsec_rcv_sha1[]={
++      {SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN}
++};
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++
++/*
++ * decapsulate a single layer of the system
++ *
++ * the following things should be setup to enter this function.
++ *
++ * irs->stats  == stats structure (or NULL)
++ * irs->ipp    = IP header.
++ * irs->len    = total length of packet
++ * skb->nh.iph = ipp;
++ * skb->h.raw  = start of payload
++ * irs->ipsp   = NULL.
++ * irs->iphlen = N/A = is recalculated.
++ * irs->ilen   = 0;
++ * irs->authlen = 0;
++ * irs->authfuncs = NULL;
++ * irs->skb    = the skb;
++ *
++ * proto_funcs should be from ipsec_esp.c, ipsec_ah.c or ipsec_ipcomp.c.
++ *
++ */
++enum ipsec_rcv_value
++ipsec_rcv_decap_once(struct ipsec_rcv_state *irs
++                   , struct xform_functions *proto_funcs)
++{
++      int iphlen;
++      __u8 proto;
++      struct in_addr ipsaddr;
++      struct in_addr ipdaddr;
++      int replay = 0; /* replay value in AH or ESP packet */
++      struct ipsec_sa* ipsnext = NULL;        /* next SA towards inside of packet */
++      struct ipsec_sa *newipsp;
++      struct iphdr *ipp;
++      struct sk_buff *skb;
++      struct ipsec_alg_auth *ixt_a=NULL;
++
++      skb = irs->skb;
++      irs->len = skb->len;
++      ipp = irs->ipp;
++      proto = ipp->protocol;
++      ipsaddr.s_addr = ipp->saddr;
++      addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt));
++      ipdaddr.s_addr = ipp->daddr;
++      addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt));
++
++      iphlen = ipp->ihl << 2;
++      irs->iphlen=iphlen;
++      ipp->check = 0;                 /* we know the sum is good */
++      
++      KLIPS_PRINT(debug_rcv,
++                  "klips_debug:ipsec_rcv_decap_once: "
++                  "decap (%d) from %s -> %s\n",
++                  proto, irs->ipsaddr_txt, irs->ipdaddr_txt);
++
++      /*
++       * Find tunnel control block and (indirectly) call the
++       * appropriate tranform routine. The resulting sk_buf
++       * is a valid IP packet ready to go through input processing.
++       */
++
++      irs->said.dst.u.v4.sin_addr.s_addr = ipp->daddr;
++      irs->said.dst.u.v4.sin_family = AF_INET;
++
++      /* note: rcv_checks set up the said.spi value, if appropriate */
++      if(proto_funcs->rcv_checks) {
++              enum ipsec_rcv_value retval =
++                (*proto_funcs->rcv_checks)(irs, skb);
++
++              if(retval < 0) {
++                      return retval;
++              }
++      }
++
++      irs->said.proto = proto;
++      irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa));
++      if(irs->sa_len == 0) {
++              strcpy(irs->sa, "(error)");
++      }
++
++      newipsp = ipsec_sa_getbyid(&irs->said);
++      if (newipsp == NULL) {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "no ipsec_sa for SA:%s: incoming packet with no SA dropped\n",
++                          irs->sa_len ? irs->sa : " (error)");
++              if(irs->stats) {
++                      irs->stats->rx_dropped++;
++              }
++              return IPSEC_RCV_SAIDNOTFOUND;
++      }
++
++      /* MCR - XXX this is bizarre. ipsec_sa_getbyid returned it, having
++       * incremented the refcount, why in the world would we decrement it
++       * here? */
++      /* ipsec_sa_put(irs->ipsp);*/ /* incomplete */
++
++      /* If it is in larval state, drop the packet, we cannot process yet. */
++      if(newipsp->ips_state == SADB_SASTATE_LARVAL) {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "ipsec_sa in larval state, cannot be used yet, dropping packet.\n");
++              if(irs->stats) {
++                      irs->stats->rx_dropped++;
++              }
++              ipsec_sa_put(newipsp);
++              return IPSEC_RCV_SAIDNOTLIVE;
++      }
++
++      if(newipsp->ips_state == SADB_SASTATE_DEAD) {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "ipsec_sa in dead state, cannot be used any more, dropping packet.\n");
++              if(irs->stats) {
++                      irs->stats->rx_dropped++;
++              }
++              ipsec_sa_put(newipsp);
++              return IPSEC_RCV_SAIDNOTLIVE;
++      }
++
++      if(sysctl_ipsec_inbound_policy_check) {
++              if(irs->ipp->saddr != ((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr) {
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n",
++                                  irs->sa_len ? irs->sa : " (error)",
++                                  irs->ipsaddr_txt);
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      ipsec_sa_put(newipsp);
++                      return IPSEC_RCV_FAILEDINBOUND;
++              }
++
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n",
++                          irs->sa_len ? irs->sa : " (error)",
++                          irs->ipsaddr_txt);
++
++              /*
++               * at this point, we have looked up a new SA, and we want to make sure that if this
++               * isn't the first SA in the list, that the previous SA actually points at this one.
++               */
++              if(irs->ipsp) {
++                      if(irs->ipsp->ips_inext != newipsp) {
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          "unexpected SA:%s: does not agree with ips->inext policy, dropped\n",
++                                          irs->sa_len ? irs->sa : " (error)");
++                              if(irs->stats) {
++                                      irs->stats->rx_dropped++;
++                              }
++                              ipsec_sa_put(newipsp);
++                              return IPSEC_RCV_FAILEDINBOUND;
++                      }
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "SA:%s grouping from previous SA is OK.\n",
++                                  irs->sa_len ? irs->sa : " (error)");
++              } else {
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "SA:%s First SA in group.\n",
++                                  irs->sa_len ? irs->sa : " (error)");
++              }
++
++
++
++
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++              if (proto == IPPROTO_ESP) {
++                      KLIPS_PRINT(debug_rcv,
++                              "klips_debug:ipsec_rcv: "
++                              "natt_type=%u tdbp->ips_natt_type=%u : %s\n",
++                              irs->natt_type, newipsp->ips_natt_type,
++                              (irs->natt_type==newipsp->ips_natt_type)?"ok":"bad");
++                      if (irs->natt_type != newipsp->ips_natt_type) {
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          "SA:%s does not agree with expected NAT-T policy.\n",
++                                          irs->sa_len ? irs->sa : " (error)");
++                              if(irs->stats) {
++                                      irs->stats->rx_dropped++;
++                              }
++                              ipsec_sa_put(newipsp);
++                              return IPSEC_RCV_FAILEDINBOUND;
++                      }
++              }
++#endif                 
++      }
++
++      /* okay, SA checks out, so free any previous SA, and record a new one*/
++
++      if(irs->ipsp) {
++              ipsec_sa_put(irs->ipsp);
++      }
++      irs->ipsp=newipsp;
++
++      /* note that the outer code will free the irs->ipsp
++         if there is an error */
++
++
++      /* now check the lifetimes */
++      if(ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_bytes,   "bytes",
++                              irs->sa, ipsec_life_countbased, ipsec_incoming,
++                              irs->ipsp) == ipsec_life_harddied ||
++         ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "addtime",
++                              irs->sa, ipsec_life_timebased,  ipsec_incoming,
++                              irs->ipsp) == ipsec_life_harddied ||
++         ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "usetime",
++                              irs->sa, ipsec_life_timebased,  ipsec_incoming,
++                              irs->ipsp) == ipsec_life_harddied ||
++         ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_packets, "packets",
++                              irs->sa, ipsec_life_countbased, ipsec_incoming,
++                              irs->ipsp) == ipsec_life_harddied) {
++              ipsec_sa_delchain(irs->ipsp);
++              if(irs->stats) {
++                      irs->stats->rx_dropped++;
++              }
++              
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv_decap_once: "
++                          "decap (%d) failed lifetime check\n",
++                          proto);
++
++              return IPSEC_RCV_LIFETIMEFAILED;
++      }
++
++#if 0
++      /*
++       * This is removed for some reasons:
++       *   1) it needs to happen *after* authentication.
++       *   2) do we really care, if it authenticates, if it came
++       *      from the wrong location?
++         *   3) the NAT_KA messages in IKE will also get to pluto
++       *      and it will figure out that stuff has moved.
++       *   4) the 2.6 udp-esp encap function does not pass us
++       *      the originating port number, and I can't tell
++       *      if skb->sk is guaranteed to be valid here.
++       *  2005-04-16: mcr@xelerance.com
++       */
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      /*
++       *
++       * XXX we should ONLY update pluto if the SA passes all checks,
++       *     which we clearly do not now.
++       */
++      if ((irs->natt_type) &&
++              ( (irs->ipp->saddr != (((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr)) ||
++                (irs->natt_sport != newipsp->ips_natt_sport)
++              )) {
++              struct sockaddr sipaddr;
++              struct sockaddr_in *psin = (struct sockaddr_in*)(newipsp->ips_addr_s);
++
++              /** Advertise NAT-T addr change to pluto **/
++              sipaddr.sa_family = AF_INET;
++              ((struct sockaddr_in*)&sipaddr)->sin_addr.s_addr = irs->ipp->saddr;
++              ((struct sockaddr_in*)&sipaddr)->sin_port = htons(irs->natt_sport);
++              pfkey_nat_t_new_mapping(newipsp, &sipaddr, irs->natt_sport);
++
++              /**
++               * Then allow or block packet depending on
++               * sysctl_ipsec_inbound_policy_check.
++               *
++               * In all cases, pluto will update SA if new mapping is
++               * accepted.
++               */
++              if (sysctl_ipsec_inbound_policy_check) {
++                      KLIPS_PRINT(debug_rcv,
++                              "klips_debug:ipsec_rcv: "
++                              "SA:%s, src=%s:%u of pkt does not agree with expected "
++                              "SA source address [%08x:%u] (notifying pluto of change).\n",
++                              irs->sa_len ? irs->sa : " (error)",
++                                  irs->ipsaddr_txt, irs->natt_sport,
++                                  psin->sin_addr.s_addr,
++                                  newipsp->ips_natt_sport);
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      ipsec_sa_put(newipsp);
++                      return IPSEC_RCV_FAILEDINBOUND;
++              }
++      }
++#endif
++#endif
++
++      irs->authfuncs=NULL;
++
++      /* authenticate, if required */
++      if ((ixt_a=irs->ipsp->ips_alg_auth)) {
++              irs->authlen = AHHMAC_HASHLEN;
++              irs->authfuncs = NULL;
++              irs->ictx = NULL;
++              irs->octx = NULL;
++              irs->ictx_len = 0;
++              irs->octx_len = 0;
++              KLIPS_PRINT(debug_rcv,
++                              "klips_debug:ipsec_rcv: "
++                              "authalg=%d authlen=%d\n",
++                              irs->ipsp->ips_authalg, 
++                              irs->authlen);
++      } else
++      switch(irs->ipsp->ips_authalg) {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++      case AH_MD5:
++              irs->authlen = AHHMAC_HASHLEN;
++              irs->authfuncs = ipsec_rcv_md5;
++              irs->ictx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx;
++              irs->octx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx;
++              irs->ictx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx);
++              irs->octx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx);
++              break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++      case AH_SHA:
++              irs->authlen = AHHMAC_HASHLEN;
++              irs->authfuncs = ipsec_rcv_sha1;
++              irs->ictx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx;
++              irs->octx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx;
++              irs->ictx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx);
++              irs->octx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx);
++              break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++      case AH_NONE:
++              irs->authlen = 0;
++              irs->authfuncs = NULL;
++              irs->ictx = NULL;
++              irs->octx = NULL;
++              irs->ictx_len = 0;
++              irs->octx_len = 0;
++              break;
++      default:
++              irs->ipsp->ips_errs.ips_alg_errs += 1;
++              if(irs->stats) {
++                      irs->stats->rx_errors++;
++              }
++              return IPSEC_RCV_BADAUTH;
++      }
++
++      /* ilen counts number of bytes in ESP portion */
++      irs->ilen = ((skb->data + skb->len) - skb->h.raw) - irs->authlen;
++      if(irs->ilen <= 0) {
++        KLIPS_PRINT(debug_rcv,
++                    "klips_debug:ipsec_rcv: "
++                    "runt %s packet with no data, dropping.\n",
++                    (proto == IPPROTO_ESP ? "esp" : "ah"));
++        if(irs->stats) {
++          irs->stats->rx_dropped++;
++        }
++        return IPSEC_RCV_BADLEN;
++      }
++
++      if(irs->authfuncs || ixt_a) {
++              unsigned char *authenticator = NULL;
++
++              if(proto_funcs->rcv_setup_auth) {
++                      enum ipsec_rcv_value retval
++                          = (*proto_funcs->rcv_setup_auth)(irs, skb,
++                                                       &replay,
++                                                       &authenticator);
++                      if(retval < 0) {
++                              return retval;
++                      }
++              }
++
++              if(!authenticator) {
++                      irs->ipsp->ips_errs.ips_auth_errs += 1;
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      return IPSEC_RCV_BADAUTH;
++              }
++
++              if(!ipsec_checkreplaywindow(irs->ipsp, replay)) {
++                      irs->ipsp->ips_errs.ips_replaywin_errs += 1;
++                      KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,
++                                  "klips_debug:ipsec_rcv: "
++                                  "duplicate frame from %s, packet dropped\n",
++                                  irs->ipsaddr_txt);
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      return IPSEC_RCV_REPLAYFAILED;
++              }
++
++              /*
++               * verify authenticator
++               */
++
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "encalg = %d, authalg = %d.\n",
++                          irs->ipsp->ips_encalg,
++                          irs->ipsp->ips_authalg);
++
++              /* calculate authenticator */
++              if(proto_funcs->rcv_calc_auth == NULL) {
++                      return IPSEC_RCV_BADAUTH;
++              }
++              (*proto_funcs->rcv_calc_auth)(irs, skb);
++
++              if (memcmp(irs->hash, authenticator, irs->authlen)) {
++                      irs->ipsp->ips_errs.ips_auth_errs += 1;
++                      KLIPS_PRINT(debug_rcv & DB_RX_INAU,
++                                  "klips_debug:ipsec_rcv: "
++                                  "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n",
++                                  irs->ipsaddr_txt,
++                                  ntohl(*(__u32*)&irs->hash[0]),
++                                  ntohl(*(__u32*)&irs->hash[4]),
++                                  ntohl(*(__u32*)&irs->hash[8]),
++                                  ntohl(*(__u32*)authenticator),
++                                  ntohl(*((__u32*)authenticator + 1)),
++                                  ntohl(*((__u32*)authenticator + 2)));
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      return IPSEC_RCV_AUTHFAILED;
++              } else {
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "authentication successful.\n");
++              }
++
++              /* Crypto hygiene: clear memory used to calculate autheticator.
++               * The length varies with the algorithm.
++               */
++              memset(irs->hash, 0, irs->authlen);
++
++              /* If the sequence number == 0, expire SA, it had rolled */
++              if(irs->ipsp->ips_replaywin && !replay /* !irs->ipsp->ips_replaywin_lastseq */) {
++                      ipsec_sa_delchain(irs->ipsp);
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "replay window counter rolled, expiring SA.\n");
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      return IPSEC_RCV_REPLAYROLLED;
++              }
++
++              /* now update the replay counter */
++              if (!ipsec_updatereplaywindow(irs->ipsp, replay)) {
++                      irs->ipsp->ips_errs.ips_replaywin_errs += 1;
++                      KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,
++                                  "klips_debug:ipsec_rcv: "
++                                  "duplicate frame from %s, packet dropped\n",
++                                  irs->ipsaddr_txt);
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      return IPSEC_RCV_REPLAYROLLED;
++              }
++      }
++
++      if(proto_funcs->rcv_decrypt) {
++              enum ipsec_rcv_value retval =
++                (*proto_funcs->rcv_decrypt)(irs);
++
++              if(retval != IPSEC_RCV_OK) {
++                      return retval;
++              }
++      }
++
++      /*
++       *      Adjust pointers
++       */
++      skb = irs->skb;
++      irs->len = skb->len;
++      ipp = irs->ipp = skb->nh.iph;
++      iphlen = ipp->ihl<<2;
++      skb->h.raw = skb->nh.raw + iphlen;
++      
++      /* zero any options that there might be */
++      memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
++
++      ipsaddr.s_addr = ipp->saddr;
++      addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt));
++      ipdaddr.s_addr = ipp->daddr;
++      addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt));
++
++      /*
++       *      Discard the original ESP/AH header
++       */
++      ipp->protocol = irs->next_header;
++
++      ipp->check = 0; /* NOTE: this will be included in checksum */
++      ipp->check = ip_fast_csum((unsigned char *)skb->nh.iph, iphlen >> 2);
++
++      KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                  "klips_debug:ipsec_rcv: "
++                  "after <%s%s%s>, SA:%s:\n",
++                  IPS_XFORM_NAME(irs->ipsp),
++                  irs->sa_len ? irs->sa : " (error)");
++      KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);
++
++      skb->protocol = htons(ETH_P_IP);
++      skb->ip_summed = 0;
++
++      ipsnext = irs->ipsp->ips_inext;
++      if(sysctl_ipsec_inbound_policy_check) {
++              if(ipsnext) {
++                      if(
++                              ipp->protocol != IPPROTO_AH
++                              && ipp->protocol != IPPROTO_ESP
++#ifdef CONFIG_KLIPS_IPCOMP
++                              && ipp->protocol != IPPROTO_COMP
++                              && (ipsnext->ips_said.proto != IPPROTO_COMP
++                                  || ipsnext->ips_inext)
++#endif /* CONFIG_KLIPS_IPCOMP */
++                              && ipp->protocol != IPPROTO_IPIP
++                              && ipp->protocol != IPPROTO_ATT_HEARTBEAT  /* heartbeats to AT&T SIG/GIG */
++                              ) {
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          "packet with incomplete policy dropped, last successful SA:%s.\n",
++                                          irs->sa_len ? irs->sa : " (error)");
++                              if(irs->stats) {
++                                      irs->stats->rx_dropped++;
++                              }
++                              return IPSEC_RCV_FAILEDINBOUND;
++                      }
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "SA:%s, Another IPSEC header to process.\n",
++                                  irs->sa_len ? irs->sa : " (error)");
++              } else {
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "No ips_inext from this SA:%s.\n",
++                                  irs->sa_len ? irs->sa : " (error)");
++              }
++      }
++
++#ifdef CONFIG_KLIPS_IPCOMP
++      /* update ipcomp ratio counters, even if no ipcomp packet is present */
++      if (ipsnext
++          && ipsnext->ips_said.proto == IPPROTO_COMP
++          && ipp->protocol != IPPROTO_COMP) {
++              ipsnext->ips_comp_ratio_cbytes += ntohs(ipp->tot_len);
++              ipsnext->ips_comp_ratio_dbytes += ntohs(ipp->tot_len);
++      }
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++      irs->ipsp->ips_life.ipl_bytes.ipl_count += irs->len;
++      irs->ipsp->ips_life.ipl_bytes.ipl_last   = irs->len;
++
++      if(!irs->ipsp->ips_life.ipl_usetime.ipl_count) {
++              irs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;
++      }
++      irs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;
++      irs->ipsp->ips_life.ipl_packets.ipl_count += 1;
++
++#ifdef CONFIG_NETFILTER
++      if(proto == IPPROTO_ESP || proto == IPPROTO_AH) {
++              skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_MASK))))
++                      | IPsecSAref2NFmark(IPsecSA2SAref(irs->ipsp));
++              KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                          "klips_debug:ipsec_rcv: "
++                          "%s SA sets skb->nfmark=0x%x.\n",
++                          proto == IPPROTO_ESP ? "ESP" : "AH",
++                          (unsigned)skb->nfmark);
++      }
++#endif /* CONFIG_NETFILTER */
++
++      return IPSEC_RCV_OK;
++}
++
++
++/*
++ * core decapsulation loop for all protocols.
++ *
++ * the following things should be setup to enter this function.
++ *
++ * irs->stats  == stats structure (or NULL)
++ * irs->ipp    = IP header.
++ * irs->ipsp   = NULL.
++ * irs->ilen   = 0;
++ * irs->authlen = 0;
++ * irs->authfuncs = NULL;
++ * irs->skb    = skb;
++ * skb->nh.iph = ipp;
++ * skb->h.raw  = start of payload
++ *
++ */
++int ipsec_rcv_decap(struct ipsec_rcv_state *irs)
++{
++      struct ipsec_sa *ipsp = NULL;
++      struct ipsec_sa* ipsnext = NULL;
++      struct in_addr ipsaddr;
++      struct in_addr ipdaddr;
++      struct iphdr *ipp;
++      struct sk_buff *skb = NULL;
++
++      /* begin decapsulating loop here */
++
++      /*
++        The spinlock is to prevent any other process from
++        accessing or deleting the ipsec_sa hash table or any of the
++        ipsec_sa s while we are using and updating them.
++
++        This is not optimal, but was relatively straightforward
++        at the time.  A better way to do it has been planned for
++        more than a year, to lock the hash table and put reference
++        counts on each ipsec_sa instead.  This is not likely to happen
++        in KLIPS1 unless a volunteer contributes it, but will be
++        designed into KLIPS2.
++      */
++      spin_lock(&tdb_lock);
++
++      do {
++              int decap_stat;
++              struct xform_functions *proto_funcs;
++
++              switch(irs->ipp->protocol) {
++              case IPPROTO_ESP:
++                proto_funcs = esp_xform_funcs;
++                break;
++                
++#ifdef CONFIG_KLIPS_AH
++              case IPPROTO_AH:
++                proto_funcs = ah_xform_funcs;
++                break;
++#endif /* !CONFIG_KLIPS_AH */
++                
++#ifdef CONFIG_KLIPS_IPCOMP
++              case IPPROTO_COMP:
++                proto_funcs = ipcomp_xform_funcs;
++                break;
++#endif /* !CONFIG_KLIPS_IPCOMP */
++              default:
++                if(irs->stats) {
++                  irs->stats->rx_errors++;
++                }
++                decap_stat = IPSEC_RCV_BADPROTO;
++                goto rcvleave;
++              }
++
++              decap_stat = ipsec_rcv_decap_once(irs, proto_funcs);
++
++              if(decap_stat != IPSEC_RCV_OK) {
++                      spin_unlock(&tdb_lock);
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: decap_once failed: %d\n",
++                                  decap_stat);
++              
++                      goto rcvleave;
++              }
++      /* end decapsulation loop here */
++      } while(   (irs->ipp->protocol == IPPROTO_ESP )
++              || (irs->ipp->protocol == IPPROTO_AH  )
++#ifdef CONFIG_KLIPS_IPCOMP
++              || (irs->ipp->protocol == IPPROTO_COMP)
++#endif /* CONFIG_KLIPS_IPCOMP */
++              );
++
++      /* set up for decap loop */
++      ipp  =irs->ipp;
++      ipsp =irs->ipsp;
++      ipsnext = ipsp->ips_inext;
++      skb = irs->skb;
++
++      /* if there is an IPCOMP, but we don't have an IPPROTO_COMP,
++       * then we can just skip it
++       */
++#ifdef CONFIG_KLIPS_IPCOMP
++      if(ipsnext && ipsnext->ips_said.proto == IPPROTO_COMP) {
++              ipsp = ipsnext;
++              ipsnext = ipsp->ips_inext;
++      }
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      if ((irs->natt_type) && (ipp->protocol != IPPROTO_IPIP)) {
++        /**
++         * NAT-Traversal and Transport Mode:
++         *   we need to correct TCP/UDP checksum
++         *
++         * If we've got NAT-OA, we can fix checksum without recalculation.
++         */
++        __u32 natt_oa = ipsp->ips_natt_oa ?
++          ((struct sockaddr_in*)(ipsp->ips_natt_oa))->sin_addr.s_addr : 0;
++        __u16 pkt_len = skb->tail - (unsigned char *)ipp;
++        __u16 data_len = pkt_len - (ipp->ihl << 2);
++        
++        switch (ipp->protocol) {
++        case IPPROTO_TCP:
++          if (data_len >= sizeof(struct tcphdr)) {
++            struct tcphdr *tcp = skb->h.th;
++            if (natt_oa) {
++              __u32 buff[2] = { ~natt_oa, ipp->saddr };
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NAT-T & TRANSPORT: "
++                          "fix TCP checksum using NAT-OA\n");
++              tcp->check = csum_fold(
++                                     csum_partial((unsigned char *)buff, sizeof(buff),
++                                                  tcp->check^0xffff));
++            }
++            else {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NAT-T & TRANSPORT: recalc TCP checksum\n");
++              if (pkt_len > (ntohs(ipp->tot_len)))
++                data_len -= (pkt_len - ntohs(ipp->tot_len));
++              tcp->check = 0;
++              tcp->check = csum_tcpudp_magic(ipp->saddr, ipp->daddr,
++                                             data_len, IPPROTO_TCP,
++                                             csum_partial((unsigned char *)tcp, data_len, 0));
++            }
++          }
++          else {
++            KLIPS_PRINT(debug_rcv,
++                        "klips_debug:ipsec_rcv: "
++                        "NAT-T & TRANSPORT: can't fix TCP checksum\n");
++          }
++          break;
++        case IPPROTO_UDP:
++          if (data_len >= sizeof(struct udphdr)) {
++            struct udphdr *udp = skb->h.uh;
++            if (udp->check == 0) {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NAT-T & TRANSPORT: UDP checksum already 0\n");
++            }
++            else if (natt_oa) {
++              __u32 buff[2] = { ~natt_oa, ipp->saddr };
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NAT-T & TRANSPORT: "
++                          "fix UDP checksum using NAT-OA\n");
++#ifdef DISABLE_UDP_CHECKSUM
++              udp->check=0
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NAT-T & TRANSPORT: "
++                          "UDP checksum using NAT-OA disabled at compile time\n");
++#else
++              udp->check = csum_fold(
++                                     csum_partial((unsigned char *)buff, sizeof(buff),
++                                                  udp->check^0xffff));
++#endif
++            }
++            else {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NAT-T & TRANSPORT: zero UDP checksum\n");
++              udp->check = 0;
++            }
++          }
++          else {
++            KLIPS_PRINT(debug_rcv,
++                        "klips_debug:ipsec_rcv: "
++                        "NAT-T & TRANSPORT: can't fix UDP checksum\n");
++          }
++          break;
++        default:
++          KLIPS_PRINT(debug_rcv,
++                      "klips_debug:ipsec_rcv: "
++                      "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n");
++          break;
++        }
++      }
++#endif
++
++      /*
++       * XXX this needs to be locked from when it was first looked
++       * up in the decapsulation loop.  Perhaps it is better to put
++       * the IPIP decap inside the loop.
++       */
++      if(ipsnext) {
++              ipsp = ipsnext;
++              irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa));
++              if((ipp->protocol != IPPROTO_IPIP) && 
++                   (ipp->protocol != IPPROTO_ATT_HEARTBEAT)) {  /* AT&T heartbeats to SIG/GIG */
++                      spin_unlock(&tdb_lock);
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "SA:%s, Hey!  How did this get through?  Dropped.\n",
++                                  irs->sa_len ? irs->sa : " (error)");
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      goto rcvleave;
++              }
++              if(sysctl_ipsec_inbound_policy_check) {
++                      struct sockaddr_in *psin = (struct sockaddr_in*)(ipsp->ips_addr_s);
++                      if((ipsnext = ipsp->ips_inext)) {
++                              char sa2[SATOT_BUF];
++                              size_t sa_len2;
++                              sa_len2 = satot(&ipsnext->ips_said, 0, sa2, sizeof(sa2));
++                              spin_unlock(&tdb_lock);
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          "unexpected SA:%s after IPIP SA:%s\n",
++                                          sa_len2 ? sa2 : " (error)",
++                                          irs->sa_len ? irs->sa : " (error)");
++                              if(irs->stats) {
++                                      irs->stats->rx_dropped++;
++                              }
++                              goto rcvleave;
++                      }
++                      if(ipp->saddr != psin->sin_addr.s_addr) {
++                              spin_unlock(&tdb_lock);
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          "SA:%s, src=%s(%08x) does match expected 0x%08x.\n",
++                                          irs->sa_len ? irs->sa : " (error)",
++                                          irs->ipsaddr_txt, 
++                                          ipp->saddr, psin->sin_addr.s_addr);
++                              if(irs->stats) {
++                                      irs->stats->rx_dropped++;
++                              }
++                              goto rcvleave;
++                      }
++              }
++
++      if(ipp->protocol == IPPROTO_IPIP)  /* added to support AT&T heartbeats to SIG/GIG */
++      {  
++              /*
++               * XXX this needs to be locked from when it was first looked
++               * up in the decapsulation loop.  Perhaps it is better to put
++               * the IPIP decap inside the loop.
++               */
++              ipsp->ips_life.ipl_bytes.ipl_count += skb->len;
++              ipsp->ips_life.ipl_bytes.ipl_last   = skb->len;
++
++              if(!ipsp->ips_life.ipl_usetime.ipl_count) {
++                      ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;
++              }
++              ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;
++              ipsp->ips_life.ipl_packets.ipl_count += 1;
++
++              if(skb->len < irs->iphlen) {
++                      spin_unlock(&tdb_lock);
++                      printk(KERN_WARNING "klips_debug:ipsec_rcv: "
++                             "tried to skb_pull iphlen=%d, %d available.  This should never happen, please report.\n",
++                             irs->iphlen,
++                             (int)(skb->len));
++
++                      goto rcvleave;
++              }
++
++              /*
++               * we need to pull up by size of IP header,
++               * options, but also by any UDP/ESP encap there might
++               * have been, and this deals with all cases.
++               */
++              skb_pull(skb, (skb->h.raw - skb->nh.raw));
++
++              /* new L3 header is where L4 payload was */
++              skb->nh.raw = skb->h.raw;
++
++              /* now setup new L4 payload location */
++              ipp = (struct iphdr *)skb->nh.raw;
++              skb->h.raw = skb->nh.raw + (ipp->ihl << 2);
++
++
++              /* remove any saved options that we might have,
++               * since we have a new IP header.
++               */
++              memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
++
++#if 0
++              KLIPS_PRINT(debug_rcv, "csum: %d\n", ip_fast_csum((u8 *)ipp, ipp->ihl));
++#endif
++
++              /* re-do any strings for debugging */
++              ipsaddr.s_addr = ipp->saddr;
++              addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt));
++              ipdaddr.s_addr = ipp->daddr;
++              addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt));
++
++              skb->protocol = htons(ETH_P_IP);
++              skb->ip_summed = 0;
++              KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                          "klips_debug:ipsec_rcv: "
++                          "IPIP tunnel stripped.\n");
++              KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);
++  }
++
++              if(sysctl_ipsec_inbound_policy_check
++                 /*
++                    Note: "xor" (^) logically replaces "not equal"
++                    (!=) and "bitwise or" (|) logically replaces
++                    "boolean or" (||).  This is done to speed up
++                    execution by doing only bitwise operations and
++                    no branch operations
++                 */
++                 && (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr)
++                                  ^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr)
++                     | ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr)
++                                    ^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) )
++              {
++                      char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF];
++
++                      subnettoa(ipsp->ips_flow_s.u.v4.sin_addr,
++                              ipsp->ips_mask_s.u.v4.sin_addr,
++                              0, sflow_txt, sizeof(sflow_txt));
++                      subnettoa(ipsp->ips_flow_d.u.v4.sin_addr,
++                              ipsp->ips_mask_d.u.v4.sin_addr,
++                              0, dflow_txt, sizeof(dflow_txt));
++                      spin_unlock(&tdb_lock);
++                      KLIPS_PRINT(debug_rcv,
++                                  "klips_debug:ipsec_rcv: "
++                                  "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n",
++                                  irs->sa_len ? irs->sa : " (error)",
++                                  sflow_txt,
++                                  dflow_txt,
++                                  irs->ipsaddr_txt,
++                                  irs->ipdaddr_txt);
++                      if(irs->stats) {
++                              irs->stats->rx_dropped++;
++                      }
++                      goto rcvleave;
++              }
++#ifdef CONFIG_NETFILTER
++              skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_TABLE_MASK))))
++                      | IPsecSAref2NFmark(IPsecSA2SAref(ipsp));
++              KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                          "klips_debug:ipsec_rcv: "
++                          "IPIP SA sets skb->nfmark=0x%x.\n",
++                          (unsigned)skb->nfmark);
++#endif /* CONFIG_NETFILTER */
++      }
++
++      spin_unlock(&tdb_lock);
++
++      if(irs->stats) {
++              irs->stats->rx_bytes += skb->len;
++      }
++      if(skb->dst) {
++              dst_release(skb->dst);
++              skb->dst = NULL;
++      }
++      skb->pkt_type = PACKET_HOST;
++      if(irs->hard_header_len &&
++         (skb->mac.raw != (skb->nh.raw - irs->hard_header_len)) &&
++         (irs->hard_header_len <= skb_headroom(skb))) {
++              /* copy back original MAC header */
++              memmove(skb->nh.raw - irs->hard_header_len,
++                      skb->mac.raw, irs->hard_header_len);
++              skb->mac.raw = skb->nh.raw - irs->hard_header_len;
++      }
++
++#ifdef CONFIG_KLIPS_IPCOMP
++      if(ipp->protocol == IPPROTO_COMP) {
++              unsigned int flags = 0;
++
++              if(sysctl_ipsec_inbound_policy_check) {
++                      KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                              "klips_debug:ipsec_rcv: "
++                              "inbound policy checking enabled, IPCOMP follows IPIP, dropped.\n");
++                      if (irs->stats) {
++                              irs->stats->rx_errors++;
++                      }
++                      goto rcvleave;
++              }
++              /*
++                XXX need a ipsec_sa for updating ratio counters but it is not
++                following policy anyways so it is not a priority
++              */
++              skb = skb_decompress(skb, NULL, &flags);
++              if (!skb || flags) {
++                      KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                              "klips_debug:ipsec_rcv: "
++                              "skb_decompress() returned error flags: %d, dropped.\n",
++                              flags);
++                      if (irs->stats) {
++                              irs->stats->rx_errors++;
++                      }
++                      goto rcvleave;
++              }
++      }
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++      /*
++       * make sure that data now starts at IP header, since we are going
++       * to pass this back to ip_input (aka netif_rx). Rules for what the
++       * pointers wind up a different for 2.6 vs 2.4, so we just fudge it here.
++       */
++#ifdef NET_26
++      skb->data = skb_push(skb, skb->h.raw - skb->nh.raw);
++#else
++      skb->data = skb->nh.raw;
++      {
++        struct iphdr *iph = skb->nh.iph;
++        int len = ntohs(iph->tot_len);
++        skb->len  = len;
++      }
++#endif
++
++#ifdef SKB_RESET_NFCT
++      nf_conntrack_put(skb->nfct);
++      skb->nfct = NULL;
++#if defined(CONFIG_NETFILTER_DEBUG) && defined(HAVE_SKB_NF_DEBUG)
++      skb->nf_debug = 0;
++#endif /* CONFIG_NETFILTER_DEBUG */
++#endif /* SKB_RESET_NFCT */
++      KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
++                  "klips_debug:ipsec_rcv: "
++                  "netif_rx() called.\n");
++      netif_rx(skb);
++      skb=NULL;
++
++ rcvleave:
++      if(skb) {
++              ipsec_kfree_skb(skb);
++      }
++
++      /* KLIPS_DEC_USE; Artifact from refactor? bug # 454 */
++      return(0);
++}
++
++struct sk_buff *ipsec_rcv_unclone(struct sk_buff *skb,
++                                struct ipsec_rcv_state *irs)
++{
++      /* if skb was cloned (most likely due to a packet sniffer such as
++         tcpdump being momentarily attached to the interface), make
++         a copy of our own to modify */
++      if(skb_cloned(skb)) {
++              /* include any mac header while copying.. */
++              if(skb_headroom(skb) < irs->hard_header_len) {
++                      printk(KERN_WARNING "klips_error:ipsec_rcv: "
++                             "tried to skb_push hhlen=%d, %d available.  This should never happen, please report.\n",
++                             irs->hard_header_len,
++                             skb_headroom(skb));
++                      goto rcvleave;
++              }
++              skb_push(skb, irs->hard_header_len);
++              if
++#ifdef SKB_COW_NEW
++                (skb_cow(skb, skb_headroom(skb)) != 0)
++#else /* SKB_COW_NEW */
++                ((skb = skb_cow(skb, skb_headroom(skb))) == NULL)
++#endif /* SKB_COW_NEW */
++              {
++                      goto rcvleave;
++              }
++              if(skb->len < irs->hard_header_len) {
++                      printk(KERN_WARNING "klips_error:ipsec_rcv: "
++                             "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",
++                             irs->hard_header_len,
++                             skb->len);
++                      goto rcvleave;
++              }
++              skb_pull(skb, irs->hard_header_len);
++      }
++      return skb;
++
++rcvleave:
++      ipsec_kfree_skb(skb);
++      return NULL;
++}
++
++
++#if !defined(NET_26) && defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++/*
++ * decapsulate a UDP encapsulated ESP packet
++ */
++struct sk_buff *ipsec_rcv_natt_decap(struct sk_buff *skb
++                                   , struct ipsec_rcv_state *irs
++                                   , int *udp_decap_ret_p)
++{
++      *udp_decap_ret_p = 0;
++      if (skb->sk && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_UDP) {
++              /**
++               * Packet comes from udp_queue_rcv_skb so it is already defrag,
++               * checksum verified, ... (ie safe to use)
++               *
++               * If the packet is not for us, return -1 and udp_queue_rcv_skb
++               * will continue to handle it (do not kfree skb !!).
++               */
++
++#ifndef UDP_OPT_IN_SOCK
++              struct udp_opt {
++                      __u32 esp_in_udp;
++              };
++              struct udp_opt *tp =  (struct udp_opt *)&(skb->sk->tp_pinfo.af_tcp);
++#else
++              struct udp_opt *tp =  &(skb->sk->tp_pinfo.af_udp);
++#endif
++
++              struct iphdr *ip = (struct iphdr *)skb->nh.iph;
++              struct udphdr *udp = (struct udphdr *)((__u32 *)ip+ip->ihl);
++              __u8 *udpdata = (__u8 *)udp + sizeof(struct udphdr);
++              __u32 *udpdata32 = (__u32 *)udpdata;
++              
++              irs->natt_sport = ntohs(udp->source);
++              irs->natt_dport = ntohs(udp->dest);
++        
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "suspected ESPinUDP packet (NAT-Traversal) [%d].\n",
++                          tp->esp_in_udp);
++              KLIPS_IP_PRINT(debug_rcv, ip);
++        
++              if (udpdata < skb->tail) {
++                      unsigned int len = skb->tail - udpdata;
++                      if ((len==1) && (udpdata[0]==0xff)) {
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          /* not IPv6 compliant message */
++                                          "NAT-keepalive from %d.%d.%d.%d.\n", NIPQUAD(ip->saddr));
++                              *udp_decap_ret_p = 0;
++                              return NULL;
++                      }
++                      else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_IKE) &&
++                                (len > (2*sizeof(__u32) + sizeof(struct esphdr))) &&
++                                (udpdata32[0]==0) && (udpdata32[1]==0) ) {
++                              /* ESP Packet with Non-IKE header */
++                              KLIPS_PRINT(debug_rcv, 
++                                          "klips_debug:ipsec_rcv: "
++                                          "ESPinUDP pkt with Non-IKE - spi=0x%x\n",
++                                          ntohl(udpdata32[2]));
++                              irs->natt_type = ESPINUDP_WITH_NON_IKE;
++                              irs->natt_len = sizeof(struct udphdr)+(2*sizeof(__u32));
++                      }
++                      else if ( (tp->esp_in_udp == ESPINUDP_WITH_NON_ESP) &&
++                                (len > sizeof(struct esphdr)) &&
++                                (udpdata32[0]!=0) ) {
++                              /* ESP Packet without Non-ESP header */
++                              irs->natt_type = ESPINUDP_WITH_NON_ESP;
++                              irs->natt_len = sizeof(struct udphdr);
++                              KLIPS_PRINT(debug_rcv, 
++                                          "klips_debug:ipsec_rcv: "
++                                          "ESPinUDP pkt without Non-ESP - spi=0x%x\n",
++                                          ntohl(udpdata32[0]));
++                      }
++                      else {
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          "IKE packet - not handled here\n");
++                              *udp_decap_ret_p = -1;
++                              return NULL;
++                      }
++              }
++              else {
++                      return NULL;
++              }
++      }
++      return skb;
++}
++#endif
++
++
++int
++ipsec_rcv(struct sk_buff *skb
++#ifndef PROTO_HANDLER_SINGLE_PARM
++        unsigned short xlen
++#endif /* PROTO_HANDLER_SINGLE_PARM */
++        )
++{
++#ifdef CONFIG_KLIPS_DEBUG
++      struct net_device *dev = skb->dev;
++#endif /* CONFIG_KLIPS_DEBUG */
++      unsigned char protoc;
++      struct net_device_stats *stats = NULL;          /* This device's statistics */
++      struct net_device *ipsecdev = NULL, *prvdev;
++      struct ipsecpriv *prv;
++      struct ipsec_rcv_state nirs, *irs = &nirs;
++      struct iphdr *ipp;
++      char name[9];
++      int i;
++
++      /* Don't unlink in the middle of a turnaround */
++      KLIPS_INC_USE;
++
++      memset(&nirs, 0, sizeof(struct ipsec_rcv_state));
++
++      if (skb == NULL) {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NULL skb passed in.\n");
++              goto rcvleave;
++      }
++
++      if (skb->data == NULL) {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "NULL skb->data passed in, packet is bogus, dropping.\n");
++              goto rcvleave;
++      }
++
++#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26)
++      {
++              /* NET_26 NAT-T is handled by seperate function */
++              struct sk_buff *nskb;
++              int udp_decap_ret = 0;
++
++              nskb = ipsec_rcv_natt_decap(skb, irs, &udp_decap_ret);
++              if(nskb == NULL) {
++                      /* return with non-zero, because UDP.c code
++                       * need to send it upstream.
++                       */
++                      if(skb && udp_decap_ret == 0) {
++                              ipsec_kfree_skb(skb);
++                      }
++                      KLIPS_DEC_USE;
++                      return(udp_decap_ret);
++              }
++              skb = nskb;
++      }
++#endif /* NAT_T */
++
++      /* dev->hard_header_len is unreliable and should not be used */
++      irs->hard_header_len = skb->mac.raw ? (skb->nh.raw - skb->mac.raw) : 0;
++      if((irs->hard_header_len < 0) || (irs->hard_header_len > skb_headroom(skb)))
++              irs->hard_header_len = 0;
++
++      skb = ipsec_rcv_unclone(skb, irs);
++      if(skb == NULL) {
++              goto rcvleave;
++      }
++
++#if IP_FRAGMENT_LINEARIZE
++      /* In Linux 2.4.4, we may have to reassemble fragments. They are
++         not assembled automatically to save TCP from having to copy
++         twice.
++      */
++      if (skb_is_nonlinear(skb)) {
++#ifdef HAVE_NEW_SKB_LINEARIZE
++              if (skb_linearize_cow(skb) != 0)
++#else
++              if (skb_linearize(skb, GFP_ATOMIC) != 0) 
++#endif
++              {
++                      goto rcvleave;
++              }
++      }
++#endif /* IP_FRAGMENT_LINEARIZE */
++
++#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) && !defined(NET_26)
++      if (irs->natt_len) {
++              /**
++               * Now, we are sure packet is ESPinUDP, and we have a private
++               * copy that has been linearized, remove natt_len bytes
++               * from packet and modify protocol to ESP.
++               */
++              if (((unsigned char *)skb->data > (unsigned char *)skb->nh.iph)
++                  && ((unsigned char *)skb->nh.iph > (unsigned char *)skb->head))
++              {
++                      unsigned int _len = (unsigned char *)skb->data -
++                              (unsigned char *)skb->nh.iph;
++                      KLIPS_PRINT(debug_rcv,
++                              "klips_debug:ipsec_rcv: adjusting skb: skb_push(%u)\n",
++                              _len);
++                      skb_push(skb, _len);
++              }
++              KLIPS_PRINT(debug_rcv,
++                  "klips_debug:ipsec_rcv: "
++                      "removing %d bytes from ESPinUDP packet\n", irs->natt_len);
++              ipp = skb->nh.iph;
++              irs->iphlen = ipp->ihl << 2;
++              ipp->tot_len = htons(ntohs(ipp->tot_len) - irs->natt_len);
++              if (skb->len < irs->iphlen + irs->natt_len) {
++                      printk(KERN_WARNING
++                     "klips_error:ipsec_rcv: "
++                     "ESPinUDP packet is too small (%d < %d+%d). "
++                         "This should never happen, please report.\n",
++                     (int)(skb->len), irs->iphlen, irs->natt_len);
++                      goto rcvleave;
++              }
++
++              /* advance payload pointer to point past the UDP header */
++              skb->h.raw = skb->h.raw + irs->natt_len;
++
++              /* modify protocol */
++              ipp->protocol = IPPROTO_ESP;
++
++              skb->sk = NULL;
++
++              KLIPS_IP_PRINT(debug_rcv, skb->nh.iph);
++      }
++#endif
++
++      ipp = skb->nh.iph;
++
++      {
++              struct in_addr ipsaddr;
++              struct in_addr ipdaddr;
++
++              ipsaddr.s_addr = ipp->saddr;
++              addrtoa(ipsaddr, 0, irs->ipsaddr_txt
++                      , sizeof(irs->ipsaddr_txt));
++              ipdaddr.s_addr = ipp->daddr;
++              addrtoa(ipdaddr, 0, irs->ipdaddr_txt
++                      , sizeof(irs->ipdaddr_txt));
++      }
++
++      irs->iphlen = ipp->ihl << 2;
++
++      KLIPS_PRINT(debug_rcv,
++                  "klips_debug:ipsec_rcv: "
++                  "<<< Info -- ");
++      KLIPS_PRINTMORE(debug_rcv && skb->dev, "skb->dev=%s ",
++                      skb->dev->name ? skb->dev->name : "NULL");
++      KLIPS_PRINTMORE(debug_rcv && dev, "dev=%s ",
++                      dev->name ? dev->name : "NULL");
++      KLIPS_PRINTMORE(debug_rcv, "\n");
++
++      KLIPS_PRINT(debug_rcv && !(skb->dev && dev && (skb->dev == dev)),
++                  "klips_debug:ipsec_rcv: "
++                  "Informational -- **if this happens, find out why** skb->dev:%s is not equal to dev:%s\n",
++                  skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL",
++                  dev ? (dev->name ? dev->name : "NULL") : "NULL");
++
++      protoc = ipp->protocol;
++#ifndef NET_21
++      if((!protocol) || (protocol->protocol != protoc)) {
++              KLIPS_PRINT(debug_rcv & DB_RX_IPSA,
++                          "klips_debug:ipsec_rcv: "
++                          "protocol arg is NULL or unequal to the packet contents, this is odd, using value in packet.\n");
++      }
++#endif /* !NET_21 */
++
++      if( (protoc != IPPROTO_AH) &&
++#ifdef CONFIG_KLIPS_IPCOMP_disabled_until_we_register_IPCOMP_HANDLER
++          (protoc != IPPROTO_COMP) &&
++#endif /* CONFIG_KLIPS_IPCOMP */
++          (protoc != IPPROTO_ESP) ) {
++              KLIPS_PRINT(debug_rcv & DB_RX_IPSA,
++                          "klips_debug:ipsec_rcv: Why the hell is someone "
++                          "passing me a non-ipsec protocol = %d packet? -- dropped.\n",
++                          protoc);
++              goto rcvleave;
++      }
++
++      if(skb->dev) {
++              for(i = 0; i < IPSEC_NUM_IF; i++) {
++                      sprintf(name, IPSEC_DEV_FORMAT, i);
++                      if(!strcmp(name, skb->dev->name)) {
++                              prv = (struct ipsecpriv *)(skb->dev->priv);
++                              if(prv) {
++                                      stats = (struct net_device_stats *) &(prv->mystats);
++                              }
++                              ipsecdev = skb->dev;
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_debug:ipsec_rcv: "
++                                          "Info -- pkt already proc'ed a group of ipsec headers, processing next group of ipsec headers.\n");
++                              break;
++                      }
++                      if((ipsecdev = __ipsec_dev_get(name)) == NULL) {
++                              KLIPS_PRINT(debug_rcv,
++                                          "klips_error:ipsec_rcv: "
++                                          "device %s does not exist\n",
++                                          name);
++                      }
++                      prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL;
++                      prvdev = prv ? (struct net_device *)(prv->dev) : NULL;
++
++#if 0
++                      KLIPS_PRINT(debug_rcv && prvdev,
++                                  "klips_debug:ipsec_rcv: "
++                                  "physical device for device %s is %s\n",
++                                  name,
++                                  prvdev->name);
++#endif
++                      if(prvdev && skb->dev &&
++                         !strcmp(prvdev->name, skb->dev->name)) {
++                              stats = prv ? ((struct net_device_stats *) &(prv->mystats)) : NULL;
++                              skb->dev = ipsecdev;
++                              KLIPS_PRINT(debug_rcv && prvdev,
++                                          "klips_debug:ipsec_rcv: "
++                                          "assigning packet ownership to virtual device %s from physical device %s.\n",
++                                          name, prvdev->name);
++                              if(stats) {
++                                      stats->rx_packets++;
++                              }
++                              break;
++                      }
++              }
++      } else {
++              KLIPS_PRINT(debug_rcv,
++                          "klips_debug:ipsec_rcv: "
++                          "device supplied with skb is NULL\n");
++      }
++
++      if(stats == NULL) {
++              KLIPS_PRINT((debug_rcv),
++                          "klips_error:ipsec_rcv: "
++                          "packet received from physical I/F (%s) not connected to ipsec I/F.  Cannot record stats.  May not have SA for decoding.  Is IPSEC traffic expected on this I/F?  Check routing.\n",
++                          skb->dev ? (skb->dev->name ? skb->dev->name : "NULL") : "NULL");
++      }
++              
++      KLIPS_IP_PRINT(debug_rcv, ipp);
++
++      /* set up for decap loop */
++      irs->stats= stats;
++      irs->ipp  = ipp;
++      irs->ipsp = NULL;
++      irs->ilen = 0;
++      irs->authlen=0;
++      irs->authfuncs=NULL;
++      irs->skb = skb;
++
++      ipsec_rcv_decap(irs);
++      KLIPS_DEC_USE;
++      return(0);
++
++ rcvleave:
++      if(skb) {
++              ipsec_kfree_skb(skb);
++      }
++      KLIPS_DEC_USE;
++      return(0);
++
++}
++
++#ifdef NET_26
++/*
++ * this entry point is not a protocol entry point, so the entry
++ * is a bit different.
++ *
++ * skb->iph->tot_len has been byte-swapped, and reduced by the size of
++ *              the IP header (and options).
++ * 
++ * skb->h.raw has been pulled up the ESP header.
++ *
++ * skb->iph->protocol = 50 IPPROTO_ESP;
++ *
++ */
++int klips26_rcv_encap(struct sk_buff *skb, __u16 encap_type)
++{
++      struct ipsec_rcv_state nirs, *irs = &nirs;
++      struct iphdr *ipp;
++
++      /* Don't unlink in the middle of a turnaround */
++      KLIPS_INC_USE;
++
++      memset(irs, 0, sizeof(*irs));
++
++      /* XXX fudge it so that all nat-t stuff comes from ipsec0    */
++      /*     eventually, the SA itself will determine which device
++       *     it comes from
++       */ 
++      {
++        skb->dev = ipsec_get_device(0);
++      }
++
++      /* set up for decap loop */
++      irs->hard_header_len = skb->dev->hard_header_len;
++
++      skb = ipsec_rcv_unclone(skb, irs);
++
++#if IP_FRAGMENT_LINEARIZE
++      /* In Linux 2.4.4, we may have to reassemble fragments. They are
++         not assembled automatically to save TCP from having to copy
++         twice.
++      */
++      if (skb_is_nonlinear(skb)) {
++#ifdef HAVE_NEW_SKB_LINEARIZE
++              if (skb_linearize_cow(skb) != 0) 
++#else
++              if (skb_linearize(skb, GFP_ATOMIC) != 0) 
++#endif
++              {
++                      goto rcvleave;
++              }
++      }
++#endif /* IP_FRAGMENT_LINEARIZE */
++
++      ipp = skb->nh.iph;
++
++      {
++              struct in_addr ipsaddr;
++              struct in_addr ipdaddr;
++
++              ipsaddr.s_addr = ipp->saddr;
++              addrtoa(ipsaddr, 0, irs->ipsaddr_txt
++                      , sizeof(irs->ipsaddr_txt));
++              ipdaddr.s_addr = ipp->daddr;
++              addrtoa(ipdaddr, 0, irs->ipdaddr_txt
++                      , sizeof(irs->ipdaddr_txt));
++      }
++
++      irs->iphlen = ipp->ihl << 2;
++
++      KLIPS_IP_PRINT(debug_rcv, ipp);
++
++      irs->stats= NULL;
++      irs->ipp  = ipp;
++      irs->ipsp = NULL;
++      irs->ilen = 0;
++      irs->authlen=0;
++      irs->authfuncs=NULL;
++      irs->skb = skb;
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      switch(encap_type) {
++      case UDP_ENCAP_ESPINUDP:
++        irs->natt_type = ESPINUDP_WITH_NON_ESP;
++        break;
++        
++      case UDP_ENCAP_ESPINUDP_NON_IKE:
++        irs->natt_type = ESPINUDP_WITH_NON_IKE;
++        break;
++        
++      default:
++        if(printk_ratelimit()) {
++          printk(KERN_INFO "KLIPS received unknown UDP-ESP encap type %u\n",
++                 encap_type);
++        }
++        return -1;
++      }
++
++#endif
++      ipsec_rcv_decap(irs);
++      KLIPS_DEC_USE;
++      return 0;
++
++rcvleave:
++      if(skb) {
++              ipsec_kfree_skb(skb);
++      }
++      KLIPS_DEC_USE;
++      return 0;
++}
++#endif
++
++
++/*
++ * $Log: ipsec_rcv.c,v $
++ * Revision 1.171.2.11  2007/04/28 20:46:40  paul
++ * Added compile time switch for -DDISABLE_UDP_CHECKSUM that seems to be
++ * breaking IPsec+NAT+Transport mode with NAT-OA. Enabled this per default
++ * via Makefile.inc's USERCOMPILE flags.
++ *
++ * Revision 1.171.2.10  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.171.2.9  2006/07/30 02:09:33  paul
++ * Author: Bart Trojanowski <bart@xelerance.com>
++ * This fixes a NATT+ESP bug in rcv path.
++ *
++ *     We only want to test NATT policy on the ESP packet.  Doing so on the
++ *     bundled SA breaks because the next layer does not know anything about
++ *     NATT.
++ *
++ *     Fix just puts an if(proto == IPPROTO_ESP) around the NATT policy check.
++ *
++ * Revision 1.171.2.8  2006/07/29 05:03:04  paul
++ * Added check for new version of skb_linearize that only takes 1 argument,
++ * for 2.6.18+ kernels.
++ *
++ * Revision 1.171.2.7  2006/04/20 16:33:07  mcr
++ * remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++ * Fix in-kernel module compilation. Sub-makefiles do not work.
++ *
++ * Revision 1.171.2.6  2005/12/07 06:07:04  paul
++ * comment out KLIPS_DEC_USE in ipsec_rcv_decap. Likely an artifact from
++ * refactoring. http://bugs.xelerance.com/view.php?id=454
++ *
++ * Revision 1.171.2.5  2005/10/21 02:22:29  mcr
++ *    pull up of another try at 2.4.x kernel fix
++ *
++ * Revision 1.171.2.4  2005/10/21 01:39:56  mcr
++ *     nat-t fix is 2.4/2.6 specific
++ *
++ * Revision 1.178  2005/10/21 02:19:34  mcr
++ *    on 2.4 systems, we have to fix up the length as well.
++ *
++ * Revision 1.177  2005/10/21 00:18:31  mcr
++ *    nat-t fix is 2.4 specific.
++ *
++ * Revision 1.176  2005/10/20 21:06:11  mcr
++ *    possible fix for nat-t problem on 2.4 kernels.
++ *
++ * Revision 1.175  2005/10/13 02:49:24  mcr
++ *    tested UDP-encapsulated ESP packets that were not actually ESP,
++ *    (but IKE) were being eaten.
++ *
++ * Revision 1.174  2005/10/13 01:25:22  mcr
++ *    UDP-encapsulated ESP packets that were not actually ESP,
++ *    (but IKE) were being eaten.
++ *
++ * Revision 1.173  2005/08/31 23:26:11  mcr
++ *    fixes for 2.6.13
++ *
++ * Revision 1.172  2005/08/05 08:44:54  mcr
++ *    ipsec_kern24.h (compat code for 2.4) must be include
++ *    explicitely now.
++ *
++ * Revision 1.171  2005/07/08 23:56:06  ken
++ * #ifdef
++ *
++ * Revision 1.170  2005/07/08 23:50:05  ken
++ * Don't attempt to decapsulate if NAT-T isn't available in the code
++ *
++ * Revision 1.169  2005/06/06 00:27:31  mcr
++ *    fix for making tcpdump (packet capture) work correctly for
++ *    nat-t received packets.
++ *
++ * Revision 1.168  2005/06/04 16:06:06  mcr
++ *    better patch for nat-t rcv-device code.
++ *
++ * Revision 1.167  2005/06/03 17:04:46  mcr
++ *    nat-t packets are forced to arrive from ipsec0.
++ *
++ * Revision 1.166  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.165  2005/04/20 17:11:32  mcr
++ *    fixed to compile on 2.4.
++ *
++ * Revision 1.164  2005/04/18 03:09:50  ken
++ * Fix typo
++ *
++ * Revision 1.163  2005/04/17 05:32:58  mcr
++ *    remove extraneous debugging
++ *    make sure to return success from klips26_encap_rcv().
++ *
++ * Revision 1.162  2005/04/17 04:37:01  mcr
++ *    make sure that irs->ipp is still set.
++ *
++ * Revision 1.161  2005/04/17 03:51:52  mcr
++ *    removed old comment about removed code.
++ *    added translation from udp.c/2.6 to KLIPS NAT-ESP naming.
++ *    comment about check for origin address/port for incoming NAT-ESP packets.
++ *
++ * Revision 1.160  2005/04/15 19:55:58  mcr
++ *    adjustments to use proper skb fields for data.
++ *
++ * Revision 1.159  2005/04/10 22:58:20  mcr
++ *    refactoring of receive functions to make it easier to
++ *    call the ESP decap.
++ *
++ * Revision 1.158  2005/04/08 18:27:53  mcr
++ *    refactored ipsec_rcv() into ipsec_rcv() and ipsec_rcv_decap().
++ *
++ * Revision 1.157  2004/12/28 23:13:09  mcr
++ *    use consistent CONFIG_IPSEC_NAT_TRAVERSAL.
++ *
++ * Revision 1.156  2004/12/03 21:34:51  mcr
++ *    mistype of KLIPS_USE_COUNT -> KLIPS_INC_USE;
++ *
++ * Revision 1.155  2004/12/03 21:25:57  mcr
++ *    compile time fixes for running on 2.6.
++ *    still experimental.
++ *
++ * Revision 1.154  2004/09/08 17:21:36  ken
++ * Rename MD5* -> osMD5 functions to prevent clashes with other symbols exported by kernel modules (CIFS in 2.6 initiated this)
++ *
++ * Revision 1.153  2004/08/22 20:10:00  mcr
++ *    removed check for incorrect setting of NET_26.
++ *
++ * Revision 1.152  2004/08/21 15:22:39  mcr
++ *    added #defines for ATT heartbeat.
++ *
++ * Revision 1.151  2004/08/21 02:16:32  ken
++ * Patch from Jochen Eisinger for AT&T MTS Heartbeat packet support
++ *
++ * Revision 1.150  2004/08/21 00:44:48  mcr
++ *    CONFIG_KLIPS_NAT was wrong, also need to include udp.h.
++ *
++ * Revision 1.149  2004/08/20 21:45:45  mcr
++ *    CONFIG_KLIPS_NAT_TRAVERSAL is not used in an attempt to
++ *    be 26sec compatible. But, some defines where changed.
++ *
++ * Revision 1.148  2004/08/17 03:27:23  mcr
++ *    klips 2.6 edits.
++ *
++ * Revision 1.147  2004/08/05 23:29:27  mcr
++ *    fixed nesting of #ifdef vs {} in ipsec_rcv().
++ *
++ * Revision 1.146  2004/08/04 15:57:07  mcr
++ *    moved des .h files to include/des/ *
++ *    included 2.6 protocol specific things
++ *    started at NAT-T support, but it will require a kernel patch.
++ *
++ * Revision 1.145  2004/08/03 18:19:08  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.144  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.143  2004/05/10 22:27:00  mcr
++ *    fix for ESP-3DES-noauth test case.
++ *
++ * Revision 1.142  2004/05/10 22:25:57  mcr
++ *    reformat of calls to ipsec_lifetime_check().
++ *
++ * Revision 1.141  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.140  2004/02/03 03:12:53  mcr
++ *    removed erroneously, double patched code.
++ *
++ * Revision 1.139  2004/01/05 23:21:29  mcr
++ *    initialize sin_family in ipsec_rcv.c
++ *
++ * Revision 1.138  2003/12/24 19:46:52  mcr
++ *    if sock.h patch has not been applied, then define appropriate
++ *    structure so we can use it. This is serious inferior, and
++ *    depends upon the concept that the structure in question is
++ *    smaller than the other members of that union.
++ *    getting rid of differing methods is a better solution.
++ *
++ * Revision 1.137  2003/12/22 19:40:57  mcr
++ *    NAT-T patches 0.6c.
++ *
++ * Revision 1.136  2003/12/15 18:13:12  mcr
++ *    when compiling with NAT traversal, don't assume that the
++ *    kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP
++ *    is set.
++ *
++ * Revision 1.135  2003/12/13 19:10:21  mcr
++ *    refactored rcv and xmit code - same as FS 2.05.
++ *
++ * Revision 1.134.2.1  2003/12/22 15:25:52  jjo
++ *      Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.134  2003/12/10 01:14:27  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.133  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.132.2.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.132  2003/09/02 19:51:48  mcr
++ *    fixes for PR#252.
++ *
++ * Revision 1.131  2003/07/31 22:47:16  mcr
++ *    preliminary (untested by FS-team) 2.5 patches.
++ *
++ * Revision 1.130  2003/04/03 17:38:25  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ * Clarified logic for non-connected devices.
++ *
++ * Revision 1.129  2003/02/06 02:21:34  rgb
++ *
++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h .
++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr".
++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code.
++ *
++ * Revision 1.128  2002/12/13 20:58:03  rgb
++ * Relegated MCR's recent "_dmp" routine to debug_verbose.
++ * Cleaned up printing of source and destination addresses in debug output.
++ *
++ * Revision 1.127  2002/12/04 16:00:16  rgb
++ *
++ * Fixed AH decapsulation pointer update bug and added some comments and
++ * debugging.
++ * This bug was caught by west-ah-0[12].
++ *
++ * Revision 1.126  2002/11/04 05:03:43  mcr
++ *    fixes for IPCOMP. There were two problems:
++ *    1) the irs->ipp pointer was not being updated properly after
++ *       the ESP descryption. The meant nothing for IPIP, as the
++ *       later IP header overwrote the earlier one.
++ *    2) the more serious problem was that skb_decompress will
++ *       usually allocate a new SKB, so we have to make sure that
++ *       it doesn't get lost.
++ *    #2 meant removing the skb argument from the ->decrypt routine
++ *    and moving it to the irs->skb, so it could be value/result.
++ *
++ * Revision 1.125  2002/11/01 01:53:35  dhr
++ *
++ * fix typo
++ *
++ * Revision 1.124  2002/10/31 22:49:01  dhr
++ *
++ * - eliminate unused variable "hash"
++ * - reduce scope of variable "authenticator"
++ * - add comment on a couple of tricky bits
++ *
++ * Revision 1.123  2002/10/31 22:39:56  dhr
++ *
++ * use correct type for result of function calls
++ *
++ * Revision 1.122  2002/10/31 22:36:25  dhr
++ *
++ * simplify complex test
++ *
++ * Revision 1.121  2002/10/31 22:34:04  dhr
++ *
++ * ipsprev is never used: ditch it
++ *
++ * Revision 1.120  2002/10/31 22:30:21  dhr
++ *
++ * eliminate redundant assignments
++ *
++ * Revision 1.119  2002/10/31 22:27:43  dhr
++ *
++ * make whitespace canonical
++ *
++ * Revision 1.118  2002/10/30 05:47:17  rgb
++ * Fixed cut-and-paste error mis-identifying comp runt as ah.
++ *
++ * Revision 1.117  2002/10/17 16:37:45  rgb
++ * Remove compp intermediate variable and in-line its contents
++ * where used
++ *
++ * Revision 1.116  2002/10/12 23:11:53  dhr
++ *
++ * [KenB + DHR] more 64-bit cleanup
++ *
++ * Revision 1.115  2002/10/07 19:06:58  rgb
++ * Minor fixups and activation to west-rcv-nfmark-set-01 test to check for SA reference properly set on incoming.
++ *
++ * Revision 1.114  2002/10/07 18:31:31  rgb
++ * Set saref on incoming packets.
++ *
++ * Revision 1.113  2002/09/16 21:28:12  mcr
++ *    adjust hash length for HMAC calculation - must look at whether
++ *    it is MD5 or SHA1.
++ *
++ * Revision 1.112  2002/09/16 21:19:15  mcr
++ *    fixes for west-ah-icmp-01 - length of AH header must be
++ *    calculated properly, and next_header field properly copied.
++ *
++ * Revision 1.111  2002/09/10 02:45:56  mcr
++ *    re-factored the ipsec_rcv function into several functions,
++ *    ipsec_rcv_decap_once, and a set of functions for AH, ESP and IPCOMP.
++ *    In addition, the MD5 and SHA1 functions are replaced with pointers.
++ *
++ * Revision 1.110  2002/08/30 06:34:33  rgb
++ * Fix scope of shift in AH header length check.
++ *
++ * Revision 1.109  2002/08/27 16:49:20  rgb
++ * Fixed ESP short packet DOS (and AH and IPCOMP).
++ *
++ * Revision 1.108  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.107  2002/05/27 18:58:18  rgb
++ * Convert to dynamic ipsec device allocation.
++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT.
++ *
++ * Revision 1.106  2002/05/23 07:15:21  rgb
++ * Pointer clean-up.
++ * Added refcount code.
++ *
++ * Revision 1.105  2002/05/14 02:35:06  rgb
++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips,
++ * ipsec_sa or ipsec_sa.
++ * Change references to _TDB to _IPSA.
++ *
++ * Revision 1.104  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.103  2002/04/24 07:36:30  mcr
++ * Moved from ./klips/net/ipsec/ipsec_rcv.c,v
++ *
++ * Revision 1.102  2002/01/29 17:17:56  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.101  2002/01/29 04:00:52  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.100  2002/01/29 02:13:17  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.99  2002/01/28 21:40:59  mcr
++ *    should use #if to test boolean option rather than #ifdef.
++ *
++ * Revision 1.98  2002/01/20 20:19:36  mcr
++ *    renamed option to IP_FRAGMENT_LINEARIZE.
++ *
++ * Revision 1.97  2002/01/12 02:55:36  mcr
++ *    fix for post-2.4.4 to linearize skb's when ESP packet
++ *    was assembled from fragments.
++ *
++ * Revision 1.96  2001/11/26 09:23:49  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.93.2.2  2001/10/22 20:54:07  mcr
++ *    include des.h, removed phony prototypes and fixed calling
++ *    conventions to match real prototypes.
++ *
++ * Revision 1.93.2.1  2001/09/25 02:22:22  mcr
++ *    struct tdb -> struct ipsec_sa.
++ *    lifetime checks moved to ipsec_life.c
++ *    some sa(tdb) manipulation functions renamed.
++ *
++ * Revision 1.95  2001/11/06 19:49:07  rgb
++ * Added variable descriptions.
++ * Removed unauthenticated sequence==0 check to prevent DoS.
++ *
++ * Revision 1.94  2001/10/18 04:45:20  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.93  2001/09/07 22:17:24  rgb
++ * Fix for removal of transport layer protocol handler arg in 2.4.4.
++ * Fix to accomodate peer non-conformance to IPCOMP rfc2393.
++ *
++ * Revision 1.92  2001/08/27 19:44:41  rgb
++ * Fix error in comment.
++ *
++ * Revision 1.91  2001/07/20 19:31:48  dhr
++ * [DHR] fix source and destination subnets of policy in diagnostic
++ *
++ * Revision 1.90  2001/07/06 19:51:09  rgb
++ * Added inbound policy checking code for IPIP SAs.
++ * Renamed unused function argument for ease and intuitive naming.
++ *
++ * Revision 1.89  2001/06/22 19:35:23  rgb
++ * Disable ipcomp processing if we are handed a ipcomp packet with no esp
++ * or ah header.
++ * Print protocol if we are handed a non-ipsec packet.
++ *
++ * Revision 1.88  2001/06/20 06:30:47  rgb
++ * Fixed transport mode IPCOMP policy check bug.
++ *
++ * Revision 1.87  2001/06/13 20:58:40  rgb
++ * Added parentheses around assignment used as truth value to silence
++ * compiler.
++ *
++ * Revision 1.86  2001/06/07 22:25:23  rgb
++ * Added a source address policy check for tunnel mode.  It still does
++ * not check client addresses and masks.
++ * Only decapsulate IPIP if it is expected.
++ *
++ * Revision 1.85  2001/05/30 08:14:02  rgb
++ * Removed vestiges of esp-null transforms.
++ *
++ * Revision 1.84  2001/05/27 06:12:11  rgb
++ * Added structures for pid, packet count and last access time to eroute.
++ * Added packet count to beginning of /proc/net/ipsec_eroute.
++ *
++ * Revision 1.83  2001/05/04 16:45:47  rgb
++ * Remove unneeded code.  ipp is not used after this point.
++ *
++ * Revision 1.82  2001/05/04 16:36:00  rgb
++ * Fix skb_cow() call for 2.4.4. (SS)
++ *
++ * Revision 1.81  2001/05/02 14:46:53  rgb
++ * Fix typo for compiler directive to pull IPH back.
++ *
++ * Revision 1.80  2001/04/30 19:46:34  rgb
++ * Update for 2.4.4.  We now receive the skb with skb->data pointing to
++ * h.raw.
++ *
++ * Revision 1.79  2001/04/23 15:01:15  rgb
++ * Added spin_lock() check to prevent double-locking for multiple
++ * transforms and hence kernel lock-ups with SMP kernels.
++ * Minor spin_unlock() adjustments to unlock before non-dependant prints
++ * and IPSEC device stats updates.
++ *
++ * Revision 1.78  2001/04/21 23:04:24  rgb
++ * Check if soft expire has already been sent before sending another to
++ * prevent ACQUIRE flooding.
++ *
++ * Revision 1.77  2001/03/16 07:35:20  rgb
++ * Ditch extra #if 1 around now permanent policy checking code.
++ *
++ * Revision 1.76  2001/02/27 22:24:54  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.75  2001/02/19 22:28:30  rgb
++ * Minor change to virtual device discovery code to assert which I/F has
++ * been found.
++ *
++ * Revision 1.74  2000/11/25 03:50:36  rgb
++ * Oops fix by minor re-arrangement of code to avoid accessing a freed tdb.
++ *
++ * Revision 1.73  2000/11/09 20:52:15  rgb
++ * More spinlock shuffling, locking earlier and unlocking later in rcv to
++ * include ipcomp and prevent races, renaming some tdb variables that got
++ * forgotten, moving some unlocks to include tdbs and adding a missing
++ * unlock.  Thanks to Svenning for some of these.
++ *
++ * Revision 1.72  2000/11/09 20:11:22  rgb
++ * Minor shuffles to fix non-standard kernel config option selection.
++ *
++ * Revision 1.71  2000/11/06 04:36:18  rgb
++ * Ditched spin_lock_irqsave in favour of spin_lock.
++ * Minor initial protocol check rewrite.
++ * Clean up debug printing.
++ * Clean up tdb handling on ipcomp.
++ * Fixed transport mode null pointer de-reference without ipcomp.
++ * Add Svenning's adaptive content compression.
++ * Disabled registration of ipcomp handler.
++ *
++ * Revision 1.70  2000/10/30 23:41:43  henry
++ * Hans-Joerg Hoexer's null-pointer fix
++ *
++ * Revision 1.69  2000/10/10 18:54:16  rgb
++ * Added a fix for incoming policy check with ipcomp enabled but
++ * uncompressible.
++ *
++ * Revision 1.68  2000/09/22 17:53:12  rgb
++ * Fixed ipcomp tdb pointers update for policy checking.
++ *
++ * Revision 1.67  2000/09/21 03:40:58  rgb
++ * Added more debugging to try and track down the cpi outward copy problem.
++ *
++ * Revision 1.66  2000/09/20 04:00:10  rgb
++ * Changed static functions to DEBUG_NO_STATIC to reveal function names for
++ * debugging oopsen.
++ *
++ * Revision 1.65  2000/09/19 07:07:16  rgb
++ * Added debugging to inbound policy check for ipcomp.
++ * Added missing spin_unlocks (thanks Svenning!).
++ * Fixed misplaced tdbnext pointers causing mismatched ipip policy check.
++ * Protect ipcomp policy check following ipip decap with sysctl switch.
++ *
++ * Revision 1.64  2000/09/18 21:27:29  rgb
++ * 2.0 fixes.
++ *
++ * Revision 1.63  2000/09/18 02:35:50  rgb
++ * Added policy checking to ipcomp and re-enabled policy checking by
++ * default.
++ * Optimised satoa calls.
++ *
++ * Revision 1.62  2000/09/17 21:02:32  rgb
++ * Clean up debugging, removing slow timestamp debug code.
++ *
++ * Revision 1.61  2000/09/16 01:07:55  rgb
++ * Fixed erroneous ref from struct ipcomp to struct ipcomphdr.
++ *
++ * Revision 1.60  2000/09/15 11:37:01  rgb
++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++ * IPCOMP zlib deflate code.
++ *
++ * Revision 1.59  2000/09/15 04:56:20  rgb
++ * Remove redundant satoa() call, reformat comment.
++ *
++ * Revision 1.58  2000/09/13 08:00:52  rgb
++ * Flick on inbound policy checking.
++ *
++ * Revision 1.57  2000/09/12 03:22:19  rgb
++ * Converted inbound_policy_check to sysctl.
++ * Re-enabled policy backcheck.
++ * Moved policy checks to top and within tdb lock.
++ *
++ * Revision 1.56  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.55  2000/08/28 18:15:46  rgb
++ * Added MB's nf-debug reset patch.
++ *
++ * Revision 1.54  2000/08/27 01:41:26  rgb
++ * More minor tweaks to the bad padding debug code.
++ *
++ * Revision 1.53  2000/08/24 16:54:16  rgb
++ * Added KLIPS_PRINTMORE macro to continue lines without KERN_INFO level
++ * info.
++ * Tidied up device reporting at the start of ipsec_rcv.
++ * Tidied up bad padding debugging and processing.
++ *
++ * Revision 1.52  2000/08/20 21:36:03  rgb
++ * Activated pfkey_expire() calls.
++ * Added a hard/soft expiry parameter to pfkey_expire().
++ * Added sanity checking to avoid propagating zero or smaller-length skbs
++ * from a bogus decryption.
++ * Re-arranged the order of soft and hard expiry to conform to RFC2367.
++ * Clean up references to CONFIG_IPSEC_PFKEYv2.
++ *
++ * Revision 1.51  2000/08/18 21:23:30  rgb
++ * Improve bad padding warning so that the printk buffer doesn't get
++ * trampled.
++ *
++ * Revision 1.50  2000/08/01 14:51:51  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.49  2000/07/28 13:50:53  rgb
++ * Changed enet_statistics to net_device_stats and added back compatibility
++ * for pre-2.1.19.
++ *
++ * Revision 1.48  2000/05/10 19:14:40  rgb
++ * Only check usetime against soft and hard limits if the tdb has been
++ * used.
++ * Cast output of ntohl so that the broken prototype doesn't make our
++ * compile noisy.
++ *
++ * Revision 1.47  2000/05/09 17:45:43  rgb
++ * Fix replay bitmap corruption bug upon receipt of bogus packet
++ * with correct SPI.  This was a DoS.
++ *
++ * Revision 1.46  2000/03/27 02:31:58  rgb
++ * Fixed authentication failure printout bug.
++ *
++ * Revision 1.45  2000/03/22 16:15:37  rgb
++ * Fixed renaming of dev_get (MB).
++ *
++ * Revision 1.44  2000/03/16 08:17:24  rgb
++ * Hardcode PF_KEYv2 support.
++ * Fixed minor bug checking AH header length.
++ *
++ * Revision 1.43  2000/03/14 12:26:59  rgb
++ * Added skb->nfct support for clearing netfilter conntrack bits (MB).
++ *
++ * Revision 1.42  2000/01/26 10:04:04  rgb
++ * Fixed inbound policy checking on transport mode bug.
++ * Fixed noisy 2.0 printk arguments.
++ *
++ * Revision 1.41  2000/01/24 20:58:02  rgb
++ * Improve debugging/reporting support for (disabled) inbound
++ * policy checking.
++ *
++ * Revision 1.40  2000/01/22 23:20:10  rgb
++ * Fixed up inboud policy checking code.
++ * Cleaned out unused crud.
++ *
++ * Revision 1.39  2000/01/21 06:15:29  rgb
++ * Added sanity checks on skb_push(), skb_pull() to prevent panics.
++ * Fixed cut-and-paste debug_tunnel to debug_rcv.
++ * Added inbound policy checking code, disabled.
++ * Simplified output code by updating ipp to post-IPIP decapsulation.
++ *
++ * elided pre-2000 comments. Use "cvs log"
++ *
++ *
++ * Local Variables:
++ * c-set-style: linux
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_sa.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1870 @@
++/*
++ * Common routines for IPsec SA maintenance routines.
++ *
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001, 2002  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_sa.c,v 1.30.2.2 2006/10/06 21:39:26 paul Exp $
++ *
++ * This is the file formerly known as "ipsec_xform.h"
++ *
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/vmalloc.h> /* vmalloc() */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++#include <openswan.h>
++#ifdef SPINLOCK
++#ifdef SPINLOCK_23
++#include <linux/spinlock.h> /* *lock* */
++#else /* SPINLOCK_23 */
++#include <asm/spinlock.h> /* *lock* */
++#endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++
++#include "openswan/radij.h"
++
++#include "openswan/ipsec_stats.h"
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_sa.h"
++#include "openswan/ipsec_xform.h"
++
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_ipe4.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_alg.h"
++
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_xform = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
++
++struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];
++#ifdef SPINLOCK
++spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED;
++#else /* SPINLOCK */
++spinlock_t tdb_lock;
++#endif /* SPINLOCK */
++
++struct ipsec_sadb ipsec_sadb;
++
++#if IPSEC_SA_REF_CODE
++
++/* the sub table must be narrower (or equal) in bits than the variable type
++   in the main table to count the number of unused entries in it. */
++typedef struct {
++      int testSizeOf_refSubTable :
++              ((sizeof(IPsecRefTableUnusedCount) * 8) < IPSEC_SA_REF_SUBTABLE_IDX_WIDTH ? -1 : 1);
++} dummy;
++
++
++/* The field where the saref will be hosted in the skb must be wide enough to
++   accomodate the information it needs to store. */
++typedef struct {
++      int testSizeOf_refField : 
++              (IPSEC_SA_REF_HOST_FIELD_WIDTH < IPSEC_SA_REF_TABLE_IDX_WIDTH ? -1 : 1 );
++} dummy2;
++
++
++#define IPS_HASH(said) (((said)->spi + (said)->dst.u.v4.sin_addr.s_addr + (said)->proto) % SADB_HASHMOD)
++
++
++void
++ipsec_SAtest(void)
++{
++      IPsecSAref_t SAref = 258;
++      struct ipsec_sa ips;
++      ips.ips_ref = 772;
++
++      printk("klips_debug:ipsec_SAtest: "
++             "IPSEC_SA_REF_SUBTABLE_IDX_WIDTH=%u\n"
++             "IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES=%u\n"
++             "IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES=%u\n"
++             "IPSEC_SA_REF_HOST_FIELD_WIDTH=%lu\n"
++             "IPSEC_SA_REF_TABLE_MASK=%x\n"
++             "IPSEC_SA_REF_ENTRY_MASK=%x\n"
++             "IPsecSAref2table(%d)=%u\n"
++             "IPsecSAref2entry(%d)=%u\n"
++             "IPsecSAref2NFmark(%d)=%u\n"
++             "IPsecSAref2SA(%d)=%p\n"
++             "IPsecSA2SAref(%p)=%d\n"
++             ,
++             IPSEC_SA_REF_SUBTABLE_IDX_WIDTH,
++             IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES,
++             IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES,
++             (unsigned long) IPSEC_SA_REF_HOST_FIELD_WIDTH,
++             IPSEC_SA_REF_TABLE_MASK,
++             IPSEC_SA_REF_ENTRY_MASK,
++             SAref, IPsecSAref2table(SAref),
++             SAref, IPsecSAref2entry(SAref),
++             SAref, IPsecSAref2NFmark(SAref),
++             SAref, IPsecSAref2SA(SAref),
++             (&ips), IPsecSA2SAref((&ips))
++              );
++      return;
++}
++
++int
++ipsec_SAref_recycle(void)
++{
++      int table;
++      int entry;
++      int error = 0;
++
++      ipsec_sadb.refFreeListHead = -1;
++      ipsec_sadb.refFreeListTail = -1;
++
++      if(ipsec_sadb.refFreeListCont == IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_SAref_recycle: "
++                          "end of table reached, continuing at start..\n");
++              ipsec_sadb.refFreeListCont = 0;
++      }
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_SAref_recycle: "
++                  "recycling, continuing from SAref=%d (0p%p), table=%d, entry=%d.\n",
++                  ipsec_sadb.refFreeListCont,
++                  (ipsec_sadb.refTable[IPsecSAref2table(ipsec_sadb.refFreeListCont)] != NULL) ? IPsecSAref2SA(ipsec_sadb.refFreeListCont) : NULL,
++                  IPsecSAref2table(ipsec_sadb.refFreeListCont),
++                  IPsecSAref2entry(ipsec_sadb.refFreeListCont));
++
++      for(table = IPsecSAref2table(ipsec_sadb.refFreeListCont);
++          table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES;
++          table++) {
++              if(ipsec_sadb.refTable[table] == NULL) {
++                      error = ipsec_SArefSubTable_alloc(table);
++                      if(error) {
++                              return error;
++                      }
++              }
++              for(entry = IPsecSAref2entry(ipsec_sadb.refFreeListCont);
++                  entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES;
++                  entry++) {
++                      if(ipsec_sadb.refTable[table]->entry[entry] == NULL) {
++                              ipsec_sadb.refFreeList[++ipsec_sadb.refFreeListTail] = IPsecSArefBuild(table, entry);
++                              if(ipsec_sadb.refFreeListTail == (IPSEC_SA_REF_FREELIST_NUM_ENTRIES - 1)) {
++                                      ipsec_sadb.refFreeListHead = 0;
++                                      ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1;
++                                      KLIPS_PRINT(debug_xform,
++                                                  "klips_debug:ipsec_SAref_recycle: "
++                                                  "SArefFreeList refilled.\n");
++                                      return 0;
++                              }
++                      }
++              }
++      }
++
++      if(ipsec_sadb.refFreeListTail == -1) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_SAref_recycle: "
++                          "out of room in the SArefTable.\n");
++
++              return(-ENOSPC);
++      }
++
++      ipsec_sadb.refFreeListHead = 0;
++      ipsec_sadb.refFreeListCont = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListTail] + 1;
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_SAref_recycle: "
++                  "SArefFreeList partly refilled to %d of %d.\n",
++                  ipsec_sadb.refFreeListTail,
++                  IPSEC_SA_REF_FREELIST_NUM_ENTRIES);
++      return 0;
++}
++
++int
++ipsec_SArefSubTable_alloc(unsigned table)
++{
++      unsigned entry;
++      struct IPsecSArefSubTable* SArefsub;
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_SArefSubTable_alloc: "
++                  "allocating %lu bytes for table %u of %u.\n",
++                  (unsigned long) (IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *)),
++                  table,
++                  IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES);
++
++      /* allocate another sub-table */
++      SArefsub = vmalloc(IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES * sizeof(struct ipsec_sa *));
++      if(SArefsub == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_SArefSubTable_alloc: "
++                          "error allocating memory for table %u of %u!\n",
++                          table,
++                          IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES);
++              return -ENOMEM;
++      }
++
++      /* add this sub-table to the main table */
++      ipsec_sadb.refTable[table] = SArefsub;
++
++      /* initialise each element to NULL */
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_SArefSubTable_alloc: "
++                  "initialising %u elements (2 ^ %u) of table %u.\n",
++                  IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES,
++                  IPSEC_SA_REF_SUBTABLE_IDX_WIDTH,
++                  table);
++      for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) {
++              SArefsub->entry[entry] = NULL;
++      }
++
++      return 0;
++}
++#endif /* IPSEC_SA_REF_CODE */
++
++int
++ipsec_saref_freelist_init(void)
++{
++      int i;
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_saref_freelist_init: "
++                  "initialising %u elements of FreeList.\n",
++                  IPSEC_SA_REF_FREELIST_NUM_ENTRIES);
++
++      for(i = 0; i < IPSEC_SA_REF_FREELIST_NUM_ENTRIES; i++) {
++              ipsec_sadb.refFreeList[i] = IPSEC_SAREF_NULL;
++      }
++      ipsec_sadb.refFreeListHead = -1;
++      ipsec_sadb.refFreeListCont = 0;
++      ipsec_sadb.refFreeListTail = -1;
++       
++      return 0;
++}
++
++int
++ipsec_sadb_init(void)
++{
++      int error = 0;
++      unsigned i;
++
++      for(i = 0; i < SADB_HASHMOD; i++) {
++              ipsec_sadb_hash[i] = NULL;
++      }
++      /* parts above are for the old style SADB hash table */
++      
++
++#if IPSEC_SA_REF_CODE
++      /* initialise SA reference table */
++
++      /* initialise the main table */
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sadb_init: "
++                  "initialising main table of size %u (2 ^ %u).\n",
++                  IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES,
++                  IPSEC_SA_REF_MAINTABLE_IDX_WIDTH);
++      {
++              unsigned table;
++              for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) {
++                      ipsec_sadb.refTable[table] = NULL;
++              }
++      }
++
++      /* allocate the first sub-table */
++      error = ipsec_SArefSubTable_alloc(0);
++      if(error) {
++              return error;
++      }
++
++      error = ipsec_saref_freelist_init();
++#endif /* IPSEC_SA_REF_CODE */
++      return error;
++}
++
++#if IPSEC_SA_REF_CODE
++IPsecSAref_t
++ipsec_SAref_alloc(int*error) /* pass in error var by pointer */
++{
++      IPsecSAref_t SAref;
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_SAref_alloc: "
++                  "SAref requested... head=%d, cont=%d, tail=%d, listsize=%d.\n",
++                  ipsec_sadb.refFreeListHead,
++                  ipsec_sadb.refFreeListCont,
++                  ipsec_sadb.refFreeListTail,
++                  IPSEC_SA_REF_FREELIST_NUM_ENTRIES);
++
++      if(ipsec_sadb.refFreeListHead == -1) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_SAref_alloc: "
++                          "FreeList empty, recycling...\n");
++              *error = ipsec_SAref_recycle();
++              if(*error) {
++                      return IPSEC_SAREF_NULL;
++              }
++      }
++
++      SAref = ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead];
++      if(SAref == IPSEC_SAREF_NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_SAref_alloc: "
++                          "unexpected error, refFreeListHead = %d points to invalid entry.\n",
++                          ipsec_sadb.refFreeListHead);
++                      *error = -ESPIPE;
++                      return IPSEC_SAREF_NULL;
++      }
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_SAref_alloc: "
++                  "allocating SAref=%d, table=%u, entry=%u of %u.\n",
++                  SAref,
++                  IPsecSAref2table(SAref),
++                  IPsecSAref2entry(SAref),
++                  IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES * IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES);
++      
++      ipsec_sadb.refFreeList[ipsec_sadb.refFreeListHead] = IPSEC_SAREF_NULL;
++      ipsec_sadb.refFreeListHead++;
++      if(ipsec_sadb.refFreeListHead > ipsec_sadb.refFreeListTail) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_SAref_alloc: "
++                          "last FreeList entry allocated, resetting list head to empty.\n");
++              ipsec_sadb.refFreeListHead = -1;
++      }
++
++      return SAref;
++}
++#endif /* IPSEC_SA_REF_CODE */
++
++int
++ipsec_sa_print(struct ipsec_sa *ips)
++{
++        char sa[SATOT_BUF];
++      size_t sa_len;
++
++      printk(KERN_INFO "klips_debug:   SA:");
++      if(ips == NULL) {
++              printk("NULL\n");
++              return -ENOENT;
++      }
++      printk(" ref=%d", ips->ips_ref);
++      printk(" refcount=%d", atomic_read(&ips->ips_refcount));
++      if(ips->ips_hnext != NULL) {
++              printk(" hnext=0p%p", ips->ips_hnext);
++      }
++      if(ips->ips_inext != NULL) {
++              printk(" inext=0p%p", ips->ips_inext);
++      }
++      if(ips->ips_onext != NULL) {
++              printk(" onext=0p%p", ips->ips_onext);
++      }
++      sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++      printk(" said=%s", sa_len ? sa : " (error)");
++      if(ips->ips_seq) {
++              printk(" seq=%u", ips->ips_seq);
++      }
++      if(ips->ips_pid) {
++              printk(" pid=%u", ips->ips_pid);
++      }
++      if(ips->ips_authalg) {
++              printk(" authalg=%u", ips->ips_authalg);
++      }
++      if(ips->ips_encalg) {
++              printk(" encalg=%u", ips->ips_encalg);
++      }
++      printk(" XFORM=%s%s%s", IPS_XFORM_NAME(ips));
++      if(ips->ips_replaywin) {
++              printk(" ooowin=%u", ips->ips_replaywin);
++      }
++      if(ips->ips_flags) {
++              printk(" flags=%u", ips->ips_flags);
++      }
++      if(ips->ips_addr_s) {
++              char buf[SUBNETTOA_BUF];
++              addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr,
++                      0, buf, sizeof(buf));
++              printk(" src=%s", buf);
++      }
++      if(ips->ips_addr_d) {
++              char buf[SUBNETTOA_BUF];
++              addrtoa(((struct sockaddr_in*)(ips->ips_addr_s))->sin_addr,
++                      0, buf, sizeof(buf));
++              printk(" dst=%s", buf);
++      }
++      if(ips->ips_addr_p) {
++              char buf[SUBNETTOA_BUF];
++              addrtoa(((struct sockaddr_in*)(ips->ips_addr_p))->sin_addr,
++                      0, buf, sizeof(buf));
++              printk(" proxy=%s", buf);
++      }
++      if(ips->ips_key_bits_a) {
++              printk(" key_bits_a=%u", ips->ips_key_bits_a);
++      }
++      if(ips->ips_key_bits_e) {
++              printk(" key_bits_e=%u", ips->ips_key_bits_e);
++      }
++
++      printk("\n");
++      return 0;
++}
++
++struct ipsec_sa*
++ipsec_sa_alloc(int*error) /* pass in error var by pointer */
++{
++      struct ipsec_sa* ips;
++
++      if((ips = kmalloc(sizeof(*ips), GFP_ATOMIC) ) == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_alloc: "
++                          "memory allocation error\n");
++              *error = -ENOMEM;
++              return NULL;
++      }
++      memset((caddr_t)ips, 0, sizeof(*ips));
++#if IPSEC_SA_REF_CODE
++      ips->ips_ref = ipsec_SAref_alloc(error); /* pass in error return by pointer */
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sa_alloc: "
++                  "allocated %lu bytes for ipsec_sa struct=0p%p ref=%d.\n",
++                  (unsigned long) sizeof(*ips),
++                  ips,
++                  ips->ips_ref);
++      if(ips->ips_ref == IPSEC_SAREF_NULL) {
++              kfree(ips);
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_alloc: "
++                          "SAref allocation error\n");
++              return NULL;
++      }
++
++      atomic_inc(&ips->ips_refcount);
++      IPsecSAref2SA(ips->ips_ref) = ips;
++#endif /* IPSEC_SA_REF_CODE */
++
++      *error = 0;
++      return(ips);
++}
++
++int
++ipsec_sa_free(struct ipsec_sa* ips)
++{
++      return ipsec_sa_wipe(ips);
++}
++
++struct ipsec_sa *
++ipsec_sa_getbyid(ip_said *said)
++{
++      int hashval;
++      struct ipsec_sa *ips;
++        char sa[SATOT_BUF];
++      size_t sa_len;
++
++      if(said == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_error:ipsec_sa_getbyid: "
++                          "null pointer passed in!\n");
++              return NULL;
++      }
++
++      sa_len = satot(said, 0, sa, sizeof(sa));
++
++      hashval = IPS_HASH(said);
++      
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sa_getbyid: "
++                  "linked entry in ipsec_sa table for hash=%d of SA:%s requested.\n",
++                  hashval,
++                  sa_len ? sa : " (error)");
++
++      if((ips = ipsec_sadb_hash[hashval]) == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_getbyid: "
++                          "no entries in ipsec_sa table for hash=%d of SA:%s.\n",
++                          hashval,
++                          sa_len ? sa : " (error)");
++              return NULL;
++      }
++
++      for (; ips; ips = ips->ips_hnext) {
++              if ((ips->ips_said.spi == said->spi) &&
++                  (ips->ips_said.dst.u.v4.sin_addr.s_addr == said->dst.u.v4.sin_addr.s_addr) &&
++                  (ips->ips_said.proto == said->proto)) {
++                      atomic_inc(&ips->ips_refcount);
++                      return ips;
++              }
++      }
++      
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sa_getbyid: "
++                  "no entry in linked list for hash=%d of SA:%s.\n",
++                  hashval,
++                  sa_len ? sa : " (error)");
++      return NULL;
++}
++
++int
++ipsec_sa_put(struct ipsec_sa *ips)
++{
++        char sa[SATOT_BUF];
++      size_t sa_len;
++
++      if(ips == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_error:ipsec_sa_put: "
++                          "null pointer passed in!\n");
++              return -1;
++      }
++
++      sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sa_put: "
++                  "ipsec_sa SA:%s, ref:%d reference count decremented.\n",
++                  sa_len ? sa : " (error)",
++                  ips->ips_ref);
++
++      atomic_dec(&ips->ips_refcount);
++
++      return 0;
++}
++
++/*
++  The ipsec_sa table better *NOT* be locked before it is handed in, or SMP locks will happen
++*/
++int
++ipsec_sa_add(struct ipsec_sa *ips)
++{
++      int error = 0;
++      unsigned int hashval;
++
++      if(ips == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_error:ipsec_sa_add: "
++                          "null pointer passed in!\n");
++              return -ENODATA;
++      }
++      hashval = IPS_HASH(&ips->ips_said);
++
++      atomic_inc(&ips->ips_refcount);
++      spin_lock_bh(&tdb_lock);
++      
++      ips->ips_hnext = ipsec_sadb_hash[hashval];
++      ipsec_sadb_hash[hashval] = ips;
++      
++      spin_unlock_bh(&tdb_lock);
++
++      return error;
++}
++
++/*
++  The ipsec_sa table better be locked before it is handed in, or races might happen
++*/
++int
++ipsec_sa_del(struct ipsec_sa *ips)
++{
++      unsigned int hashval;
++      struct ipsec_sa *ipstp;
++        char sa[SATOT_BUF];
++      size_t sa_len;
++
++      if(ips == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_error:ipsec_sa_del: "
++                          "null pointer passed in!\n");
++              return -ENODATA;
++      }
++      
++      sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++      if(ips->ips_inext || ips->ips_onext) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_error:ipsec_sa_del: "
++                          "SA:%s still linked!\n",
++                          sa_len ? sa : " (error)");
++              return -EMLINK;
++      }
++      
++      hashval = IPS_HASH(&ips->ips_said);
++      
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sa_del: "
++                  "deleting SA:%s, hashval=%d.\n",
++                  sa_len ? sa : " (error)",
++                  hashval);
++      if(ipsec_sadb_hash[hashval] == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_del: "
++                          "no entries in ipsec_sa table for hash=%d of SA:%s.\n",
++                          hashval,
++                          sa_len ? sa : " (error)");
++              return -ENOENT;
++      }
++      
++      if (ips == ipsec_sadb_hash[hashval]) {
++              ipsec_sadb_hash[hashval] = ipsec_sadb_hash[hashval]->ips_hnext;
++              ips->ips_hnext = NULL;
++              atomic_dec(&ips->ips_refcount);
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_del: "
++                          "successfully deleted first ipsec_sa in chain.\n");
++              return 0;
++      } else {
++              for (ipstp = ipsec_sadb_hash[hashval];
++                   ipstp;
++                   ipstp = ipstp->ips_hnext) {
++                      if (ipstp->ips_hnext == ips) {
++                              ipstp->ips_hnext = ips->ips_hnext;
++                              ips->ips_hnext = NULL;
++                              atomic_dec(&ips->ips_refcount);
++                              KLIPS_PRINT(debug_xform,
++                                          "klips_debug:ipsec_sa_del: "
++                                          "successfully deleted link in ipsec_sa chain.\n");
++                              return 0;
++                      }
++              }
++      }
++      
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sa_del: "
++                  "no entries in linked list for hash=%d of SA:%s.\n",
++                  hashval,
++                  sa_len ? sa : " (error)");
++      return -ENOENT;
++}
++
++/*
++  The ipsec_sa table better be locked before it is handed in, or races
++  might happen
++*/
++int
++ipsec_sa_delchain(struct ipsec_sa *ips)
++{
++      struct ipsec_sa *ipsdel;
++      int error = 0;
++        char sa[SATOT_BUF];
++      size_t sa_len;
++
++      if(ips == NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_error:ipsec_sa_delchain: "
++                          "null pointer passed in!\n");
++              return -ENODATA;
++      }
++
++      sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sa_delchain: "
++                  "passed SA:%s\n",
++                  sa_len ? sa : " (error)");
++      while(ips->ips_onext != NULL) {
++              ips = ips->ips_onext;
++      }
++
++      while(ips) {
++              /* XXX send a pfkey message up to advise of deleted ipsec_sa */
++              sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_delchain: "
++                          "unlinking and delting SA:%s",
++                          sa_len ? sa : " (error)");
++              ipsdel = ips;
++              ips = ips->ips_inext;
++              if(ips != NULL) {
++                      sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++                      KLIPS_PRINT(debug_xform,
++                                  ", inext=%s",
++                                  sa_len ? sa : " (error)");
++                      atomic_dec(&ipsdel->ips_refcount);
++                      ipsdel->ips_inext = NULL;
++                      atomic_dec(&ips->ips_refcount);
++                      ips->ips_onext = NULL;
++              }
++              KLIPS_PRINT(debug_xform,
++                          ".\n");
++              if((error = ipsec_sa_del(ipsdel))) {
++                      KLIPS_PRINT(debug_xform,
++                                  "klips_debug:ipsec_sa_delchain: "
++                                  "ipsec_sa_del returned error %d.\n", -error);
++                      return error;
++              }
++              if((error = ipsec_sa_wipe(ipsdel))) {
++                      KLIPS_PRINT(debug_xform,
++                                  "klips_debug:ipsec_sa_delchain: "
++                                  "ipsec_sa_wipe returned error %d.\n", -error);
++                      return error;
++              }
++      }
++      return error;
++}
++
++int 
++ipsec_sadb_cleanup(__u8 proto)
++{
++      unsigned i;
++      int error = 0;
++      struct ipsec_sa *ips, **ipsprev, *ipsdel;
++        char sa[SATOT_BUF];
++      size_t sa_len;
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sadb_cleanup: "
++                  "cleaning up proto=%d.\n",
++                  proto);
++
++      spin_lock_bh(&tdb_lock);
++
++      for (i = 0; i < SADB_HASHMOD; i++) {
++              ipsprev = &(ipsec_sadb_hash[i]);
++              ips = ipsec_sadb_hash[i];
++              if(ips != NULL) {
++                      atomic_inc(&ips->ips_refcount);
++              }
++              for(; ips != NULL;) {
++                      sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++                      KLIPS_PRINT(debug_xform,
++                                  "klips_debug:ipsec_sadb_cleanup: "
++                                  "checking SA:%s, hash=%d, ref=%d",
++                                  sa_len ? sa : " (error)",
++                                  i,
++                                  ips->ips_ref);
++                      ipsdel = ips;
++                      ips = ipsdel->ips_hnext;
++                      if(ips != NULL) {
++                              atomic_inc(&ips->ips_refcount);
++                              sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++                              KLIPS_PRINT(debug_xform,
++                                          ", hnext=%s",
++                                          sa_len ? sa : " (error)");
++                      }
++                      if(*ipsprev != NULL) {
++                              sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa));
++                              KLIPS_PRINT(debug_xform,
++                                          ", *ipsprev=%s",
++                                          sa_len ? sa : " (error)");
++                              if((*ipsprev)->ips_hnext) {
++                                      sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa));
++                                      KLIPS_PRINT(debug_xform,
++                                                  ", *ipsprev->ips_hnext=%s",
++                                                  sa_len ? sa : " (error)");
++                              }
++                      }
++                      KLIPS_PRINT(debug_xform,
++                                  ".\n");
++                      if(proto == 0 || (proto == ipsdel->ips_said.proto)) {
++                              sa_len = satot(&ipsdel->ips_said, 0, sa, sizeof(sa));
++                              KLIPS_PRINT(debug_xform,
++                                          "klips_debug:ipsec_sadb_cleanup: "
++                                          "deleting SA chain:%s.\n",
++                                          sa_len ? sa : " (error)");
++                              if((error = ipsec_sa_delchain(ipsdel))) {
++                                      SENDERR(-error);
++                              }
++                              ipsprev = &(ipsec_sadb_hash[i]);
++                              ips = ipsec_sadb_hash[i];
++
++                              KLIPS_PRINT(debug_xform,
++                                          "klips_debug:ipsec_sadb_cleanup: "
++                                          "deleted SA chain:%s",
++                                          sa_len ? sa : " (error)");
++                              if(ips != NULL) {
++                                      sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++                                      KLIPS_PRINT(debug_xform,
++                                                  ", ipsec_sadb_hash[%d]=%s",
++                                                  i,
++                                                  sa_len ? sa : " (error)");
++                              }
++                              if(*ipsprev != NULL) {
++                                      sa_len = satot(&(*ipsprev)->ips_said, 0, sa, sizeof(sa));
++                                      KLIPS_PRINT(debug_xform,
++                                                  ", *ipsprev=%s",
++                                                  sa_len ? sa : " (error)");
++                                      if((*ipsprev)->ips_hnext != NULL) {
++                                              sa_len = satot(&(*ipsprev)->ips_hnext->ips_said, 0, sa, sizeof(sa));
++                                              KLIPS_PRINT(debug_xform,
++                                                          ", *ipsprev->ips_hnext=%s",
++                                                          sa_len ? sa : " (error)");
++                                      }
++                              }
++                              KLIPS_PRINT(debug_xform,
++                                          ".\n");
++                      } else {
++                              ipsprev = &ipsdel;
++                      }
++                      if(ipsdel != NULL) {
++                              ipsec_sa_put(ipsdel);
++                      }
++              }
++      }
++ errlab:
++
++      spin_unlock_bh(&tdb_lock);
++
++
++#if IPSEC_SA_REF_CODE
++      /* clean up SA reference table */
++
++      /* go through the ref table and clean out all the SAs */
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sadb_cleanup: "
++                  "removing SAref entries and tables.");
++      {
++              unsigned table, entry;
++              for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) {
++                      KLIPS_PRINT(debug_xform,
++                                  "klips_debug:ipsec_sadb_cleanup: "
++                                  "cleaning SAref table=%u.\n",
++                                  table);
++                      if(ipsec_sadb.refTable[table] == NULL) {
++                              printk("\n");
++                              KLIPS_PRINT(debug_xform,
++                                          "klips_debug:ipsec_sadb_cleanup: "
++                                          "cleaned %u used refTables.\n",
++                                          table);
++                              break;
++                      }
++                      for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) {
++                              if(ipsec_sadb.refTable[table]->entry[entry] != NULL) {
++                                      ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]);
++                                      ipsec_sadb.refTable[table]->entry[entry] = NULL;
++                              }
++                      }
++              }
++      }
++#endif /* IPSEC_SA_REF_CODE */
++
++      return(error);
++}
++
++int 
++ipsec_sadb_free(void)
++{
++      int error = 0;
++
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sadb_free: "
++                  "freeing SArefTable memory.\n");
++
++      /* clean up SA reference table */
++
++      /* go through the ref table and clean out all the SAs if any are
++         left and free table memory */
++      KLIPS_PRINT(debug_xform,
++                  "klips_debug:ipsec_sadb_free: "
++                  "removing SAref entries and tables.\n");
++      {
++              unsigned table, entry;
++              for(table = 0; table < IPSEC_SA_REF_MAINTABLE_NUM_ENTRIES; table++) {
++                      KLIPS_PRINT(debug_xform,
++                                  "klips_debug:ipsec_sadb_free: "
++                                  "removing SAref table=%u.\n",
++                                  table);
++                      if(ipsec_sadb.refTable[table] == NULL) {
++                              KLIPS_PRINT(debug_xform,
++                                          "klips_debug:ipsec_sadb_free: "
++                                          "removed %u used refTables.\n",
++                                          table);
++                              break;
++                      }
++                      for(entry = 0; entry < IPSEC_SA_REF_SUBTABLE_NUM_ENTRIES; entry++) {
++                              if(ipsec_sadb.refTable[table]->entry[entry] != NULL) {
++                                      ipsec_sa_delchain(ipsec_sadb.refTable[table]->entry[entry]);
++                                      ipsec_sadb.refTable[table]->entry[entry] = NULL;
++                              }
++                      }
++                      vfree(ipsec_sadb.refTable[table]);
++                      ipsec_sadb.refTable[table] = NULL;
++              }
++      }
++
++      return(error);
++}
++
++int
++ipsec_sa_wipe(struct ipsec_sa *ips)
++{
++      if(ips == NULL) {
++              return -ENODATA;
++      }
++
++      /* if(atomic_dec_and_test(ips)) {
++      }; */
++
++#if IPSEC_SA_REF_CODE
++      /* remove me from the SArefTable */
++      {
++              char sa[SATOT_BUF];
++              size_t sa_len;
++              sa_len = satot(&ips->ips_said, 0, sa, sizeof(sa));
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_wipe: "
++                          "removing SA=%s(0p%p), SAref=%d, table=%d(0p%p), entry=%d from the refTable.\n",
++                          sa_len ? sa : " (error)",
++                          ips,
++                          ips->ips_ref,
++                          IPsecSAref2table(IPsecSA2SAref(ips)),
++                          ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))],
++                          IPsecSAref2entry(IPsecSA2SAref(ips)));
++      }
++      if(ips->ips_ref == IPSEC_SAREF_NULL) {
++              KLIPS_PRINT(debug_xform,
++                          "klips_debug:ipsec_sa_wipe: "
++                          "why does this SA not have a valid SAref?.\n");
++      }
++      ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))]->entry[IPsecSAref2entry(IPsecSA2SAref(ips))] = NULL;
++      ips->ips_ref = IPSEC_SAREF_NULL;
++      ipsec_sa_put(ips);
++#endif /* IPSEC_SA_REF_CODE */
++
++      /* paranoid clean up */
++      if(ips->ips_addr_s != NULL) {
++              memset((caddr_t)(ips->ips_addr_s), 0, ips->ips_addr_s_size);
++              kfree(ips->ips_addr_s);
++      }
++      ips->ips_addr_s = NULL;
++
++      if(ips->ips_addr_d != NULL) {
++              memset((caddr_t)(ips->ips_addr_d), 0, ips->ips_addr_d_size);
++              kfree(ips->ips_addr_d);
++      }
++      ips->ips_addr_d = NULL;
++
++      if(ips->ips_addr_p != NULL) {
++              memset((caddr_t)(ips->ips_addr_p), 0, ips->ips_addr_p_size);
++              kfree(ips->ips_addr_p);
++      }
++      ips->ips_addr_p = NULL;
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      if(ips->ips_natt_oa) {
++              memset((caddr_t)(ips->ips_natt_oa), 0, ips->ips_natt_oa_size);
++              kfree(ips->ips_natt_oa);
++      }
++      ips->ips_natt_oa = NULL;
++#endif
++
++      if(ips->ips_key_a != NULL) {
++              memset((caddr_t)(ips->ips_key_a), 0, ips->ips_key_a_size);
++              kfree(ips->ips_key_a);
++      }
++      ips->ips_key_a = NULL;
++
++      if(ips->ips_key_e != NULL) {
++              if (ips->ips_alg_enc &&
++                  ips->ips_alg_enc->ixt_e_destroy_key)
++              {
++                      ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc, 
++                                                          ips->ips_key_e);
++              } else
++              {
++                      memset((caddr_t)(ips->ips_key_e), 0, ips->ips_key_e_size);
++                      kfree(ips->ips_key_e);
++              }
++      }
++      ips->ips_key_e = NULL;
++
++      if(ips->ips_iv != NULL) {
++              memset((caddr_t)(ips->ips_iv), 0, ips->ips_iv_size);
++              kfree(ips->ips_iv);
++      }
++      ips->ips_iv = NULL;
++
++      if(ips->ips_ident_s.data != NULL) {
++              memset((caddr_t)(ips->ips_ident_s.data),
++                       0,
++                     ips->ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident));
++              kfree(ips->ips_ident_s.data);
++        }
++      ips->ips_ident_s.data = NULL;
++      
++      if(ips->ips_ident_d.data != NULL) {
++              memset((caddr_t)(ips->ips_ident_d.data),
++                       0,
++                     ips->ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident));
++              kfree(ips->ips_ident_d.data);
++        }
++      ips->ips_ident_d.data = NULL;
++
++      if (ips->ips_alg_enc||ips->ips_alg_auth) {
++              ipsec_alg_sa_wipe(ips);
++      }
++      
++      memset((caddr_t)ips, 0, sizeof(*ips));
++      kfree(ips);
++      ips = NULL;
++
++      return 0;
++}
++
++extern int sysctl_ipsec_debug_verbose;
++
++int ipsec_sa_init(struct ipsec_sa *ipsp)
++{
++        int i;
++        int error = 0;
++        char sa[SATOT_BUF];
++      size_t sa_len;
++      char ipaddr_txt[ADDRTOA_BUF];
++      char ipaddr2_txt[ADDRTOA_BUF];
++#if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1)
++      unsigned char kb[AHMD596_BLKLEN];
++#endif
++      struct ipsec_alg_enc *ixt_e = NULL;
++      struct ipsec_alg_auth *ixt_a = NULL;
++
++      if(ipsp == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "ipsec_sa_init: "
++                          "ipsp is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      sa_len = satot(&ipsp->ips_said, 0, sa, sizeof(sa));
++
++        KLIPS_PRINT(debug_pfkey,
++                  "ipsec_sa_init: "
++                  "(pfkey defined) called for SA:%s\n",
++                  sa_len ? sa : " (error)");
++
++      KLIPS_PRINT(debug_pfkey,
++                  "ipsec_sa_init: "
++                  "calling init routine of %s%s%s\n",
++                  IPS_XFORM_NAME(ipsp));
++      
++      switch(ipsp->ips_said.proto) {
++              
++#ifdef CONFIG_KLIPS_IPIP
++      case IPPROTO_IPIP: {
++              addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr,
++                      0,
++                      ipaddr_txt, sizeof(ipaddr_txt));
++              addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr,
++                      0,
++                      ipaddr2_txt, sizeof(ipaddr_txt));
++              KLIPS_PRINT(debug_pfkey,
++                          "ipsec_sa_init: "
++                          "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n",
++                          ipaddr_txt,
++                          ipaddr2_txt);
++      }
++      break;
++#endif /* !CONFIG_KLIPS_IPIP */
++
++#ifdef CONFIG_KLIPS_AH
++      case IPPROTO_AH:
++              switch(ipsp->ips_authalg) {
++# ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              case AH_MD5: {
++                      unsigned char *akp;
++                      unsigned int aks;
++                      MD5_CTX *ictx;
++                      MD5_CTX *octx;
++                      
++                      if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) {
++                              KLIPS_PRINT(debug_pfkey,
++                                          "ipsec_sa_init: "
++                                          "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
++                                          ipsp->ips_key_bits_a, AHMD596_KLEN * 8);
++                              SENDERR(EINVAL);
++                      }
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "hmac md5-96 key is 0x%08x %08x %08x %08x\n",
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+0)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+1)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+2)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+3)));
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      
++                      ipsp->ips_auth_bits = AHMD596_ALEN * 8;
++                      
++                      /* save the pointer to the key material */
++                      akp = ipsp->ips_key_a;
++                      aks = ipsp->ips_key_a_size;
++                      
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                 "ipsec_sa_init: "
++                                 "allocating %lu bytes for md5_ctx.\n",
++                                 (unsigned long) sizeof(struct md5_ctx));
++                      if((ipsp->ips_key_a = (caddr_t)
++                          kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) {
++                              ipsp->ips_key_a = akp;
++                              SENDERR(ENOMEM);
++                      }
++                      ipsp->ips_key_a_size = sizeof(struct md5_ctx);
++
++                      for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) {
++                              kb[i] = akp[i] ^ HMAC_IPAD;
++                      }
++                      for (; i < AHMD596_BLKLEN; i++) {
++                              kb[i] = HMAC_IPAD;
++                      }
++
++                      ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx);
++                      osMD5Init(ictx);
++                      osMD5Update(ictx, kb, AHMD596_BLKLEN);
++
++                      for (i = 0; i < AHMD596_BLKLEN; i++) {
++                              kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
++                      }
++
++                      octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx);
++                      osMD5Init(octx);
++                      osMD5Update(octx, kb, AHMD596_BLKLEN);
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
++                                  ((__u32*)ictx)[0],
++                                  ((__u32*)ictx)[1],
++                                  ((__u32*)ictx)[2],
++                                  ((__u32*)ictx)[3],
++                                  ((__u32*)octx)[0],
++                                  ((__u32*)octx)[1],
++                                  ((__u32*)octx)[2],
++                                  ((__u32*)octx)[3] );
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      
++                      /* zero key buffer -- paranoid */
++                      memset(akp, 0, aks);
++                      kfree(akp);
++              }
++              break;
++# endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++# ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              case AH_SHA: {
++                      unsigned char *akp;
++                      unsigned int aks;
++                      SHA1_CTX *ictx;
++                      SHA1_CTX *octx;
++                      
++                      if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) {
++                              KLIPS_PRINT(debug_pfkey,
++                                          "ipsec_sa_init: "
++                                          "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
++                                          ipsp->ips_key_bits_a, AHSHA196_KLEN * 8);
++                              SENDERR(EINVAL);
++                      }
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+0)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+1)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+2)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+3)));
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      
++                      ipsp->ips_auth_bits = AHSHA196_ALEN * 8;
++                      
++                      /* save the pointer to the key material */
++                      akp = ipsp->ips_key_a;
++                      aks = ipsp->ips_key_a_size;
++                      
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "allocating %lu bytes for sha1_ctx.\n",
++                                  (unsigned long) sizeof(struct sha1_ctx));
++                      if((ipsp->ips_key_a = (caddr_t)
++                          kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) {
++                              ipsp->ips_key_a = akp;
++                              SENDERR(ENOMEM);
++                      }
++                      ipsp->ips_key_a_size = sizeof(struct sha1_ctx);
++
++                      for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) {
++                              kb[i] = akp[i] ^ HMAC_IPAD;
++                      }
++                      for (; i < AHMD596_BLKLEN; i++) {
++                              kb[i] = HMAC_IPAD;
++                      }
++
++                      ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx);
++                      SHA1Init(ictx);
++                      SHA1Update(ictx, kb, AHSHA196_BLKLEN);
++
++                      for (i = 0; i < AHSHA196_BLKLEN; i++) {
++                              kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
++                      }
++
++                      octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx);
++                      SHA1Init(octx);
++                      SHA1Update(octx, kb, AHSHA196_BLKLEN);
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", 
++                                  ((__u32*)ictx)[0],
++                                  ((__u32*)ictx)[1],
++                                  ((__u32*)ictx)[2],
++                                  ((__u32*)ictx)[3],
++                                  ((__u32*)octx)[0],
++                                  ((__u32*)octx)[1],
++                                  ((__u32*)octx)[2],
++                                  ((__u32*)octx)[3] );
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      /* zero key buffer -- paranoid */
++                      memset(akp, 0, aks);
++                      kfree(akp);
++              }
++              break;
++# endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++              default:
++                      KLIPS_PRINT(debug_pfkey,
++                                  "ipsec_sa_init: "
++                                  "authalg=%d support not available in the kernel",
++                                  ipsp->ips_authalg);
++                      SENDERR(EINVAL);
++              }
++      break;
++#endif /* CONFIG_KLIPS_AH */
++
++#ifdef CONFIG_KLIPS_ESP
++      case IPPROTO_ESP:
++      {
++#if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1)
++              unsigned char *akp;
++              unsigned int aks;
++#endif
++
++              ipsec_alg_sa_init(ipsp);
++              ixt_e=ipsp->ips_alg_enc;
++
++              if (ixt_e == NULL) {
++                      if(printk_ratelimit()) {
++                              printk(KERN_INFO 
++                                     "ipsec_sa_init: "
++                                     "encalg=%d support not available in the kernel",
++                                     ipsp->ips_encalg);
++                      }
++                      SENDERR(ENOENT);
++              }
++
++              ipsp->ips_iv_size = ixt_e->ixt_common.ixt_support.ias_ivlen/8;
++
++              /* Create IV */
++              if (ipsp->ips_iv_size) {
++                      if((ipsp->ips_iv = (caddr_t)
++                          kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) {
++                              SENDERR(ENOMEM);
++                      }
++                      prng_bytes(&ipsec_prng,
++                                 (char *)ipsp->ips_iv,
++                                 ipsp->ips_iv_size);
++                      ipsp->ips_iv_bits = ipsp->ips_iv_size * 8;
++              }
++              
++              if ((error=ipsec_alg_enc_key_create(ipsp)) < 0)
++                      SENDERR(-error);
++
++              if ((ixt_a=ipsp->ips_alg_auth)) {
++                      if ((error=ipsec_alg_auth_key_create(ipsp)) < 0)
++                              SENDERR(-error);
++              } else  
++              
++              switch(ipsp->ips_authalg) {
++# ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              case AH_MD5: {
++                      MD5_CTX *ictx;
++                      MD5_CTX *octx;
++
++                      if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) {
++                              KLIPS_PRINT(debug_pfkey,
++                                          "ipsec_sa_init: "
++                                          "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
++                                          ipsp->ips_key_bits_a,
++                                          AHMD596_KLEN * 8);
++                              SENDERR(EINVAL);
++                      }
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "hmac md5-96 key is 0x%08x %08x %08x %08x\n",
++                                  ntohl(*(((__u32 *)(ipsp->ips_key_a))+0)),
++                                  ntohl(*(((__u32 *)(ipsp->ips_key_a))+1)),
++                                  ntohl(*(((__u32 *)(ipsp->ips_key_a))+2)),
++                                  ntohl(*(((__u32 *)(ipsp->ips_key_a))+3)));
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      ipsp->ips_auth_bits = AHMD596_ALEN * 8;
++                      
++                      /* save the pointer to the key material */
++                      akp = ipsp->ips_key_a;
++                      aks = ipsp->ips_key_a_size;
++                      
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "allocating %lu bytes for md5_ctx.\n",
++                                  (unsigned long) sizeof(struct md5_ctx));
++                      if((ipsp->ips_key_a = (caddr_t)
++                          kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) {
++                              ipsp->ips_key_a = akp;
++                              SENDERR(ENOMEM);
++                      }
++                      ipsp->ips_key_a_size = sizeof(struct md5_ctx);
++
++                      for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) {
++                              kb[i] = akp[i] ^ HMAC_IPAD;
++                      }
++                      for (; i < AHMD596_BLKLEN; i++) {
++                              kb[i] = HMAC_IPAD;
++                      }
++
++                      ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx);
++                      osMD5Init(ictx);
++                      osMD5Update(ictx, kb, AHMD596_BLKLEN);
++
++                      for (i = 0; i < AHMD596_BLKLEN; i++) {
++                              kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
++                      }
++
++                      octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx);
++                      osMD5Init(octx);
++                      osMD5Update(octx, kb, AHMD596_BLKLEN);
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
++                                  ((__u32*)ictx)[0],
++                                  ((__u32*)ictx)[1],
++                                  ((__u32*)ictx)[2],
++                                  ((__u32*)ictx)[3],
++                                  ((__u32*)octx)[0],
++                                  ((__u32*)octx)[1],
++                                  ((__u32*)octx)[2],
++                                  ((__u32*)octx)[3] );
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      /* paranoid */
++                      memset(akp, 0, aks);
++                      kfree(akp);
++                      break;
++              }
++# endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++# ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              case AH_SHA: {
++                      SHA1_CTX *ictx;
++                      SHA1_CTX *octx;
++
++                      if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) {
++                              KLIPS_PRINT(debug_pfkey,
++                                          "ipsec_sa_init: "
++                                          "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
++                                          ipsp->ips_key_bits_a,
++                                          AHSHA196_KLEN * 8);
++                              SENDERR(EINVAL);
++                      }
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+0)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+1)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+2)),
++                                  ntohl(*(((__u32 *)ipsp->ips_key_a)+3)));
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      ipsp->ips_auth_bits = AHSHA196_ALEN * 8;
++                      
++                      /* save the pointer to the key material */
++                      akp = ipsp->ips_key_a;
++                      aks = ipsp->ips_key_a_size;
++
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "allocating %lu bytes for sha1_ctx.\n",
++                                  (unsigned long) sizeof(struct sha1_ctx));
++                      if((ipsp->ips_key_a = (caddr_t)
++                          kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) {
++                              ipsp->ips_key_a = akp;
++                              SENDERR(ENOMEM);
++                      }
++                      ipsp->ips_key_a_size = sizeof(struct sha1_ctx);
++
++                      for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) {
++                              kb[i] = akp[i] ^ HMAC_IPAD;
++                      }
++                      for (; i < AHMD596_BLKLEN; i++) {
++                              kb[i] = HMAC_IPAD;
++                      }
++
++                      ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx);
++                      SHA1Init(ictx);
++                      SHA1Update(ictx, kb, AHSHA196_BLKLEN);
++
++                      for (i = 0; i < AHSHA196_BLKLEN; i++) {
++                              kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);
++                      }
++
++                      octx = &((struct sha1_ctx*)(ipsp->ips_key_a))->octx;
++                      SHA1Init(octx);
++                      SHA1Update(octx, kb, AHSHA196_BLKLEN);
++                      
++#  if KLIPS_DIVULGE_HMAC_KEY
++                      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                  "ipsec_sa_init: "
++                                  "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
++                                  ((__u32*)ictx)[0],
++                                  ((__u32*)ictx)[1],
++                                  ((__u32*)ictx)[2],
++                                  ((__u32*)ictx)[3],
++                                  ((__u32*)octx)[0],
++                                  ((__u32*)octx)[1],
++                                  ((__u32*)octx)[2],
++                                  ((__u32*)octx)[3] );
++#  endif /* KLIPS_DIVULGE_HMAC_KEY */
++                      memset(akp, 0, aks);
++                      kfree(akp);
++                      break;
++              }
++# endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++              case AH_NONE:
++                      break;
++              default:
++                      KLIPS_PRINT(debug_pfkey,
++                                  "ipsec_sa_init: "
++                                  "authalg=%d support not available in the kernel.\n",
++                                  ipsp->ips_authalg);
++                      SENDERR(EINVAL);
++              }
++      }
++                      break;
++#endif /* !CONFIG_KLIPS_ESP */
++#ifdef CONFIG_KLIPS_IPCOMP
++      case IPPROTO_COMP:
++              ipsp->ips_comp_adapt_tries = 0;
++              ipsp->ips_comp_adapt_skip = 0;
++              ipsp->ips_comp_ratio_cbytes = 0;
++              ipsp->ips_comp_ratio_dbytes = 0;
++              break;
++#endif /* CONFIG_KLIPS_IPCOMP */
++      default:
++              printk(KERN_ERR "KLIPS sa initialization: "
++                     "proto=%d unknown.\n",
++                     ipsp->ips_said.proto);
++              SENDERR(EINVAL);
++      }
++      
++ errlab:
++      return(error);
++}
++
++
++
++/*
++ * $Log: ipsec_sa.c,v $
++ * Revision 1.30.2.2  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.30.2.1  2006/04/20 16:33:07  mcr
++ * remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++ * Fix in-kernel module compilation. Sub-makefiles do not work.
++ *
++ * Revision 1.30  2005/05/24 01:02:35  mcr
++ *    some refactoring/simplification of situation where alg
++ *    is not found.
++ *
++ * Revision 1.29  2005/05/18 19:13:28  mcr
++ *    rename debug messages. make sure that algo not found is not
++ *    a debug message.
++ *
++ * Revision 1.28  2005/05/11 01:30:20  mcr
++ *    removed "poor-man"s OOP in favour of proper C structures.
++ *
++ * Revision 1.27  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.26  2005/04/14 20:56:24  mcr
++ *    moved (pfkey_)ipsec_sa_init to ipsec_sa.c.
++ *
++ * Revision 1.25  2004/08/22 20:12:16  mcr
++ *    one more KLIPS_NAT->IPSEC_NAT.
++ *
++ * Revision 1.24  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.23  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.22.2.1  2003/12/22 15:25:52  jjo
++ * . Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.22  2003/12/10 01:14:27  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.21  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.20.4.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.20  2003/02/06 01:50:34  rgb
++ * Fixed initialisation bug for first sadb hash bucket that would only manifest itself on platforms where NULL != 0.
++ *
++ * Revision 1.19  2003/01/30 02:32:22  rgb
++ *
++ * Rename SAref table macro names for clarity.
++ * Transmit error code through to caller from callee for better diagnosis of problems.
++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
++ *
++ * Revision 1.18  2002/10/12 23:11:53  dhr
++ *
++ * [KenB + DHR] more 64-bit cleanup
++ *
++ * Revision 1.17  2002/10/07 18:31:43  rgb
++ * Move field width sanity checks to ipsec_sa.c
++ *
++ * Revision 1.16  2002/09/20 15:41:02  rgb
++ * Re-wrote most of the SAref code to eliminate Entry pointers.
++ * Added SAref code compiler directive switch.
++ * Added a saref test function for testing macros.
++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc().
++ * Split ipsec_sadb_cleanup from new funciton ipsec_sadb_free to avoid problem
++ * of freeing newly created structures when clearing the reftable upon startup
++ * to start from a known state.
++ * Place all ipsec sadb globals into one struct.
++ * Rework saref freelist.
++ * Added memory allocation debugging.
++ *
++ * Revision 1.15  2002/09/20 05:01:44  rgb
++ * Update copyright date.
++ *
++ * Revision 1.14  2002/08/13 19:01:25  mcr
++ *    patches from kenb to permit compilation of FreeSWAN on ia64.
++ *    des library patched to use proper DES_LONG type for ia64.
++ *
++ * Revision 1.13  2002/07/29 03:06:20  mcr
++ *    get rid of variable not used warnings.
++ *
++ * Revision 1.12  2002/07/26 08:48:31  rgb
++ * Added SA ref table code.
++ *
++ * Revision 1.11  2002/06/04 16:48:49  rgb
++ * Tidied up pointer code for processor independance.
++ *
++ * Revision 1.10  2002/05/23 07:16:17  rgb
++ * Added ipsec_sa_put() for releasing an ipsec_sa refcount.
++ * Pointer clean-up.
++ * Added refcount code.
++ * Convert "usecount" to "refcount" to remove ambiguity.
++ *
++ * Revision 1.9  2002/05/14 02:34:49  rgb
++ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion
++ * with "put" usage in the kernel.
++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips,
++ * ipsec_sa or ipsec_sa.
++ * Added some preliminary refcount code.
++ *
++ * Revision 1.8  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.7  2002/04/24 07:36:30  mcr
++ * Moved from ./klips/net/ipsec/ipsec_sa.c,v
++ *
++ * Revision 1.6  2002/04/20 00:12:25  rgb
++ * Added esp IV CBC attack fix, disabled.
++ *
++ * Revision 1.5  2002/01/29 17:17:56  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.4  2002/01/29 04:00:52  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.3  2002/01/29 02:13:18  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.2  2001/11/26 09:16:15  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.1.2.2  2001/10/22 21:05:41  mcr
++ *    removed phony prototype for des_set_key.
++ *
++ * Revision 1.1.2.1  2001/09/25 02:24:57  mcr
++ *    struct tdb -> struct ipsec_sa.
++ *    sa(tdb) manipulation functions renamed and moved to ipsec_sa.c
++ *    ipsec_xform.c removed. header file still contains useful things.
++ *
++ *
++ *
++ * CLONED from ipsec_xform.c:
++ * Revision 1.53  2001/09/08 21:13:34  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.52  2001/06/14 19:35:11  rgb
++ * Update copyright date.
++ *
++ * Revision 1.51  2001/05/30 08:14:03  rgb
++ * Removed vestiges of esp-null transforms.
++ *
++ * Revision 1.50  2001/05/03 19:43:18  rgb
++ * Initialise error return variable.
++ * Update SENDERR macro.
++ * Fix sign of error return code for ipsec_tdbcleanup().
++ * Use more appropriate return code for ipsec_tdbwipe().
++ *
++ * Revision 1.49  2001/04/19 18:56:17  rgb
++ * Fixed tdb table locking comments.
++ *
++ * Revision 1.48  2001/02/27 22:24:55  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.47  2000/11/06 04:32:08  rgb
++ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
++ *
++ * Revision 1.46  2000/09/20 16:21:57  rgb
++ * Cleaned up ident string alloc/free.
++ *
++ * Revision 1.45  2000/09/08 19:16:51  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ * Removed all references to CONFIG_IPSEC_PFKEYv2.
++ *
++ * Revision 1.44  2000/08/30 05:29:04  rgb
++ * Compiler-define out no longer used tdb_init() in ipsec_xform.c.
++ *
++ * Revision 1.43  2000/08/18 21:30:41  rgb
++ * Purged all tdb_spi, tdb_proto and tdb_dst macros.  They are unclear.
++ *
++ * Revision 1.42  2000/08/01 14:51:51  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.41  2000/07/28 14:58:31  rgb
++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
++ *
++ * Revision 1.40  2000/06/28 05:50:11  rgb
++ * Actually set iv_bits.
++ *
++ * Revision 1.39  2000/05/10 23:11:09  rgb
++ * Added netlink debugging output.
++ * Added a cast to quiet down the ntohl bug.
++ *
++ * Revision 1.38  2000/05/10 19:18:42  rgb
++ * Cast output of ntohl so that the broken prototype doesn't make our
++ * compile noisy.
++ *
++ * Revision 1.37  2000/03/16 14:04:59  rgb
++ * Hardwired CONFIG_IPSEC_PFKEYv2 on.
++ *
++ * Revision 1.36  2000/01/26 10:11:28  rgb
++ * Fixed spacing in error text causing run-in words.
++ *
++ * Revision 1.35  2000/01/21 06:17:16  rgb
++ * Tidied up compiler directive indentation for readability.
++ * Added ictx,octx vars for simplification.(kravietz)
++ * Added macros for HMAC padding magic numbers.(kravietz)
++ * Fixed missing key length reporting bug.
++ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in.
++ *
++ * Revision 1.34  1999/12/08 00:04:19  rgb
++ * Fixed SA direction overwriting bug for netlink users.
++ *
++ * Revision 1.33  1999/12/01 22:16:44  rgb
++ * Minor formatting changes in ESP MD5 initialisation.
++ *
++ * Revision 1.32  1999/11/25 09:06:36  rgb
++ * Fixed error return messages, should be returning negative numbers.
++ * Implemented SENDERR macro for propagating error codes.
++ * Added debug message and separate error code for algorithms not compiled
++ * in.
++ *
++ * Revision 1.31  1999/11/23 23:06:26  rgb
++ * Sort out pfkey and freeswan headers, putting them in a library path.
++ *
++ * Revision 1.30  1999/11/18 04:09:20  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ *
++ * Revision 1.29  1999/11/17 15:53:40  rgb
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ *
++ * Revision 1.28  1999/10/18 20:04:01  rgb
++ * Clean-out unused cruft.
++ *
++ * Revision 1.27  1999/10/03 19:01:03  rgb
++ * Spinlock support for 2.3.xx and 2.0.xx kernels.
++ *
++ * Revision 1.26  1999/10/01 16:22:24  rgb
++ * Switch from assignment init. to functional init. of spinlocks.
++ *
++ * Revision 1.25  1999/10/01 15:44:54  rgb
++ * Move spinlock header include to 2.1> scope.
++ *
++ * Revision 1.24  1999/10/01 00:03:46  rgb
++ * Added tdb structure locking.
++ * Minor formatting changes.
++ * Add function to initialize tdb hash table.
++ *
++ * Revision 1.23  1999/05/25 22:42:12  rgb
++ * Add deltdbchain() debugging.
++ *
++ * Revision 1.22  1999/05/25 21:24:31  rgb
++ * Add debugging statements to deltdbchain().
++ *
++ * Revision 1.21  1999/05/25 03:51:48  rgb
++ * Refix error return code.
++ *
++ * Revision 1.20  1999/05/25 03:34:07  rgb
++ * Fix error return for flush.
++ *
++ * Revision 1.19  1999/05/09 03:25:37  rgb
++ * Fix bug introduced by 2.2 quick-and-dirty patch.
++ *
++ * Revision 1.18  1999/05/05 22:02:32  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.17  1999/04/29 15:20:16  rgb
++ * Change gettdb parameter to a pointer to reduce stack loading and
++ * facilitate parameter sanity checking.
++ * Add sanity checking for null pointer arguments.
++ * Add debugging instrumentation.
++ * Add function deltdbchain() which will take care of unlinking,
++ * zeroing and deleting a chain of tdbs.
++ * Add a parameter to tdbcleanup to be able to delete a class of SAs.
++ * tdbwipe now actually zeroes the tdb as well as any of its pointed
++ * structures.
++ *
++ * Revision 1.16  1999/04/16 15:36:29  rgb
++ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing.
++ *
++ * Revision 1.15  1999/04/11 00:29:01  henry
++ * GPL boilerplate
++ *
++ * Revision 1.14  1999/04/06 04:54:28  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.13  1999/02/19 18:23:01  rgb
++ * Nix debug off compile warning.
++ *
++ * Revision 1.12  1999/02/17 16:52:16  rgb
++ * Consolidate satoa()s for space and speed efficiency.
++ * Convert DEBUG_IPSEC to KLIPS_PRINT
++ * Clean out unused cruft.
++ * Ditch NET_IPIP dependancy.
++ * Loop for 3des key setting.
++ *
++ * Revision 1.11  1999/01/26 02:09:05  rgb
++ * Remove ah/esp/IPIP switching on include files.
++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
++ * Removed dead code.
++ * Clean up debug code when switched off.
++ * Remove references to INET_GET_PROTOCOL.
++ * Added code exclusion macros to reduce code from unused algorithms.
++ *
++ * Revision 1.10  1999/01/22 06:28:55  rgb
++ * Cruft clean-out.
++ * Put random IV generation in kernel.
++ * Added algorithm switch code.
++ * Enhanced debugging.
++ * 64-bit clean-up.
++ *
++ * Revision 1.9  1998/11/30 13:22:55  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.8  1998/11/25 04:59:06  rgb
++ * Add conditionals for no IPIP tunnel code.
++ * Delete commented out code.
++ *
++ * Revision 1.7  1998/10/31 06:50:41  rgb
++ * Convert xform ASCII names to no spaces.
++ * Fixed up comments in #endif directives.
++ *
++ * Revision 1.6  1998/10/19 14:44:28  rgb
++ * Added inclusion of freeswan.h.
++ * sa_id structure implemented and used: now includes protocol.
++ *
++ * Revision 1.5  1998/10/09 04:32:19  rgb
++ * Added 'klips_debug' prefix to all klips printk debug statements.
++ *
++ * Revision 1.4  1998/08/12 00:11:31  rgb
++ * Added new xform functions to the xform table.
++ * Fixed minor debug output spelling error.
++ *
++ * Revision 1.3  1998/07/09 17:45:31  rgb
++ * Clarify algorithm not available message.
++ *
++ * Revision 1.2  1998/06/23 03:00:51  rgb
++ * Check for presence of IPIP protocol if it is setup one way (we don't
++ * know what has been set up the other way and can only assume it will be
++ * symmetrical with the exception of keys).
++ *
++ * Revision 1.1  1998/06/18 21:27:51  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.3  1998/06/11 05:54:59  rgb
++ * Added transform version string pointer to xformsw initialisations.
++ *
++ * Revision 1.2  1998/04/21 21:28:57  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.1  1998/04/09 03:06:13  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.5  1997/06/03 04:24:48  ji
++ * Added ESP-3DES-MD5-96
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * Added new transforms.
++ *
++ * Revision 0.3  1996/11/20 14:39:04  ji
++ * Minor cleanups.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_sha1.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,219 @@
++/*
++ * RCSID $Id: ipsec_sha1.c,v 1.9 2004/04/06 02:49:26 mcr Exp $
++ */
++
++/*
++ * The rest of the code is derived from sha1.c by Steve Reid, which is
++ * public domain.
++ * Minor cosmetic changes to accomodate it in the Linux kernel by ji.
++ */
++
++#include <asm/byteorder.h>
++#include <linux/string.h>
++
++#include "openswan/ipsec_sha1.h"
++
++#if defined(rol)
++#undef rol
++#endif
++
++#define SHA1HANDSOFF
++
++#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
++
++/* blk0() and blk() perform the initial expand. */
++/* I got the idea of expanding during the round function from SSLeay */
++#ifdef __LITTLE_ENDIAN
++#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
++    |(rol(block->l[i],8)&0x00FF00FF))
++#else
++#define blk0(i) block->l[i]
++#endif
++#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
++    ^block->l[(i+2)&15]^block->l[i&15],1))
++
++/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
++#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
++#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
++#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
++#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
++#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
++
++
++/* Hash a single 512-bit block. This is the core of the algorithm. */
++
++void SHA1Transform(__u32 state[5], __u8 buffer[64])
++{
++__u32 a, b, c, d, e;
++typedef union {
++    unsigned char c[64];
++    __u32 l[16];
++} CHAR64LONG16;
++CHAR64LONG16* block;
++#ifdef SHA1HANDSOFF
++static unsigned char workspace[64];
++    block = (CHAR64LONG16*)workspace;
++    memcpy(block, buffer, 64);
++#else
++    block = (CHAR64LONG16*)buffer;
++#endif
++    /* Copy context->state[] to working vars */
++    a = state[0];
++    b = state[1];
++    c = state[2];
++    d = state[3];
++    e = state[4];
++    /* 4 rounds of 20 operations each. Loop unrolled. */
++    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
++    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
++    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
++    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
++    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
++    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
++    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
++    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
++    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
++    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
++    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
++    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
++    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
++    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
++    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
++    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
++    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
++    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
++    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
++    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
++    /* Add the working vars back into context.state[] */
++    state[0] += a;
++    state[1] += b;
++    state[2] += c;
++    state[3] += d;
++    state[4] += e;
++    /* Wipe variables */
++    a = b = c = d = e = 0;
++}
++
++
++/* SHA1Init - Initialize new context */
++
++void SHA1Init(void *vcontext)
++{
++    SHA1_CTX* context = vcontext;
++
++    /* SHA1 initialization constants */
++    context->state[0] = 0x67452301;
++    context->state[1] = 0xEFCDAB89;
++    context->state[2] = 0x98BADCFE;
++    context->state[3] = 0x10325476;
++    context->state[4] = 0xC3D2E1F0;
++    context->count[0] = context->count[1] = 0;
++}
++
++
++/* Run your data through this. */
++
++void SHA1Update(void *vcontext, unsigned char* data, __u32 len)
++{
++    SHA1_CTX* context = vcontext;
++    __u32 i, j;
++
++    j = context->count[0];
++    if ((context->count[0] += len << 3) < j)
++      context->count[1]++;
++    context->count[1] += (len>>29);
++    j = (j >> 3) & 63;
++    if ((j + len) > 63) {
++        memcpy(&context->buffer[j], data, (i = 64-j));
++        SHA1Transform(context->state, context->buffer);
++        for ( ; i + 63 < len; i += 64) {
++            SHA1Transform(context->state, &data[i]);
++        }
++        j = 0;
++    }
++    else i = 0;
++    memcpy(&context->buffer[j], &data[i], len - i);
++}
++
++
++/* Add padding and return the message digest. */
++
++void SHA1Final(unsigned char digest[20], void *vcontext)
++{
++  __u32 i, j;
++  unsigned char finalcount[8];
++  SHA1_CTX* context = vcontext;
++    
++    for (i = 0; i < 8; i++) {
++        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
++         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
++    }
++    SHA1Update(context, (unsigned char *)"\200", 1);
++    while ((context->count[0] & 504) != 448) {
++        SHA1Update(context, (unsigned char *)"\0", 1);
++    }
++    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
++    for (i = 0; i < 20; i++) {
++        digest[i] = (unsigned char)
++         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
++    }
++    /* Wipe variables */
++    i = j = 0;
++    memset(context->buffer, 0, 64);
++    memset(context->state, 0, 20);
++    memset(context->count, 0, 8);
++    memset(&finalcount, 0, 8);
++#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite its own static vars */
++    SHA1Transform(context->state, context->buffer);
++#endif
++}
++
++
++/*
++ * $Log: ipsec_sha1.c,v $
++ * Revision 1.9  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.8  2002/09/10 01:45:14  mcr
++ *    changed type of MD5_CTX and SHA1_CTX to void * so that
++ *    the function prototypes would match, and could be placed
++ *    into a pointer to a function.
++ *
++ * Revision 1.7  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.6  2002/04/24 07:36:30  mcr
++ * Moved from ./klips/net/ipsec/ipsec_sha1.c,v
++ *
++ * Revision 1.5  1999/12/13 13:59:13  rgb
++ * Quick fix to argument size to Update bugs.
++ *
++ * Revision 1.4  1999/04/11 00:29:00  henry
++ * GPL boilerplate
++ *
++ * Revision 1.3  1999/04/06 04:54:27  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.2  1999/01/22 06:55:50  rgb
++ * 64-bit clean-up.
++ *
++ * Revision 1.1  1998/06/18 21:27:50  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.2  1998/04/23 20:54:04  rgb
++ * Fixed md5 and sha1 include file nesting issues, to be cleaned up when
++ * verified.
++ *
++ * Revision 1.1  1998/04/09 03:06:11  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:05  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * New transform
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_snprintf.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,135 @@
++/*
++ * @(#) ipsec_snprintf() function
++ *
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
++ *                                 2001  Michael Richardson <mcr@freeswan.org>
++ * Copyright (C) 2005 Michael Richardson <mcr@xelerance.com>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * Split out from ipsec_proc.c.
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_kversion.h"
++#include "openswan/ipsec_param.h"
++
++#include <net/ip.h>
++
++#include "openswan/radij.h"
++
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_stats.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_xmit.h"
++
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++#include "openswan/ipsec_kern24.h"
++
++#ifdef CONFIG_KLIPS_IPCOMP
++#include "openswan/ipcomp.h"
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#include "openswan/ipsec_proto.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++/* ipsec_snprintf: like snprintf except
++ * - size is signed and a negative value is treated as if it were 0
++ * - the returned result is never negative --
++ *   an error generates a "?" or null output (depending on space).
++ *   (Our callers are too lazy to check for an error return.)
++ * 
++ * @param buf String buffer
++ * @param size Size of the string
++ * @param fmt printf string
++ * @param ... Variables to be displayed in fmt
++ * @return int Return code
++ */
++int ipsec_snprintf(char *buf, ssize_t size, const char *fmt, ...)
++{
++       va_list args;
++       int i;
++       size_t possize = size < 0? 0 : size;
++       va_start(args, fmt);
++       i = vsnprintf(buf,possize,fmt,args);
++       va_end(args);
++       if (i < 0) {
++           /* create empty output in place of error */
++           i = 0;
++           if (size > 0) {
++               *buf = '\0';
++           }
++       }
++       return i;
++}
++
++
++void ipsec_dmp_block(char *s, caddr_t bb, int len)
++{
++      int i;
++      unsigned char *b = bb;
++  
++      printk(KERN_INFO "klips_dmp: "
++             "at %s, len=%d:\n", s, len);
++      
++      for(i = 0; i < len; i++ /*, c++*/) {
++              if(!(i % 16)) {
++                      printk(KERN_INFO
++                             "klips_debug:   @%03x:",
++                             i);
++              }
++              printk(" %02x", b[i]);
++              if(!((i + 1) % 16)) {
++                      printk("\n");
++              }
++      }
++      if(i % 16) {
++              printk("\n");
++      }
++}
++              
++/*
++ *
++ * $Log: ipsec_snprintf.c,v $
++ * Revision 1.3.2.1  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.3  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.2  2005/04/15 00:32:01  mcr
++ *    added ipsec_dmp_block routine.
++ *
++ *
++ * Local Variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_tunnel.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,2878 @@
++/*
++ * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_tunnel_c_version[] = "RCSID $Id: ipsec_tunnel.c,v 1.232.2.5 2006/10/06 21:39:26 paul Exp $";
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif        /* for CONFIG_IP_FORWARD */
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <net/tcp.h>
++#include <net/udp.h>
++#include <linux/skbuff.h>
++
++#include <linux/netdevice.h>   /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++
++#include <openswan.h>
++
++#ifdef NET_21
++# include <linux/in6.h>
++# define ip_chk_addr inet_addr_type
++# define IS_MYADDR RTN_LOCAL
++# include <net/dst.h>
++# undef dev_kfree_skb
++# define dev_kfree_skb(a,b) kfree_skb(a)
++# define PHYSDEV_TYPE
++#endif /* NET_21 */
++
++#include <net/icmp.h>         /* icmp_send() */
++#include <net/ip.h>
++#ifdef NETDEV_23
++# include <linux/netfilter_ipv4.h>
++#endif /* NETDEV_23 */
++
++#include <linux/if_arp.h>
++#include <net/arp.h>
++
++#include "openswan/ipsec_kversion.h"
++#include "openswan/radij.h"
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_eroute.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_sa.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_xmit.h"
++#include "openswan/ipsec_ipe4.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++#include "openswan/ipsec_kern24.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++#include <linux/udp.h>
++#endif
++
++static __u32 zeroes[64];
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_tunnel = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_open(struct net_device *dev)
++{
++      struct ipsecpriv *prv = dev->priv;
++      
++      /*
++       * Can't open until attached.
++       */
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                  "klips_debug:ipsec_tunnel_open: "
++                  "dev = %s, prv->dev = %s\n",
++                  dev->name, prv->dev?prv->dev->name:"NONE");
++
++      if (prv->dev == NULL)
++              return -ENODEV;
++      
++      KLIPS_INC_USE;
++      return 0;
++}
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_close(struct net_device *dev)
++{
++      KLIPS_DEC_USE;
++      return 0;
++}
++
++#ifdef NETDEV_23
++static inline int ipsec_tunnel_xmit2(struct sk_buff *skb)
++{
++#ifdef NETDEV_25      /* 2.6 kernels */
++      return dst_output(skb);
++#else
++      return ip_send(skb);
++#endif
++}
++#endif /* NETDEV_23 */
++
++enum ipsec_xmit_value
++ipsec_tunnel_strip_hard_header(struct ipsec_xmit_state *ixs)
++{
++      /* ixs->physdev->hard_header_len is unreliable and should not be used */
++        ixs->hard_header_len = (unsigned char *)(ixs->iph) - ixs->skb->data;
++
++      if(ixs->hard_header_len < 0) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_error:ipsec_xmit_strip_hard_header: "
++                          "Negative hard_header_len (%d)?!\n", ixs->hard_header_len);
++              ixs->stats->tx_dropped++;
++              return IPSEC_XMIT_BADHHLEN;
++      }
++
++      /* while ixs->physdev->hard_header_len is unreliable and
++       * should not be trusted, it accurate and required for ATM, GRE and
++       * some other interfaces to work. Thanks to Willy Tarreau 
++       * <willy@w.ods.org>.
++       */
++      if(ixs->hard_header_len == 0) { /* no hard header present */
++              ixs->hard_header_stripped = 1;
++              ixs->hard_header_len = ixs->physdev->hard_header_len;
++      }
++
++#ifdef CONFIG_KLIPS_DEBUG
++      if (debug_tunnel & DB_TN_XMIT) {
++              int i;
++              char c;
++              
++              printk(KERN_INFO "klips_debug:ipsec_xmit_strip_hard_header: "
++                     ">>> skb->len=%ld hard_header_len:%d",
++                     (unsigned long int)ixs->skb->len, ixs->hard_header_len);
++              c = ' ';
++              for (i=0; i < ixs->hard_header_len; i++) {
++                      printk("%c%02x", c, ixs->skb->data[i]);
++                      c = ':';
++              }
++              printk(" \n");
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph);
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_strip_hard_header: "
++                  "Original head,tailroom: %d,%d\n",
++                  skb_headroom(ixs->skb), skb_tailroom(ixs->skb));
++
++      return IPSEC_XMIT_OK;
++}
++
++enum ipsec_xmit_value
++ipsec_tunnel_SAlookup(struct ipsec_xmit_state *ixs)
++{
++      unsigned int bypass;
++
++      bypass = FALSE;
++
++      /*
++       * First things first -- look us up in the erouting tables.
++       */
++      ixs->matcher.sen_len = sizeof (struct sockaddr_encap);
++      ixs->matcher.sen_family = AF_ENCAP;
++      ixs->matcher.sen_type = SENT_IP4;
++      ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr;
++      ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr;
++      ixs->matcher.sen_proto = ixs->iph->protocol;
++      ipsec_extract_ports(ixs->iph, &ixs->matcher);
++
++      /*
++       * The spinlock is to prevent any other process from accessing or deleting
++       * the eroute while we are using and updating it.
++       */
++      spin_lock(&eroute_lock);
++      
++      ixs->eroute = ipsec_findroute(&ixs->matcher);
++
++      if(ixs->iph->protocol == IPPROTO_UDP) {
++              struct udphdr *t = NULL;
++
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:udp port check: "
++                          "fragoff: %d len: %d>%ld \n",
++                          ntohs(ixs->iph->frag_off) & IP_OFFSET,
++                          (ixs->skb->len - ixs->hard_header_len),
++                            (unsigned long int) ((ixs->iph->ihl << 2) + sizeof(struct udphdr)));
++              
++              if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 &&
++                 ((ixs->skb->len - ixs->hard_header_len) >=
++                  ((ixs->iph->ihl << 2) + sizeof(struct udphdr))))
++              {
++                      t =((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)));
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:udp port in packet: "
++                                  "port %d -> %d\n",
++                                  ntohs(t->source), ntohs(t->dest));
++              }
++
++              ixs->sport=0; ixs->dport=0;
++
++              if(ixs->skb->sk) {
++#ifdef NET_26
++                      struct udp_sock *us;
++                      
++                      us = (struct udp_sock *)ixs->skb->sk;
++
++                      ixs->sport = ntohs(us->inet.sport);
++                      ixs->dport = ntohs(us->inet.dport);
++#else
++                      ixs->sport = ntohs(ixs->skb->sk->sport);
++                      ixs->dport = ntohs(ixs->skb->sk->dport);
++#endif
++
++              } 
++
++              if(t != NULL) {
++                      if(ixs->sport == 0) {
++                              ixs->sport = ntohs(t->source);
++                      }
++                      if(ixs->dport == 0) {
++                              ixs->dport = ntohs(t->dest);
++                      }
++              }
++      }
++
++      /*
++       * practically identical to above, but let's be careful about
++       * tcp vs udp headers
++       */
++      if(ixs->iph->protocol == IPPROTO_TCP) {
++              struct tcphdr *t = NULL;
++
++              if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 &&
++                 ((ixs->skb->len - ixs->hard_header_len) >=
++                  ((ixs->iph->ihl << 2) + sizeof(struct tcphdr)))) {
++                      t =((struct tcphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)));
++              }
++
++              ixs->sport=0; ixs->dport=0;
++
++              if(ixs->skb->sk) {
++#ifdef NET_26
++#ifdef HAVE_INET_SK_SPORT
++                       ixs->sport = ntohs(inet_sk(ixs->skb->sk)->sport);
++                       ixs->dport = ntohs(inet_sk(ixs->skb->sk)->dport);
++#else
++                        struct tcp_tw_bucket *tw;
++
++                        tw = (struct tcp_tw_bucket *)ixs->skb->sk;
++
++                        ixs->sport = ntohs(tw->tw_sport);
++                        ixs->dport = ntohs(tw->tw_dport);
++#endif
++#else
++                        ixs->sport = ntohs(ixs->skb->sk->sport);
++                        ixs->dport = ntohs(ixs->skb->sk->dport);
++#endif
++              } 
++
++              if(t != NULL) {
++                      if(ixs->sport == 0) {
++                              ixs->sport = ntohs(t->source);
++                      }
++                      if(ixs->dport == 0) {
++                              ixs->dport = ntohs(t->dest);
++                      }
++              }
++      }
++      
++      /* default to a %drop eroute */
++      ixs->outgoing_said.proto = IPPROTO_INT;
++      ixs->outgoing_said.spi = htonl(SPI_DROP);
++      ixs->outgoing_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY;
++      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                  "klips_debug:ipsec_xmit_SAlookup: "
++                  "checking for local udp/500 IKE packet "
++                  "saddr=%x, er=0p%p, daddr=%x, er_dst=%x, proto=%d sport=%d dport=%d\n",
++                  ntohl((unsigned int)ixs->iph->saddr),
++                  ixs->eroute,
++                  ntohl((unsigned int)ixs->iph->daddr),
++                  ixs->eroute ? ntohl((unsigned int)ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) : 0,
++                  ixs->iph->protocol,
++                  ixs->sport,
++                  ixs->dport); 
++
++      /*
++       * cheat for now...are we udp/500? If so, let it through
++       * without interference since it is most likely an IKE packet.
++       */
++
++      if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR
++          && (ixs->eroute==NULL
++              || ixs->iph->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr
++              || INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr)
++          && (ixs->iph->protocol == IPPROTO_UDP &&
++              (ixs->sport == 500 || ixs->sport == 4500))) {
++              /* Whatever the eroute, this is an IKE message 
++               * from us (i.e. not being forwarded).
++               * Furthermore, if there is a tunnel eroute,
++               * the destination is the peer for this eroute.
++               * So %pass the packet: modify the default %drop.
++               */
++
++              ixs->outgoing_said.spi = htonl(SPI_PASS);
++              if(!(ixs->skb->sk) && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_SAlookup: "
++                                  "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n");
++              }
++              bypass = TRUE;
++      }
++
++#ifdef KLIPS_EXCEPT_DNS53
++      /*
++       *
++       * if we are udp/53 or tcp/53, also let it through a %trap or %hold,
++       * since it is DNS, but *also* follow the %trap.
++       * 
++       * we do not do this for tunnels, only %trap's and %hold's.
++       *
++       */
++
++      if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR
++          && (ixs->eroute==NULL
++              || ixs->iph->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr
++              || INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr)
++          && ((ixs->iph->protocol == IPPROTO_UDP
++               || ixs->iph->protocol == IPPROTO_TCP)
++              && ixs->dport == 53)) {
++              
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_xmit_SAlookup: "
++                          "possible DNS packet\n");
++
++              if(ixs->eroute)
++              {
++                      if(ixs->eroute->er_said.spi == htonl(SPI_TRAP)
++                         || ixs->eroute->er_said.spi == htonl(SPI_HOLD))
++                      {
++                              ixs->outgoing_said.spi = htonl(SPI_PASSTRAP);
++                              bypass = TRUE;
++                      }
++              }
++              else
++              {
++                      ixs->outgoing_said.spi = htonl(SPI_PASSTRAP);
++                      bypass = TRUE;
++              }
++                              
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_xmit_SAlookup: "
++                          "bypass = %d\n", bypass);
++
++              if(bypass
++                 && !(ixs->skb->sk)
++                 && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0))
++              {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_SAlookup: "
++                                  "local port 53 (probably DNS) passthrough:"
++                                  "base fragment, rest of fragments will "
++                                  "probably get filtered.\n");
++              }
++      }
++#endif
++
++      if (bypass==FALSE && ixs->eroute) {
++              ixs->eroute->er_count++;
++              ixs->eroute->er_lasttime = jiffies/HZ;
++              if(ixs->eroute->er_said.proto==IPPROTO_INT
++                 && ixs->eroute->er_said.spi==htonl(SPI_HOLD))
++              {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_SAlookup: "
++                                  "shunt SA of HOLD: skb stored in HOLD.\n");
++                      if(ixs->eroute->er_last != NULL) {
++                              kfree_skb(ixs->eroute->er_last);
++                      }
++                      ixs->eroute->er_last = ixs->skb;
++                      ixs->skb = NULL;
++                      ixs->stats->tx_dropped++;
++                      spin_unlock(&eroute_lock);
++                      return IPSEC_XMIT_STOLEN;
++              }
++              ixs->outgoing_said = ixs->eroute->er_said;
++              ixs->eroute_pid = ixs->eroute->er_pid;
++
++              /* Copy of the ident for the TRAP/TRAPSUBNET eroutes */
++              if(ixs->outgoing_said.proto==IPPROTO_INT
++                 && (ixs->outgoing_said.spi==htonl(SPI_TRAP)
++                     || (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) {
++                      int len;
++                      
++                      ixs->ips.ips_ident_s.type = ixs->eroute->er_ident_s.type;
++                      ixs->ips.ips_ident_s.id = ixs->eroute->er_ident_s.id;
++                      ixs->ips.ips_ident_s.len = ixs->eroute->er_ident_s.len;
++                      if (ixs->ips.ips_ident_s.len)
++                      {
++                              len = ixs->ips.ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
++                              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                          "klips_debug:ipsec_xmit_SAlookup: "
++                                          "allocating %d bytes for ident_s shunt SA of HOLD: skb stored in HOLD.\n",
++                                          len);
++                              if ((ixs->ips.ips_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) {
++                                      printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: "
++                                             "Failed, tried to allocate %d bytes for source ident.\n", 
++                                             len);
++                                      ixs->stats->tx_dropped++;
++                                      spin_unlock(&eroute_lock);
++                                      return IPSEC_XMIT_ERRMEMALLOC;
++                              }
++                              memcpy(ixs->ips.ips_ident_s.data, ixs->eroute->er_ident_s.data, len);
++                      }
++                      ixs->ips.ips_ident_d.type = ixs->eroute->er_ident_d.type;
++                      ixs->ips.ips_ident_d.id = ixs->eroute->er_ident_d.id;
++                      ixs->ips.ips_ident_d.len = ixs->eroute->er_ident_d.len;
++                      if (ixs->ips.ips_ident_d.len)
++                      {
++                              len = ixs->ips.ips_ident_d.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
++                              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                          "klips_debug:ipsec_xmit_SAlookup: "
++                                          "allocating %d bytes for ident_d shunt SA of HOLD: skb stored in HOLD.\n",
++                                          len);
++                              if ((ixs->ips.ips_ident_d.data = kmalloc(len, GFP_ATOMIC)) == NULL) {
++                                      printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: "
++                                             "Failed, tried to allocate %d bytes for dest ident.\n", 
++                                             len);
++                                      ixs->stats->tx_dropped++;
++                                      spin_unlock(&eroute_lock);
++                                      return IPSEC_XMIT_ERRMEMALLOC;
++                              }
++                              memcpy(ixs->ips.ips_ident_d.data, ixs->eroute->er_ident_d.data, len);
++                      }
++              }
++      }
++
++      spin_unlock(&eroute_lock);
++      return IPSEC_XMIT_OK;
++}
++
++
++enum ipsec_xmit_value
++ipsec_tunnel_restore_hard_header(struct ipsec_xmit_state*ixs)
++{
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_restore_hard_header: "
++                  "After recursive xforms -- head,tailroom: %d,%d\n",
++                  skb_headroom(ixs->skb),
++                  skb_tailroom(ixs->skb));
++
++      if(ixs->saved_header) {
++              if(skb_headroom(ixs->skb) < ixs->hard_header_len) {
++                      printk(KERN_WARNING
++                             "klips_error:ipsec_xmit_restore_hard_header: "
++                             "tried to skb_push hhlen=%d, %d available.  This should never happen, please report.\n",
++                             ixs->hard_header_len,
++                             skb_headroom(ixs->skb));
++                      ixs->stats->tx_errors++;
++                      return IPSEC_XMIT_PUSHPULLERR;
++
++              }
++              skb_push(ixs->skb, ixs->hard_header_len);
++              {
++                      int i;
++                      for (i = 0; i < ixs->hard_header_len; i++) {
++                              ixs->skb->data[i] = ixs->saved_header[i];
++                      }
++              }
++      }
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      if (ixs->natt_type && ixs->natt_head) {
++              struct iphdr *ipp = ixs->skb->nh.iph;
++              struct udphdr *udp;
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_tunnel_start_xmit: "
++                          "encapsuling packet into UDP (NAT-Traversal) (%d %d)\n",
++                          ixs->natt_type, ixs->natt_head);
++
++              ixs->iphlen = ipp->ihl << 2;
++              ipp->tot_len =
++                      htons(ntohs(ipp->tot_len) + ixs->natt_head);
++              if(skb_tailroom(ixs->skb) < ixs->natt_head) {
++                      printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
++                              "tried to skb_put %d, %d available. "
++                              "This should never happen, please report.\n",
++                              ixs->natt_head,
++                              skb_tailroom(ixs->skb));
++                      ixs->stats->tx_errors++;
++                      return IPSEC_XMIT_ESPUDP;
++              }
++              skb_put(ixs->skb, ixs->natt_head);
++
++              udp = (struct udphdr *)((char *)ipp + ixs->iphlen);
++
++              /* move ESP hdr after UDP hdr */
++              memmove((void *)((char *)udp + ixs->natt_head),
++                      (void *)(udp),
++                      ntohs(ipp->tot_len) - ixs->iphlen - ixs->natt_head);
++
++              /* clear UDP & Non-IKE Markers (if any) */
++              memset(udp, 0, ixs->natt_head);
++
++              /* fill UDP with usefull informations ;-) */
++              udp->source = htons(ixs->natt_sport);
++              udp->dest = htons(ixs->natt_dport);
++              udp->len = htons(ntohs(ipp->tot_len) - ixs->iphlen);
++
++              /* set protocol */
++              ipp->protocol = IPPROTO_UDP;
++
++              /* fix IP checksum */
++              ipp->check = 0;
++              ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl);
++      }
++#endif        
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_restore_hard_header: "
++                  "With hard_header, final head,tailroom: %d,%d\n",
++                  skb_headroom(ixs->skb),
++                  skb_tailroom(ixs->skb));
++
++      return IPSEC_XMIT_OK;
++}
++
++enum ipsec_xmit_value
++ipsec_tunnel_send(struct ipsec_xmit_state*ixs)
++{
++#ifdef NETDEV_25
++      struct flowi fl;
++#endif
++  
++#ifdef NET_21 /* 2.2 and 2.4 kernels */
++      /* new route/dst cache code from James Morris */
++      ixs->skb->dev = ixs->physdev;
++#ifdef NETDEV_25
++      memset (&fl, 0x0, sizeof (struct flowi));
++      fl.oif = ixs->physdev->iflink;
++      fl.nl_u.ip4_u.daddr = ixs->skb->nh.iph->daddr;
++      fl.nl_u.ip4_u.saddr = ixs->pass ? 0 : ixs->skb->nh.iph->saddr;
++      fl.nl_u.ip4_u.tos = RT_TOS(ixs->skb->nh.iph->tos);
++      fl.proto = ixs->skb->nh.iph->protocol;
++      if ((ixs->error = ip_route_output_key(&ixs->route, &fl))) {
++#else
++      /*skb_orphan(ixs->skb);*/
++      if((ixs->error = ip_route_output(&ixs->route,
++                                  ixs->skb->nh.iph->daddr,
++                                  ixs->pass ? 0 : ixs->skb->nh.iph->saddr,
++                                  RT_TOS(ixs->skb->nh.iph->tos),
++                                    /* mcr->rgb: should this be 0 instead? */
++                                  ixs->physdev->iflink))) {
++#endif
++              ixs->stats->tx_errors++;
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_xmit_send: "
++                          "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n",
++                          ixs->error,
++                          ixs->route->u.dst.dev->name);
++              return IPSEC_XMIT_ROUTEERR;
++      }
++      if(ixs->dev == ixs->route->u.dst.dev) {
++              ip_rt_put(ixs->route);
++              /* This is recursion, drop it. */
++              ixs->stats->tx_errors++;
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_xmit_send: "
++                          "suspect recursion, dev=rt->u.dst.dev=%s, dropped\n",
++                          ixs->dev->name);
++              return IPSEC_XMIT_RECURSDETECT;
++      }
++      dst_release(ixs->skb->dst);
++      ixs->skb->dst = &ixs->route->u.dst;
++      ixs->stats->tx_bytes += ixs->skb->len;
++      if(ixs->skb->len < ixs->skb->nh.raw - ixs->skb->data) {
++              ixs->stats->tx_errors++;
++              printk(KERN_WARNING
++                     "klips_error:ipsec_xmit_send: "
++                     "tried to __skb_pull nh-data=%ld, %d available.  This should never happen, please report.\n",
++                     (unsigned long)(ixs->skb->nh.raw - ixs->skb->data),
++                     ixs->skb->len);
++              return IPSEC_XMIT_PUSHPULLERR;
++      }
++      __skb_pull(ixs->skb, ixs->skb->nh.raw - ixs->skb->data);
++#ifdef SKB_RESET_NFCT
++      if(!ixs->pass) {
++        nf_conntrack_put(ixs->skb->nfct);
++        ixs->skb->nfct = NULL;
++      }
++#if defined(CONFIG_NETFILTER_DEBUG) && defined(HAVE_SKB_NF_DEBUG)
++      ixs->skb->nf_debug = 0;
++#endif /* CONFIG_NETFILTER_DEBUG */
++#endif /* SKB_RESET_NFCT */
++      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                  "klips_debug:ipsec_xmit_send: "
++                  "...done, calling ip_send() on device:%s\n",
++                  ixs->skb->dev ? ixs->skb->dev->name : "NULL");
++      KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->skb->nh.iph);
++#ifdef NETDEV_23      /* 2.4 kernels */
++      {
++              int err;
++
++              err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, ixs->skb, NULL, ixs->route->u.dst.dev,
++                            ipsec_tunnel_xmit2);
++              if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) {
++                      if(net_ratelimit())
++                              printk(KERN_ERR
++                                     "klips_error:ipsec_xmit_send: "
++                                     "ip_send() failed, err=%d\n", 
++                                     -err);
++                      ixs->stats->tx_errors++;
++                      ixs->stats->tx_aborted_errors++;
++                      ixs->skb = NULL;
++                      return IPSEC_XMIT_IPSENDFAILURE;
++              }
++      }
++#else /* NETDEV_23 */ /* 2.2 kernels */
++      ip_send(ixs->skb);
++#endif /* NETDEV_23 */
++#else /* NET_21 */    /* 2.0 kernels */
++      ixs->skb->arp = 1;
++      /* ISDN/ASYNC PPP from Matjaz Godec. */
++      /*      skb->protocol = htons(ETH_P_IP); */
++      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                  "klips_debug:ipsec_xmit_send: "
++                  "...done, calling dev_queue_xmit() or ip_fragment().\n");
++      IP_SEND(ixs->skb, ixs->physdev);
++#endif /* NET_21 */
++      ixs->stats->tx_packets++;
++
++      ixs->skb = NULL;
++      
++      return IPSEC_XMIT_OK;
++}
++
++void
++ipsec_tunnel_cleanup(struct ipsec_xmit_state*ixs)
++{
++#if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE)
++      netif_wake_queue(ixs->dev);
++#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
++      ixs->dev->tbusy = 0;
++#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
++      if(ixs->saved_header) {
++              kfree(ixs->saved_header);
++      }
++      if(ixs->skb) {
++              dev_kfree_skb(ixs->skb, FREE_WRITE);
++      }
++      if(ixs->oskb) {
++              dev_kfree_skb(ixs->oskb, FREE_WRITE);
++      }
++      if (ixs->ips.ips_ident_s.data) {
++              kfree(ixs->ips.ips_ident_s.data);
++      }
++      if (ixs->ips.ips_ident_d.data) {
++              kfree(ixs->ips.ips_ident_d.data);
++      }
++}
++
++/*
++ *    This function assumes it is being called from dev_queue_xmit()
++ *    and that skb is filled properly by that function.
++ */
++int
++ipsec_tunnel_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++      struct ipsec_xmit_state ixs_mem;
++      struct ipsec_xmit_state *ixs = &ixs_mem;
++      enum ipsec_xmit_value stat;
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      ixs->natt_type = 0, ixs->natt_head = 0;
++      ixs->natt_sport = 0, ixs->natt_dport = 0;
++#endif
++
++      memset((caddr_t)ixs, 0, sizeof(*ixs));
++      ixs->oskb = NULL;
++      ixs->saved_header = NULL;       /* saved copy of the hard header */
++      ixs->route = NULL;
++      memset((caddr_t)&(ixs->ips), 0, sizeof(ixs->ips));
++      ixs->dev = dev;
++      ixs->skb = skb;
++
++      stat = ipsec_xmit_sanity_check_dev(ixs);
++      if(stat != IPSEC_XMIT_OK) {
++              goto cleanup;
++      }
++
++      stat = ipsec_xmit_sanity_check_skb(ixs);
++      if(stat != IPSEC_XMIT_OK) {
++              goto cleanup;
++      }
++
++      stat = ipsec_tunnel_strip_hard_header(ixs);
++      if(stat != IPSEC_XMIT_OK) {
++              goto cleanup;
++      }
++
++      stat = ipsec_tunnel_SAlookup(ixs);
++      if(stat != IPSEC_XMIT_OK) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_tunnel_start_xmit: SAlookup failed: %d\n",
++                          stat);
++              goto cleanup;
++      }
++      
++      ixs->innersrc = ixs->iph->saddr;
++      /* start encapsulation loop here XXX */
++      do {
++              stat = ipsec_xmit_encap_bundle(ixs);
++              if(stat != IPSEC_XMIT_OK) {
++                      if(stat == IPSEC_XMIT_PASS) {
++                              goto bypass;
++                      }
++                      
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_tunnel_start_xmit: encap_bundle failed: %d\n",
++                                  stat);
++                      goto cleanup;
++              }
++
++              ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr;
++              ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr;
++              ixs->matcher.sen_proto = ixs->iph->protocol;
++              ipsec_extract_ports(ixs->iph, &ixs->matcher);
++
++              spin_lock(&eroute_lock);
++              ixs->eroute = ipsec_findroute(&ixs->matcher);
++              if(ixs->eroute) {
++                      ixs->outgoing_said = ixs->eroute->er_said;
++                      ixs->eroute_pid = ixs->eroute->er_pid;
++                      ixs->eroute->er_count++;
++                      ixs->eroute->er_lasttime = jiffies/HZ;
++              }
++              spin_unlock(&eroute_lock);
++
++              KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) &&
++                          /* ((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc)) */
++                          (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) &&
++                          ixs->outgoing_said.dst.u.v4.sin_addr.s_addr &&
++                          ixs->eroute,
++                          "klips_debug:ipsec_tunnel_start_xmit: "
++                          "We are recursing here.\n");
++
++      } while(/*((ixs->orgdst != ixs->newdst) || (ixs->orgsrc != ixs->newsrc))*/
++              (ixs->orgedst != ixs->outgoing_said.dst.u.v4.sin_addr.s_addr) &&
++              ixs->outgoing_said.dst.u.v4.sin_addr.s_addr &&
++              ixs->eroute);
++      
++      stat = ipsec_tunnel_restore_hard_header(ixs);
++      if(stat != IPSEC_XMIT_OK) {
++              goto cleanup;
++      }
++
++ bypass:
++      stat = ipsec_tunnel_send(ixs);
++
++ cleanup:
++      ipsec_tunnel_cleanup(ixs);
++
++      return 0;
++}
++
++DEBUG_NO_STATIC struct net_device_stats *
++ipsec_tunnel_get_stats(struct net_device *dev)
++{
++      return &(((struct ipsecpriv *)(dev->priv))->mystats);
++}
++
++/*
++ * Revectored calls.
++ * For each of these calls, a field exists in our private structure.
++ */
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_hard_header(struct sk_buff *skb, struct net_device *dev,
++      unsigned short type, void *daddr, void *saddr, unsigned len)
++{
++      struct ipsecpriv *prv = dev->priv;
++      struct net_device *tmp;
++      int ret;
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(skb == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_hard_header: "
++                          "no skb...\n");
++              return -ENODATA;
++      }
++
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_hard_header: "
++                          "no device...\n");
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "klips_debug:ipsec_tunnel_hard_header: "
++                  "skb->dev=%s dev=%s.\n",
++                  skb->dev ? skb->dev->name : "NULL",
++                  dev->name);
++      
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_hard_header: "
++                          "no private space associated with dev=%s\n",
++                          dev->name ? dev->name : "NULL");
++              return -ENODEV;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_hard_header: "
++                          "no physical device associated with dev=%s\n",
++                          dev->name ? dev->name : "NULL");
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      /* check if we have to send a IPv6 packet. It might be a Router
++         Solicitation, where the building of the packet happens in
++         reverse order:
++         1. ll hdr,
++         2. IPv6 hdr,
++         3. ICMPv6 hdr
++         -> skb->nh.raw is still uninitialized when this function is
++         called!!  If this is no IPv6 packet, we can print debugging
++         messages, otherwise we skip all debugging messages and just
++         build the ll header */
++      if(type != ETH_P_IPV6) {
++              /* execute this only, if we don't have to build the
++                 header for a IPv6 packet */
++              if(!prv->hard_header) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                                  "klips_debug:ipsec_tunnel_hard_header: "
++                                  "physical device has been detached, packet dropped 0p%p->0p%p len=%d type=%d dev=%s->NULL ",
++                                  saddr,
++                                  daddr,
++                                  len,
++                                  type,
++                                  dev->name);
++#ifdef NET_21
++                      KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
++                                      "ip=%08x->%08x\n",
++                                      (__u32)ntohl(skb->nh.iph->saddr),
++                                      (__u32)ntohl(skb->nh.iph->daddr) );
++#else /* NET_21 */
++                      KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
++                                      "ip=%08x->%08x\n",
++                                      (__u32)ntohl(skb->ip_hdr->saddr),
++                                      (__u32)ntohl(skb->ip_hdr->daddr) );
++#endif /* NET_21 */
++                      stats->tx_dropped++;
++                      return -ENODEV;
++              }
++              
++#define da ((struct net_device *)(prv->dev))->dev_addr
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_hard_header: "
++                          "Revectored 0p%p->0p%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ",
++                          saddr,
++                          daddr,
++                          len,
++                          type,
++                          dev->name,
++                          prv->dev->name,
++                          da[0], da[1], da[2], da[3], da[4], da[5]);
++#ifdef NET_21
++              KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
++                          "ip=%08x->%08x\n",
++                          (__u32)ntohl(skb->nh.iph->saddr),
++                          (__u32)ntohl(skb->nh.iph->daddr) );
++#else /* NET_21 */
++              KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
++                          "ip=%08x->%08x\n",
++                          (__u32)ntohl(skb->ip_hdr->saddr),
++                          (__u32)ntohl(skb->ip_hdr->daddr) );
++#endif /* NET_21 */
++      } else {
++              KLIPS_PRINT(debug_tunnel,
++                          "klips_debug:ipsec_tunnel_hard_header: "
++                          "is IPv6 packet, skip debugging messages, only revector and build linklocal header.\n");
++      }                                                                       
++      tmp = skb->dev;
++      skb->dev = prv->dev;
++      ret = prv->hard_header(skb, prv->dev, type, (void *)daddr, (void *)saddr, len);
++      skb->dev = tmp;
++      return ret;
++}
++
++DEBUG_NO_STATIC int
++#ifdef NET_21
++ipsec_tunnel_rebuild_header(struct sk_buff *skb)
++#else /* NET_21 */
++ipsec_tunnel_rebuild_header(void *buff, struct net_device *dev,
++                      unsigned long raddr, struct sk_buff *skb)
++#endif /* NET_21 */
++{
++      struct ipsecpriv *prv = skb->dev->priv;
++      struct net_device *tmp;
++      int ret;
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(skb->dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_rebuild_header: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_rebuild_header: "
++                          "no private space associated with dev=%s",
++                          skb->dev->name ? skb->dev->name : "NULL");
++              return -ENODEV;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_rebuild_header: "
++                          "no physical device associated with dev=%s",
++                          skb->dev->name ? skb->dev->name : "NULL");
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      if(!prv->rebuild_header) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_rebuild_header: "
++                          "physical device has been detached, packet dropped skb->dev=%s->NULL ",
++                          skb->dev->name);
++#ifdef NET_21
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "ip=%08x->%08x\n",
++                          (__u32)ntohl(skb->nh.iph->saddr),
++                          (__u32)ntohl(skb->nh.iph->daddr) );
++#else /* NET_21 */
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "ip=%08x->%08x\n",
++                          (__u32)ntohl(skb->ip_hdr->saddr),
++                          (__u32)ntohl(skb->ip_hdr->daddr) );
++#endif /* NET_21 */
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "klips_debug:ipsec_tunnel: "
++                  "Revectored rebuild_header dev=%s->%s ",
++                  skb->dev->name, prv->dev->name);
++#ifdef NET_21
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "ip=%08x->%08x\n",
++                  (__u32)ntohl(skb->nh.iph->saddr),
++                  (__u32)ntohl(skb->nh.iph->daddr) );
++#else /* NET_21 */
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "ip=%08x->%08x\n",
++                  (__u32)ntohl(skb->ip_hdr->saddr),
++                  (__u32)ntohl(skb->ip_hdr->daddr) );
++#endif /* NET_21 */
++      tmp = skb->dev;
++      skb->dev = prv->dev;
++      
++#ifdef NET_21
++      ret = prv->rebuild_header(skb);
++#else /* NET_21 */
++      ret = prv->rebuild_header(buff, prv->dev, raddr, skb);
++#endif /* NET_21 */
++      skb->dev = tmp;
++      return ret;
++}
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_set_mac_address(struct net_device *dev, void *addr)
++{
++      struct ipsecpriv *prv = dev->priv;
++      
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_set_mac_address: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_set_mac_address: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return -ENODEV;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_set_mac_address: "
++                          "no physical device associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              stats->tx_dropped++;
++              return -ENODEV;
++      }
++
++      if(!prv->set_mac_address) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_set_mac_address: "
++                          "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
++                          dev->name);
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "klips_debug:ipsec_tunnel_set_mac_address: "
++                  "Revectored dev=%s->%s addr=0p%p\n",
++                  dev->name, prv->dev->name, addr);
++      return prv->set_mac_address(prv->dev, addr);
++
++}
++
++#ifndef NET_21
++DEBUG_NO_STATIC void
++ipsec_tunnel_cache_bind(struct hh_cache **hhp, struct net_device *dev,
++                               unsigned short htype, __u32 daddr)
++{
++      struct ipsecpriv *prv = dev->priv;
++      
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_bind: "
++                          "no device...");
++              return;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_bind: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_bind: "
++                          "no physical device associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              stats->tx_dropped++;
++              return;
++      }
++
++      if(!prv->header_cache_bind) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_bind: "
++                          "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
++                          dev->name);
++              stats->tx_dropped++;
++              return;
++      }
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "klips_debug:ipsec_tunnel_cache_bind: "
++                  "Revectored \n");
++      prv->header_cache_bind(hhp, prv->dev, htype, daddr);
++      return;
++}
++#endif /* !NET_21 */
++
++
++DEBUG_NO_STATIC void
++ipsec_tunnel_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char *  haddr)
++{
++      struct ipsecpriv *prv = dev->priv;
++      
++      struct net_device_stats *stats; /* This device's statistics */
++      
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_update: "
++                          "no device...");
++              return;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_update: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return;
++      }
++
++      stats = (struct net_device_stats *) &(prv->mystats);
++
++      if(prv->dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_update: "
++                          "no physical device associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              stats->tx_dropped++;
++              return;
++      }
++
++      if(!prv->header_cache_update) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_cache_update: "
++                          "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
++                          dev->name);
++              return;
++      }
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "klips_debug:ipsec_tunnel: "
++                  "Revectored cache_update\n");
++      prv->header_cache_update(hh, prv->dev, haddr);
++      return;
++}
++
++#ifdef NET_21
++DEBUG_NO_STATIC int
++ipsec_tunnel_neigh_setup(struct neighbour *n)
++{
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "klips_debug:ipsec_tunnel_neigh_setup:\n");
++
++        if (n->nud_state == NUD_NONE) {
++                n->ops = &arp_broken_ops;
++                n->output = n->ops->output;
++        }
++        return 0;
++}
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
++{
++      KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                  "klips_debug:ipsec_tunnel_neigh_setup_dev: "
++                  "setting up %s\n",
++                  dev ? dev->name : "NULL");
++
++        if (p->tbl->family == AF_INET) {
++                p->neigh_setup = ipsec_tunnel_neigh_setup;
++                p->ucast_probes = 0;
++                p->mcast_probes = 0;
++        }
++        return 0;
++}
++#endif /* NET_21 */
++
++/*
++ * We call the attach routine to attach another device.
++ */
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_attach(struct net_device *dev, struct net_device *physdev)
++{
++        int i;
++      struct ipsecpriv *prv = dev->priv;
++
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_attach: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_attach: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return -ENODATA;
++      }
++
++      prv->dev = physdev;
++      prv->hard_start_xmit = physdev->hard_start_xmit;
++      prv->get_stats = physdev->get_stats;
++
++      if (physdev->hard_header) {
++              prv->hard_header = physdev->hard_header;
++              dev->hard_header = ipsec_tunnel_hard_header;
++      } else
++              dev->hard_header = NULL;
++      
++      if (physdev->rebuild_header) {
++              prv->rebuild_header = physdev->rebuild_header;
++              dev->rebuild_header = ipsec_tunnel_rebuild_header;
++      } else
++              dev->rebuild_header = NULL;
++      
++      if (physdev->set_mac_address) {
++              prv->set_mac_address = physdev->set_mac_address;
++              dev->set_mac_address = ipsec_tunnel_set_mac_address;
++      } else
++              dev->set_mac_address = NULL;
++      
++#ifndef NET_21
++      if (physdev->header_cache_bind) {
++              prv->header_cache_bind = physdev->header_cache_bind;
++              dev->header_cache_bind = ipsec_tunnel_cache_bind;
++      } else
++              dev->header_cache_bind = NULL;
++#endif /* !NET_21 */
++
++      if (physdev->header_cache_update) {
++              prv->header_cache_update = physdev->header_cache_update;
++              dev->header_cache_update = ipsec_tunnel_cache_update;
++      } else
++              dev->header_cache_update = NULL;
++
++      dev->hard_header_len = physdev->hard_header_len;
++
++#ifdef NET_21
++/*    prv->neigh_setup        = physdev->neigh_setup; */
++      dev->neigh_setup        = ipsec_tunnel_neigh_setup_dev;
++#endif /* NET_21 */
++      dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */
++      prv->mtu = physdev->mtu;
++
++#ifdef PHYSDEV_TYPE
++      dev->type = physdev->type; /* ARPHRD_TUNNEL; */
++#endif /*  PHYSDEV_TYPE */
++
++      dev->addr_len = physdev->addr_len;
++      for (i=0; i<dev->addr_len; i++) {
++              dev->dev_addr[i] = physdev->dev_addr[i];
++      }
++#ifdef CONFIG_KLIPS_DEBUG
++      if(debug_tunnel & DB_TN_INIT) {
++              printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: "
++                     "physical device %s being attached has HW address: %2x",
++                     physdev->name, physdev->dev_addr[0]);
++              for (i=1; i < physdev->addr_len; i++) {
++                      printk(":%02x", physdev->dev_addr[i]);
++              }
++              printk("\n");
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      return 0;
++}
++
++/*
++ * We call the detach routine to detach the ipsec tunnel from another device.
++ */
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_detach(struct net_device *dev)
++{
++        int i;
++      struct ipsecpriv *prv = dev->priv;
++
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_detach: "
++                          "no device...");
++              return -ENODEV;
++      }
++
++      if(prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
++                          "klips_debug:ipsec_tunnel_detach: "
++                          "no private space associated with dev=%s",
++                          dev->name ? dev->name : "NULL");
++              return -ENODATA;
++      }
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                  "klips_debug:ipsec_tunnel_detach: "
++                  "physical device %s being detached from virtual device %s\n",
++                  prv->dev ? prv->dev->name : "NULL",
++                  dev->name);
++
++      ipsec_dev_put(prv->dev);
++      prv->dev = NULL;
++      prv->hard_start_xmit = NULL;
++      prv->get_stats = NULL;
++
++      prv->hard_header = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->hard_header = NULL;
++#endif /* DETACH_AND_DOWN */
++      
++      prv->rebuild_header = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->rebuild_header = NULL;
++#endif /* DETACH_AND_DOWN */
++      
++      prv->set_mac_address = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->set_mac_address = NULL;
++#endif /* DETACH_AND_DOWN */
++      
++#ifndef NET_21
++      prv->header_cache_bind = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->header_cache_bind = NULL;
++#endif /* DETACH_AND_DOWN */
++#endif /* !NET_21 */
++
++      prv->header_cache_update = NULL;
++#ifdef DETACH_AND_DOWN
++      dev->header_cache_update = NULL;
++#endif /* DETACH_AND_DOWN */
++
++#ifdef NET_21
++/*    prv->neigh_setup        = NULL; */
++#ifdef DETACH_AND_DOWN
++      dev->neigh_setup        = NULL;
++#endif /* DETACH_AND_DOWN */
++#endif /* NET_21 */
++      dev->hard_header_len = 0;
++#ifdef DETACH_AND_DOWN
++      dev->mtu = 0;
++#endif /* DETACH_AND_DOWN */
++      prv->mtu = 0;
++      for (i=0; i<MAX_ADDR_LEN; i++) {
++              dev->dev_addr[i] = 0;
++      }
++      dev->addr_len = 0;
++#ifdef PHYSDEV_TYPE
++      dev->type = ARPHRD_VOID; /* ARPHRD_TUNNEL; */
++#endif /*  PHYSDEV_TYPE */
++      
++      return 0;
++}
++
++/*
++ * We call the clear routine to detach all ipsec tunnels from other devices.
++ */
++DEBUG_NO_STATIC int
++ipsec_tunnel_clear(void)
++{
++      int i;
++      struct net_device *ipsecdev = NULL, *prvdev;
++      struct ipsecpriv *prv;
++      int ret;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                  "klips_debug:ipsec_tunnel_clear: .\n");
++
++      for(i = 0; i < IPSEC_NUM_IF; i++) {
++              ipsecdev = ipsecdevices[i];
++              if(ipsecdev != NULL) {
++                      if((prv = (struct ipsecpriv *)(ipsecdev->priv))) {
++                              prvdev = (struct net_device *)(prv->dev);
++                              if(prvdev) {
++                                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                                  "klips_debug:ipsec_tunnel_clear: "
++                                                  "physical device for device %s is %s\n",
++                                                  ipsecdev->name, prvdev->name);
++                                      if((ret = ipsec_tunnel_detach(ipsecdev))) {
++                                              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                                          "klips_debug:ipsec_tunnel_clear: "
++                                                          "error %d detatching device %s from device %s.\n",
++                                                          ret, ipsecdev->name, prvdev->name);
++                                              return ret;
++                                      }
++                              }
++                      }
++              }
++      }
++      return 0;
++}
++
++DEBUG_NO_STATIC int
++ipsec_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++      struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data;
++      struct ipsecpriv *prv = dev->priv;
++      struct net_device *them; /* physical device */
++#ifdef CONFIG_IP_ALIAS
++      char *colon;
++      char realphysname[IFNAMSIZ];
++#endif /* CONFIG_IP_ALIAS */
++      
++      if(dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_tunnel_ioctl: "
++                          "device not supplied.\n");
++              return -ENODEV;
++      }
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                  "klips_debug:ipsec_tunnel_ioctl: "
++                  "tncfg service call #%d for dev=%s\n",
++                  cmd,
++                  dev->name ? dev->name : "NULL");
++      switch (cmd) {
++      /* attach a virtual ipsec? device to a physical device */
++      case IPSEC_SET_DEV:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_tunnel_ioctl: "
++                          "calling ipsec_tunnel_attatch...\n");
++#ifdef CONFIG_IP_ALIAS
++              /* If this is an IP alias interface, get its real physical name */
++              strncpy(realphysname, cf->cf_name, IFNAMSIZ);
++              realphysname[IFNAMSIZ-1] = 0;
++              colon = strchr(realphysname, ':');
++              if (colon) *colon = 0;
++              them = ipsec_dev_get(realphysname);
++#else /* CONFIG_IP_ALIAS */
++              them = ipsec_dev_get(cf->cf_name);
++#endif /* CONFIG_IP_ALIAS */
++
++              if (them == NULL) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_ioctl: "
++                                  "physical device %s requested is null\n",
++                                  cf->cf_name);
++                      return -ENXIO;
++              }
++              
++#if 0
++              if (them->flags & IFF_UP) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_ioctl: "
++                                  "physical device %s requested is not up.\n",
++                                  cf->cf_name);
++                      ipsec_dev_put(them);
++                      return -ENXIO;
++              }
++#endif
++              
++              if (prv && prv->dev) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_ioctl: "
++                                  "virtual device is already connected to %s.\n",
++                                  prv->dev->name ? prv->dev->name : "NULL");
++                      ipsec_dev_put(them);
++                      return -EBUSY;
++              }
++              return ipsec_tunnel_attach(dev, them);
++
++      case IPSEC_DEL_DEV:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_tunnel_ioctl: "
++                          "calling ipsec_tunnel_detatch.\n");
++              if (! prv->dev) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_ioctl: "
++                                  "physical device not connected.\n");
++                      return -ENODEV;
++              }
++              return ipsec_tunnel_detach(dev);
++             
++      case IPSEC_CLR_DEV:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_tunnel_ioctl: "
++                          "calling ipsec_tunnel_clear.\n");
++              return ipsec_tunnel_clear();
++
++      default:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_tunnel_ioctl: "
++                          "unknown command %d.\n",
++                          cmd);
++              return -EOPNOTSUPP;
++      }
++}
++
++struct net_device *ipsec_get_device(int inst)
++{
++  struct net_device *ipsec_dev;
++
++  ipsec_dev = NULL;
++
++  if(inst < IPSEC_NUM_IF) {
++    ipsec_dev = ipsecdevices[inst];
++  }
++
++  return ipsec_dev;
++}
++
++int
++ipsec_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
++{
++      struct net_device *dev = ptr;
++      struct net_device *ipsec_dev;
++      struct ipsecpriv *priv;
++      int i;
++
++      if (dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "dev=NULL for event type %ld.\n",
++                          event);
++              return(NOTIFY_DONE);
++      }
++
++      /* check for loopback devices */
++      if (dev && (dev->flags & IFF_LOOPBACK)) {
++              return(NOTIFY_DONE);
++      }
++
++      switch (event) {
++      case NETDEV_DOWN:
++              /* look very carefully at the scope of these compiler
++                 directives before changing anything... -- RGB */
++#ifdef NET_21
++      case NETDEV_UNREGISTER:
++              switch (event) {
++              case NETDEV_DOWN:
++#endif /* NET_21 */
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_device_event: "
++                                  "NETDEV_DOWN dev=%s flags=%x\n",
++                                  dev->name,
++                                  dev->flags);
++                      if(strncmp(dev->name, "ipsec", strlen("ipsec")) == 0) {
++                              printk(KERN_CRIT "IPSEC EVENT: KLIPS device %s shut down.\n",
++                                     dev->name);
++                      }
++#ifdef NET_21
++                      break;
++              case NETDEV_UNREGISTER:
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_device_event: "
++                                  "NETDEV_UNREGISTER dev=%s flags=%x\n",
++                                  dev->name,
++                                  dev->flags);
++                      break;
++              }
++#endif /* NET_21 */
++              
++              /* find the attached physical device and detach it. */
++              for(i = 0; i < IPSEC_NUM_IF; i++) {
++                      ipsec_dev = ipsecdevices[i];
++
++                      if(ipsec_dev) {
++                              priv = (struct ipsecpriv *)(ipsec_dev->priv);
++                              if(priv) {
++                                      ;
++                                      if(((struct net_device *)(priv->dev)) == dev) {
++                                              /* dev_close(ipsec_dev); */
++                                              /* return */ ipsec_tunnel_detach(ipsec_dev);
++                                              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                                          "klips_debug:ipsec_device_event: "
++                                                          "device '%s' has been detached.\n",
++                                                          ipsec_dev->name);
++                                              break;
++                                      }
++                              } else {
++                                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                                  "klips_debug:ipsec_device_event: "
++                                                  "device '%s' has no private data space!\n",
++                                                  ipsec_dev->name);
++                              }
++                      }
++              }
++              break;
++      case NETDEV_UP:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_UP dev=%s\n",
++                          dev->name);
++              break;
++#ifdef NET_21
++      case NETDEV_REBOOT:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_REBOOT dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_CHANGE:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_CHANGE dev=%s flags=%x\n",
++                          dev->name,
++                          dev->flags);
++              break;
++      case NETDEV_REGISTER:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_REGISTER dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_CHANGEMTU:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_CHANGEMTU dev=%s to mtu=%d\n",
++                          dev->name,
++                          dev->mtu);
++              break;
++      case NETDEV_CHANGEADDR:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_CHANGEADDR dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_GOING_DOWN:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_GOING_DOWN dev=%s\n",
++                          dev->name);
++              break;
++      case NETDEV_CHANGENAME:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "NETDEV_CHANGENAME dev=%s\n",
++                          dev->name);
++              break;
++#endif /* NET_21 */
++      default:
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_device_event: "
++                          "event type %ld unrecognised for dev=%s\n",
++                          event,
++                          dev->name);
++              break;
++      }
++      return NOTIFY_DONE;
++}
++
++/*
++ *    Called when an ipsec tunnel device is initialized.
++ *    The ipsec tunnel device structure is passed to us.
++ */
++ 
++int
++ipsec_tunnel_init(struct net_device *dev)
++{
++      int i;
++
++      KLIPS_PRINT(debug_tunnel,
++                  "klips_debug:ipsec_tunnel_init: "
++                  "allocating %lu bytes initialising device: %s\n",
++                  (unsigned long) sizeof(struct ipsecpriv),
++                  dev->name ? dev->name : "NULL");
++
++      /* Add our tunnel functions to the device */
++      dev->open               = ipsec_tunnel_open;
++      dev->stop               = ipsec_tunnel_close;
++      dev->hard_start_xmit    = ipsec_tunnel_start_xmit;
++      dev->get_stats          = ipsec_tunnel_get_stats;
++
++      dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL);
++      if (dev->priv == NULL)
++              return -ENOMEM;
++      memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv));
++
++      for(i = 0; i < sizeof(zeroes); i++) {
++              ((__u8*)(zeroes))[i] = 0;
++      }
++      
++#ifndef NET_21
++      /* Initialize the tunnel device structure */
++      for (i = 0; i < DEV_NUMBUFFS; i++)
++              skb_queue_head_init(&dev->buffs[i]);
++#endif /* !NET_21 */
++
++      dev->set_multicast_list = NULL;
++      dev->do_ioctl           = ipsec_tunnel_ioctl;
++      dev->hard_header        = NULL;
++      dev->rebuild_header     = NULL;
++      dev->set_mac_address    = NULL;
++#ifndef NET_21
++      dev->header_cache_bind  = NULL;
++#endif /* !NET_21 */
++      dev->header_cache_update= NULL;
++
++#ifdef NET_21
++/*    prv->neigh_setup        = NULL; */
++      dev->neigh_setup        = ipsec_tunnel_neigh_setup_dev;
++#endif /* NET_21 */
++      dev->hard_header_len    = 0;
++      dev->mtu                = 0;
++      dev->addr_len           = 0;
++      dev->type               = ARPHRD_VOID; /* ARPHRD_TUNNEL; */ /* ARPHRD_ETHER; */
++      dev->tx_queue_len       = 10;           /* Small queue */
++      memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN);       /* what if this is not attached to ethernet? */
++
++      /* New-style flags. */
++      dev->flags              = IFF_NOARP /* 0 */ /* Petr Novak */;
++
++#if 0
++#ifdef NET_21
++      dev_init_buffers(dev);
++#else /* NET_21 */
++      dev->family             = AF_INET;
++      dev->pa_addr            = 0;
++      dev->pa_brdaddr         = 0;
++      dev->pa_mask            = 0;
++      dev->pa_alen            = 4;
++#endif /* NET_21 */
++#endif
++
++      /* We're done.  Have I forgotten anything? */
++      return 0;
++}
++
++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
++/*  Module specific interface (but it links with the rest of IPSEC)  */
++/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
++
++int
++ipsec_tunnel_probe(struct net_device *dev)
++{
++      ipsec_tunnel_init(dev); 
++      return 0;
++}
++
++struct net_device *ipsecdevices[IPSEC_NUM_IF];
++
++int 
++ipsec_tunnel_init_devices(void)
++{
++      int i;
++      char name[IFNAMSIZ];
++      struct net_device *dev_ipsec;
++      
++      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                  "klips_debug:ipsec_tunnel_init_devices: "
++                  "creating and registering IPSEC_NUM_IF=%u devices, allocating %lu per device, IFNAMSIZ=%u.\n",
++                  IPSEC_NUM_IF,
++                  (unsigned long) (sizeof(struct net_device) + IFNAMSIZ),
++                  IFNAMSIZ);
++
++      for(i = 0; i < IPSEC_NUM_IF; i++) {
++              sprintf(name, IPSEC_DEV_FORMAT, i);
++              dev_ipsec = (struct net_device*)kmalloc(sizeof(struct net_device), GFP_KERNEL);
++              if (dev_ipsec == NULL) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_init_devices: "
++                                  "failed to allocate memory for device %s, quitting device init.\n",
++                                  name);
++                      return -ENOMEM;
++              }
++              memset((caddr_t)dev_ipsec, 0, sizeof(struct net_device));
++#ifdef NETDEV_23
++              strncpy(dev_ipsec->name, name, sizeof(dev_ipsec->name));
++#else /* NETDEV_23 */
++              dev_ipsec->name = (char*)kmalloc(IFNAMSIZ, GFP_KERNEL);
++              if (dev_ipsec->name == NULL) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_init_devices: "
++                                  "failed to allocate memory for device %s name, quitting device init.\n",
++                                  name);
++                      return -ENOMEM;
++              }
++              memset((caddr_t)dev_ipsec->name, 0, IFNAMSIZ);
++              strncpy(dev_ipsec->name, name, IFNAMSIZ);
++#endif /* NETDEV_23 */
++              dev_ipsec->next = NULL;
++              dev_ipsec->init = &ipsec_tunnel_probe;
++              KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                          "klips_debug:ipsec_tunnel_init_devices: "
++                          "registering device %s\n",
++                          dev_ipsec->name);
++
++              /* reference and hold the device reference */
++              dev_hold(dev_ipsec);
++              ipsecdevices[i]=dev_ipsec;
++
++              if (register_netdev(dev_ipsec) != 0) {
++                      KLIPS_PRINT(1 || debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_init_devices: "
++                                  "registering device %s failed, quitting device init.\n",
++                                  dev_ipsec->name);
++                      return -EIO;
++              } else {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
++                                  "klips_debug:ipsec_tunnel_init_devices: "
++                                  "registering device %s succeeded, continuing...\n",
++                                  dev_ipsec->name);
++              }
++      }
++      return 0;
++}
++
++/* void */
++int
++ipsec_tunnel_cleanup_devices(void)
++{
++      int error = 0;
++      int i;
++      struct net_device *dev_ipsec;
++      
++      for(i = 0; i < IPSEC_NUM_IF; i++) {
++              dev_ipsec = ipsecdevices[i];
++              if(dev_ipsec == NULL) {
++                continue;
++              }
++
++              /* release reference */
++              ipsecdevices[i]=NULL;
++              ipsec_dev_put(dev_ipsec);
++
++              KLIPS_PRINT(debug_tunnel, "Unregistering %s (refcnt=%d)\n",
++                          dev_ipsec->name,
++                          atomic_read(&dev_ipsec->refcnt));
++              unregister_netdev(dev_ipsec);
++              KLIPS_PRINT(debug_tunnel, "Unregisted %s\n", dev_ipsec->name);
++#ifndef NETDEV_23
++              kfree(dev_ipsec->name);
++              dev_ipsec->name=NULL;
++#endif /* !NETDEV_23 */
++              kfree(dev_ipsec->priv);
++              dev_ipsec->priv=NULL;
++      }
++      return error;
++}
++
++/*
++ * $Log: ipsec_tunnel.c,v $
++ * Revision 1.232.2.5  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.232.2.4  2006/03/28 20:58:19  ken
++ * Fix for KLIPS on 2.6.16 - need to include <net/arp.h> now
++ *
++ * Revision 1.232.2.3  2006/02/15 05:14:12  paul
++ * 568: uninitialized struct in ipsec_tunnel.c coud break routing under 2.6 kernels
++ * ipsec_tunnel_send() calls the entry point function of routing subsystem
++ * (ip_route_output_key()) using a not fully initialized struct of type
++ * struct flowi.
++ * This will cause a failure in routing packets through an ipsec interface
++ * when patches for multipath routing from http://www.ssi.bg/~ja/
++ * are applied.
++ *
++ * Revision 1.232.2.2  2005/11/22 04:11:52  ken
++ * Backport fixes for 2.6.14 kernels from HEAD
++ *
++ * Revision 1.232.2.1  2005/09/21 22:57:43  paul
++ * pulled up compile fix for 2.6.13
++ *
++ * Revision 1.232  2005/06/04 16:06:06  mcr
++ *    better patch for nat-t rcv-device code.
++ *
++ * Revision 1.231  2005/05/21 03:28:51  mcr
++ *    make sure that port-500 hole is used for port-4500 as well.
++ *
++ * Revision 1.230  2005/05/11 01:42:04  mcr
++ *    removal of debugging showed useless/wrong variables used.
++ *
++ * Revision 1.229  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.228  2005/01/26 00:50:35  mcr
++ *    adjustment of confusion of CONFIG_IPSEC_NAT vs CONFIG_KLIPS_NAT,
++ *    and make sure that NAT_TRAVERSAL is set as well to match
++ *    userspace compiles of code.
++ *
++ * Revision 1.227  2004/12/10 21:16:08  ken
++ * 64bit fixes from Opteron port of KLIPS 2.6
++ *
++ * Revision 1.226  2004/12/04 07:11:23  mcr
++ *    fix for snmp SIOCPRIVATE use of snmpd.
++ *    http://bugs.xelerance.com/view.php?id=144
++ *
++ * Revision 1.225  2004/12/03 21:25:57  mcr
++ *    compile time fixes for running on 2.6.
++ *    still experimental.
++ *
++ * Revision 1.224  2004/08/14 03:28:24  mcr
++ *    fixed log comment to remove warning about embedded comment.
++ *
++ * Revision 1.223  2004/08/04 15:57:07  mcr
++ *    moved des .h files to include/des/ *
++ *    included 2.6 protocol specific things
++ *    started at NAT-T support, but it will require a kernel patch.
++ *
++ * Revision 1.222  2004/08/03 18:19:08  mcr
++ *    in 2.6, use "net_device" instead of #define device->net_device.
++ *    this probably breaks 2.0 compiles.
++ *
++ * Revision 1.221  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.220  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.219  2004/02/03 03:13:17  mcr
++ *    minor edits for readability, and error reporting.
++ *
++ * Revision 1.218  2004/01/27 20:29:20  mcr
++ *    fix for unregister_netdev() problem for underlying eth0.
++ *
++ * Revision 1.217  2003/12/10 01:14:27  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.216  2003/12/04 23:01:17  mcr
++ *    removed ipsec_netlink.h
++ *
++ * Revision 1.215  2003/12/04 16:35:16  ken
++ * Fix for ATM devices where physdev->hard_header_len *is* correct
++ *
++ * Revision 1.214  2003/11/25 23:52:37  mcr
++ *    fix typo in patch - ixs-> needed.
++ *
++ * Revision 1.213  2003/11/24 18:25:49  mcr
++ *    patch from willy@w.ods.org to fix problems with ATM interfaces.
++ *
++ * Revision 1.212  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.211.2.2  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.211.2.1  2003/09/21 13:59:56  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.211  2003/09/10 16:46:30  mcr
++ *    patches for 2.4 backport/2.6 existence.
++ *
++ * Revision 1.210  2003/07/31 22:47:16  mcr
++ *    preliminary (untested by FS-team) 2.5 patches.
++ *
++ * Revision 1.209  2003/06/22 21:28:43  mcr
++ *    inability to unload module was caused by calls to dev_get
++ *    (ipsec_dev_get), to gather a device from a name. There is
++ *    simply no reason to look the devices up - they should be kept
++ *    in a nice array, ready for use.
++ *
++ * Revision 1.208  2003/06/22 21:25:07  mcr
++ *    all staticly counted ipsecXXX device support removed.
++ *
++ * Revision 1.207  2003/04/02 20:15:37  mcr
++ *    fix for PR#204 - do not clear connection tracking info if we
++ *    the packet is being sent in the clear.
++ *
++ * Revision 1.206  2003/02/12 19:32:51  rgb
++ * Refactored file to:
++ * ipsec_xmit.c
++ * ipsec_xmit.h
++ * ipsec_mast.c
++ *
++ * Revision 1.205  2003/02/06 17:47:00  rgb
++ *
++ * Remove unused ipsec_tunnel_lock() and ipsec_tunnel_unlock() code.
++ * Refactor ipsec_tunnel_start_xmit() further into:
++ *         ipsec_xmit_sanity_check_dev()
++ *         ipsec_xmit_sanity_check_skb()
++ *         ipsec_xmit_strip_hard_header()
++ *         ipsec_xmit_restore_hard_header()
++ *         ipsec_xmit_send()
++ *         ipsec_xmit_cleanup()
++ * and start a skeletal ipsec_mast_start_xmit() .
++ *
++ * Revision 1.204  2003/02/06 06:43:46  rgb
++ *
++ * Refactor ipsec_tunnel_start_xmit, bringing out:
++ *     ipsec_xmit_SAlookup
++ *     ipsec_xmit_encap_once
++ *     ipsec_xmit_encap_bundle
++ *
++ * Revision 1.203  2003/02/06 02:21:34  rgb
++ *
++ * Moved "struct auth_alg" from ipsec_rcv.c to ipsec_ah.h .
++ * Changed "struct ah" to "struct ahhdr" and "struct esp" to "struct esphdr".
++ * Removed "#ifdef INBOUND_POLICY_CHECK_eroute" dead code.
++ *
++ * Revision 1.202  2003/01/03 07:38:01  rgb
++ *
++ * Start to refactor ipsec_tunnel_start_xmit() by putting local variables
++ * into struct ipsec_xmit_state and renaming a few variables to give more
++ * unique or searchable names.
++ *
++ * Revision 1.201  2003/01/03 00:31:28  rgb
++ *
++ * Clean up memset usage, including fixing 2 places where keys were not
++ * properly wiped.
++ *
++ * Revision 1.200  2002/12/06 02:24:02  mcr
++ *    patches for compiling against SUSE 8.1 kernels. Requires
++ *    an additional -DSUSE_LINUX_2_4_19_IS_STUPID.
++ *
++ * Revision 1.199  2002/10/12 23:11:53  dhr
++ *
++ * [KenB + DHR] more 64-bit cleanup
++ *
++ * Revision 1.198  2002/10/05 05:02:58  dhr
++ *
++ * C labels go on statements
++ *
++ * Revision 1.197  2002/09/20 05:01:50  rgb
++ * Added compiler directive to switch on IP options and fix IP options bug.
++ * Make ip->ihl treatment consistent using shifts rather than multiplications.
++ * Check for large enough packet before accessing udp header for IKE bypass.
++ * Added memory allocation debugging.
++ * Fixed potential memory allocation failure-induced oops.
++ *
++ * Revision 1.196  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.195  2002/07/23 03:36:07  rgb
++ * Fixed 2.2 device initialisation hang.
++ *
++ * Revision 1.194  2002/05/27 21:40:34  rgb
++ * Set unused ipsec devices to ARPHRD_VOID to avoid confusing iproute2.
++ * Cleaned up intermediate step to dynamic device allocation.
++ *
++ * Revision 1.193  2002/05/27 19:31:36  rgb
++ * Convert to dynamic ipsec device allocation.
++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT.
++ *
++ * Revision 1.192  2002/05/23 07:14:28  rgb
++ * Added refcount code.
++ * Cleaned up %p variants to 0p%p for test suite cleanup.
++ *
++ * Revision 1.191  2002/05/14 02:34:37  rgb
++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips,
++ * ipsec_sa or ipsec_sa.
++ *
++ * Revision 1.190  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.189  2002/04/24 07:36:32  mcr
++ * Moved from ./klips/net/ipsec/ipsec_tunnel.c,v
++ *
++ * Revision 1.188  2002/04/20 00:12:25  rgb
++ * Added esp IV CBC attack fix, disabled.
++ *
++ * Revision 1.187  2002/03/23 19:55:17  rgb
++ * Fix for 2.2 local IKE fragmentation blackhole.  Still won't work if
++ * iptraf or another pcap app is running.
++ *
++ * Revision 1.186  2002/03/19 03:26:22  rgb
++ * Applied DHR's tunnel patch to streamline IKE/specialSA processing.
++ *
++ * Revision 1.185  2002/02/20 04:13:05  rgb
++ * Send back ICMP_PKT_FILTERED upon %reject.
++ *
++ * Revision 1.184  2002/01/29 17:17:56  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.183  2002/01/29 04:00:53  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.182  2002/01/29 02:13:18  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.181  2002/01/07 20:00:33  rgb
++ * Added IKE destination port debugging.
++ *
++ * Revision 1.180  2001/12/21 21:49:54  rgb
++ * Fixed bug as a result of moving IKE bypass above %trap/%hold code.
++ *
++ * Revision 1.179  2001/12/19 21:08:14  rgb
++ * Added transport protocol ports to ipsec_print_ip().
++ * Update eroute info for non-SA targets.
++ * Added obey DF code disabled.
++ * Fixed formatting bugs in ipsec_tunnel_hard_header().
++ *
++ * Revision 1.178  2001/12/05 09:36:10  rgb
++ * Moved the UDP/500 IKE check just above the %hold/%trap checks to avoid
++ * IKE packets being stolen by the %hold (and returned to the sending KMd
++ * in an ACQUIRE, ironically  ;-).
++ *
++ * Revision 1.177  2001/11/26 09:23:50  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.170.2.1  2001/09/25 02:28:27  mcr
++ *    struct tdb -> struct ipsec_sa.
++ *    lifetime checks moved to common routines.
++ *    cleaned up includes.
++ *
++ * Revision 1.170.2.2  2001/10/22 21:08:01  mcr
++ *    include des.h, removed phony prototypes and fixed calling
++ *    conventions to match real prototypes.
++ *
++ * Revision 1.176  2001/11/09 18:32:31  rgb
++ * Added Hans Schultz' fragmented UDP/500 IKE socket port selector.
++ *
++ * Revision 1.175  2001/11/06 20:47:00  rgb
++ * Added Eric Espie's TRAPSUBNET fix, minus spin-lock-bh dabbling.
++ *
++ * Revision 1.174  2001/11/06 19:50:43  rgb
++ * Moved IP_SEND, ICMP_SEND, DEV_QUEUE_XMIT macros to ipsec_tunnel.h for
++ * use also by pfkey_v2_parser.c
++ *
++ * Revision 1.173  2001/10/29 21:53:44  henry
++ * tone down the device-down message slightly, until we can make it smarter
++ *
++ * Revision 1.172  2001/10/26 04:59:37  rgb
++ * Added a critical level syslog message if an ipsec device goes down.
++ *
++ * Revision 1.171  2001/10/18 04:45:21  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.170  2001/09/25 00:09:50  rgb
++ * Added NetCelo's TRAPSUBNET code to convert a new type TRAPSUBNET into a
++ * HOLD.
++ *
++ * Revision 1.169  2001/09/15 16:24:05  rgb
++ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
++ *
++ * Revision 1.168  2001/09/14 16:58:37  rgb
++ * Added support for storing the first and last packets through a HOLD.
++ *
++ * Revision 1.167  2001/09/08 21:13:33  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.166  2001/08/27 19:47:59  rgb
++ * Clear tdb  before usage.
++ * Added comment: clear IF before calling routing?
++ *
++ * Revision 1.165  2001/07/03 01:23:53  rgb
++ * Send back ICMP iff DF set, !ICMP, offset==0, sysctl_icmp, iph->tot_len >
++ * emtu, and don't drop.
++ *
++ * Revision 1.164  2001/06/14 19:35:10  rgb
++ * Update copyright date.
++ *
++ * Revision 1.163  2001/06/06 20:28:51  rgb
++ * Added sanity checks for NULL skbs and devices.
++ * Added more debugging output to various functions.
++ * Removed redundant dev->priv argument to ipsec_tunnel_{at,de}tach().
++ * Renamed ipsec_tunnel_attach() virtual and physical device arguments.
++ * Corrected neigh_setup() device function assignment.
++ * Keep valid pointers to ipsec_tunnel_*() on detach.
++ * Set dev->type to the originally-initiallised value.
++ *
++ * Revision 1.162  2001/06/01 07:28:04  rgb
++ * Added sanity checks for detached devices.  Don't down virtual devices
++ * to prevent packets going out in the clear if the detached device comes
++ * back up.
++ *
++ * Revision 1.161  2001/05/30 08:14:52  rgb
++ * Removed vestiges of esp-null transforms.
++ * NetDev Notifier instrumentation to track down disappearing devices.
++ *
++ * Revision 1.160  2001/05/29 05:15:12  rgb
++ * Added SS' PMTU patch which notifies sender if packet doesn't fit
++ * physical MTU (if it wasn't ICMP) and then drops it.
++ *
++ * Revision 1.159  2001/05/27 06:12:12  rgb
++ * Added structures for pid, packet count and last access time to eroute.
++ * Added packet count to beginning of /proc/net/ipsec_eroute.
++ *
++ * Revision 1.158  2001/05/24 05:39:33  rgb
++ * Applied source zeroing to 2.2 ip_route_output() call as well to enable
++ * PASS eroutes for opportunism.
++ *
++ * Revision 1.157  2001/05/23 22:35:28  rgb
++ * 2.4 source override simplification.
++ *
++ * Revision 1.156  2001/05/23 21:41:31  rgb
++ * Added error return code printing on ip_route_output().
++ *
++ * Revision 1.155  2001/05/23 05:09:13  rgb
++ * Fixed incorrect ip_route_output() failure message.
++ *
++ * Revision 1.154  2001/05/21 14:53:31  rgb
++ * Added debug statement for case when ip_route_output() fails, causing
++ * packet to be dropped, but log looked ok.
++ *
++ * Revision 1.153  2001/05/19 02:37:54  rgb
++ * Fixed missing comment termination.
++ *
++ * Revision 1.152  2001/05/19 02:35:50  rgb
++ * Debug code optimisation for non-debug speed.
++ * Kernel version compiler define comments.
++ * 2.2 and 2.4 kernel ip_send device and ip debug output added.
++ *
++ * Revision 1.151  2001/05/18 16:17:35  rgb
++ * Changed reference from "magic" to "shunt" SAs.
++ *
++ * Revision 1.150  2001/05/18 16:12:19  rgb
++ * Changed UDP/500 bypass test from 3 nested ifs to one anded if.
++ *
++ * Revision 1.149  2001/05/16 04:39:33  rgb
++ * Add default == eroute.dest to IKE bypass conditions for magic eroutes.
++ *
++ * Revision 1.148  2001/05/05 03:31:41  rgb
++ * IP frag debugging updates and enhancements.
++ *
++ * Revision 1.147  2001/05/03 19:41:40  rgb
++ * Added SS' skb_cow fix for 2.4.4.
++ *
++ * Revision 1.146  2001/04/30 19:28:16  rgb
++ * Update for 2.4.4.  ip_select_ident() now has 3 args.
++ *
++ * Revision 1.145  2001/04/23 14:56:10  rgb
++ * Added spin_lock() check to prevent double-locking for multiple
++ * transforms and hence kernel lock-ups with SMP kernels.
++ *
++ * Revision 1.144  2001/04/21 23:04:45  rgb
++ * Define out skb->used for 2.4 kernels.
++ * Check if soft expire has already been sent before sending another to
++ * prevent ACQUIRE flooding.
++ *
++ * Revision 1.143  2001/03/16 07:37:21  rgb
++ * Added comments to all #endifs.
++ *
++ * Revision 1.142  2001/02/28 05:03:27  rgb
++ * Clean up and rationalise startup messages.
++ *
++ * Revision 1.141  2001/02/27 22:24:54  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.140  2001/02/27 06:40:12  rgb
++ * Fixed TRAP->HOLD eroute byte order.
++ *
++ * Revision 1.139  2001/02/26 20:38:59  rgb
++ * Added compiler defines for 2.4.x-specific code.
++ *
++ * Revision 1.138  2001/02/26 19:57:27  rgb
++ * Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
++ * of the new SPD and to support opportunistic.
++ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs.
++ *
++ * Revision 1.137  2001/02/19 22:29:49  rgb
++ * Fixes for presence of active ipv6 segments which share ipsec physical
++ * device (gg).
++ *
++ * Revision 1.136  2001/01/29 22:30:38  rgb
++ * Fixed minor acquire debug printing bug.
++ *
++ * Revision 1.135  2001/01/29 22:19:45  rgb
++ * Zero source address for 2.4 bypass route lookup.
++ *
++ * Revision 1.134  2001/01/23 20:19:49  rgb
++ * 2.4 fix to remove removed is_clone member.
++ *
++ * Revision 1.133  2000/12/09 22:08:35  rgb
++ * Fix NET_23 bug, should be NETDEV_23.
++ *
++ * Revision 1.132  2000/12/01 06:54:50  rgb
++ * Fix for new 2.4 IP TTL default variable name.
++ *
++ * Revision 1.131  2000/11/09 20:52:15  rgb
++ * More spinlock shuffling, locking earlier and unlocking later in rcv to
++ * include ipcomp and prevent races, renaming some tdb variables that got
++ * forgotten, moving some unlocks to include tdbs and adding a missing
++ * unlock.  Thanks to Svenning for some of these.
++ *
++ * Revision 1.130  2000/11/09 20:11:22  rgb
++ * Minor shuffles to fix non-standard kernel config option selection.
++ *
++ * Revision 1.129  2000/11/06 04:32:49  rgb
++ * Clean up debug printing.
++ * Copy skb->protocol for all kernel versions.
++ * Ditched spin_lock_irqsave in favour of spin_lock.
++ * Disabled TTL decrement, done in ip_forward.
++ * Added debug printing before pfkey_acquire().
++ * Fixed printk-deltdbchain-spin_lock races (Svenning).
++ * Use defaultTTL for 2.1+ kernels.
++ * Add Svenning's adaptive content compression.
++ * Fix up debug display arguments.
++ *
++ * Revision 1.128  2000/09/28 00:58:57  rgb
++ * Moved the IKE passthrough check after the eroute lookup so we can pass
++ * IKE through intermediate tunnels.
++ *
++ * Revision 1.127  2000/09/22 17:52:11  rgb
++ * Fixed misleading ipcomp debug output.
++ *
++ * Revision 1.126  2000/09/22 04:22:56  rgb
++ * Fixed dumb spi->cpi conversion error.
++ *
++ * Revision 1.125  2000/09/21 04:34:48  rgb
++ * A few debug-specific things should be hidden under
++ * CONFIG_IPSEC_DEBUG.(MB)
++ * Improved ip_send() error handling.(MB)
++ *
++ * Revision 1.124  2000/09/21 03:40:58  rgb
++ * Added more debugging to try and track down the cpi outward copy problem.
++ *
++ * Revision 1.123  2000/09/19 07:08:49  rgb
++ * Added debugging to outgoing compression report.
++ *
++ * Revision 1.122  2000/09/18 19:21:26  henry
++ * RGB-supplied fix for RH5.2 problem
++ *
++ * Revision 1.121  2000/09/17 21:05:09  rgb
++ * Added tdb to skb_compress call to write in cpi.
++ *
++ * Revision 1.120  2000/09/17 16:57:16  rgb
++ * Added Svenning's patch to remove restriction of ipcomp to innermost
++ * transform.
++ *
++ * Revision 1.119  2000/09/15 11:37:01  rgb
++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++ * IPCOMP zlib deflate code.
++ *
++ * Revision 1.118  2000/09/15 04:57:16  rgb
++ * Moved debug output after sanity check.
++ * Added tos copy sysctl.
++ *
++ * Revision 1.117  2000/09/12 03:22:51  rgb
++ * Converted ipsec_icmp, no_eroute_pass, opportunistic and #if0 debugs to
++ * sysctl.
++ *
++ * Revision 1.116  2000/09/08 19:18:19  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ * Added outgoing opportunistic hook, ifdef'ed out.
++ *
++ * Revision 1.115  2000/08/30 05:27:29  rgb
++ * Removed all the rest of the references to tdb_spi, tdb_proto, tdb_dst.
++ * Kill remainder of tdb_xform, tdb_xdata, xformsw.
++ *
++ * Revision 1.114  2000/08/28 18:15:46  rgb
++ * Added MB's nf-debug reset patch.
++ *
++ * Revision 1.113  2000/08/27 02:26:40  rgb
++ * Send all no-eroute-bypass, pluto-bypass and passthrough packets through
++ * fragmentation machinery for 2.0, 2.2 and 2.4 kernels.
++ *
++ * Revision 1.112  2000/08/20 21:37:33  rgb
++ * Activated pfkey_expire() calls.
++ * Added a hard/soft expiry parameter to pfkey_expire(). (Momchil)
++ * Re-arranged the order of soft and hard expiry to conform to RFC2367.
++ * Clean up references to CONFIG_IPSEC_PFKEYv2.
++ *
++ * Revision 1.111  2000/08/01 14:51:51  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.110  2000/07/28 14:58:31  rgb
++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
++ *
++ * Revision 1.109  2000/07/28 13:50:54  rgb
++ * Changed enet_statistics to net_device_stats and added back compatibility
++ * for pre-2.1.19.
++ *
++ * Revision 1.108  2000/05/16 03:03:11  rgb
++ * Updates for 2.3.99pre8 from MB.
++ *
++ * Revision 1.107  2000/05/10 23:08:21  rgb
++ * Print a debug warning about bogus packets received by the outgoing
++ * processing machinery only when klipsdebug is not set to none.
++ * Comment out the device initialisation informational messages.
++ *
++ * Revision 1.106  2000/05/10 19:17:14  rgb
++ * Define an IP_SEND macro, intending to have all packet passthroughs
++ * use fragmentation.  This didn't quite work, but is a step in the
++ * right direction.
++ * Added buffer allocation debugging statements.
++ * Added configure option to shut off no eroute passthrough.
++ * Only check usetime against soft and hard limits if the tdb has been
++ * used.
++ * Cast output of ntohl so that the broken prototype doesn't make our
++ * compile noisy.
++ *
++ * Revision 1.105  2000/03/22 16:15:37  rgb
++ * Fixed renaming of dev_get (MB).
++ *
++ * Revision 1.104  2000/03/16 14:04:15  rgb
++ * Indented headers for readability.
++ * Fixed debug scope to enable compilation with debug off.
++ * Added macros for ip_chk_addr and IS_MYADDR for identifying self.
++ *
++ * Revision 1.103  2000/03/16 07:11:07  rgb
++ * Hardcode PF_KEYv2 support.
++ * Fixed bug which allowed UDP/500 packet from another machine
++ * through in the clear.
++ * Added disabled skb->protocol fix for ISDN/ASYNC PPP from Matjaz Godec.
++ *
++ * Revision 1.102  2000/03/14 12:26:59  rgb
++ * Added skb->nfct support for clearing netfilter conntrack bits (MB).
++ *
++ * Revision 1.101  2000/02/14 21:05:22  rgb
++ * Added MB's netif_queue fix for kernels 2.3.43+.
++ *
++ * Revision 1.100  2000/01/26 10:04:57  rgb
++ * Fixed noisy 2.0 printk arguments.
++ *
++ * Revision 1.99  2000/01/21 06:16:25  rgb
++ * Added sanity checks on skb_push(), skb_pull() to prevent panics.
++ * Switched to AF_ENCAP macro.
++ * Shortened debug output per packet and re-arranging debug_tunnel
++ * bitmap flags, while retaining necessary information to avoid
++ * trampling the kernel print ring buffer.
++ * Reformatted recursion switch code.
++ * Changed all references to tdb_proto to tdb_said.proto for clarity.
++ *
++ * Revision 1.98  2000/01/13 08:09:31  rgb
++ * Shuffled debug_tunnel switches to focus output.
++ * Fixed outgoing recursion bug, limiting to recursing only if the remote
++ * SG changes and if it is valid, ie. not passthrough.
++ * Clarified a number of debug messages.
++ *
++ * Revision 1.97  2000/01/10 16:37:16  rgb
++ * MB support for new ip_select_ident() upon disappearance of
++ * ip_id_count in 2.3.36+.
++ *
++ * Revision 1.96  1999/12/31 14:59:08  rgb
++ * MB fix to use new skb_copy_expand in kernel 2.3.35.
++ *
++ * Revision 1.95  1999/12/29 21:15:44  rgb
++ * Fix tncfg to aliased device bug.
++ *
++ * Revision 1.94  1999/12/22 04:26:06  rgb
++ * Converted all 'static' functions to 'DEBUG_NO_STATIC' to enable
++ * debugging by providing external labels to all functions with debugging
++ * turned on.
++ *
++ * Revision 1.93  1999/12/13 13:30:14  rgb
++ * Changed MTU reports and HW address reporting back to debug only.
++ *
++ * Revision 1.92  1999/12/07 18:57:56  rgb
++ * Fix PFKEY symbol compile error (SADB_*) without pfkey enabled.
++ *
++ * Revision 1.91  1999/12/01 22:15:36  rgb
++ * Add checks for LARVAL and DEAD SAs.
++ * Change state of SA from MATURE to DYING when a soft lifetime is
++ * reached and print debug warning.
++ *
++ * Revision 1.90  1999/11/23 23:04:04  rgb
++ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
++ * Sort out pfkey and freeswan headers, putting them in a library path.
++ *
++ * Revision 1.89  1999/11/18 18:50:59  rgb
++ * Changed all device registrations for static linking to
++ * dynamic to reduce the number and size of patches.
++ *
++ * Revision 1.88  1999/11/18 04:09:19  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ *
++ * Revision 1.87  1999/11/17 15:53:40  rgb
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ *
++ * Revision 1.86  1999/10/16 18:25:37  rgb
++ * Moved SA lifetime expiry checks before packet processing.
++ * Expire SA on replay counter rollover.
++ *
++ * Revision 1.85  1999/10/16 04:24:31  rgb
++ * Add stats for time since last packet.
++ *
++ * Revision 1.84  1999/10/16 00:30:47  rgb
++ * Added SA lifetime counting.
++ *
++ * Revision 1.83  1999/10/15 22:15:57  rgb
++ * Clean out cruft.
++ * Add debugging.
++ *
++ * Revision 1.82  1999/10/08 18:26:19  rgb
++ * Fix 2.0.3x outgoing fragmented packet memory leak.
++ *
++ * Revision 1.81  1999/10/05 02:38:54  rgb
++ * Lower the default mtu of virtual devices to 16260.
++ *
++ * Revision 1.80  1999/10/03 18:56:41  rgb
++ * Spinlock support for 2.3.xx.
++ * Don't forget to undo spinlocks on error!
++ * Check for valid eroute before copying the structure.
++ *
++ * Revision 1.79  1999/10/01 15:44:53  rgb
++ * Move spinlock header include to 2.1> scope.
++ *
++ * Revision 1.78  1999/10/01 00:02:43  rgb
++ * Added tdb structure locking.
++ * Added eroute structure locking.
++ *
++ * Revision 1.77  1999/09/30 02:52:29  rgb
++ * Add Marc Boucher's Copy-On-Write code (same as ipsec_rcv.c).
++ *
++ * Revision 1.76  1999/09/25 19:31:27  rgb
++ * Refine MSS hack to affect SYN, but not SYN+ACK packets.
++ *
++ * Revision 1.75  1999/09/24 22:52:38  rgb
++ * Fix two things broken in 2.0.38 by trying to fix network notifiers.
++ *
++ * Revision 1.74  1999/09/24 00:30:37  rgb
++ * Add test for changed source as well as destination to check for
++ * recursion.
++ *
++ * Revision 1.73  1999/09/23 20:52:24  rgb
++ * Add James Morris' MSS hack patch, disabled.
++ *
++ * Revision 1.72  1999/09/23 20:22:40  rgb
++ * Enable, tidy and fix network notifier code.
++ *
++ * Revision 1.71  1999/09/23 18:09:05  rgb
++ * Clean up 2.2.x fragmenting traces.
++ * Disable dev->type switching, forcing ARPHRD_TUNNEL.
++ *
++ * Revision 1.70  1999/09/22 14:14:24  rgb
++ * Add sanity checks for revectored calls to prevent calling a downed I/F.
++ *
++ * Revision 1.69  1999/09/21 15:00:57  rgb
++ * Add Marc Boucher's packet size check.
++ * Flesh out network device notifier code.
++ *
++ * Revision 1.68  1999/09/18 11:39:57  rgb
++ * Start to add (disabled) netdevice notifier code.
++ *
++ * Revision 1.67  1999/09/17 23:44:40  rgb
++ * Add a comment warning potential code hackers to stay away from mac.raw.
++ *
++ * Revision 1.66  1999/09/17 18:04:02  rgb
++ * Add fix for unpredictable hard_header_len for ISDN folks (thanks MB).
++ * Ditch TTL decrement in 2.2 (MB).
++ *
++ * Revision 1.65  1999/09/15 23:15:35  henry
++ * Marc Boucher's PPP fixes
++ *
++ * Revision 1.64  1999/09/07 13:40:53  rgb
++ * Ditch unreliable references to skb->mac.raw.
++ *
++ * Revision 1.63  1999/08/28 11:33:09  rgb
++ * Check for null skb->mac pointer.
++ *
++ * Revision 1.62  1999/08/28 02:02:30  rgb
++ * Add Marc Boucher's fix for properly dealing with skb->sk.
++ *
++ * Revision 1.61  1999/08/27 05:23:05  rgb
++ * Clean up skb->data/raw/nh/h manipulation.
++ * Add Marc Boucher's mods to aid tcpdump.
++ * Add sanity checks to skb->raw/nh/h pointer copies in skb_copy_expand.
++ * Re-order hard_header stripping -- might be able to remove it...
++ *
++ * Revision 1.60  1999/08/26 20:01:02  rgb
++ * Tidy up compiler directives and macros.
++ * Re-enable ICMP for tunnels where inner_dst !=  outer_dst.
++ * Remove unnecessary skb->dev = physdev assignment affecting 2.2.x.
++ *
++ * Revision 1.59  1999/08/25 15:44:41  rgb
++ * Clean up from 2.2.x instrumenting for compilation under 2.0.36.
++ *
++ * Revision 1.58  1999/08/25 15:00:54  rgb
++ * Add dst cache code for 2.2.xx.
++ * Add sanity check for skb packet header pointers.
++ * Add/modify debugging instrumentation to *_start_xmit, *_hard_header and
++ * *_rebuild_header.
++ * Add neigh_* cache code.
++ * Change dev->type back to ARPHRD_TUNNEL.
++ *
++ * Revision 1.57  1999/08/17 21:50:23  rgb
++ * Fixed minor debug output bugs.
++ * Regrouped error recovery exit code.
++ * Added compiler directives to remove unwanted code and symbols.
++ * Shut off ICMP messages: to be refined to only send ICMP to remote systems.
++ * Add debugging code for output function addresses.
++ * Fix minor bug in (possibly unused) header_cache_bind function.
++ * Add device neighbour caching code.
++ * Change dev->type from ARPHRD_TUNNEL to physdev->type.
++ *
++ * Revision 1.56  1999/08/03 17:22:56  rgb
++ * Debug output clarification using KERN_* macros.  Other inactive changes
++ * added.
++ *
++ * Revision 1.55  1999/08/03 16:58:46  rgb
++ * Fix skb_copy_expand size bug.  Was getting incorrect size.
++ *
++ * Revision 1.54  1999/07/14 19:32:38  rgb
++ * Fix oversize packet crash and ssh stalling in 2.2.x kernels.
++ *
++ * Revision 1.53  1999/06/10 15:44:02  rgb
++ * Minor reformatting and clean-up.
++ *
++ * Revision 1.52  1999/05/09 03:25:36  rgb
++ * Fix bug introduced by 2.2 quick-and-dirty patch.
++ *
++ * Revision 1.51  1999/05/08 21:24:59  rgb
++ * Add casting to silence the 2.2.x compile.
++ *
++ * Revision 1.50  1999/05/05 22:02:32  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.49  1999/04/29 15:18:52  rgb
++ * Change gettdb parameter to a pointer to reduce stack loading and
++ * facilitate parameter sanity checking.
++ * Fix undetected bug that might have tried to access a null pointer.
++ * Eliminate unnessessary usage of tdb_xform member to further switch
++ * away from the transform switch to the algorithm switch.
++ * Add return values to init and cleanup functions.
++ *
++ * Revision 1.48  1999/04/16 15:38:00  rgb
++ * Minor rearrangement of freeing code to avoid memory leaks with impossible or
++ * rare situations.
++ *
++ * Revision 1.47  1999/04/15 15:37:25  rgb
++ * Forward check changes from POST1_00 branch.
++ *
++ * Revision 1.32.2.4  1999/04/13 21:00:18  rgb
++ * Ditch 'things I wish I had known before...'.
++ *
++ * Revision 1.32.2.3  1999/04/13 20:34:38  rgb
++ * Free skb after fragmentation.
++ * Use stats more effectively.
++ * Add I/F to mtu notch-down reporting.
++ *
++ * Revision 1.32.2.2  1999/04/02 04:26:14  rgb
++ * Backcheck from HEAD, pre1.0.
++ *
++ * Revision 1.46  1999/04/11 00:29:00  henry
++ * GPL boilerplate
++ *
++ * Revision 1.45  1999/04/07 15:42:01  rgb
++ * Fix mtu/ping bug AGAIN!
++ *
++ * Revision 1.44  1999/04/06 04:54:27  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.43  1999/04/04 03:57:07  rgb
++ * ip_fragment() doesn't free the supplied skb.  Freed.
++ *
++ * Revision 1.42  1999/04/01 23:27:15  rgb
++ * Preload size of virtual mtu.
++ *
++ * Revision 1.41  1999/04/01 09:31:23  rgb
++ * Invert meaning of ICMP PMTUD config option and clarify.
++ * Code clean-up.
++ *
++ * Revision 1.40  1999/04/01 04:37:17  rgb
++ * SSH stalling bug fix.
++ *
++ * Revision 1.39  1999/03/31 23:44:28  rgb
++ * Don't send ICMP on DF and frag_off.
++ *
++ * Revision 1.38  1999/03/31 15:20:10  rgb
++ * Quiet down debugging.
++ *
++ * Revision 1.37  1999/03/31 08:30:31  rgb
++ * Add switch to shut off ICMP PMTUD packets.
++ *
++ * Revision 1.36  1999/03/31 05:44:47  rgb
++ * Keep PMTU reduction private.
++ *
++ * Revision 1.35  1999/03/27 15:13:02  rgb
++ * PMTU/fragmentation bug fix.
++ *
++ * Revision 1.34  1999/03/17 21:19:26  rgb
++ * Fix kmalloc nonatomic bug.
++ *
++ * Revision 1.33  1999/03/17 15:38:42  rgb
++ * Code clean-up.
++ * ESP_NULL IV bug fix.
++ *
++ * Revision 1.32  1999/03/01 20:44:25  rgb
++ * Code clean-up.
++ * Memory leak bug fix.
++ *
++ * Revision 1.31  1999/02/27 00:02:09  rgb
++ * Tune to report the MTU reduction once, rather than after every recursion
++ * through the encapsulating code, preventing tcp stream stalling.
++ *
++ * Revision 1.30  1999/02/24 20:21:01  rgb
++ * Reformat debug printk's.
++ * Fix recursive encapsulation, dynamic MTU bugs and add debugging code.
++ * Clean-up.
++ *
++ * Revision 1.29  1999/02/22 17:08:14  rgb
++ * Fix recursive encapsulation code.
++ *
++ * Revision 1.28  1999/02/19 18:27:02  rgb
++ * Improve DF, fragmentation and PMTU behaviour and add dynamic MTU discovery.
++ *
++ * Revision 1.27  1999/02/17 16:51:37  rgb
++ * Clean out unused cruft.
++ * Temporarily tone down volume of debug output.
++ * Temporarily shut off fragment rejection.
++ * Disabled temporary failed recursive encapsulation loop.
++ *
++ * Revision 1.26  1999/02/12 21:21:26  rgb
++ * Move KLIPS_PRINT to ipsec_netlink.h for accessibility.
++ *
++ * Revision 1.25  1999/02/11 19:38:27  rgb
++ * More clean-up.
++ * Add sanity checking for skb_copy_expand() to prevent kernel panics on
++ * skb_put() values out of range.
++ * Fix head/tailroom calculation causing skb_put() out-of-range values.
++ * Fix return values to prevent 'nonatomic alloc_skb' warnings.
++ * Allocate new skb iff needed.
++ * Added more debug statements.
++ * Make headroom depend on structure, not hard-coded values.
++ *
++ * Revision 1.24  1999/02/10 23:20:33  rgb
++ * Shut up annoying 'statement has no effect' compiler warnings with
++ * debugging compiled out.
++ *
++ * Revision 1.23  1999/02/10 22:36:30  rgb
++ * Clean-up obsolete, unused and messy code.
++ * Converted most IPSEC_DEBUG statements to KLIPS_PRINT macros.
++ * Rename ipsec_tunnel_do_xmit to ipsec_tunnel_start_xmit and eliminated
++ * original ipsec_tunnel_start_xmit.
++ * Send all packet with different inner and outer destinations directly to
++ * the attached physical device, rather than back through ip_forward,
++ * preventing disappearing routes problems.
++ * Do sanity checking before investing too much CPU in allocating new
++ * structures.
++ * Fail on IP header options: We cannot process them yet.
++ * Add some helpful comments.
++ * Use virtual device for parameters instead of physical device.
++ *
++ * Revision 1.22  1999/02/10 03:03:02  rgb
++ * Duh.  Fixed the TTL bug: forgot to update the checksum.
++ *
++ * Revision 1.21  1999/02/09 23:17:53  rgb
++ * Add structure members to ipsec_print_ip debug function.
++ * Temporarily fix TTL bug preventing tunnel mode from functioning.
++ *
++ * Revision 1.20  1999/02/09 00:14:25  rgb
++ * Add KLIPSPRINT macro.  (Not used yet, though.)
++ * Delete old ip_tunnel code (BADCODE).
++ * Decrement TTL in outgoing packet.
++ * Set TTL on new IPIP_TUNNEL to default, not existing packet TTL.
++ * Delete ethernet only feature and fix hard-coded hard_header_len.
++ *
++ * Revision 1.19  1999/01/29 17:56:22  rgb
++ * 64-bit re-fix submitted by Peter Onion.
++ *
++ * Revision 1.18  1999/01/28 22:43:24  rgb
++ * Fixed bug in ipsec_print_ip that caused an OOPS, found by P.Onion.
++ *
++ * Revision 1.17  1999/01/26 02:08:16  rgb
++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
++ * Removed dead code.
++ *
++ * Revision 1.16  1999/01/22 06:25:26  rgb
++ * Cruft clean-out.
++ * Added algorithm switch code.
++ * 64-bit clean-up.
++ * Passthrough on IPIP protocol, spi 0x0 fix.
++ * Enhanced debugging.
++ *
++ * Revision 1.15  1998/12/01 13:22:04  rgb
++ * Added support for debug printing of version info.
++ *
++ * Revision 1.14  1998/11/30 13:22:55  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.13  1998/11/17 21:13:52  rgb
++ * Put IKE port bypass debug output in user-switched debug statements.
++ *
++ * Revision 1.12  1998/11/13 13:20:25  rgb
++ * Fixed ntohs bug in udp/500 hole for IKE.
++ *
++ * Revision 1.11  1998/11/10 08:01:19  rgb
++ * Kill tcp/500 hole,  keep udp/500 hole.
++ *
++ * Revision 1.10  1998/11/09 21:29:26  rgb
++ * If no eroute is found, discard packet and incr. tx_error.
++ *
++ * Revision 1.9  1998/10/31 06:50:00  rgb
++ * Add tcp/udp/500 bypass.
++ * Fixed up comments in #endif directives.
++ *
++ * Revision 1.8  1998/10/27 00:34:31  rgb
++ * Reformat debug output of IP headers.
++ * Newlines added before calls to ipsec_print_ip.
++ *
++ * Revision 1.7  1998/10/19 14:44:28  rgb
++ * Added inclusion of freeswan.h.
++ * sa_id structure implemented and used: now includes protocol.
++ *
++ * Revision 1.6  1998/10/09 04:31:35  rgb
++ * Added 'klips_debug' prefix to all klips printk debug statements.
++ *
++ * Revision 1.5  1998/08/28 03:09:51  rgb
++ * Prevent kernel log spam with default route through ipsec.
++ *
++ * Revision 1.4  1998/08/05 22:23:09  rgb
++ * Change setdev return code to ENXIO for a non-existant physical device.
++ *
++ * Revision 1.3  1998/07/29 20:41:11  rgb
++ * Add ipsec_tunnel_clear to clear all tunnel attachments.
++ *
++ * Revision 1.2  1998/06/25 20:00:33  rgb
++ * Clean up #endif comments.
++ * Rename dev_ipsec to dev_ipsec0 for consistency.
++ * Document ipsec device fields.
++ * Make ipsec_tunnel_probe visible from rest of kernel for static linking.
++ * Get debugging report for *every* ipsec device initialisation.
++ * Comment out redundant code.
++ *
++ * Revision 1.1  1998/06/18 21:27:50  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.8  1998/06/14 23:49:40  rgb
++ * Clarify version reporting on module loading.
++ *
++ * Revision 1.7  1998/05/27 23:19:20  rgb
++ * Added version reporting.
++ *
++ * Revision 1.6  1998/05/18 21:56:23  rgb
++ * Clean up for numerical consistency of output and cleaning up debug code.
++ *
++ * Revision 1.5  1998/05/12 02:44:23  rgb
++ * Clarifying 'no e-route to host' message.
++ *
++ * Revision 1.4  1998/04/30 15:34:35  rgb
++ * Enclosed most remaining debugging statements in #ifdef's to make it quieter.
++ *
++ * Revision 1.3  1998/04/21 21:28:54  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.2  1998/04/12 22:03:24  rgb
++ * Updated ESP-3DES-HMAC-MD5-96,
++ *    ESP-DES-HMAC-MD5-96,
++ *    AH-HMAC-MD5-96,
++ *    AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
++ *
++ * Fixed eroute references in /proc/net/ipsec*.
++ *
++ * Started to patch module unloading memory leaks in ipsec_netlink and
++ * radij tree unloading.
++ *
++ * Revision 1.1  1998/04/09 03:06:12  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:04  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.5  1997/06/03 04:24:48  ji
++ * Added transport mode.
++ * Changed the way routing is done.
++ * Lots of bug fixes.
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:39:04  ji
++ * Minor cleanups.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ * Local Variables:
++ * c-style: linux
++ * End:
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_xform.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,360 @@
++/*
++ * Common routines for IPSEC transformations.
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: ipsec_xform.c,v 1.65.2.1 2006/10/06 21:39:26 paul Exp $
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "freeswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++#include <linux/random.h>     /* get_random_bytes() */
++#include <freeswan.h>
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <net/ip.h>
++
++#include "freeswan/radij.h"
++#include "freeswan/ipsec_encap.h"
++#include "freeswan/ipsec_radij.h"
++#include "freeswan/ipsec_xform.h"
++#include "freeswan/ipsec_ipe4.h"
++#include "freeswan/ipsec_ah.h"
++#include "freeswan/ipsec_esp.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_xform = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#ifdef SPINLOCK
++spinlock_t tdb_lock = SPIN_LOCK_UNLOCKED;
++#else /* SPINLOCK */
++spinlock_t tdb_lock;
++#endif /* SPINLOCK */
++
++/*
++ * $Log: ipsec_xform.c,v $
++ * Revision 1.65.2.1  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.65  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.64  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.63  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.62.30.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.62  2002/05/14 02:34:21  rgb
++ * Delete stale code.
++ *
++ * Revision 1.61  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.60  2002/04/24 07:36:33  mcr
++ * Moved from ./klips/net/ipsec/ipsec_xform.c,v
++ *
++ * Revision 1.59  2002/03/29 15:01:36  rgb
++ * Delete decommissioned code.
++ *
++ * Revision 1.58  2002/01/29 17:17:57  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.57  2002/01/29 04:00:53  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.56  2001/11/27 05:17:22  mcr
++ *    turn off the worst of the per-packet debugging.
++ *
++ * Revision 1.55  2001/11/26 09:23:50  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.54  2001/10/18 04:45:21  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.53  2001/09/08 21:13:34  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.52  2001/06/14 19:35:11  rgb
++ * Update copyright date.
++ *
++ * Revision 1.51  2001/05/30 08:14:03  rgb
++ * Removed vestiges of esp-null transforms.
++ *
++ * Revision 1.50  2001/05/03 19:43:18  rgb
++ * Initialise error return variable.
++ * Update SENDERR macro.
++ * Fix sign of error return code for ipsec_tdbcleanup().
++ * Use more appropriate return code for ipsec_tdbwipe().
++ *
++ * Revision 1.49  2001/04/19 18:56:17  rgb
++ * Fixed tdb table locking comments.
++ *
++ * Revision 1.48  2001/02/27 22:24:55  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.47  2000/11/06 04:32:08  rgb
++ * Ditched spin_lock_irqsave in favour of spin_lock_bh.
++ *
++ * Revision 1.46  2000/09/20 16:21:57  rgb
++ * Cleaned up ident string alloc/free.
++ *
++ * Revision 1.45  2000/09/08 19:16:51  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ * Removed all references to CONFIG_IPSEC_PFKEYv2.
++ *
++ * Revision 1.44  2000/08/30 05:29:04  rgb
++ * Compiler-define out no longer used tdb_init() in ipsec_xform.c.
++ *
++ * Revision 1.43  2000/08/18 21:30:41  rgb
++ * Purged all tdb_spi, tdb_proto and tdb_dst macros.  They are unclear.
++ *
++ * Revision 1.42  2000/08/01 14:51:51  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.41  2000/07/28 14:58:31  rgb
++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
++ *
++ * Revision 1.40  2000/06/28 05:50:11  rgb
++ * Actually set iv_bits.
++ *
++ * Revision 1.39  2000/05/10 23:11:09  rgb
++ * Added netlink debugging output.
++ * Added a cast to quiet down the ntohl bug.
++ *
++ * Revision 1.38  2000/05/10 19:18:42  rgb
++ * Cast output of ntohl so that the broken prototype doesn't make our
++ * compile noisy.
++ *
++ * Revision 1.37  2000/03/16 14:04:59  rgb
++ * Hardwired CONFIG_IPSEC_PFKEYv2 on.
++ *
++ * Revision 1.36  2000/01/26 10:11:28  rgb
++ * Fixed spacing in error text causing run-in words.
++ *
++ * Revision 1.35  2000/01/21 06:17:16  rgb
++ * Tidied up compiler directive indentation for readability.
++ * Added ictx,octx vars for simplification.(kravietz)
++ * Added macros for HMAC padding magic numbers.(kravietz)
++ * Fixed missing key length reporting bug.
++ * Fixed bug in tdbwipe to return immediately on NULL tdbp passed in.
++ *
++ * Revision 1.34  1999/12/08 00:04:19  rgb
++ * Fixed SA direction overwriting bug for netlink users.
++ *
++ * Revision 1.33  1999/12/01 22:16:44  rgb
++ * Minor formatting changes in ESP MD5 initialisation.
++ *
++ * Revision 1.32  1999/11/25 09:06:36  rgb
++ * Fixed error return messages, should be returning negative numbers.
++ * Implemented SENDERR macro for propagating error codes.
++ * Added debug message and separate error code for algorithms not compiled
++ * in.
++ *
++ * Revision 1.31  1999/11/23 23:06:26  rgb
++ * Sort out pfkey and freeswan headers, putting them in a library path.
++ *
++ * Revision 1.30  1999/11/18 04:09:20  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ *
++ * Revision 1.29  1999/11/17 15:53:40  rgb
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ *
++ * Revision 1.28  1999/10/18 20:04:01  rgb
++ * Clean-out unused cruft.
++ *
++ * Revision 1.27  1999/10/03 19:01:03  rgb
++ * Spinlock support for 2.3.xx and 2.0.xx kernels.
++ *
++ * Revision 1.26  1999/10/01 16:22:24  rgb
++ * Switch from assignment init. to functional init. of spinlocks.
++ *
++ * Revision 1.25  1999/10/01 15:44:54  rgb
++ * Move spinlock header include to 2.1> scope.
++ *
++ * Revision 1.24  1999/10/01 00:03:46  rgb
++ * Added tdb structure locking.
++ * Minor formatting changes.
++ * Add function to initialize tdb hash table.
++ *
++ * Revision 1.23  1999/05/25 22:42:12  rgb
++ * Add deltdbchain() debugging.
++ *
++ * Revision 1.22  1999/05/25 21:24:31  rgb
++ * Add debugging statements to deltdbchain().
++ *
++ * Revision 1.21  1999/05/25 03:51:48  rgb
++ * Refix error return code.
++ *
++ * Revision 1.20  1999/05/25 03:34:07  rgb
++ * Fix error return for flush.
++ *
++ * Revision 1.19  1999/05/09 03:25:37  rgb
++ * Fix bug introduced by 2.2 quick-and-dirty patch.
++ *
++ * Revision 1.18  1999/05/05 22:02:32  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.17  1999/04/29 15:20:16  rgb
++ * Change gettdb parameter to a pointer to reduce stack loading and
++ * facilitate parameter sanity checking.
++ * Add sanity checking for null pointer arguments.
++ * Add debugging instrumentation.
++ * Add function deltdbchain() which will take care of unlinking,
++ * zeroing and deleting a chain of tdbs.
++ * Add a parameter to tdbcleanup to be able to delete a class of SAs.
++ * tdbwipe now actually zeroes the tdb as well as any of its pointed
++ * structures.
++ *
++ * Revision 1.16  1999/04/16 15:36:29  rgb
++ * Fix cut-and-paste error causing a memory leak in IPIP TDB freeing.
++ *
++ * Revision 1.15  1999/04/11 00:29:01  henry
++ * GPL boilerplate
++ *
++ * Revision 1.14  1999/04/06 04:54:28  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.13  1999/02/19 18:23:01  rgb
++ * Nix debug off compile warning.
++ *
++ * Revision 1.12  1999/02/17 16:52:16  rgb
++ * Consolidate satoa()s for space and speed efficiency.
++ * Convert DEBUG_IPSEC to KLIPS_PRINT
++ * Clean out unused cruft.
++ * Ditch NET_IPIP dependancy.
++ * Loop for 3des key setting.
++ *
++ * Revision 1.11  1999/01/26 02:09:05  rgb
++ * Remove ah/esp/IPIP switching on include files.
++ * Removed CONFIG_IPSEC_ALGO_SWITCH macro.
++ * Removed dead code.
++ * Clean up debug code when switched off.
++ * Remove references to INET_GET_PROTOCOL.
++ * Added code exclusion macros to reduce code from unused algorithms.
++ *
++ * Revision 1.10  1999/01/22 06:28:55  rgb
++ * Cruft clean-out.
++ * Put random IV generation in kernel.
++ * Added algorithm switch code.
++ * Enhanced debugging.
++ * 64-bit clean-up.
++ *
++ * Revision 1.9  1998/11/30 13:22:55  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.8  1998/11/25 04:59:06  rgb
++ * Add conditionals for no IPIP tunnel code.
++ * Delete commented out code.
++ *
++ * Revision 1.7  1998/10/31 06:50:41  rgb
++ * Convert xform ASCII names to no spaces.
++ * Fixed up comments in #endif directives.
++ *
++ * Revision 1.6  1998/10/19 14:44:28  rgb
++ * Added inclusion of freeswan.h.
++ * sa_id structure implemented and used: now includes protocol.
++ *
++ * Revision 1.5  1998/10/09 04:32:19  rgb
++ * Added 'klips_debug' prefix to all klips printk debug statements.
++ *
++ * Revision 1.4  1998/08/12 00:11:31  rgb
++ * Added new xform functions to the xform table.
++ * Fixed minor debug output spelling error.
++ *
++ * Revision 1.3  1998/07/09 17:45:31  rgb
++ * Clarify algorithm not available message.
++ *
++ * Revision 1.2  1998/06/23 03:00:51  rgb
++ * Check for presence of IPIP protocol if it is setup one way (we don't
++ * know what has been set up the other way and can only assume it will be
++ * symmetrical with the exception of keys).
++ *
++ * Revision 1.1  1998/06/18 21:27:51  henry
++ * move sources from klips/src to klips/net/ipsec, to keep stupid
++ * kernel-build scripts happier in the presence of symlinks
++ *
++ * Revision 1.3  1998/06/11 05:54:59  rgb
++ * Added transform version string pointer to xformsw initialisations.
++ *
++ * Revision 1.2  1998/04/21 21:28:57  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.1  1998/04/09 03:06:13  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:02  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.5  1997/06/03 04:24:48  ji
++ * Added ESP-3DES-MD5-96
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * Added new transforms.
++ *
++ * Revision 0.3  1996/11/20 14:39:04  ji
++ * Minor cleanups.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ipsec_xmit.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1850 @@
++/*
++ * IPSEC Transmit code.
++ * Copyright (C) 1996, 1997  John Ioannidis.
++ * Copyright (C) 1998-2003   Richard Guy Briggs.
++ * Copyright (C) 2004-2005   Michael Richardson <mcr@xelerance.com>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ */
++
++char ipsec_xmit_c_version[] = "RCSID $Id: ipsec_xmit.c,v 1.20.2.8 2006/10/06 21:39:26 paul Exp $";
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif        /* for CONFIG_IP_FORWARD */
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, struct net_device_stats, dev_queue_xmit() and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/tcp.h>         /* struct tcphdr */
++#include <linux/udp.h>         /* struct udphdr */
++#include <linux/skbuff.h>
++#include <asm/uaccess.h>
++#include <asm/checksum.h>
++#include <openswan.h>
++#ifdef NET_21
++# define MSS_HACK_            /* experimental */
++# include <linux/in6.h>
++# include <net/dst.h>
++# define proto_priv cb
++#endif /* NET_21 */
++
++#include <net/icmp.h>         /* icmp_send() */
++#include <net/ip.h>
++#ifdef NETDEV_23
++# include <linux/netfilter_ipv4.h>
++#endif /* NETDEV_23 */
++
++#include <linux/if_arp.h>
++#ifdef MSS_HACK
++# include <net/tcp.h>         /* TCP options */
++#endif        /* MSS_HACK */
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_life.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_eroute.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xmit.h"
++#include "openswan/ipsec_sa.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_ipe4.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++
++#ifdef CONFIG_KLIPS_IPCOMP
++#include "openswan/ipcomp.h"
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_alg.h"
++
++
++/* 
++ * Stupid kernel API differences in APIs. Not only do some
++ * kernels not have ip_select_ident, but some have differing APIs,
++ * and SuSE has one with one parameter, but no way of checking to
++ * see what is really what.
++ */
++
++#ifdef SUSE_LINUX_2_4_19_IS_STUPID
++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph)
++#else
++
++/* simplest case, nothing */
++#if !defined(IP_SELECT_IDENT)
++#define KLIPS_IP_SELECT_IDENT(iph, skb)  do { iph->id = htons(ip_id_count++); } while(0)
++#endif
++
++/* kernels > 2.3.37-ish */
++#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW)
++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst)
++#endif
++
++/* kernels > 2.4.2 */
++#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW)
++#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL)
++#endif
++
++#endif /* SUSE_LINUX_2_4_19_IS_STUPID */
++
++
++
++#if defined(CONFIG_KLIPS_AH)
++static __u32 zeroes[64];
++#endif
++
++#ifdef CONFIG_KLIPS_DEBUG
++int sysctl_ipsec_debug_verbose = 0;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++int ipsec_xmit_trap_count = 0;
++int ipsec_xmit_trap_sendcount = 0;
++
++int sysctl_ipsec_icmp = 0;
++int sysctl_ipsec_tos = 0;
++
++#ifdef CONFIG_KLIPS_DEBUG
++#define dmp(_x,_y,_z) if(debug_tunnel) ipsec_dmp_block(_x,_y,_z)
++#else /* CONFIG_KLIPS_DEBUG */
++#define dmp(_x, _y, _z) 
++#endif /* CONFIG_KLIPS_DEBUG */
++
++
++#if !defined(SKB_COPY_EXPAND) || defined(KLIPS_UNIT_TESTS)
++/*
++ *    This is mostly skbuff.c:skb_copy().
++ */
++struct sk_buff *
++skb_copy_expand(const struct sk_buff *skb, int headroom,
++              int tailroom, int priority)
++{
++      struct sk_buff *n;
++      unsigned long offset;
++
++      /*
++       *      Do sanity checking
++       */
++      if((headroom < 0) || (tailroom < 0) || ((headroom+tailroom) < 0)) {
++              printk(KERN_WARNING
++                     "klips_error:skb_copy_expand: "
++                     "Illegal negative head,tailroom %d,%d\n",
++                     headroom,
++                     tailroom);
++              return NULL;
++      }
++      /*
++       *      Allocate the copy buffer
++       */
++       
++#ifndef NET_21
++      IS_SKB(skb);
++#endif /* !NET_21 */
++
++
++      n=alloc_skb(skb->end - skb->head + headroom + tailroom, priority);
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:skb_copy_expand: "
++                  "allocating %d bytes, head=0p%p data=0p%p tail=0p%p end=0p%p end-head=%d tail-data=%d\n",
++                  skb->end - skb->head + headroom + tailroom,
++                  skb->head,
++                  skb->data,
++                  skb->tail,
++                  skb->end,
++                  skb->end - skb->head,
++                  skb->tail - skb->data);
++
++      if(n==NULL)
++              return NULL;
++
++      /*
++       *      Shift between the two data areas in bytes
++       */
++       
++      /* Set the data pointer */
++      skb_reserve(n,skb->data-skb->head+headroom);
++      /* Set the tail pointer and length */
++      if(skb_tailroom(n) < skb->len) {
++              printk(KERN_WARNING "klips_error:skb_copy_expand: "
++                     "tried to skb_put %ld, %d available.  This should never happen, please report.\n",
++                     (unsigned long int)skb->len,
++                     skb_tailroom(n));
++              ipsec_kfree_skb(n);
++              return NULL;
++      }
++      skb_put(n,skb->len);
++
++      offset=n->head + headroom - skb->head;
++
++      /* Copy the bytes */
++      memcpy(n->head + headroom, skb->head,skb->end-skb->head);
++#ifdef NET_21
++      n->csum=skb->csum;
++      n->priority=skb->priority;
++      n->dst=dst_clone(skb->dst);
++      if(skb->nh.raw)
++              n->nh.raw=skb->nh.raw+offset;
++#ifndef NETDEV_23
++      n->is_clone=0;
++#endif /* NETDEV_23 */
++      atomic_set(&n->users, 1);
++      n->destructor = NULL;
++#ifdef HAVE_SOCK_SECURITY
++      n->security=skb->security;
++#endif
++#else /* NET_21 */
++      n->link3=NULL;
++      n->when=skb->when;
++      if(skb->ip_hdr)
++              n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
++      n->saddr=skb->saddr;
++      n->daddr=skb->daddr;
++      n->raddr=skb->raddr;
++      n->seq=skb->seq;
++      n->end_seq=skb->end_seq;
++      n->ack_seq=skb->ack_seq;
++      n->acked=skb->acked;
++      n->free=1;
++      n->arp=skb->arp;
++      n->tries=0;
++      n->lock=0;
++      n->users=0;
++#endif /* NET_21 */
++      n->protocol=skb->protocol;
++      n->list=NULL;
++      n->sk=NULL;
++      n->dev=skb->dev;
++      if(skb->h.raw)
++              n->h.raw=skb->h.raw+offset;
++      if(skb->mac.raw) 
++              n->mac.raw=skb->mac.raw+offset;
++      memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
++#ifndef NETDEV_23
++      n->used=skb->used;
++#endif /* !NETDEV_23 */
++      n->pkt_type=skb->pkt_type;
++      n->stamp=skb->stamp;
++      
++#ifndef NET_21
++      IS_SKB(n);
++#endif /* !NET_21 */
++      return n;
++}
++#endif /* !SKB_COPY_EXPAND */
++
++#ifdef CONFIG_KLIPS_DEBUG
++void
++ipsec_print_ip(struct iphdr *ip)
++{
++      char buf[ADDRTOA_BUF];
++
++      printk(KERN_INFO "klips_debug:   IP:");
++      printk(" ihl:%d", ip->ihl << 2);
++      printk(" ver:%d", ip->version);
++      printk(" tos:%d", ip->tos);
++      printk(" tlen:%d", ntohs(ip->tot_len));
++      printk(" id:%d", ntohs(ip->id));
++      printk(" %s%s%sfrag_off:%d",
++               ip->frag_off & __constant_htons(IP_CE) ? "CE " : "",
++               ip->frag_off & __constant_htons(IP_DF) ? "DF " : "",
++               ip->frag_off & __constant_htons(IP_MF) ? "MF " : "",
++               (ntohs(ip->frag_off) & IP_OFFSET) << 3);
++      printk(" ttl:%d", ip->ttl);
++      printk(" proto:%d", ip->protocol);
++      if(ip->protocol == IPPROTO_UDP)
++              printk(" (UDP)");
++      if(ip->protocol == IPPROTO_TCP)
++              printk(" (TCP)");
++      if(ip->protocol == IPPROTO_ICMP)
++              printk(" (ICMP)");
++      if(ip->protocol == IPPROTO_ESP)
++              printk(" (ESP)");
++      if(ip->protocol == IPPROTO_AH)
++              printk(" (AH)");
++      if(ip->protocol == IPPROTO_COMP)
++              printk(" (COMP)");
++      printk(" chk:%d", ntohs(ip->check));
++      addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf));
++      printk(" saddr:%s", buf);
++      if(ip->protocol == IPPROTO_UDP)
++              printk(":%d",
++                     ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));
++      if(ip->protocol == IPPROTO_TCP)
++              printk(":%d",
++                     ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));
++      addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf));
++      printk(" daddr:%s", buf);
++      if(ip->protocol == IPPROTO_UDP)
++              printk(":%d",
++                     ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));
++      if(ip->protocol == IPPROTO_TCP)
++              printk(":%d",
++                     ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));
++      if(ip->protocol == IPPROTO_ICMP)
++              printk(" type:code=%d:%d",
++                     ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type,
++                     ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code);
++      printk("\n");
++
++      if(sysctl_ipsec_debug_verbose) {
++              __u8 *c;
++              int len = ntohs(ip->tot_len) - ip->ihl*4;
++              
++              c = ((__u8*)ip) + ip->ihl*4;
++              ipsec_dmp_block("ip_print", c, len);
++      }
++}
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#ifdef MSS_HACK
++/*
++ * Issues:
++ *  1) Fragments arriving in the tunnel should probably be rejected.
++ *  2) How does this affect syncookies, mss_cache, dst cache ?
++ *  3) Path MTU discovery handling needs to be reviewed.  For example,
++ *     if we receive an ICMP 'packet too big' message from an intermediate 
++ *     router specifying it's next hop MTU, our stack may process this and
++ *     adjust the MSS without taking our AH/ESP overheads into account.
++ */
++
++ 
++/*
++ * Recaclulate checksum using differences between changed datum, 
++ * borrowed from netfilter.
++ */
++DEBUG_NO_STATIC u_int16_t 
++ipsec_fast_csum(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
++{
++      u_int32_t diffs[] = { oldvalinv, newval };
++      return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
++      oldcheck^0xFFFF));
++}
++
++/*
++ * Determine effective MSS.
++ *
++ * Note that we assume that there is always an MSS option for our own
++ * SYN segments, which is mentioned in tcp_syn_build_options(), kernel 2.2.x.
++ * This could change, and we should probably parse TCP options instead.
++ *
++ */
++DEBUG_NO_STATIC u_int8_t
++ipsec_adjust_mss(struct sk_buff *skb, struct tcphdr *tcph, u_int16_t mtu)
++{
++      u_int16_t oldmss, newmss;
++      u_int32_t *mssp;
++      struct sock *sk = skb->sk;
++      
++      newmss = tcp_sync_mss(sk, mtu);
++      printk(KERN_INFO "klips: setting mss to %u\n", newmss);
++      mssp = (u_int32_t *)tcph + sizeof(struct tcphdr) / sizeof(u_int32_t);
++      oldmss = ntohl(*mssp) & 0x0000FFFF;
++      *mssp = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | newmss);
++      tcph->check = ipsec_fast_csum(htons(~oldmss), 
++                                    htons(newmss), tcph->check);
++      return 1;
++}
++#endif        /* MSS_HACK */
++                                                        
++/*
++ * Sanity checks
++ */
++enum ipsec_xmit_value
++ipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs)
++{
++
++      if (ixs->dev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_error:ipsec_xmit_sanity_check_dev: "
++                          "No device associated with skb!\n" );
++              return IPSEC_XMIT_NODEV;
++      }
++
++      ixs->prv = ixs->dev->priv;
++      if (ixs->prv == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_error:ipsec_xmit_sanity_check_dev: "
++                          "Device has no private structure!\n" );
++              return  IPSEC_XMIT_NOPRIVDEV;
++      }
++
++      ixs->physdev = ixs->prv->dev;
++      if (ixs->physdev == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_error:ipsec_xmit_sanity_check_dev: "
++                          "Device is not attached to physical device!\n" );
++              return IPSEC_XMIT_NOPHYSDEV;
++      }
++
++      ixs->physmtu = ixs->physdev->mtu;
++        ixs->cur_mtu = ixs->physdev->mtu;
++      ixs->stats = (struct net_device_stats *) &(ixs->prv->mystats);
++
++      return IPSEC_XMIT_OK;
++}
++
++enum ipsec_xmit_value
++ipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs)
++{
++      /*
++       *      Return if there is nothing to do.  (Does this ever happen?) XXX
++       */
++      if (ixs->skb == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_error:ipsec_xmit_sanity_check_skb: "
++                          "Nothing to do!\n" );
++              return IPSEC_XMIT_NOSKB;
++      }
++
++      /* if skb was cloned (most likely due to a packet sniffer such as
++         tcpdump being momentarily attached to the interface), make
++         a copy of our own to modify */
++      if(skb_cloned(ixs->skb)) {
++              if
++#ifdef SKB_COW_NEW
++             (skb_cow(ixs->skb, skb_headroom(ixs->skb)) != 0)
++#else /* SKB_COW_NEW */
++             ((ixs->skb = skb_cow(ixs->skb, skb_headroom(ixs->skb))) == NULL)
++#endif /* SKB_COW_NEW */
++              {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_error:ipsec_xmit_sanity_check_skb: "
++                                  "skb_cow failed to allocate buffer, dropping.\n" );
++                      ixs->stats->tx_dropped++;
++                      return IPSEC_XMIT_ERRSKBALLOC;
++              }
++      }
++
++      ixs->iph = ixs->skb->nh.iph;
++
++      /* sanity check for IP version as we can't handle IPv6 right now */
++      if (ixs->iph->version != 4) {
++              KLIPS_PRINT(debug_tunnel,
++                          "klips_debug:ipsec_xmit_sanity_check_skb: "
++                          "found IP Version %d but cannot process other IP versions than v4.\n",
++                          ixs->iph->version); /* XXX */
++              ixs->stats->tx_dropped++;
++              return IPSEC_XMIT_NOIPV6;
++      }
++      
++#if IPSEC_DISALLOW_IPOPTIONS
++      if ((ixs->iph->ihl << 2) != sizeof (struct iphdr)) {
++              KLIPS_PRINT(debug_tunnel,
++                          "klips_debug:ipsec_xmit_sanity_check_skb: "
++                          "cannot process IP header options yet.  May be mal-formed packet.\n"); /* XXX */
++              ixs->stats->tx_dropped++;
++              return IPSEC_XMIT_NOIPOPTIONS;
++      }
++#endif /* IPSEC_DISALLOW_IPOPTIONS */
++      
++#ifndef NET_21
++      if (ixs->iph->ttl <= 0) {
++              /* Tell the sender its packet died... */
++              ICMP_SEND(ixs->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, ixs->physdev);
++
++              KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_xmit_sanity_check_skb: "
++                          "TTL=0, too many hops!\n");
++              ixs->stats->tx_dropped++;
++              return IPSEC_XMIT_TTLEXPIRED;
++      }
++#endif /* !NET_21 */
++      
++      return IPSEC_XMIT_OK;
++}
++
++enum ipsec_xmit_value
++ipsec_xmit_encap_once(struct ipsec_xmit_state *ixs)
++{
++#ifdef CONFIG_KLIPS_ESP
++      struct esphdr *espp;
++      unsigned char *idat, *pad;
++      int authlen = 0, padlen = 0, i;
++#endif /* !CONFIG_KLIPS_ESP */
++#ifdef CONFIG_KLIPS_AH
++      struct iphdr ipo;
++      struct ahhdr *ahp;
++#endif /* CONFIG_KLIPS_AH */
++#if defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMAC_SHA1)
++      union {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              MD5_CTX md5;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              SHA1_CTX sha1;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++      } tctx;
++      __u8 hash[AH_AMAX];
++#endif /* defined(CONFIG_KLIPS_AUTH_HMAC_MD5) || defined(CONFIG_KLIPS_AUTH_HMACn_SHA1) */
++      int headroom = 0, tailroom = 0, ilen = 0, len = 0;
++      unsigned char *dat;
++      int blocksize = 8; /* XXX: should be inside ixs --jjo */
++      struct ipsec_alg_enc *ixt_e = NULL;
++      struct ipsec_alg_auth *ixt_a = NULL;
++      
++      ixs->iphlen = ixs->iph->ihl << 2;
++      ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen;
++      ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, SATOT_BUF);
++      KLIPS_PRINT(debug_tunnel & DB_TN_OXFS,
++                  "klips_debug:ipsec_xmit_encap_once: "
++                  "calling output for <%s%s%s>, SA:%s\n", 
++                  IPS_XFORM_NAME(ixs->ipsp),
++                  ixs->sa_len ? ixs->sa_txt : " (error)");
++      
++      switch(ixs->ipsp->ips_said.proto) {
++#ifdef CONFIG_KLIPS_AH
++      case IPPROTO_AH:
++              headroom += sizeof(struct ahhdr);
++              break;
++#endif /* CONFIG_KLIPS_AH */
++
++#ifdef CONFIG_KLIPS_ESP
++      case IPPROTO_ESP:
++              ixt_e=ixs->ipsp->ips_alg_enc;
++              if (ixt_e) {
++                      blocksize = ixt_e->ixt_common.ixt_blocksize;
++                      headroom += ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8;
++              } else {
++                      ixs->stats->tx_errors++;
++                      return IPSEC_XMIT_ESP_BADALG;
++              }
++
++              ixt_a=ixs->ipsp->ips_alg_auth;
++              if (ixt_a) {
++                      tailroom += AHHMAC_HASHLEN;
++              } else 
++              switch(ixs->ipsp->ips_authalg) {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              case AH_MD5:
++                      authlen = AHHMAC_HASHLEN;
++                      break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              case AH_SHA:
++                      authlen = AHHMAC_HASHLEN;
++                      break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++              case AH_NONE:
++                      break;
++              default:
++                      ixs->stats->tx_errors++;
++                      return IPSEC_XMIT_ESP_BADALG;
++              }               
++              tailroom += blocksize != 1 ?
++                      ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 :
++                      ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2;
++              tailroom += authlen;
++              break;
++#endif /* CONFIG_KLIPS_ESP */
++
++#ifdef CONFIG_KLIPS_IPIP
++      case IPPROTO_IPIP:
++              headroom += sizeof(struct iphdr);
++              ixs->iphlen = sizeof(struct iphdr);
++              break;
++#endif /* !CONFIG_KLIPS_IPIP */
++
++#ifdef CONFIG_KLIPS_IPCOMP
++      case IPPROTO_COMP:
++              break;
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++      default:
++              ixs->stats->tx_errors++;
++              return IPSEC_XMIT_BADPROTO;
++      }
++      
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_encap_once: "
++                  "pushing %d bytes, putting %d, proto %d.\n", 
++                  headroom, tailroom, ixs->ipsp->ips_said.proto);
++      if(skb_headroom(ixs->skb) < headroom) {
++              printk(KERN_WARNING
++                     "klips_error:ipsec_xmit_encap_once: "
++                     "tried to skb_push headroom=%d, %d available.  This should never happen, please report.\n",
++                     headroom, skb_headroom(ixs->skb));
++              ixs->stats->tx_errors++;
++              return IPSEC_XMIT_ESP_PUSHPULLERR;
++      }
++
++      dat = skb_push(ixs->skb, headroom);
++      ilen = ixs->skb->len - tailroom;
++      if(skb_tailroom(ixs->skb) < tailroom) {
++              printk(KERN_WARNING
++                     "klips_error:ipsec_xmit_encap_once: "
++                     "tried to skb_put %d, %d available.  This should never happen, please report.\n",
++                     tailroom, skb_tailroom(ixs->skb));
++              ixs->stats->tx_errors++;
++              return IPSEC_XMIT_ESP_PUSHPULLERR;
++      }
++      skb_put(ixs->skb, tailroom);
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_encap_once: "
++                  "head,tailroom: %d,%d before xform.\n",
++                  skb_headroom(ixs->skb), skb_tailroom(ixs->skb));
++      len = ixs->skb->len;
++      if(len > 0xfff0) {
++              printk(KERN_WARNING "klips_error:ipsec_xmit_encap_once: "
++                     "tot_len (%d) > 65520.  This should never happen, please report.\n",
++                     len);
++              ixs->stats->tx_errors++;
++              return IPSEC_XMIT_BADLEN;
++      }
++      memmove((void *)dat, (void *)(dat + headroom), ixs->iphlen);
++      ixs->iph = (struct iphdr *)dat;
++      ixs->iph->tot_len = htons(ixs->skb->len);
++
++      switch(ixs->ipsp->ips_said.proto) {
++#ifdef CONFIG_KLIPS_ESP
++      case IPPROTO_ESP:
++              espp = (struct esphdr *)(dat + ixs->iphlen);
++              espp->esp_spi = ixs->ipsp->ips_said.spi;
++              espp->esp_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq));
++              
++              if (!ixt_e) {
++                      ixs->stats->tx_errors++;
++                      return IPSEC_XMIT_ESP_BADALG;
++              }
++              
++              idat = dat + ixs->iphlen + headroom;
++              ilen = len - (ixs->iphlen + headroom + authlen);
++              
++              /* Self-describing padding */
++              pad = &dat[len - tailroom];
++              padlen = tailroom - 2 - authlen;
++              for (i = 0; i < padlen; i++) {
++                      pad[i] = i + 1; 
++              }
++              dat[len - authlen - 2] = padlen;
++              
++              dat[len - authlen - 1] = ixs->iph->protocol;
++              ixs->iph->protocol = IPPROTO_ESP;
++#ifdef CONFIG_KLIPS_DEBUG
++              if(debug_tunnel & DB_TN_ENCAP) {
++                      dmp("pre-encrypt", dat, len);
++              }
++#endif
++
++              /*
++               * Do all operations here:
++               * copy IV->ESP, encrypt, update ips IV
++               *
++               */
++              {
++                      int ret;
++                      memcpy(espp->esp_iv, 
++                             ixs->ipsp->ips_iv, 
++                             ixs->ipsp->ips_iv_size);
++                      ret=ipsec_alg_esp_encrypt(ixs->ipsp, 
++                                                idat, ilen, espp->esp_iv,
++                                                IPSEC_ALG_ENCRYPT);
++
++                      prng_bytes(&ipsec_prng,
++                                 (char *)ixs->ipsp->ips_iv,
++                                 ixs->ipsp->ips_iv_size);
++              } 
++              
++              if (ixt_a) {
++                      ipsec_alg_sa_esp_hash(ixs->ipsp,
++                                      (caddr_t)espp, len - ixs->iphlen - authlen,
++                                      &(dat[len - authlen]), authlen);
++
++              } else
++              switch(ixs->ipsp->ips_authalg) {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              case AH_MD5:
++                      dmp("espp", (char*)espp, len - ixs->iphlen - authlen);
++                      tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++                      dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Update(&tctx.md5, (caddr_t)espp, len - ixs->iphlen - authlen);
++                      dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Final(hash, &tctx.md5);
++                      dmp("ictx hash", (char*)&hash, sizeof(hash));
++                      tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx;
++                      dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Update(&tctx.md5, hash, AHMD596_ALEN);
++                      dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Final(hash, &tctx.md5);
++                      dmp("octx hash", (char*)&hash, sizeof(hash));
++                      memcpy(&(dat[len - authlen]), hash, authlen);
++                      
++                      /* paranoid */
++                      memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));
++                      memset((caddr_t)hash, 0, sizeof(*hash));
++                      break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              case AH_SHA:
++                      tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++                      SHA1Update(&tctx.sha1, (caddr_t)espp, len - ixs->iphlen - authlen);
++                      SHA1Final(hash, &tctx.sha1);
++                      tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx;
++                      SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);
++                      SHA1Final(hash, &tctx.sha1);
++                      memcpy(&(dat[len - authlen]), hash, authlen);
++                      
++                      /* paranoid */
++                      memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));
++                      memset((caddr_t)hash, 0, sizeof(*hash));
++                      break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++              case AH_NONE:
++                      break;
++              default:
++                      ixs->stats->tx_errors++;
++                      return IPSEC_XMIT_AH_BADALG;
++              }
++#ifdef NET_21
++              ixs->skb->h.raw = (unsigned char*)espp;
++#endif /* NET_21 */
++              break;
++#endif /* !CONFIG_KLIPS_ESP */
++#ifdef CONFIG_KLIPS_AH
++      case IPPROTO_AH:
++              ahp = (struct ahhdr *)(dat + ixs->iphlen);
++              ahp->ah_spi = ixs->ipsp->ips_said.spi;
++              ahp->ah_rpl = htonl(++(ixs->ipsp->ips_replaywin_lastseq));
++              ahp->ah_rv = 0;
++              ahp->ah_nh = ixs->iph->protocol;
++              ahp->ah_hl = (headroom >> 2) - sizeof(__u64)/sizeof(__u32);
++              ixs->iph->protocol = IPPROTO_AH;
++              dmp("ahp", (char*)ahp, sizeof(*ahp));
++              
++              ipo = *ixs->iph;
++              ipo.tos = 0;
++              ipo.frag_off = 0;
++              ipo.ttl = 0;
++              ipo.check = 0;
++              dmp("ipo", (char*)&ipo, sizeof(ipo));
++              
++              switch(ixs->ipsp->ips_authalg) {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              case AH_MD5:
++                      tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++                      dmp("ictx", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Update(&tctx.md5, (unsigned char *)&ipo, sizeof (struct iphdr));
++                      dmp("ictx+ipo", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Update(&tctx.md5, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data));
++                      dmp("ictx+ahp", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Update(&tctx.md5, (unsigned char *)zeroes, AHHMAC_HASHLEN);
++                      dmp("ictx+zeroes", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Update(&tctx.md5,  dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom);
++                      dmp("ictx+dat", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Final(hash, &tctx.md5);
++                      dmp("ictx hash", (char*)&hash, sizeof(hash));
++                      tctx.md5 = ((struct md5_ctx*)(ixs->ipsp->ips_key_a))->octx;
++                      dmp("octx", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Update(&tctx.md5, hash, AHMD596_ALEN);
++                      dmp("octx+hash", (char*)&tctx.md5, sizeof(tctx.md5));
++                      osMD5Final(hash, &tctx.md5);
++                      dmp("octx hash", (char*)&hash, sizeof(hash));
++                                      
++                      memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);
++                                      
++                      /* paranoid */
++                      memset((caddr_t)&tctx.md5, 0, sizeof(tctx.md5));
++                      memset((caddr_t)hash, 0, sizeof(*hash));
++                      break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              case AH_SHA:
++                      tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->ictx;
++                      SHA1Update(&tctx.sha1, (unsigned char *)&ipo, sizeof (struct iphdr));
++                      SHA1Update(&tctx.sha1, (unsigned char *)ahp, headroom - sizeof(ahp->ah_data));
++                      SHA1Update(&tctx.sha1, (unsigned char *)zeroes, AHHMAC_HASHLEN);
++                      SHA1Update(&tctx.sha1,  dat + ixs->iphlen + headroom, len - ixs->iphlen - headroom);
++                      SHA1Final(hash, &tctx.sha1);
++                      tctx.sha1 = ((struct sha1_ctx*)(ixs->ipsp->ips_key_a))->octx;
++                      SHA1Update(&tctx.sha1, hash, AHSHA196_ALEN);
++                      SHA1Final(hash, &tctx.sha1);
++                                      
++                      memcpy(ahp->ah_data, hash, AHHMAC_HASHLEN);
++                                      
++                      /* paranoid */
++                      memset((caddr_t)&tctx.sha1, 0, sizeof(tctx.sha1));
++                      memset((caddr_t)hash, 0, sizeof(*hash));
++                      break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++              default:
++                      ixs->stats->tx_errors++;
++                      return IPSEC_XMIT_AH_BADALG;
++              }
++#ifdef NET_21
++              ixs->skb->h.raw = (unsigned char*)ahp;
++#endif /* NET_21 */
++              break;
++#endif /* CONFIG_KLIPS_AH */
++#ifdef CONFIG_KLIPS_IPIP
++      case IPPROTO_IPIP:
++              ixs->iph->version  = 4;
++              switch(sysctl_ipsec_tos) {
++              case 0:
++#ifdef NET_21
++                      ixs->iph->tos = ixs->skb->nh.iph->tos;
++#else /* NET_21 */
++                      ixs->iph->tos = ixs->skb->ip_hdr->tos;
++#endif /* NET_21 */
++                      break;
++              case 1:
++                      ixs->iph->tos = 0;
++                      break;
++              default:
++                      break;
++              }
++              ixs->iph->ttl      = SYSCTL_IPSEC_DEFAULT_TTL;
++              ixs->iph->frag_off = 0;
++              ixs->iph->saddr    = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_s))->sin_addr.s_addr;
++              ixs->iph->daddr    = ((struct sockaddr_in*)(ixs->ipsp->ips_addr_d))->sin_addr.s_addr;
++              ixs->iph->protocol = IPPROTO_IPIP;
++              ixs->iph->ihl      = sizeof(struct iphdr) >> 2;
++
++              KLIPS_IP_SELECT_IDENT(ixs->iph, ixs->skb);
++
++              ixs->newdst = (__u32)ixs->iph->daddr;
++              ixs->newsrc = (__u32)ixs->iph->saddr;
++              
++#ifdef NET_21
++              ixs->skb->h.ipiph = ixs->skb->nh.iph;
++#endif /* NET_21 */
++              break;
++#endif /* !CONFIG_KLIPS_IPIP */
++#ifdef CONFIG_KLIPS_IPCOMP
++      case IPPROTO_COMP:
++      {
++              unsigned int flags = 0;
++#ifdef CONFIG_KLIPS_DEBUG
++              unsigned int old_tot_len = ntohs(ixs->iph->tot_len);
++#endif /* CONFIG_KLIPS_DEBUG */
++              ixs->ipsp->ips_comp_ratio_dbytes += ntohs(ixs->iph->tot_len);
++
++              ixs->skb = skb_compress(ixs->skb, ixs->ipsp, &flags);
++
++#ifdef NET_21
++              ixs->iph = ixs->skb->nh.iph;
++#else /* NET_21 */
++              ixs->iph = ixs->skb->ip_hdr;
++#endif /* NET_21 */
++
++              ixs->ipsp->ips_comp_ratio_cbytes += ntohs(ixs->iph->tot_len);
++
++#ifdef CONFIG_KLIPS_DEBUG
++              if (debug_tunnel & DB_TN_CROUT)
++              {
++                      if (old_tot_len > ntohs(ixs->iph->tot_len))
++                              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                                          "klips_debug:ipsec_xmit_encap_once: "
++                                          "packet shrunk from %d to %d bytes after compression, cpi=%04x (should be from spi=%08x, spi&0xffff=%04x.\n",
++                                          old_tot_len, ntohs(ixs->iph->tot_len),
++                                          ntohs(((struct ipcomphdr*)(((char*)ixs->iph) + ((ixs->iph->ihl) << 2)))->ipcomp_cpi),
++                                          ntohl(ixs->ipsp->ips_said.spi),
++                                          (__u16)(ntohl(ixs->ipsp->ips_said.spi) & 0x0000ffff));
++                      else
++                              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                                          "klips_debug:ipsec_xmit_encap_once: "
++                                          "packet did not compress (flags = %d).\n",
++                                          flags);
++              }
++#endif /* CONFIG_KLIPS_DEBUG */
++      }
++      break;
++#endif /* CONFIG_KLIPS_IPCOMP */
++      default:
++              ixs->stats->tx_errors++;
++              return IPSEC_XMIT_BADPROTO;
++      }
++                      
++#ifdef NET_21
++      ixs->skb->nh.raw = ixs->skb->data;
++#else /* NET_21 */
++      ixs->skb->ip_hdr = ixs->skb->h.iph = (struct iphdr *) ixs->skb->data;
++#endif /* NET_21 */
++      ixs->iph->check = 0;
++      ixs->iph->check = ip_fast_csum((unsigned char *)ixs->iph, ixs->iph->ihl);
++                      
++      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                  "klips_debug:ipsec_xmit_encap_once: "
++                  "after <%s%s%s>, SA:%s:\n",
++                  IPS_XFORM_NAME(ixs->ipsp),
++                  ixs->sa_len ? ixs->sa_txt : " (error)");
++      KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph);
++                      
++      ixs->ipsp->ips_life.ipl_bytes.ipl_count += len;
++      ixs->ipsp->ips_life.ipl_bytes.ipl_last = len;
++
++      if(!ixs->ipsp->ips_life.ipl_usetime.ipl_count) {
++              ixs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;
++      }
++      ixs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;
++      ixs->ipsp->ips_life.ipl_packets.ipl_count++; 
++
++      ixs->ipsp = ixs->ipsp->ips_onext;
++                      
++      return IPSEC_XMIT_OK;
++}
++
++/*
++ * If the IP packet (iph) is a carrying TCP/UDP, then set the encaps
++ * source and destination ports to those from the TCP/UDP header.
++ */
++void ipsec_extract_ports(struct iphdr * iph, struct sockaddr_encap * er)
++{
++      struct udphdr *udp;
++
++      switch (iph->protocol) {
++      case IPPROTO_UDP:
++      case IPPROTO_TCP:
++              /*
++               * The ports are at the same offsets in a TCP and UDP
++               * header so hack it ...
++               */
++              udp = (struct udphdr*)(((char*)iph)+(iph->ihl<<2));
++              er->sen_sport = udp->source;
++              er->sen_dport = udp->dest;
++              break;
++      default:
++              er->sen_sport = 0;
++              er->sen_dport = 0;
++              break;
++      }
++}
++
++/*
++ * A TRAP eroute is installed and we want to replace it with a HOLD
++ * eroute.
++ */
++static int create_hold_eroute(struct eroute *origtrap,
++                            struct sk_buff * skb, struct iphdr * iph,
++                            uint32_t eroute_pid)
++{
++      struct eroute hold_eroute;
++      ip_said hold_said;
++      struct sk_buff *first, *last;
++      int error;
++
++      first = last = NULL;
++      memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute));
++      memset((caddr_t)&hold_said, 0, sizeof(hold_said));
++      
++      hold_said.proto = IPPROTO_INT;
++      hold_said.spi = htonl(SPI_HOLD);
++      hold_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY;
++      
++      hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap);
++      hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap);
++      hold_eroute.er_eaddr.sen_family = AF_ENCAP;
++      hold_eroute.er_emask.sen_family = AF_ENCAP;
++      hold_eroute.er_eaddr.sen_type = SENT_IP4;
++      hold_eroute.er_emask.sen_type = 255;
++      
++      hold_eroute.er_eaddr.sen_ip_src.s_addr = iph->saddr;
++      hold_eroute.er_eaddr.sen_ip_dst.s_addr = iph->daddr;
++      hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST;
++      hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST;
++      hold_eroute.er_emask.sen_sport = 0;
++      hold_eroute.er_emask.sen_dport = 0;
++      hold_eroute.er_pid = eroute_pid;
++      hold_eroute.er_count = 0;
++      hold_eroute.er_lasttime = jiffies/HZ;
++
++      /*
++       * if it wasn't captured by a wildcard, then don't record it as
++       * a wildcard.
++       */
++      if(origtrap->er_eaddr.sen_proto != 0) {
++        hold_eroute.er_eaddr.sen_proto = iph->protocol;
++
++        if((iph->protocol == IPPROTO_TCP ||
++            iph->protocol == IPPROTO_UDP) &&
++           (origtrap->er_eaddr.sen_sport != 0 ||
++            origtrap->er_eaddr.sen_dport != 0)) {
++
++          if(origtrap->er_eaddr.sen_sport != 0)
++            hold_eroute.er_emask.sen_sport = ~0;
++
++          if(origtrap->er_eaddr.sen_dport != 0) 
++            hold_eroute.er_emask.sen_dport = ~0;
++
++          ipsec_extract_ports(iph, &hold_eroute.er_eaddr);
++        }
++      }
++
++#ifdef CONFIG_KLIPS_DEBUG
++      if (debug_pfkey) {
++              char buf1[64], buf2[64];
++              subnettoa(hold_eroute.er_eaddr.sen_ip_src,
++                        hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
++              subnettoa(hold_eroute.er_eaddr.sen_ip_dst,
++                        hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_tunnel_start_xmit: "
++                          "calling breakeroute and makeroute for %s:%d->%s:%d %d HOLD eroute.\n",
++                          buf1, ntohs(hold_eroute.er_eaddr.sen_sport),
++                          buf2, ntohs(hold_eroute.er_eaddr.sen_dport),
++                          hold_eroute.er_eaddr.sen_proto);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      if (ipsec_breakroute(&(hold_eroute.er_eaddr), &(hold_eroute.er_emask),
++                           &first, &last)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_tunnel_start_xmit: "
++                          "HOLD breakeroute found nothing.\n");
++      } else {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_tunnel_start_xmit: "
++                          "HOLD breakroute deleted %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u %u\n",
++                          NIPQUAD(hold_eroute.er_eaddr.sen_ip_src),
++                          ntohs(hold_eroute.er_eaddr.sen_sport),
++                          NIPQUAD(hold_eroute.er_eaddr.sen_ip_dst),
++                          ntohs(hold_eroute.er_eaddr.sen_dport),
++                          hold_eroute.er_eaddr.sen_proto);
++      }
++      if (first != NULL)
++              kfree_skb(first);
++      if (last != NULL)
++              kfree_skb(last);
++
++      error = ipsec_makeroute(&(hold_eroute.er_eaddr),
++                              &(hold_eroute.er_emask),
++                              hold_said, eroute_pid, skb, NULL, NULL);
++      if (error) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_tunnel_start_xmit: "
++                          "HOLD makeroute returned %d, failed.\n", error);
++      } else {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:ipsec_tunnel_start_xmit: "
++                          "HOLD makeroute call successful.\n");
++      }
++      return (error == 0);
++}
++
++/*
++ * upon entry to this function, ixs->skb should be setup
++ * as follows:
++ *
++ *   data   = beginning of IP packet   <- differs from ipsec_rcv().
++ *   nh.raw = beginning of IP packet.
++ *   h.raw  = data after the IP packet.
++ *
++ */
++enum ipsec_xmit_value
++ipsec_xmit_encap_bundle(struct ipsec_xmit_state *ixs)
++{
++      struct ipsec_alg_enc *ixt_e = NULL;
++      struct ipsec_alg_auth *ixt_a = NULL;
++      int blocksize = 8;
++      enum ipsec_xmit_value bundle_stat = IPSEC_XMIT_OK;
++ 
++      ixs->newdst = ixs->orgdst = ixs->iph->daddr;
++      ixs->newsrc = ixs->orgsrc = ixs->iph->saddr;
++      ixs->orgedst = ixs->outgoing_said.dst.u.v4.sin_addr.s_addr;
++      ixs->iphlen = ixs->iph->ihl << 2;
++      ixs->pyldsz = ntohs(ixs->iph->tot_len) - ixs->iphlen;
++      ixs->max_headroom = ixs->max_tailroom = 0;
++              
++      if (ixs->outgoing_said.proto == IPPROTO_INT) {
++              switch (ntohl(ixs->outgoing_said.spi)) {
++              case SPI_DROP:
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "shunt SA of DROP or no eroute: dropping.\n");
++                      ixs->stats->tx_dropped++;
++                      break;
++                              
++              case SPI_REJECT:
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "shunt SA of REJECT: notifying and dropping.\n");
++                      ICMP_SEND(ixs->skb,
++                                ICMP_DEST_UNREACH,
++                                ICMP_PKT_FILTERED,
++                                0,
++                                ixs->physdev);
++                      ixs->stats->tx_dropped++;
++                      break;
++                              
++              case SPI_PASS:
++#ifdef NET_21
++                      ixs->pass = 1;
++#endif /* NET_21 */
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "PASS: calling dev_queue_xmit\n");
++                      return IPSEC_XMIT_PASS;
++                      goto cleanup;
++                              
++              case SPI_HOLD:
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "shunt SA of HOLD: this does not make sense here, dropping.\n");
++                      ixs->stats->tx_dropped++;
++                      break;
++
++              case SPI_TRAP:
++              case SPI_TRAPSUBNET:
++              {
++                      struct sockaddr_in src, dst;
++#ifdef CONFIG_KLIPS_DEBUG
++                      char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF];
++#endif /* CONFIG_KLIPS_DEBUG */
++
++                      /* Signal all listening KMds with a PF_KEY ACQUIRE */
++
++                      memset(&src, 0, sizeof(src));
++                      memset(&dst, 0, sizeof(dst));
++                      src.sin_family = AF_INET;
++                      dst.sin_family = AF_INET;
++                      src.sin_addr.s_addr = ixs->iph->saddr;
++                      dst.sin_addr.s_addr = ixs->iph->daddr;
++
++                      ixs->ips.ips_transport_protocol = 0;
++                      src.sin_port = 0;
++                      dst.sin_port = 0;
++                      
++                      if(ixs->eroute->er_eaddr.sen_proto != 0) {
++                        ixs->ips.ips_transport_protocol = ixs->iph->protocol;
++                        
++                        if(ixs->eroute->er_eaddr.sen_sport != 0) {
++                          src.sin_port = 
++                            (ixs->iph->protocol == IPPROTO_UDP
++                             ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->source
++                             : (ixs->iph->protocol == IPPROTO_TCP
++                                ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->source
++                                : 0));
++                        }
++                        if(ixs->eroute->er_eaddr.sen_dport != 0) {
++                          dst.sin_port = 
++                            (ixs->iph->protocol == IPPROTO_UDP
++                             ? ((struct udphdr*) (((caddr_t)ixs->iph) + (ixs->iph->ihl << 2)))->dest
++                             : (ixs->iph->protocol == IPPROTO_TCP
++                                ? ((struct tcphdr*)((caddr_t)ixs->iph + (ixs->iph->ihl << 2)))->dest
++                                : 0));
++                        }
++                      }
++                              
++                      ixs->ips.ips_addr_s = (struct sockaddr*)(&src);
++                      ixs->ips.ips_addr_d = (struct sockaddr*)(&dst);
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n",
++                                  addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR",
++                                  ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_s))->sin_port),
++                                  addrtoa(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR",
++                                  ntohs(((struct sockaddr_in*)(ixs->ips.ips_addr_d))->sin_port),
++                                  ixs->ips.ips_said.proto);
++                              
++                      /* increment count of total traps needed */
++                      ipsec_xmit_trap_count++;
++
++                      if (pfkey_acquire(&ixs->ips) == 0) {
++
++                              /* note that we succeeded */
++                              ipsec_xmit_trap_sendcount++;
++                                      
++                              if (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)) {
++                                      /*
++                                       * The spinlock is to prevent any other
++                                       * process from accessing or deleting
++                                       * the eroute while we are using and
++                                       * updating it.
++                                       */
++                                      spin_lock(&eroute_lock);
++                                      ixs->eroute = ipsec_findroute(&ixs->matcher);
++                                      if(ixs->eroute) {
++                                              ixs->eroute->er_said.spi = htonl(SPI_HOLD);
++                                              ixs->eroute->er_first = ixs->skb;
++                                              ixs->skb = NULL;
++                                      }
++                                      spin_unlock(&eroute_lock);
++                              } else if (create_hold_eroute(ixs->eroute,
++                                                            ixs->skb,
++                                                            ixs->iph,
++                                                            ixs->eroute_pid)) {
++                                      ixs->skb = NULL;
++                              } 
++                              /* whether or not the above succeeded, we continue */
++                              
++                      }
++                      ixs->stats->tx_dropped++;
++              }
++              default:
++                      /* XXX what do we do with an unknown shunt spi? */
++                      break;
++              } /* switch (ntohl(ixs->outgoing_said.spi)) */
++              return IPSEC_XMIT_STOLEN;
++      } /* if (ixs->outgoing_said.proto == IPPROTO_INT) */
++      
++      /*
++        The spinlock is to prevent any other process from
++        accessing or deleting the ipsec_sa hash table or any of the
++        ipsec_sa s while we are using and updating them.
++                
++        This is not optimal, but was relatively straightforward
++        at the time.  A better way to do it has been planned for
++        more than a year, to lock the hash table and put reference
++        counts on each ipsec_sa instead.  This is not likely to happen
++        in KLIPS1 unless a volunteer contributes it, but will be
++        designed into KLIPS2.
++      */
++      spin_lock(&tdb_lock);
++
++      ixs->ipsp = ipsec_sa_getbyid(&ixs->outgoing_said);
++      ixs->sa_len = satot(&ixs->outgoing_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt));
++
++      if (ixs->ipsp == NULL) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "no ipsec_sa for SA%s: outgoing packet with no SA, dropped.\n",
++                          ixs->sa_len ? ixs->sa_txt : " (error)");
++              if(ixs->stats) {
++                      ixs->stats->tx_dropped++;
++              }
++              bundle_stat = IPSEC_XMIT_SAIDNOTFOUND;
++              goto cleanup;
++      }
++              
++      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                  "klips_debug:ipsec_xmit_encap_bundle: "
++                  "found ipsec_sa -- SA:<%s%s%s> %s\n",
++                  IPS_XFORM_NAME(ixs->ipsp),
++                  ixs->sa_len ? ixs->sa_txt : " (error)");
++              
++      /*
++       * How much headroom do we need to be able to apply
++       * all the grouped transforms?
++       */
++      ixs->ipsq = ixs->ipsp;  /* save the head of the ipsec_sa chain */
++      while (ixs->ipsp) {
++              ixs->sa_len = satot(&ixs->ipsp->ips_said, 0, ixs->sa_txt, sizeof(ixs->sa_txt));
++              if(ixs->sa_len == 0) {
++                      strcpy(ixs->sa_txt, "(error)");
++              }
++
++              /* If it is in larval state, drop the packet, we cannot process yet. */
++              if(ixs->ipsp->ips_state == SADB_SASTATE_LARVAL) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "ipsec_sa in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n",
++                                  IPS_XFORM_NAME(ixs->ipsp),
++                                  ixs->sa_len ? ixs->sa_txt : " (error)");
++                      if(ixs->stats) {
++                              ixs->stats->tx_errors++;
++                      }
++                      bundle_stat = IPSEC_XMIT_SAIDNOTLIVE;
++                      goto cleanup;
++              }
++
++              if(ixs->ipsp->ips_state == SADB_SASTATE_DEAD) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "ipsec_sa in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n",
++                                  IPS_XFORM_NAME(ixs->ipsp),
++                                  ixs->sa_len ? ixs->sa_txt : " (error)");
++                      ixs->stats->tx_errors++;
++                      bundle_stat = IPSEC_XMIT_SAIDNOTLIVE;
++                      goto cleanup;
++              }
++
++              /* If the replay window counter == -1, expire SA, it will roll */
++              if(ixs->ipsp->ips_replaywin && ixs->ipsp->ips_replaywin_lastseq == -1) {
++                      pfkey_expire(ixs->ipsp, 1);
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: "
++                                  "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n",
++                                  IPS_XFORM_NAME(ixs->ipsp),
++                                  ixs->sa_len ? ixs->sa_txt : " (error)");
++                      ipsec_sa_delchain(ixs->ipsp);
++                      ixs->stats->tx_errors++;
++                      bundle_stat = IPSEC_XMIT_REPLAYROLLED;
++                      goto cleanup;
++              }
++
++              /*
++               * if this is the first time we are using this SA, mark start time,
++               * and offset hard/soft counters by "now" for later checking.
++               */
++#if 0
++              if(ixs->ipsp->ips_life.ipl_usetime.count == 0) {
++                      ixs->ipsp->ips_life.ipl_usetime.count = jiffies;
++                      ixs->ipsp->ips_life.ipl_usetime.hard += jiffies;
++                      ixs->ipsp->ips_life.ipl_usetime.soft += jiffies;
++              }
++#endif
++                        
++
++              if(ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_bytes, "bytes", ixs->sa_txt, 
++                                      ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied ||
++                 ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_addtime, "addtime",ixs->sa_txt,
++                                      ipsec_life_timebased,  ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied ||
++                 ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_usetime, "usetime",ixs->sa_txt,
++                                      ipsec_life_timebased,  ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied ||
++                 ipsec_lifetime_check(&ixs->ipsp->ips_life.ipl_packets, "packets",ixs->sa_txt,
++                                      ipsec_life_countbased, ipsec_outgoing, ixs->ipsp) == ipsec_life_harddied) {
++                              
++                      ipsec_sa_delchain(ixs->ipsp);
++                      ixs->stats->tx_errors++;
++                      bundle_stat = IPSEC_XMIT_LIFETIMEFAILED;
++                      goto cleanup;
++              }
++                      
++
++              ixs->headroom = ixs->tailroom = 0;
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "calling room for <%s%s%s>, SA:%s\n", 
++                          IPS_XFORM_NAME(ixs->ipsp),
++                          ixs->sa_len ? ixs->sa_txt : " (error)");
++              switch(ixs->ipsp->ips_said.proto) {
++#ifdef CONFIG_KLIPS_AH
++              case IPPROTO_AH:
++                      ixs->headroom += sizeof(struct ahhdr);
++                      break;
++#endif /* CONFIG_KLIPS_AH */
++#ifdef CONFIG_KLIPS_ESP
++              case IPPROTO_ESP:
++                      ixt_e=ixs->ipsp->ips_alg_enc;
++                      if (ixt_e) {
++                              blocksize = ixt_e->ixt_common.ixt_blocksize;
++                              ixs->headroom += ESP_HEADER_LEN + ixt_e->ixt_common.ixt_support.ias_ivlen/8;
++                      }
++                      else {
++                              ixs->stats->tx_errors++;
++                              bundle_stat = IPSEC_XMIT_ESP_BADALG;
++                              goto cleanup;
++                      }
++
++                      if ((ixt_a=ixs->ipsp->ips_alg_auth)) {
++                              ixs->tailroom += AHHMAC_HASHLEN;
++                      } else
++                      switch(ixs->ipsp->ips_authalg) {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++                      case AH_MD5:
++                              ixs->tailroom += AHHMAC_HASHLEN;
++                              break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++                      case AH_SHA:
++                              ixs->tailroom += AHHMAC_HASHLEN;
++                              break;
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++                      case AH_NONE:
++                              break;
++                      default:
++                              ixs->stats->tx_errors++;
++                              bundle_stat = IPSEC_XMIT_AH_BADALG;
++                              goto cleanup;
++                      }                       
++                      ixs->tailroom += blocksize != 1 ?
++                              ((blocksize - ((ixs->pyldsz + 2) % blocksize)) % blocksize) + 2 :
++                              ((4 - ((ixs->pyldsz + 2) % 4)) % 4) + 2;
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++              if ((ixs->ipsp->ips_natt_type) && (!ixs->natt_type)) {
++                      ixs->natt_type = ixs->ipsp->ips_natt_type;
++                      ixs->natt_sport = ixs->ipsp->ips_natt_sport;
++                      ixs->natt_dport = ixs->ipsp->ips_natt_dport;
++                      switch (ixs->natt_type) {
++                              case ESPINUDP_WITH_NON_IKE:
++                                      ixs->natt_head = sizeof(struct udphdr)+(2*sizeof(__u32));
++                                      break;
++                                      
++                              case ESPINUDP_WITH_NON_ESP:
++                                      ixs->natt_head = sizeof(struct udphdr);
++                                      break;
++                                      
++                              default:
++                                KLIPS_PRINT(debug_tunnel & DB_TN_CROUT
++                                            , "klips_xmit: invalid nat-t type %d"
++                                            , ixs->natt_type);
++                                bundle_stat = IPSEC_XMIT_ESPUDP_BADTYPE;
++                                goto cleanup;
++                                            
++                                      break;
++                      }
++                      ixs->tailroom += ixs->natt_head;
++              }
++#endif
++                      break;
++#endif /* !CONFIG_KLIPS_ESP */
++#ifdef CONFIG_KLIPS_IPIP
++              case IPPROTO_IPIP:
++                      ixs->headroom += sizeof(struct iphdr);
++                      break;
++#endif /* !CONFIG_KLIPS_IPIP */
++              case IPPROTO_COMP:
++#ifdef CONFIG_KLIPS_IPCOMP
++                      /*
++                        We can't predict how much the packet will
++                        shrink without doing the actual compression.
++                        We could do it here, if we were the first
++                        encapsulation in the chain.  That might save
++                        us a skb_copy_expand, since we might fit
++                        into the existing skb then.  However, this
++                        would be a bit unclean (and this hack has
++                        bit us once), so we better not do it. After
++                        all, the skb_copy_expand is cheap in
++                        comparison to the actual compression.
++                        At least we know the packet will not grow.
++                      */
++                      break;
++#endif /* CONFIG_KLIPS_IPCOMP */
++              default:
++                      ixs->stats->tx_errors++;
++                      bundle_stat = IPSEC_XMIT_BADPROTO;
++                      goto cleanup;
++              }
++              ixs->ipsp = ixs->ipsp->ips_onext;
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "Required head,tailroom: %d,%d\n", 
++                          ixs->headroom, ixs->tailroom);
++              ixs->max_headroom += ixs->headroom;
++              ixs->max_tailroom += ixs->tailroom;
++              ixs->pyldsz += (ixs->headroom + ixs->tailroom);
++      }
++      ixs->ipsp = ixs->ipsq;  /* restore the head of the ipsec_sa chain */
++              
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_encap_bundle: "
++                  "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n",
++                  skb_headroom(ixs->skb), skb_tailroom(ixs->skb),
++                  ixs->max_headroom, ixs->max_tailroom);
++              
++      ixs->tot_headroom += ixs->max_headroom;
++      ixs->tot_tailroom += ixs->max_tailroom;
++
++      ixs->mtudiff = ixs->cur_mtu + ixs->tot_headroom + ixs->tot_tailroom - ixs->physmtu;
++
++      KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                  "klips_debug:ipsec_xmit_encap_bundle: "
++                  "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n",
++                  ixs->cur_mtu, ixs->physmtu,
++                  ixs->tot_headroom, ixs->tot_tailroom, ixs->mtudiff, ntohs(ixs->iph->tot_len));
++      if(ixs->mtudiff > 0) {
++              int newmtu = ixs->physmtu - (ixs->tot_headroom + ((ixs->tot_tailroom + 2) & ~7) + 5);
++
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_info:ipsec_xmit_encap_bundle: "
++                          "dev %s mtu of %d decreased by %d to %d\n",
++                          ixs->dev ? ixs->dev->name : "ifX",
++                          ixs->cur_mtu,
++                          ixs->cur_mtu - newmtu,
++                          newmtu);
++              ixs->cur_mtu = newmtu;
++
++              /* this would seem to adjust the MTU of the route as well */
++#if 0
++              ixs->skb->dst->pmtu = ixs->prv->mtu; /* RGB */
++#endif /* 0 */
++      }
++
++      /* 
++         If the sender is doing PMTU discovery, and the
++         packet doesn't fit within ixs->prv->mtu, notify him
++         (unless it was an ICMP packet, or it was not the
++         zero-offset packet) and send it anyways.
++
++         Note: buggy firewall configuration may prevent the
++         ICMP packet from getting back.
++      */
++      if(sysctl_ipsec_icmp
++         && ixs->cur_mtu < ntohs(ixs->iph->tot_len)
++         && (ixs->iph->frag_off & __constant_htons(IP_DF)) ) {
++              int notify = ixs->iph->protocol != IPPROTO_ICMP
++                      && (ixs->iph->frag_off & __constant_htons(IP_OFFSET)) == 0;
++                      
++#ifdef IPSEC_obey_DF
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "fragmentation needed and DF set; %sdropping packet\n",
++                          notify ? "sending ICMP and " : "");
++              if (notify)
++                      ICMP_SEND(ixs->skb,
++                                ICMP_DEST_UNREACH,
++                                ICMP_FRAG_NEEDED,
++                                ixs->cur_mtu,
++                                ixs->physdev);
++              ixs->stats->tx_errors++;
++              bundle_stat = IPSEC_XMIT_CANNOTFRAG;
++              goto cleanup;
++#else /* IPSEC_obey_DF */
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "fragmentation needed and DF set; %spassing packet\n",
++                          notify ? "sending ICMP and " : "");
++              if (notify)
++                      ICMP_SEND(ixs->skb,
++                                ICMP_DEST_UNREACH,
++                                ICMP_FRAG_NEEDED,
++                                ixs->cur_mtu,
++                                ixs->physdev);
++#endif /* IPSEC_obey_DF */
++      }
++              
++#ifdef MSS_HACK
++      /*
++       * If this is a transport mode TCP packet with
++       * SYN set, determine an effective MSS based on 
++       * AH/ESP overheads determined above.
++       */
++      if (ixs->iph->protocol == IPPROTO_TCP 
++          && ixs->outgoing_said.proto != IPPROTO_IPIP) {
++              struct tcphdr *tcph = ixs->skb->h.th;
++              if (tcph->syn && !tcph->ack) {
++                      if(!ipsec_adjust_mss(ixs->skb, tcph, ixs->cur_mtu)) {
++                              printk(KERN_WARNING
++                                     "klips_warning:ipsec_xmit_encap_bundle: "
++                                     "ipsec_adjust_mss() failed\n");
++                              ixs->stats->tx_errors++;
++                              bundle_stat = IPSEC_XMIT_MSSERR;
++                              goto cleanup;
++                      }
++              }
++      }
++#endif /* MSS_HACK */
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      if ((ixs->natt_type) && (ixs->outgoing_said.proto != IPPROTO_IPIP)) {
++            /**
++             * NAT-Traversal and Transport Mode:
++             *   we need to correct TCP/UDP checksum
++             *
++             * If we've got NAT-OA, we can fix checksum without recalculation.
++             * If we don't we can zero udp checksum.
++             */
++            __u32 natt_oa = ixs->ipsp->ips_natt_oa ?
++                    ((struct sockaddr_in*)(ixs->ipsp->ips_natt_oa))->sin_addr.s_addr : 0;
++            __u16 pkt_len = ixs->skb->tail - (unsigned char *)ixs->iph;
++            __u16 data_len = pkt_len - (ixs->iph->ihl << 2);
++            switch (ixs->iph->protocol) {
++                    case IPPROTO_TCP:
++                            if (data_len >= sizeof(struct tcphdr)) {
++                                    struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ixs->iph+ixs->iph->ihl);
++                                    if (natt_oa) {
++                                            __u32 buff[2] = { ~ixs->iph->daddr, natt_oa };
++                                            KLIPS_PRINT(debug_tunnel,
++                                                    "klips_debug:ipsec_tunnel_start_xmit: "
++                                                    "NAT-T & TRANSPORT: "
++                                                    "fix TCP checksum using NAT-OA\n");
++                                            tcp->check = csum_fold(
++                                                    csum_partial((unsigned char *)buff, sizeof(buff),
++                                                    tcp->check^0xffff));
++                                    }
++                                    else {
++                                            KLIPS_PRINT(debug_tunnel,
++                                                    "klips_debug:ipsec_tunnel_start_xmit: "
++                                                    "NAT-T & TRANSPORT: do not recalc TCP checksum\n");
++                                    }
++                            }
++                            else {
++                                    KLIPS_PRINT(debug_tunnel,
++                                            "klips_debug:ipsec_tunnel_start_xmit: "
++                                            "NAT-T & TRANSPORT: can't fix TCP checksum\n");
++                            }
++                            break;
++                    case IPPROTO_UDP:
++                            if (data_len >= sizeof(struct udphdr)) {
++                                    struct udphdr *udp = (struct udphdr *)((__u32 *)ixs->iph+ixs->iph->ihl);
++                                    if (udp->check == 0) {
++                                            KLIPS_PRINT(debug_tunnel,
++                                                    "klips_debug:ipsec_tunnel_start_xmit: "
++                                                    "NAT-T & TRANSPORT: UDP checksum already 0\n");
++                                    }
++                                    else if (natt_oa) {
++                                            __u32 buff[2] = { ~ixs->iph->daddr, natt_oa };
++                                            KLIPS_PRINT(debug_tunnel,
++                                                    "klips_debug:ipsec_tunnel_start_xmit: "
++                                                    "NAT-T & TRANSPORT: "
++                                                    "fix UDP checksum using NAT-OA\n");
++                                            udp->check = csum_fold(
++                                                    csum_partial((unsigned char *)buff, sizeof(buff),
++                                                    udp->check^0xffff));
++                                    }
++                                    else {
++                                            KLIPS_PRINT(debug_tunnel,
++                                                    "klips_debug:ipsec_tunnel_start_xmit: "
++                                                    "NAT-T & TRANSPORT: zero UDP checksum\n");
++                                            udp->check = 0;
++                                    }
++                            }
++                            else {
++                                    KLIPS_PRINT(debug_tunnel,
++                                            "klips_debug:ipsec_tunnel_start_xmit: "
++                                            "NAT-T & TRANSPORT: can't fix UDP checksum\n");
++                            }
++                            break;
++                    default:
++                            KLIPS_PRINT(debug_tunnel,
++                                    "klips_debug:ipsec_tunnel_start_xmit: "
++                                    "NAT-T & TRANSPORT: non TCP/UDP packet -- do nothing\n");
++                            break;
++            }
++      }
++#endif /* CONFIG_IPSEC_NAT_TRAVERSAL */
++
++      if(!ixs->hard_header_stripped && ixs->hard_header_len>0) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "allocating %d bytes for hardheader.\n",
++                          ixs->hard_header_len);
++              if((ixs->saved_header = kmalloc(ixs->hard_header_len, GFP_ATOMIC)) == NULL) {
++                      printk(KERN_WARNING "klips_debug:ipsec_xmit_encap_bundle: "
++                             "Failed, tried to allocate %d bytes for temp hard_header.\n", 
++                             ixs->hard_header_len);
++                      ixs->stats->tx_errors++;
++                      bundle_stat = IPSEC_XMIT_ERRMEMALLOC;
++                      goto cleanup;
++              }
++              {
++                      int i;
++                      for (i = 0; i < ixs->hard_header_len; i++) {
++                              ixs->saved_header[i] = ixs->skb->data[i];
++                      }
++              }
++              if(ixs->skb->len < ixs->hard_header_len) {
++                      printk(KERN_WARNING "klips_error:ipsec_xmit_encap_bundle: "
++                             "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",
++                             ixs->hard_header_len, (int)(ixs->skb->len));
++                      ixs->stats->tx_errors++;
++                      bundle_stat = IPSEC_XMIT_ESP_PUSHPULLERR;
++                      goto cleanup;
++              }
++              skb_pull(ixs->skb, ixs->hard_header_len);
++              ixs->hard_header_stripped = 1;
++                      
++/*                    ixs->iph = (struct iphdr *) (ixs->skb->data); */
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "head,tailroom: %d,%d after hard_header stripped.\n",
++                          skb_headroom(ixs->skb), skb_tailroom(ixs->skb));
++              KLIPS_IP_PRINT(debug_tunnel & DB_TN_CROUT, ixs->iph);
++      } else {
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "hard header already stripped.\n");
++      }
++              
++      ixs->ll_headroom = (ixs->hard_header_len + 15) & ~15;
++
++      if ((skb_headroom(ixs->skb) >= ixs->max_headroom + 2 * ixs->ll_headroom) && 
++          (skb_tailroom(ixs->skb) >= ixs->max_tailroom)
++#ifndef NET_21
++          && ixs->skb->free
++#endif /* !NET_21 */
++              ) {
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "data fits in existing skb\n");
++      } else {
++              struct sk_buff* tskb;
++
++              if(!ixs->oskb) {
++                      ixs->oskb = ixs->skb;
++              }
++
++              tskb = skb_copy_expand(ixs->skb,
++                                     /* The need for 2 * link layer length here remains unexplained...RGB */
++                                     ixs->max_headroom + 2 * ixs->ll_headroom,
++                                     ixs->max_tailroom,
++                                     GFP_ATOMIC);
++
++              if(tskb && ixs->skb->sk) {
++                      skb_set_owner_w(tskb, ixs->skb->sk);
++              }
++
++              if(ixs->skb != ixs->oskb) {
++                      ipsec_kfree_skb(ixs->skb);
++              }
++              ixs->skb = tskb;
++              if (!ixs->skb) {
++                      printk(KERN_WARNING
++                             "klips_debug:ipsec_xmit_encap_bundle: "
++                             "Failed, tried to allocate %d head and %d tailroom\n", 
++                             ixs->max_headroom, ixs->max_tailroom);
++                      ixs->stats->tx_errors++;
++                      bundle_stat = IPSEC_XMIT_ERRSKBALLOC;
++                      goto cleanup;
++              }
++              KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
++                          "klips_debug:ipsec_xmit_encap_bundle: "
++                          "head,tailroom: %d,%d after allocation\n",
++                          skb_headroom(ixs->skb), skb_tailroom(ixs->skb));
++      }
++#ifdef CONFIG_KLIPS_DEBUG             
++      if(debug_tunnel & DB_TN_ENCAP) {
++              ipsec_print_ip(ixs->iph);
++      }
++#endif
++
++      /*
++       * Apply grouped transforms to packet
++       */
++      while (ixs->ipsp) {
++              enum ipsec_xmit_value encap_stat = IPSEC_XMIT_OK;
++
++              encap_stat = ipsec_xmit_encap_once(ixs);
++#ifdef CONFIG_KLIPS_DEBUG
++              if(debug_tunnel & DB_TN_ENCAP) {
++                      ipsec_print_ip(ixs->iph);
++              }
++#endif
++
++              if(encap_stat != IPSEC_XMIT_OK) {
++                      KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
++                                  "klips_debug:ipsec_xmit_encap_bundle: encap_once failed: %d\n",
++                                  encap_stat);
++                              
++                      bundle_stat = IPSEC_XMIT_ENCAPFAIL;
++                      goto cleanup;
++              }
++      }
++
++      /* we are done with this SA */
++      ipsec_sa_put(ixs->ipsp); 
++
++      /* end encapsulation loop here XXX */
++ cleanup:
++      spin_unlock(&tdb_lock);
++      return bundle_stat;
++}
++
++/*
++ * $Log: ipsec_xmit.c,v $
++ * Revision 1.20.2.8  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.20.2.7  2006/08/24 03:02:01  paul
++ * Compile fixes for when CONFIG_KLIPS_DEBUG is not set. (bug #642)
++ *
++ * Revision 1.20.2.6  2006/07/07 22:09:49  paul
++ * From: Bart Trojanowski <bart@xelerance.com>
++ * Removing a left over '#else' that split another '#if/#endif' block in two.
++ *
++ * Revision 1.20.2.5  2006/07/07 15:43:17  paul
++ * From: Bart Trojanowski <bart@xelerance.com>
++ * improved protocol detection in ipsec_print_ip() -- a debug aid.
++ *
++ * Revision 1.20.2.4  2006/04/20 16:33:07  mcr
++ * remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++ * Fix in-kernel module compilation. Sub-makefiles do not work.
++ *
++ * Revision 1.20.2.3  2005/11/29 21:52:57  ken
++ * Fix for #518 MTU issues
++ *
++ * Revision 1.20.2.2  2005/11/27 21:41:03  paul
++ * Pull down TTL fixes from head. this fixes "Unknown symbol sysctl_ip_default_ttl"in for klips as module.
++ *
++ * Revision 1.20.2.1  2005/08/27 23:40:00  paul
++ * recommited HAVE_SOCK_SECURITY fixes for linux 2.6.13
++ *
++ * Revision 1.20  2005/07/12 15:39:27  paul
++ * include asm/uaccess.h for VERIFY_WRITE
++ *
++ * Revision 1.19  2005/05/24 01:02:35  mcr
++ *    some refactoring/simplification of situation where alg
++ *    is not found.
++ *
++ * Revision 1.18  2005/05/23 23:52:33  mcr
++ *    adjust comments, add additional debugging.
++ *
++ * Revision 1.17  2005/05/23 22:57:23  mcr
++ *    removed explicit 3DES support.
++ *
++ * Revision 1.16  2005/05/21 03:29:15  mcr
++ *    fixed warning about unused zeroes if AH is off.
++ *
++ * Revision 1.15  2005/05/20 16:47:59  mcr
++ *    include asm/checksum.h to get ip_fast_csum macro.
++ *
++ * Revision 1.14  2005/05/11 01:43:03  mcr
++ *    removed "poor-man"s OOP in favour of proper C structures.
++ *
++ * Revision 1.13  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.12  2005/04/15 01:28:34  mcr
++ *    use ipsec_dmp_block.
++ *
++ * Revision 1.11  2005/01/26 00:50:35  mcr
++ *    adjustment of confusion of CONFIG_IPSEC_NAT vs CONFIG_KLIPS_NAT,
++ *    and make sure that NAT_TRAVERSAL is set as well to match
++ *    userspace compiles of code.
++ *
++ * Revision 1.10  2004/09/13 17:55:21  ken
++ * MD5* -> osMD5*
++ *
++ * Revision 1.9  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.8  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.7  2004/02/03 03:13:41  mcr
++ *    mark invalid encapsulation states.
++ *
++ * Revision 1.6.2.1  2003/12/22 15:25:52  jjo
++ *      Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.6  2003/12/10 01:14:27  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.5  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.4.4.2  2003/10/29 01:37:39  mcr
++ *    when creating %hold from %trap, only make the %hold as
++ *    specific as the %trap was - so if the protocol and ports
++ *    were wildcards, then the %hold will be too.
++ *
++ * Revision 1.4.4.1  2003/09/21 13:59:56  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.4  2003/06/20 02:28:10  mcr
++ *    misstype of variable name, not detected by module build.
++ *
++ * Revision 1.3  2003/06/20 01:42:21  mcr
++ *    added counters to measure how many ACQUIREs we send to pluto,
++ *    and how many are successfully sent.
++ *
++ * Revision 1.2  2003/04/03 17:38:35  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ * Normalised coding style.
++ * Simplified logic and reduced duplication of code.
++ *
++ * Revision 1.1  2003/02/12 19:31:23  rgb
++ * Refactored from ipsec_tunnel.c
++ *
++ * Local Variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/match586.S     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,357 @@
++/* match.s -- Pentium-optimized version of longest_match()
++ * Written for zlib 1.1.2
++ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License.
++ */
++
++#ifndef NO_UNDERLINE
++#define       match_init      _ipcomp_match_init
++#define       longest_match   _ipcomp_longest_match
++#else
++#define match_init    ipcomp_match_init
++#define longest_match ipcomp_longest_match
++#endif
++
++#define       MAX_MATCH       (258)
++#define       MIN_MATCH       (3)
++#define       MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)
++#define       MAX_MATCH_8     ((MAX_MATCH + 7) & ~7)
++
++/* stack frame offsets */
++
++#define       wmask                   0       /* local copy of s->wmask       */
++#define       window                  4       /* local copy of s->window      */
++#define       windowbestlen           8       /* s->window + bestlen          */
++#define       chainlenscanend         12      /* high word: current chain len */
++                                      /* low word: last bytes sought  */
++#define       scanstart               16      /* first two bytes of string    */
++#define       scanalign               20      /* dword-misalignment of string */
++#define       nicematch               24      /* a good enough match size     */
++#define       bestlen                 28      /* size of best match so far    */
++#define       scan                    32      /* ptr to string wanting match  */
++
++#define       LocalVarsSize           (36)
++/*    saved ebx               36 */
++/*    saved edi               40 */
++/*    saved esi               44 */
++/*    saved ebp               48 */
++/*    return address          52 */
++#define       deflatestate            56      /* the function arguments       */
++#define       curmatch                60
++
++/* Offsets for fields in the deflate_state structure. These numbers
++ * are calculated from the definition of deflate_state, with the
++ * assumption that the compiler will dword-align the fields. (Thus,
++ * changing the definition of deflate_state could easily cause this
++ * program to crash horribly, without so much as a warning at
++ * compile time. Sigh.)
++ */
++#define       dsWSize                 36
++#define       dsWMask                 44
++#define       dsWindow                48
++#define       dsPrev                  56
++#define       dsMatchLen              88
++#define       dsPrevMatch             92
++#define       dsStrStart              100
++#define       dsMatchStart            104
++#define       dsLookahead             108
++#define       dsPrevLen               112
++#define       dsMaxChainLen           116
++#define       dsGoodMatch             132
++#define       dsNiceMatch             136
++
++
++.file "match.S"
++
++.globl        match_init, longest_match
++
++.text
++
++/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
++
++longest_match:
++
++/* Save registers that the compiler may be using, and adjust %esp to  */
++/* make room for our stack frame.                                     */
++
++              pushl   %ebp
++              pushl   %edi
++              pushl   %esi
++              pushl   %ebx
++              subl    $LocalVarsSize, %esp
++
++/* Retrieve the function arguments. %ecx will hold cur_match          */
++/* throughout the entire function. %edx will hold the pointer to the  */
++/* deflate_state structure during the function's setup (before                */
++/* entering the main loop).                                           */
++
++              movl    deflatestate(%esp), %edx
++              movl    curmatch(%esp), %ecx
++
++/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;    */
++
++              movl    dsNiceMatch(%edx), %eax
++              movl    dsLookahead(%edx), %ebx
++              cmpl    %eax, %ebx
++              jl      LookaheadLess
++              movl    %eax, %ebx
++LookaheadLess:        movl    %ebx, nicematch(%esp)
++
++/* register Bytef *scan = s->window + s->strstart;                    */
++
++              movl    dsWindow(%edx), %esi
++              movl    %esi, window(%esp)
++              movl    dsStrStart(%edx), %ebp
++              lea     (%esi,%ebp), %edi
++              movl    %edi, scan(%esp)
++
++/* Determine how many bytes the scan ptr is off from being            */
++/* dword-aligned.                                                     */
++
++              movl    %edi, %eax
++              negl    %eax
++              andl    $3, %eax
++              movl    %eax, scanalign(%esp)
++
++/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                     */
++/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                         */
++
++              movl    dsWSize(%edx), %eax
++              subl    $MIN_LOOKAHEAD, %eax
++              subl    %eax, %ebp
++              jg      LimitPositive
++              xorl    %ebp, %ebp
++LimitPositive:
++
++/* unsigned chain_length = s->max_chain_length;                               */
++/* if (s->prev_length >= s->good_match) {                             */
++/*     chain_length >>= 2;                                            */
++/* }                                                                  */
++
++              movl    dsPrevLen(%edx), %eax
++              movl    dsGoodMatch(%edx), %ebx
++              cmpl    %ebx, %eax
++              movl    dsMaxChainLen(%edx), %ebx
++              jl      LastMatchGood
++              shrl    $2, %ebx
++LastMatchGood:
++
++/* chainlen is decremented once beforehand so that the function can   */
++/* use the sign flag instead of the zero flag for the exit test.      */
++/* It is then shifted into the high word, to make room for the scanend        */
++/* scanend value, which it will always accompany.                     */
++
++              decl    %ebx
++              shll    $16, %ebx
++
++/* int best_len = s->prev_length;                                     */
++
++              movl    dsPrevLen(%edx), %eax
++              movl    %eax, bestlen(%esp)
++
++/* Store the sum of s->window + best_len in %esi locally, and in %esi.        */
++
++              addl    %eax, %esi
++              movl    %esi, windowbestlen(%esp)
++
++/* register ush scan_start = *(ushf*)scan;                            */
++/* register ush scan_end   = *(ushf*)(scan+best_len-1);                       */
++
++              movw    (%edi), %bx
++              movw    %bx, scanstart(%esp)
++              movw    -1(%edi,%eax), %bx
++              movl    %ebx, chainlenscanend(%esp)
++
++/* Posf *prev = s->prev;                                              */
++/* uInt wmask = s->w_mask;                                            */
++
++              movl    dsPrev(%edx), %edi
++              movl    dsWMask(%edx), %edx
++              mov     %edx, wmask(%esp)
++
++/* Jump into the main loop.                                           */
++
++              jmp     LoopEntry
++
++.balign 16
++
++/* do {
++ *     match = s->window + cur_match;
++ *     if (*(ushf*)(match+best_len-1) != scan_end ||
++ *         *(ushf*)match != scan_start) continue;
++ *     [...]
++ * } while ((cur_match = prev[cur_match & wmask]) > limit
++ *          && --chain_length != 0);
++ *
++ * Here is the inner loop of the function. The function will spend the
++ * majority of its time in this loop, and majority of that time will
++ * be spent in the first ten instructions.
++ *
++ * Within this loop:
++ * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
++ * %ecx = curmatch
++ * %edx = curmatch & wmask
++ * %esi = windowbestlen - i.e., (window + bestlen)
++ * %edi = prev
++ * %ebp = limit
++ *
++ * Two optimization notes on the choice of instructions:
++ *
++ * The first instruction uses a 16-bit address, which costs an extra,
++ * unpairable cycle. This is cheaper than doing a 32-bit access and
++ * zeroing the high word, due to the 3-cycle misalignment penalty which
++ * would occur half the time. This also turns out to be cheaper than
++ * doing two separate 8-bit accesses, as the memory is so rarely in the
++ * L1 cache.
++ *
++ * The window buffer, however, apparently spends a lot of time in the
++ * cache, and so it is faster to retrieve the word at the end of the
++ * match string with two 8-bit loads. The instructions that test the
++ * word at the beginning of the match string, however, are executed
++ * much less frequently, and there it was cheaper to use 16-bit
++ * instructions, which avoided the necessity of saving off and
++ * subsequently reloading one of the other registers.
++ */
++LookupLoop:
++                                                      /* 1 U & V  */
++              movw    (%edi,%edx,2), %cx              /* 2 U pipe */
++              movl    wmask(%esp), %edx               /* 2 V pipe */
++              cmpl    %ebp, %ecx                      /* 3 U pipe */
++              jbe     LeaveNow                        /* 3 V pipe */
++              subl    $0x00010000, %ebx               /* 4 U pipe */
++              js      LeaveNow                        /* 4 V pipe */
++LoopEntry:    movb    -1(%esi,%ecx), %al              /* 5 U pipe */
++              andl    %ecx, %edx                      /* 5 V pipe */
++              cmpb    %bl, %al                        /* 6 U pipe */
++              jnz     LookupLoop                      /* 6 V pipe */
++              movb    (%esi,%ecx), %ah
++              cmpb    %bh, %ah
++              jnz     LookupLoop
++              movl    window(%esp), %eax
++              movw    (%eax,%ecx), %ax
++              cmpw    scanstart(%esp), %ax
++              jnz     LookupLoop
++
++/* Store the current value of chainlen.                                       */
++
++              movl    %ebx, chainlenscanend(%esp)
++
++/* Point %edi to the string under scrutiny, and %esi to the string we */
++/* are hoping to match it up with. In actuality, %esi and %edi are    */
++/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is    */
++/* initialized to -(MAX_MATCH_8 - scanalign).                         */
++
++              movl    window(%esp), %esi
++              movl    scan(%esp), %edi
++              addl    %ecx, %esi
++              movl    scanalign(%esp), %eax
++              movl    $(-MAX_MATCH_8), %edx
++              lea     MAX_MATCH_8(%edi,%eax), %edi
++              lea     MAX_MATCH_8(%esi,%eax), %esi
++
++/* Test the strings for equality, 8 bytes at a time. At the end,
++ * adjust %edx so that it is offset to the exact byte that mismatched.
++ *
++ * We already know at this point that the first three bytes of the
++ * strings match each other, and they can be safely passed over before
++ * starting the compare loop. So what this code does is skip over 0-3
++ * bytes, as much as necessary in order to dword-align the %edi
++ * pointer. (%esi will still be misaligned three times out of four.)
++ *
++ * It should be confessed that this loop usually does not represent
++ * much of the total running time. Replacing it with a more
++ * straightforward "rep cmpsb" would not drastically degrade
++ * performance.
++ */
++LoopCmps:
++              movl    (%esi,%edx), %eax
++              movl    (%edi,%edx), %ebx
++              xorl    %ebx, %eax
++              jnz     LeaveLoopCmps
++              movl    4(%esi,%edx), %eax
++              movl    4(%edi,%edx), %ebx
++              xorl    %ebx, %eax
++              jnz     LeaveLoopCmps4
++              addl    $8, %edx
++              jnz     LoopCmps
++              jmp     LenMaximum
++LeaveLoopCmps4:       addl    $4, %edx
++LeaveLoopCmps:        testl   $0x0000FFFF, %eax
++              jnz     LenLower
++              addl    $2, %edx
++              shrl    $16, %eax
++LenLower:     subb    $1, %al
++              adcl    $0, %edx
++
++/* Calculate the length of the match. If it is longer than MAX_MATCH, */
++/* then automatically accept it as the best possible match and leave. */
++
++              lea     (%edi,%edx), %eax
++              movl    scan(%esp), %edi
++              subl    %edi, %eax
++              cmpl    $MAX_MATCH, %eax
++              jge     LenMaximum
++
++/* If the length of the match is not longer than the best match we    */
++/* have so far, then forget it and return to the lookup loop.         */
++
++              movl    deflatestate(%esp), %edx
++              movl    bestlen(%esp), %ebx
++              cmpl    %ebx, %eax
++              jg      LongerMatch
++              movl    chainlenscanend(%esp), %ebx
++              movl    windowbestlen(%esp), %esi
++              movl    dsPrev(%edx), %edi
++              movl    wmask(%esp), %edx
++              andl    %ecx, %edx
++              jmp     LookupLoop
++
++/*         s->match_start = cur_match;                                        */
++/*         best_len = len;                                            */
++/*         if (len >= nice_match) break;                              */
++/*         scan_end = *(ushf*)(scan+best_len-1);                      */
++
++LongerMatch:  movl    nicematch(%esp), %ebx
++              movl    %eax, bestlen(%esp)
++              movl    %ecx, dsMatchStart(%edx)
++              cmpl    %ebx, %eax
++              jge     LeaveNow
++              movl    window(%esp), %esi
++              addl    %eax, %esi
++              movl    %esi, windowbestlen(%esp)
++              movl    chainlenscanend(%esp), %ebx
++              movw    -1(%edi,%eax), %bx
++              movl    dsPrev(%edx), %edi
++              movl    %ebx, chainlenscanend(%esp)
++              movl    wmask(%esp), %edx
++              andl    %ecx, %edx
++              jmp     LookupLoop
++
++/* Accept the current string, with the maximum possible length.               */
++
++LenMaximum:   movl    deflatestate(%esp), %edx
++              movl    $MAX_MATCH, bestlen(%esp)
++              movl    %ecx, dsMatchStart(%edx)
++
++/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;         */
++/* return s->lookahead;                                                       */
++
++LeaveNow:
++              movl    deflatestate(%esp), %edx
++              movl    bestlen(%esp), %ebx
++              movl    dsLookahead(%edx), %eax
++              cmpl    %eax, %ebx
++              jg      LookaheadRet
++              movl    %ebx, %eax
++LookaheadRet:
++
++/* Restore the stack and return from whence we came.                  */
++
++              addl    $LocalVarsSize, %esp
++              popl    %ebx
++              popl    %esi
++              popl    %edi
++              popl    %ebp
++match_init:   ret
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/match686.S     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,330 @@
++/* match.s -- Pentium-Pro-optimized version of longest_match()
++ * Written for zlib 1.1.2
++ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License.
++ */
++
++#ifndef NO_UNDERLINE
++#define       match_init      _ipcomp_match_init
++#define       longest_match   _ipcomp_longest_match
++#else
++#define match_init    ipcomp_match_init
++#define longest_match ipcomp_longest_match
++#endif
++
++#define       MAX_MATCH       (258)
++#define       MIN_MATCH       (3)
++#define       MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)
++#define       MAX_MATCH_8     ((MAX_MATCH + 7) & ~7)
++
++/* stack frame offsets */
++
++#define       chainlenwmask           0       /* high word: current chain len */
++                                      /* low word: s->wmask           */
++#define       window                  4       /* local copy of s->window      */
++#define       windowbestlen           8       /* s->window + bestlen          */
++#define       scanstart               16      /* first two bytes of string    */
++#define       scanend                 12      /* last two bytes of string     */
++#define       scanalign               20      /* dword-misalignment of string */
++#define       nicematch               24      /* a good enough match size     */
++#define       bestlen                 28      /* size of best match so far    */
++#define       scan                    32      /* ptr to string wanting match  */
++
++#define       LocalVarsSize           (36)
++/*    saved ebx               36 */
++/*    saved edi               40 */
++/*    saved esi               44 */
++/*    saved ebp               48 */
++/*    return address          52 */
++#define       deflatestate            56      /* the function arguments       */
++#define       curmatch                60
++
++/* Offsets for fields in the deflate_state structure. These numbers
++ * are calculated from the definition of deflate_state, with the
++ * assumption that the compiler will dword-align the fields. (Thus,
++ * changing the definition of deflate_state could easily cause this
++ * program to crash horribly, without so much as a warning at
++ * compile time. Sigh.)
++ */
++#define       dsWSize                 36
++#define       dsWMask                 44
++#define       dsWindow                48
++#define       dsPrev                  56
++#define       dsMatchLen              88
++#define       dsPrevMatch             92
++#define       dsStrStart              100
++#define       dsMatchStart            104
++#define       dsLookahead             108
++#define       dsPrevLen               112
++#define       dsMaxChainLen           116
++#define       dsGoodMatch             132
++#define       dsNiceMatch             136
++
++
++.file "match.S"
++
++.globl        match_init, longest_match
++
++.text
++
++/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
++
++longest_match:
++
++/* Save registers that the compiler may be using, and adjust %esp to  */
++/* make room for our stack frame.                                     */
++
++              pushl   %ebp
++              pushl   %edi
++              pushl   %esi
++              pushl   %ebx
++              subl    $LocalVarsSize, %esp
++
++/* Retrieve the function arguments. %ecx will hold cur_match          */
++/* throughout the entire function. %edx will hold the pointer to the  */
++/* deflate_state structure during the function's setup (before                */
++/* entering the main loop).                                           */
++
++              movl    deflatestate(%esp), %edx
++              movl    curmatch(%esp), %ecx
++
++/* uInt wmask = s->w_mask;                                            */
++/* unsigned chain_length = s->max_chain_length;                               */
++/* if (s->prev_length >= s->good_match) {                             */
++/*     chain_length >>= 2;                                            */
++/* }                                                                  */
++
++              movl    dsPrevLen(%edx), %eax
++              movl    dsGoodMatch(%edx), %ebx
++              cmpl    %ebx, %eax
++              movl    dsWMask(%edx), %eax
++              movl    dsMaxChainLen(%edx), %ebx
++              jl      LastMatchGood
++              shrl    $2, %ebx
++LastMatchGood:
++
++/* chainlen is decremented once beforehand so that the function can   */
++/* use the sign flag instead of the zero flag for the exit test.      */
++/* It is then shifted into the high word, to make room for the wmask  */
++/* value, which it will always accompany.                             */
++
++              decl    %ebx
++              shll    $16, %ebx
++              orl     %eax, %ebx
++              movl    %ebx, chainlenwmask(%esp)
++
++/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;    */
++
++              movl    dsNiceMatch(%edx), %eax
++              movl    dsLookahead(%edx), %ebx
++              cmpl    %eax, %ebx
++              jl      LookaheadLess
++              movl    %eax, %ebx
++LookaheadLess:        movl    %ebx, nicematch(%esp)
++
++/* register Bytef *scan = s->window + s->strstart;                    */
++
++              movl    dsWindow(%edx), %esi
++              movl    %esi, window(%esp)
++              movl    dsStrStart(%edx), %ebp
++              lea     (%esi,%ebp), %edi
++              movl    %edi, scan(%esp)
++
++/* Determine how many bytes the scan ptr is off from being            */
++/* dword-aligned.                                                     */
++
++              movl    %edi, %eax
++              negl    %eax
++              andl    $3, %eax
++              movl    %eax, scanalign(%esp)
++
++/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                     */
++/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                         */
++
++              movl    dsWSize(%edx), %eax
++              subl    $MIN_LOOKAHEAD, %eax
++              subl    %eax, %ebp
++              jg      LimitPositive
++              xorl    %ebp, %ebp
++LimitPositive:
++
++/* int best_len = s->prev_length;                                     */
++
++              movl    dsPrevLen(%edx), %eax
++              movl    %eax, bestlen(%esp)
++
++/* Store the sum of s->window + best_len in %esi locally, and in %esi.        */
++
++              addl    %eax, %esi
++              movl    %esi, windowbestlen(%esp)
++
++/* register ush scan_start = *(ushf*)scan;                            */
++/* register ush scan_end   = *(ushf*)(scan+best_len-1);                       */
++/* Posf *prev = s->prev;                                              */
++
++              movzwl  (%edi), %ebx
++              movl    %ebx, scanstart(%esp)
++              movzwl  -1(%edi,%eax), %ebx
++              movl    %ebx, scanend(%esp)
++              movl    dsPrev(%edx), %edi
++
++/* Jump into the main loop.                                           */
++
++              movl    chainlenwmask(%esp), %edx
++              jmp     LoopEntry
++
++.balign 16
++
++/* do {
++ *     match = s->window + cur_match;
++ *     if (*(ushf*)(match+best_len-1) != scan_end ||
++ *         *(ushf*)match != scan_start) continue;
++ *     [...]
++ * } while ((cur_match = prev[cur_match & wmask]) > limit
++ *          && --chain_length != 0);
++ *
++ * Here is the inner loop of the function. The function will spend the
++ * majority of its time in this loop, and majority of that time will
++ * be spent in the first ten instructions.
++ *
++ * Within this loop:
++ * %ebx = scanend
++ * %ecx = curmatch
++ * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
++ * %esi = windowbestlen - i.e., (window + bestlen)
++ * %edi = prev
++ * %ebp = limit
++ */
++LookupLoop:
++              andl    %edx, %ecx
++              movzwl  (%edi,%ecx,2), %ecx
++              cmpl    %ebp, %ecx
++              jbe     LeaveNow
++              subl    $0x00010000, %edx
++              js      LeaveNow
++LoopEntry:    movzwl  -1(%esi,%ecx), %eax
++              cmpl    %ebx, %eax
++              jnz     LookupLoop
++              movl    window(%esp), %eax
++              movzwl  (%eax,%ecx), %eax
++              cmpl    scanstart(%esp), %eax
++              jnz     LookupLoop
++
++/* Store the current value of chainlen.                                       */
++
++              movl    %edx, chainlenwmask(%esp)
++
++/* Point %edi to the string under scrutiny, and %esi to the string we */
++/* are hoping to match it up with. In actuality, %esi and %edi are    */
++/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is    */
++/* initialized to -(MAX_MATCH_8 - scanalign).                         */
++
++              movl    window(%esp), %esi
++              movl    scan(%esp), %edi
++              addl    %ecx, %esi
++              movl    scanalign(%esp), %eax
++              movl    $(-MAX_MATCH_8), %edx
++              lea     MAX_MATCH_8(%edi,%eax), %edi
++              lea     MAX_MATCH_8(%esi,%eax), %esi
++
++/* Test the strings for equality, 8 bytes at a time. At the end,
++ * adjust %edx so that it is offset to the exact byte that mismatched.
++ *
++ * We already know at this point that the first three bytes of the
++ * strings match each other, and they can be safely passed over before
++ * starting the compare loop. So what this code does is skip over 0-3
++ * bytes, as much as necessary in order to dword-align the %edi
++ * pointer. (%esi will still be misaligned three times out of four.)
++ *
++ * It should be confessed that this loop usually does not represent
++ * much of the total running time. Replacing it with a more
++ * straightforward "rep cmpsb" would not drastically degrade
++ * performance.
++ */
++LoopCmps:
++              movl    (%esi,%edx), %eax
++              xorl    (%edi,%edx), %eax
++              jnz     LeaveLoopCmps
++              movl    4(%esi,%edx), %eax
++              xorl    4(%edi,%edx), %eax
++              jnz     LeaveLoopCmps4
++              addl    $8, %edx
++              jnz     LoopCmps
++              jmp     LenMaximum
++LeaveLoopCmps4:       addl    $4, %edx
++LeaveLoopCmps:        testl   $0x0000FFFF, %eax
++              jnz     LenLower
++              addl    $2, %edx
++              shrl    $16, %eax
++LenLower:     subb    $1, %al
++              adcl    $0, %edx
++
++/* Calculate the length of the match. If it is longer than MAX_MATCH, */
++/* then automatically accept it as the best possible match and leave. */
++
++              lea     (%edi,%edx), %eax
++              movl    scan(%esp), %edi
++              subl    %edi, %eax
++              cmpl    $MAX_MATCH, %eax
++              jge     LenMaximum
++
++/* If the length of the match is not longer than the best match we    */
++/* have so far, then forget it and return to the lookup loop.         */
++
++              movl    deflatestate(%esp), %edx
++              movl    bestlen(%esp), %ebx
++              cmpl    %ebx, %eax
++              jg      LongerMatch
++              movl    windowbestlen(%esp), %esi
++              movl    dsPrev(%edx), %edi
++              movl    scanend(%esp), %ebx
++              movl    chainlenwmask(%esp), %edx
++              jmp     LookupLoop
++
++/*         s->match_start = cur_match;                                        */
++/*         best_len = len;                                            */
++/*         if (len >= nice_match) break;                              */
++/*         scan_end = *(ushf*)(scan+best_len-1);                      */
++
++LongerMatch:  movl    nicematch(%esp), %ebx
++              movl    %eax, bestlen(%esp)
++              movl    %ecx, dsMatchStart(%edx)
++              cmpl    %ebx, %eax
++              jge     LeaveNow
++              movl    window(%esp), %esi
++              addl    %eax, %esi
++              movl    %esi, windowbestlen(%esp)
++              movzwl  -1(%edi,%eax), %ebx
++              movl    dsPrev(%edx), %edi
++              movl    %ebx, scanend(%esp)
++              movl    chainlenwmask(%esp), %edx
++              jmp     LookupLoop
++
++/* Accept the current string, with the maximum possible length.               */
++
++LenMaximum:   movl    deflatestate(%esp), %edx
++              movl    $MAX_MATCH, bestlen(%esp)
++              movl    %ecx, dsMatchStart(%edx)
++
++/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;         */
++/* return s->lookahead;                                                       */
++
++LeaveNow:
++              movl    deflatestate(%esp), %edx
++              movl    bestlen(%esp), %ebx
++              movl    dsLookahead(%edx), %eax
++              cmpl    %eax, %ebx
++              jg      LookaheadRet
++              movl    %ebx, %eax
++LookaheadRet:
++
++/* Restore the stack and return from whence we came.                  */
++
++              addl    $LocalVarsSize, %esp
++              popl    %ebx
++              popl    %esi
++              popl    %edi
++              popl    %ebp
++match_init:   ret
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/null/ipsec_alg_null.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,145 @@
++/*
++ * ipsec_alg NULL cipher stubs
++ *
++ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
++ * 
++ * $Id: ipsec_alg_null.c,v 1.1.2.1 2006/10/11 18:14:33 paul Exp $
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ */
++#include <linux/config.h>
++#include <linux/version.h>
++
++/*    
++ *    special case: ipsec core modular with this static algo inside:
++ *    must avoid MODULE magic for this file
++ */
++#if defined(CONFIG_KLIPS_MODULE) && defined(CONFIG_KLIPS_ENC_NULL)
++#undef MODULE
++#endif
++
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/string.h>
++
++/* Check if __exit is defined, if not null it */
++#ifndef __exit
++#define __exit
++#endif
++
++/*    Low freeswan header coupling    */
++#include "openswan/ipsec_alg.h"
++
++#define ESP_NULL              11      /* from ipsec drafts */
++#define ESP_NULL_BLK_LEN      1
++
++MODULE_AUTHOR("JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>");
++static int debug_null=0;
++static int test_null=0;
++#ifdef module_param
++module_param(debug_null, int, 0600);
++module_param(test_null, int, 0600);
++#else
++MODULE_PARM(debug_null, "i");
++MODULE_PARM(test_null, "i");
++#endif
++
++typedef int null_context;
++
++struct null_eks{
++      null_context null_ctx;
++};
++static int _null_set_key(struct ipsec_alg_enc *alg, 
++                      __u8 * key_e, const __u8 * key, 
++                      size_t keysize) {
++      null_context *ctx=&((struct null_eks*)key_e)->null_ctx;
++      if (debug_null > 0)
++              printk(KERN_DEBUG "klips_debug:_null_set_key:"
++                              "key_e=%p key=%p keysize=%d\n",
++                              key_e, key, keysize);
++      *ctx = 1;
++      return 0;
++}
++static int _null_cbc_encrypt(struct ipsec_alg_enc *alg, 
++              __u8 * key_e, __u8 * in, int ilen, const __u8 * iv, 
++              int encrypt) {
++      null_context *ctx=&((struct null_eks*)key_e)->null_ctx;
++      if (debug_null > 0)
++              printk(KERN_DEBUG "klips_debug:_null_cbc_encrypt:"
++                              "key_e=%p in=%p ilen=%d iv=%p encrypt=%d\n",
++                              key_e, in, ilen, iv, encrypt);
++      (*ctx)++;
++      return ilen;
++}
++static struct ipsec_alg_enc ipsec_alg_NULL = {
++      ixt_common: { ixt_version:      IPSEC_ALG_VERSION,
++                    ixt_refcnt:       ATOMIC_INIT(0),
++                    ixt_name:         "null",
++                    ixt_blocksize:    ESP_NULL_BLK_LEN,
++                    ixt_support: {
++                      ias_exttype:    IPSEC_ALG_TYPE_ENCRYPT,
++                      ias_id:         ESP_NULL,
++                      ias_ivlen:      0,
++                      ias_keyminbits: 0,
++                      ias_keymaxbits: 0,
++              },
++      },
++#if defined(CONFIG_KLIPS_ENC_NULL_MODULE)
++      ixt_module:     THIS_MODULE,
++#endif
++      ixt_e_keylen:   0,
++      ixt_e_ctx_size: sizeof(null_context),
++      ixt_e_set_key:  _null_set_key,
++      ixt_e_cbc_encrypt:_null_cbc_encrypt,
++};
++
++#if defined(CONFIG_KLIPS_ENC_NULL_MODULE)
++IPSEC_ALG_MODULE_INIT_MOD( ipsec_null_init )
++#else
++IPSEC_ALG_MODULE_INIT_STATIC( ipsec_null_init )
++#endif
++{
++      int ret, test_ret;
++      ret=register_ipsec_alg_enc(&ipsec_alg_NULL);
++      printk("ipsec_null_init(alg_type=%d alg_id=%d name=%s): ret=%d\n", 
++                      ipsec_alg_NULL.ixt_common.ixt_support.ias_exttype,
++                      ipsec_alg_NULL.ixt_common.ixt_support.ias_id,
++                      ipsec_alg_NULL.ixt_common.ixt_name, 
++                      ret);
++      if (ret==0 && test_null) {
++              test_ret=ipsec_alg_test(
++                              ipsec_alg_NULL.ixt_common.ixt_support.ias_exttype,
++                              ipsec_alg_NULL.ixt_common.ixt_support.ias_id,
++                              test_null);
++              printk("ipsec_null_init(alg_type=%d alg_id=%d): test_ret=%d\n", 
++                              ipsec_alg_NULL.ixt_common.ixt_support.ias_exttype,
++                              ipsec_alg_NULL.ixt_common.ixt_support.ias_id,
++                              test_ret);
++      }
++      return ret;
++}
++#if defined(CONFIG_KLIPS_ENC_NULL_MODULE)
++IPSEC_ALG_MODULE_EXIT_MOD( ipsec_null_fini )
++#else
++IPSEC_ALG_MODULE_EXIT_STATIC( ipsec_null_fini )
++#endif
++{
++      unregister_ipsec_alg_enc(&ipsec_alg_NULL);
++      return;
++}
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/pfkey_v2.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,2022 @@
++/*
++ * @(#) RFC2367 PF_KEYv2 Key management API domain socket I/F
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey_v2.c,v 1.97.2.12 2006/11/24 05:43:29 paul Exp $
++ */
++
++/*
++ *            Template from /usr/src/linux-2.0.36/net/unix/af_unix.c.
++ *            Hints from /usr/src/linux-2.0.36/net/ipv4/udp.c.
++ */
++
++#define __NO_VERSION__
++#include <linux/module.h>
++#include <linux/version.h>
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/kernel.h>
++
++#include "openswan/ipsec_param.h"
++
++#include <linux/major.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/stat.h>
++#include <linux/socket.h>
++#include <linux/un.h>
++#include <linux/fcntl.h>
++#include <linux/termios.h>
++#include <linux/socket.h>
++#include <linux/sockios.h>
++#include <linux/net.h> /* struct socket */
++#include <linux/in.h>
++#include <linux/fs.h>
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <asm/segment.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <net/sock.h> /* struct sock */
++#include <net/protocol.h>
++/* #include <net/tcp.h> */
++#include <net/af_unix.h>
++#ifdef CONFIG_PROC_FS
++# include <linux/proc_fs.h>
++#endif /* CONFIG_PROC_FS */
++
++#include <linux/types.h>
++ 
++#include <openswan.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_kern24.h"
++
++#ifdef CONFIG_KLIPS_DEBUG
++int debug_pfkey = 0;
++extern int sysctl_ipsec_debug_verbose;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
++
++#ifndef SOCKOPS_WRAPPED
++#define SOCKOPS_WRAPPED(name) name
++#endif /* SOCKOPS_WRAPPED */
++
++#ifdef NET_26
++static rwlock_t pfkey_sock_lock = RW_LOCK_UNLOCKED;
++HLIST_HEAD(pfkey_sock_list);
++static DECLARE_WAIT_QUEUE_HEAD(pfkey_sock_wait);
++static atomic_t pfkey_sock_users = ATOMIC_INIT(0);
++#else
++struct sock *pfkey_sock_list = NULL;
++#endif
++
++struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1];
++
++struct socket_list *pfkey_open_sockets = NULL;
++struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1];
++
++int pfkey_msg_interp(struct sock *, struct sadb_msg *, struct sadb_msg **);
++
++DEBUG_NO_STATIC int pfkey_create(struct socket *sock, int protocol);
++DEBUG_NO_STATIC int pfkey_shutdown(struct socket *sock, int mode);
++DEBUG_NO_STATIC int pfkey_release(struct socket *sock);
++
++#ifdef NET_26
++DEBUG_NO_STATIC int pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len);
++DEBUG_NO_STATIC int pfkey_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg
++                                , size_t size, int flags);
++#else
++DEBUG_NO_STATIC int pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm);
++DEBUG_NO_STATIC int pfkey_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm);
++#endif
++
++struct net_proto_family pfkey_family_ops = {
++#ifdef NETDEV_23
++      .family = PF_KEY,
++      .create = pfkey_create,
++#ifdef NET_26
++      .owner  = THIS_MODULE,
++#endif
++#else
++      PF_KEY,
++      pfkey_create
++#endif
++};
++
++struct proto_ops SOCKOPS_WRAPPED(pfkey_ops) = {
++#ifdef NETDEV_23
++      family:         PF_KEY,
++#ifdef NET_26
++      owner:          THIS_MODULE,
++#endif
++      release:        pfkey_release,
++      bind:           sock_no_bind,
++      connect:        sock_no_connect,
++      socketpair:     sock_no_socketpair,
++      accept:         sock_no_accept,
++      getname:        sock_no_getname,
++      poll:           datagram_poll,
++      ioctl:          sock_no_ioctl,
++      listen:         sock_no_listen,
++      shutdown:       pfkey_shutdown,
++      setsockopt:     sock_no_setsockopt,
++      getsockopt:     sock_no_getsockopt,
++      sendmsg:        pfkey_sendmsg,
++      recvmsg:        pfkey_recvmsg,
++      mmap:           sock_no_mmap,
++#else /* NETDEV_23 */
++      PF_KEY,
++      sock_no_dup,
++      pfkey_release,
++      sock_no_bind,
++      sock_no_connect,
++      sock_no_socketpair,
++      sock_no_accept,
++      sock_no_getname,
++      datagram_poll,
++      sock_no_ioctl,
++      sock_no_listen,
++      pfkey_shutdown,
++      sock_no_setsockopt,
++      sock_no_getsockopt,
++      sock_no_fcntl,
++      pfkey_sendmsg,
++      pfkey_recvmsg
++#endif /* NETDEV_23 */
++};
++
++#ifdef NETDEV_23
++#include <linux/smp_lock.h>
++SOCKOPS_WRAP(pfkey, PF_KEY);
++#endif  /* NETDEV_23 */
++
++#ifdef NET_26
++static void pfkey_sock_list_grab(void)
++{
++      write_lock_bh(&pfkey_sock_lock);
++
++      if (atomic_read(&pfkey_sock_users)) {
++              DECLARE_WAITQUEUE(wait, current);
++
++              add_wait_queue_exclusive(&pfkey_sock_wait, &wait);
++              for(;;) {
++                      set_current_state(TASK_UNINTERRUPTIBLE);
++                      if (atomic_read(&pfkey_sock_users) == 0)
++                              break;
++                      write_unlock_bh(&pfkey_sock_lock);
++                      schedule();
++                      write_lock_bh(&pfkey_sock_lock);
++              }
++
++              __set_current_state(TASK_RUNNING);
++              remove_wait_queue(&pfkey_sock_wait, &wait);
++      }
++}
++
++static __inline__ void pfkey_sock_list_ungrab(void)
++{
++      write_unlock_bh(&pfkey_sock_lock);
++      wake_up(&pfkey_sock_wait);
++}
++
++static __inline__ void pfkey_lock_sock_list(void)
++{
++      /* read_lock() synchronizes us to pfkey_table_grab */
++
++      read_lock(&pfkey_sock_lock);
++      atomic_inc(&pfkey_sock_users);
++      read_unlock(&pfkey_sock_lock);
++}
++
++static __inline__ void pfkey_unlock_sock_list(void)
++{
++      if (atomic_dec_and_test(&pfkey_sock_users))
++              wake_up(&pfkey_sock_wait);
++}
++#endif
++
++int
++pfkey_list_remove_socket(struct socket *socketp, struct socket_list **sockets)
++{
++      struct socket_list *socket_listp,*prev;
++
++      if(!socketp) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_remove_socket: "
++                          "NULL socketp handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      if(!sockets) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_remove_socket: "
++                          "NULL sockets list handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      socket_listp = *sockets;
++      prev = NULL;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_list_remove_socket: "
++                  "removing sock=0p%p\n",
++                  socketp);
++      
++      while(socket_listp != NULL) {
++              if(socket_listp->socketp == socketp) {
++                      if(prev != NULL) {
++                              prev->next = socket_listp->next;
++                      } else {
++                              *sockets = socket_listp->next;
++                      }
++                      
++                      kfree((void*)socket_listp);
++                      
++                      break;
++              }
++              prev = socket_listp;
++              socket_listp = socket_listp->next;
++      }
++
++      return 0;
++}
++
++int
++pfkey_list_insert_socket(struct socket *socketp, struct socket_list **sockets)
++{
++      struct socket_list *socket_listp;
++
++      if(!socketp) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_insert_socket: "
++                          "NULL socketp handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      if(!sockets) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_insert_socket: "
++                          "NULL sockets list handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_list_insert_socket: "
++                  "allocating %lu bytes for socketp=0p%p\n",
++                  (unsigned long) sizeof(struct socket_list),
++                  socketp);
++      
++      if((socket_listp = (struct socket_list *)kmalloc(sizeof(struct socket_list), GFP_KERNEL)) == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_insert_socket: "
++                          "memory allocation error.\n");
++              return -ENOMEM;
++      }
++      
++      socket_listp->socketp = socketp;
++      socket_listp->next = *sockets;
++      *sockets = socket_listp;
++
++      return 0;
++}
++  
++int
++pfkey_list_remove_supported(struct ipsec_alg_supported *supported, struct supported_list **supported_list)
++{
++      struct supported_list *supported_listp = *supported_list, *prev = NULL;
++      
++      if(!supported) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_remove_supported: "
++                          "NULL supported handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      if(!supported_list) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_remove_supported: "
++                          "NULL supported_list handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_list_remove_supported: "
++                  "removing supported=0p%p\n",
++                  supported);
++      
++      while(supported_listp != NULL) {
++              if(supported_listp->supportedp == supported) {
++                      if(prev != NULL) {
++                              prev->next = supported_listp->next;
++                      } else {
++                              *supported_list = supported_listp->next;
++                      }
++                      
++                      kfree((void*)supported_listp);
++                      
++                      break;
++              }
++              prev = supported_listp;
++              supported_listp = supported_listp->next;
++      }
++
++      return 0;
++}
++
++int
++pfkey_list_insert_supported(struct ipsec_alg_supported *supported
++                          , struct supported_list **supported_list)
++{
++      struct supported_list *supported_listp;
++
++      if(!supported) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_insert_supported: "
++                          "NULL supported handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      if(!supported_list) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_insert_supported: "
++                          "NULL supported_list handed in, failed.\n");
++              return -EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_list_insert_supported: "
++                  "allocating %lu bytes for incoming, supported=0p%p, supported_list=0p%p\n",
++                  (unsigned long) sizeof(struct supported_list),
++                  supported,
++                  supported_list);
++      
++      supported_listp = (struct supported_list *)kmalloc(sizeof(struct supported_list), GFP_KERNEL);
++
++      if(supported_listp == NULL)
++      {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_list_insert_supported: "
++                          "memory allocation error.\n");
++              return -ENOMEM;
++      }
++      
++      supported_listp->supportedp = supported;
++      supported_listp->next = *supported_list;
++      *supported_list = supported_listp;
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_list_insert_supported: "
++                  "outgoing, supported=0p%p, supported_list=0p%p\n",
++                  supported,
++                  supported_list);
++
++      return 0;
++}
++  
++#ifdef NET_26
++DEBUG_NO_STATIC void
++pfkey_insert_socket(struct sock *sk)
++{
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_insert_socket: "
++                  "sk=0p%p\n",
++                  sk);
++      pfkey_sock_list_grab();
++      sk_add_node(sk, &pfkey_sock_list);
++      pfkey_sock_list_ungrab();
++}
++
++DEBUG_NO_STATIC void
++pfkey_remove_socket(struct sock *sk)
++{
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_remove_socket: 0p%p\n", sk);
++      pfkey_sock_list_grab();
++      sk_del_node_init(sk);
++      pfkey_sock_list_ungrab();
++      return;
++}
++#else
++
++DEBUG_NO_STATIC void
++pfkey_insert_socket(struct sock *sk)
++{
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_insert_socket: "
++                  "sk=0p%p\n",
++                  sk);
++      cli();
++      sk->next=pfkey_sock_list;
++      pfkey_sock_list=sk;
++      sti();
++}
++DEBUG_NO_STATIC void
++pfkey_remove_socket(struct sock *sk)
++{
++      struct sock **s;
++
++      s = NULL;
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_remove_socket: .\n");
++
++      cli();
++      s=&pfkey_sock_list;
++
++      while(*s!=NULL) {
++              if(*s==sk) {
++                      *s=sk->next;
++                      sk->next=NULL;
++                      sti();
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_remove_socket: "
++                                  "succeeded.\n");
++                      return;
++              }
++              s=&((*s)->next);
++      }
++      sti();
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_remove_socket: "
++                  "not found.\n");
++      return;
++}
++#endif
++
++DEBUG_NO_STATIC void
++pfkey_destroy_socket(struct sock *sk)
++{
++      struct sk_buff *skb;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_destroy_socket: 0p%p\n",sk);
++      pfkey_remove_socket(sk);
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_destroy_socket: "
++                  "pfkey_remove_socket called, sk=0p%p\n",sk);
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_destroy_socket: "
++                  "sk(0p%p)->(&0p%p)receive_queue.{next=0p%p,prev=0p%p}.\n",
++                  sk,
++                  &(sk->sk_receive_queue),
++                  sk->sk_receive_queue.next,
++                  sk->sk_receive_queue.prev);
++
++      while(sk && ((skb=skb_dequeue(&(sk->sk_receive_queue)))!=NULL)) {
++#ifdef CONFIG_KLIPS_DEBUG
++              if(debug_pfkey && sysctl_ipsec_debug_verbose) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_destroy_socket: "
++                                  "skb=0p%p dequeued.\n", skb);
++                      printk(KERN_INFO "klips_debug:pfkey_destroy_socket: "
++                             "pfkey_skb contents:");
++                      printk(" next:0p%p", skb->next);
++                      printk(" prev:0p%p", skb->prev);
++                      printk(" sk:0p%p", skb->sk);
++                      printk(" dev:0p%p", skb->dev);
++                      if(skb->dev) {
++                              if(skb->dev->name) {
++                                      printk(" dev->name:%s", skb->dev->name);
++                              } else {
++                                      printk(" dev->name:NULL?");
++                              }
++                      } else {
++                              printk(" dev:NULL");
++                      }
++                      printk(" h:0p%p", skb->h.raw);
++                      printk(" nh:0p%p", skb->nh.raw);
++                      printk(" mac:0p%p", skb->mac.raw);
++                      printk(" dst:0p%p", skb->dst);
++                      if(sysctl_ipsec_debug_verbose) {
++                              int i;
++                              
++                              printk(" cb");
++                              for(i=0; i<48; i++) {
++                                      printk(":%2x", skb->cb[i]);
++                              }
++                      }
++                      printk(" len:%d", skb->len);
++                      printk(" csum:%d", skb->csum);
++#ifndef NETDEV_23
++                      printk(" used:%d", skb->used);
++                      printk(" is_clone:%d", skb->is_clone);
++#endif /* NETDEV_23 */
++                      printk(" cloned:%d", skb->cloned);
++                      printk(" pkt_type:%d", skb->pkt_type);
++                      printk(" ip_summed:%d", skb->ip_summed);
++                      printk(" priority:%d", skb->priority);
++                      printk(" protocol:%d", skb->protocol);
++#ifdef HAVE_SOCK_SECURITY
++                      printk(" security:%d", skb->security);
++#endif
++                      printk(" truesize:%d", skb->truesize);
++                      printk(" head:0p%p", skb->head);
++                      printk(" data:0p%p", skb->data);
++                      printk(" tail:0p%p", skb->tail);
++                      printk(" end:0p%p", skb->end);
++                      if(sysctl_ipsec_debug_verbose) {
++                              unsigned char* i;
++                              printk(" data");
++                              for(i = skb->head; i < skb->end; i++) {
++                                      printk(":%2x", (unsigned char)(*(i)));
++                              }
++                      }
++                      printk(" destructor:0p%p", skb->destructor);
++                      printk("\n");
++              }
++#endif /* CONFIG_KLIPS_DEBUG */
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_destroy_socket: "
++                          "skb=0p%p freed.\n",
++                          skb);
++              ipsec_kfree_skb(skb);
++      }
++
++#ifdef NET_26
++      sock_set_flag(sk, SOCK_DEAD);
++#else
++      sk->dead = 1;
++#endif
++      sk_free(sk);
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_destroy_socket: destroyed.\n");
++}
++
++int
++pfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg)
++{
++      int error = 0;
++      struct sk_buff * skb = NULL;
++      struct sock *sk;
++
++      if(sock == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_upmsg: "
++                          "NULL socket passed in.\n");
++              return -EINVAL;
++      }
++
++      if(pfkey_msg == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_upmsg: "
++                          "NULL pfkey_msg passed in.\n");
++              return -EINVAL;
++      }
++
++      sk = sock->sk;
++
++      if(sk == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_upmsg: "
++                          "NULL sock passed in.\n");
++              return -EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_upmsg: "
++                  "allocating %d bytes...\n",
++                  (int)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN));
++      if(!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_upmsg: "
++                          "no buffers left to send up a message.\n");
++              return -ENOBUFS;
++      }
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_upmsg: "
++                  "...allocated at 0p%p.\n",
++                  skb);
++      
++      skb->dev = NULL;
++      
++      if(skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
++              printk(KERN_WARNING "klips_error:pfkey_upmsg: "
++                     "tried to skb_put %ld, %d available.  This should never happen, please report.\n",
++                     (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN,
++                     skb_tailroom(skb));
++              ipsec_kfree_skb(skb);
++              return -ENOBUFS;
++      }
++      skb->h.raw = skb_put(skb, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
++      memcpy(skb->h.raw, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
++
++      if((error = sock_queue_rcv_skb(sk, skb)) < 0) {
++              skb->sk=NULL;
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_upmsg: "
++                          "error=%d calling sock_queue_rcv_skb with skb=0p%p.\n",
++                          error,
++                          skb);
++              ipsec_kfree_skb(skb);
++              return error;
++      }
++      return error;
++}
++
++#ifdef NET_26_12_SKALLOC
++static struct proto key_proto = {
++      .name     = "KEY",
++      .owner    = THIS_MODULE,
++      .obj_size = sizeof(struct sock),
++      
++};
++#endif
++
++DEBUG_NO_STATIC int
++pfkey_create(struct socket *sock, int protocol)
++{
++      struct sock *sk;
++
++      if(sock == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_create: "
++                          "socket NULL.\n");
++              return -EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_create: "
++                  "sock=0p%p type:%d state:%d flags:%ld protocol:%d\n",
++                  sock,
++                  sock->type,
++                  (unsigned int)(sock->state),
++                  sock->flags, protocol);
++
++      if(sock->type != SOCK_RAW) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_create: "
++                          "only SOCK_RAW supported.\n");
++              return -ESOCKTNOSUPPORT;
++      }
++
++      if(protocol != PF_KEY_V2) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_create: "
++                          "protocol not PF_KEY_V2.\n");
++              return -EPROTONOSUPPORT;
++      }
++
++      if((current->uid != 0)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_create: "
++                          "must be root to open pfkey sockets.\n");
++              return -EACCES;
++      }
++
++      sock->state = SS_UNCONNECTED;
++
++      KLIPS_INC_USE;
++
++#ifdef NET_26
++#ifdef NET_26_12_SKALLOC
++      sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1);
++#else
++      sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL);
++#endif
++#else
++      /* 2.4 interface */
++      sk=(struct sock *)sk_alloc(PF_KEY, GFP_KERNEL, 1);
++#endif
++
++      if(sk == NULL)
++      {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_create: "
++                          "Out of memory trying to allocate.\n");
++              KLIPS_DEC_USE;
++              return -ENOMEM;
++      }
++
++      sock_init_data(sock, sk);
++
++      sk->sk_destruct = NULL;
++      sk->sk_reuse = 1;
++      sock->ops = &pfkey_ops;
++
++      sk->sk_family = PF_KEY;
++/*    sk->num = protocol; */
++      sk->sk_protocol = protocol;
++      key_pid(sk) = current->pid;
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_create: "
++                  "sock->fasync_list=0p%p sk->sleep=0p%p.\n",
++                  sock->fasync_list,
++                  sk->sk_sleep);
++
++      pfkey_insert_socket(sk);
++      pfkey_list_insert_socket(sock, &pfkey_open_sockets);
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_create: "
++                  "Socket sock=0p%p sk=0p%p initialised.\n", sock, sk);
++      return 0;
++}
++
++DEBUG_NO_STATIC int
++#ifdef NETDEV_23
++pfkey_release(struct socket *sock)
++#else /* NETDEV_23 */
++pfkey_release(struct socket *sock, struct socket *peersock)
++#endif /* NETDEV_23 */
++{
++      struct sock *sk;
++      int i;
++
++      if(sock==NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_release: "
++                          "No socket attached.\n");
++              return 0; /* -EINVAL; */
++      }
++              
++      sk=sock->sk;
++      
++      /* May not have data attached */
++      if(sk==NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_release: "
++                          "No sk attached to sock=0p%p.\n", sock);
++              return 0; /* -EINVAL; */
++      }
++              
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_release: "
++                  "sock=0p%p sk=0p%p\n", sock, sk);
++
++      if(sock_flag(sk, SOCK_DEAD))
++              if(sk->sk_state_change) {
++                      sk->sk_state_change(sk);
++              }
++
++      sock->sk = NULL;
++
++      /* Try to flush out this socket. Throw out buffers at least */
++      pfkey_destroy_socket(sk);
++      pfkey_list_remove_socket(sock, &pfkey_open_sockets);
++      for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) {
++              pfkey_list_remove_socket(sock, &(pfkey_registered_sockets[i]));
++      }
++
++      KLIPS_DEC_USE;
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_release: "
++                  "succeeded.\n");
++
++      return 0;
++}
++
++DEBUG_NO_STATIC int
++pfkey_shutdown(struct socket *sock, int mode)
++{
++      struct sock *sk;
++
++      if(sock == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_shutdown: "
++                          "NULL socket passed in.\n");
++              return -EINVAL;
++      }
++
++      sk=sock->sk;
++      
++      if(sk == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_shutdown: "
++                          "No sock attached to socket.\n");
++              return -EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_shutdown: "
++                  "mode=%x.\n", mode);
++      mode++;
++      
++      if(mode&SEND_SHUTDOWN) {
++              sk->sk_shutdown|=SEND_SHUTDOWN;
++              sk->sk_state_change(sk);
++      }
++
++      if(mode&RCV_SHUTDOWN) {
++              sk->sk_shutdown|=RCV_SHUTDOWN;
++              sk->sk_state_change(sk);
++      }
++      return 0;
++}
++
++/*
++ *    Send PF_KEY data down.
++ */
++              
++DEBUG_NO_STATIC int
++#ifdef NET_26
++pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
++#else
++pfkey_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
++#endif
++{
++      struct sock *sk;
++      int error = 0;
++      struct sadb_msg *pfkey_msg = NULL, *pfkey_reply = NULL;
++      
++      if(sock == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "Null socket passed in.\n");
++              SENDERR(EINVAL);
++      }
++      
++      sk = sock->sk;
++
++      if(sk == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "Null sock passed in.\n");
++              SENDERR(EINVAL);
++      }
++      
++      if(msg == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "Null msghdr passed in.\n");
++              SENDERR(EINVAL);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_sendmsg: .\n");
++      if(sk->sk_err) {
++              error = sock_error(sk);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "sk->err is non-zero, returns %d.\n",
++                          error);
++              SENDERR(-error);
++      }
++
++      if((current->uid != 0)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "must be root to send messages to pfkey sockets.\n");
++              SENDERR(EACCES);
++      }
++
++      if(msg->msg_control)
++      {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "can't set flags or set msg_control.\n");
++              SENDERR(EINVAL);
++      }
++              
++      if(sk->sk_shutdown & SEND_SHUTDOWN) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "shutdown.\n");
++              send_sig(SIGPIPE, current, 0);
++              SENDERR(EPIPE);
++      }
++      
++      if(len < sizeof(struct sadb_msg)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "bogus msg len of %d, too small.\n", (int)len);
++              SENDERR(EMSGSIZE);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_sendmsg: "
++                  "allocating %d bytes for downward message.\n",
++                  (int)len);
++      if((pfkey_msg = (struct sadb_msg*)kmalloc(len, GFP_KERNEL)) == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "memory allocation error.\n");
++              SENDERR(ENOBUFS);
++      }
++
++      memcpy_fromiovec((void *)pfkey_msg, msg->msg_iov, len);
++
++      if(pfkey_msg->sadb_msg_version != PF_KEY_V2) {
++              KLIPS_PRINT(1 || debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "not PF_KEY_V2 msg, found %d, should be %d.\n",
++                          pfkey_msg->sadb_msg_version,
++                          PF_KEY_V2);
++              kfree((void*)pfkey_msg);
++              return -EINVAL;
++      }
++
++      if(len != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "bogus msg len of %d, not %d byte aligned.\n",
++                          (int)len, (int)IPSEC_PFKEYv2_ALIGN);
++              SENDERR(EMSGSIZE);
++      }
++
++#if 0
++      /* This check is questionable, since a downward message could be
++         the result of an ACQUIRE either from kernel (PID==0) or
++         userspace (some other PID). */
++      /* check PID */
++      if(pfkey_msg->sadb_msg_pid != current->pid) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "pid (%d) does not equal sending process pid (%d).\n",
++                          pfkey_msg->sadb_msg_pid, current->pid);
++              SENDERR(EINVAL);
++      }
++#endif
++
++      if(pfkey_msg->sadb_msg_reserved) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "reserved field must be zero, set to %d.\n",
++                          pfkey_msg->sadb_msg_reserved);
++              SENDERR(EINVAL);
++      }
++      
++      if((pfkey_msg->sadb_msg_type > SADB_MAX) || (!pfkey_msg->sadb_msg_type)){
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "msg type too large or small:%d.\n",
++                          pfkey_msg->sadb_msg_type);
++              SENDERR(EINVAL);
++      }
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_sendmsg: "
++                  "msg sent for parsing.\n");
++      
++      if((error = pfkey_msg_interp(sk, pfkey_msg, &pfkey_reply))) {
++              struct socket_list *pfkey_socketsp;
++
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
++                          "pfkey_msg_parse returns %d.\n",
++                          error);
++
++              if((pfkey_reply = (struct sadb_msg*)kmalloc(sizeof(struct sadb_msg), GFP_KERNEL)) == NULL) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_sendmsg: "
++                                  "memory allocation error.\n");
++                      SENDERR(ENOBUFS);
++              }
++              memcpy((void*)pfkey_reply, (void*)pfkey_msg, sizeof(struct sadb_msg));
++              pfkey_reply->sadb_msg_errno = -error;
++              pfkey_reply->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
++
++              for(pfkey_socketsp = pfkey_open_sockets;
++                  pfkey_socketsp;
++                  pfkey_socketsp = pfkey_socketsp->next) {
++                      int error_upmsg = 0;
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
++                                  "sending up error=%d message=0p%p to socket=0p%p.\n",
++                                  error,
++                                  pfkey_reply,
++                                  pfkey_socketsp->socketp);
++                      if((error_upmsg = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
++                                          "sending up error message to socket=0p%p failed with error=%d.\n",
++                                          pfkey_socketsp->socketp,
++                                          error_upmsg);
++                              /* pfkey_msg_free(&pfkey_reply); */
++                              /* SENDERR(-error); */
++                      }
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
++                                  "sending up error message to socket=0p%p succeeded.\n",
++                                  pfkey_socketsp->socketp);
++              }
++              
++              pfkey_msg_free(&pfkey_reply);
++              
++              SENDERR(-error);
++      }
++
++ errlab:
++      if (pfkey_msg) {
++              kfree((void*)pfkey_msg);
++      }
++      
++      if(error) {
++              return error;
++      } else {
++              return len;
++      }
++}
++
++/*
++ *    Receive PF_KEY data up.
++ */
++              
++DEBUG_NO_STATIC int
++#ifdef NET_26
++pfkey_recvmsg(struct kiocb *kiocb
++            , struct socket *sock
++            , struct msghdr *msg
++            , size_t size
++            , int flags)
++#else
++pfkey_recvmsg(struct socket *sock
++            , struct msghdr *msg
++            , int size, int flags
++            , struct scm_cookie *scm)
++#endif
++{
++      struct sock *sk;
++      int noblock = flags & MSG_DONTWAIT;
++      struct sk_buff *skb;
++      int error;
++
++      if(sock == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_recvmsg: "
++                          "Null socket passed in.\n");
++              return -EINVAL;
++      }
++
++      sk = sock->sk;
++
++      if(sk == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_recvmsg: "
++                          "Null sock passed in for sock=0p%p.\n", sock);
++              return -EINVAL;
++      }
++
++      if(msg == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_recvmsg: "
++                          "Null msghdr passed in for sock=0p%p, sk=0p%p.\n",
++                          sock, sk);
++              return -EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                  "klips_debug:pfkey_recvmsg: sock=0p%p sk=0p%p msg=0p%p size=%d.\n",
++                  sock, sk, msg, (int)size);
++      if(flags & ~MSG_PEEK) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "flags (%d) other than MSG_PEEK not supported.\n",
++                          flags);
++              return -EOPNOTSUPP;
++      }
++              
++      msg->msg_namelen = 0; /* sizeof(*ska); */
++              
++      if(sk->sk_err) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sendmsg: "
++                          "sk->sk_err=%d.\n", sk->sk_err);
++              return sock_error(sk);
++      }
++
++      if((skb = skb_recv_datagram(sk, flags, noblock, &error) ) == NULL) {
++                return error;
++      }
++
++      if(size > skb->len) {
++              size = skb->len;
++      }
++      else if(size <skb->len) {
++              msg->msg_flags |= MSG_TRUNC;
++      }
++
++      skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size);
++#ifdef HAVE_TSTAMP
++      sk->sk_stamp.tv_sec  = skb->tstamp.off_sec;
++      sk->sk_stamp.tv_usec = skb->tstamp.off_usec;
++#else
++        sk->sk_stamp=skb->stamp;
++#endif
++
++      skb_free_datagram(sk, skb);
++      return size;
++}
++
++#ifdef CONFIG_PROC_FS
++#ifndef PROC_FS_2325
++DEBUG_NO_STATIC
++#endif /* PROC_FS_2325 */
++int
++pfkey_get_info(char *buffer, char **start, off_t offset, int length
++#ifndef  PROC_NO_DUMMY
++, int dummy
++#endif /* !PROC_NO_DUMMY */
++)
++{
++      const int max_content = length > 0? length-1 : 0;       /* limit of useful snprintf output */
++#ifdef NET_26
++      struct hlist_node *node;
++#endif
++      off_t begin=0;
++      int len=0;
++      struct sock *sk;
++      
++#ifdef CONFIG_KLIPS_DEBUG
++      if(!sysctl_ipsec_debug_verbose) {
++#endif /* CONFIG_KLIPS_DEBUG */
++      len += ipsec_snprintf(buffer, length,
++                    "    sock   pid   socket     next     prev e n p sndbf    Flags     Type St\n");
++#ifdef CONFIG_KLIPS_DEBUG
++      } else {
++      len += ipsec_snprintf(buffer, length,
++                    "    sock   pid d    sleep   socket     next     prev e r z n p sndbf    stamp    Flags     Type St\n");
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      sk_for_each(sk, node, &pfkey_sock_list) {
++
++#ifdef CONFIG_KLIPS_DEBUG
++              if(!sysctl_ipsec_debug_verbose) {
++#endif /* CONFIG_KLIPS_DEBUG */
++                len += ipsec_snprintf(buffer+len, length-len,
++                                      "%8p %5d %8p %d %d %5d %08lX %8X %2X\n",
++                                      sk,
++                                      key_pid(sk),
++                                      sk->sk_socket,
++                                      sk->sk_err,
++                                      sk->sk_protocol,
++                                      sk->sk_sndbuf,
++                                      sk->sk_socket->flags,
++                                      sk->sk_socket->type,
++                                      sk->sk_socket->state);
++#ifdef CONFIG_KLIPS_DEBUG
++              } else {
++                len += ipsec_snprintf(buffer+len, length-len,
++                                      "%8p %5d %d %8p %8p %d %d %d %d %5d %d.%06d %08lX %8X %2X\n",
++                                      sk,
++                                      key_pid(sk),
++                                      sock_flag(sk, SOCK_DEAD),
++                                      sk->sk_sleep,
++                                      sk->sk_socket,
++                                      sk->sk_err,
++                                      sk->sk_reuse,
++#ifdef HAVE_SOCK_ZAPPED
++                                      sock_flag(sk, SOCK_ZAPPED),
++#else
++                                      sk->sk_zapped,
++#endif                                        
++                                      sk->sk_protocol,
++                                      sk->sk_sndbuf,
++                                      (unsigned int)sk->sk_stamp.tv_sec,
++                                      (unsigned int)sk->sk_stamp.tv_usec,
++                                      sk->sk_socket->flags,
++                                      sk->sk_socket->type,
++                                      sk->sk_socket->state);
++              }
++#endif /* CONFIG_KLIPS_DEBUG */
++              
++              if (len >= max_content) {
++                      /* we've done all that can fit -- stop loop */
++                      len = max_content;      /* truncate crap */
++                      break;
++              } else {
++                      const off_t pos = begin + len;  /* file position of end of what we've generated */
++
++                      if (pos <= offset) {
++                              /* all is before first interesting character:
++                               * discard, but note where we are.
++                               */
++                              len = 0;
++                              begin = pos;
++                      }
++              }
++      }
++
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      return len - (offset - begin);
++}
++
++#ifndef PROC_FS_2325
++DEBUG_NO_STATIC
++#endif /* PROC_FS_2325 */
++int
++pfkey_supported_get_info(char *buffer, char **start, off_t offset, int length
++#ifndef  PROC_NO_DUMMY
++, int dummy
++#endif /* !PROC_NO_DUMMY */
++)
++{
++      /* limit of useful snprintf output */
++      const int max_content = length > 0? length-1 : 0;       
++      off_t begin=0;
++      int len=0;
++      int satype;
++      struct supported_list *ps;
++      
++      len += ipsec_snprintf(buffer, length,
++                    "satype exttype alg_id ivlen minbits maxbits name\n");
++      
++      for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) {
++              ps = pfkey_supported_list[satype];
++              while(ps) {
++                      struct ipsec_alg_supported *alg = ps->supportedp;
++                      unsigned char *n = alg->ias_name;
++                      if(n == NULL) n = "unknown";
++
++                      len += ipsec_snprintf(buffer+len, length-len,
++                                            "    %2d      %2d     %2d   %3d     %3d     %3d %20s\n",
++                                            satype,
++                                            alg->ias_exttype,
++                                            alg->ias_id,
++                                            alg->ias_ivlen,
++                                            alg->ias_keyminbits,
++                                            alg->ias_keymaxbits,
++                                            n);
++                      
++                      if (len >= max_content) {
++                              /* we've done all that can fit -- stop loop */
++                              len = max_content;      /* truncate crap */
++                              break;
++                      } else {
++                              const off_t pos = begin + len;  /* file position of end of what we've generated */
++
++                              if (pos <= offset) {
++                                      /* all is before first interesting character:
++                                       * discard, but note where we are.
++                                       */
++                                      len = 0;
++                                      begin = pos;
++                              }
++                      }
++
++                      ps = ps->next;
++              }
++      }
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      return len - (offset - begin);
++}
++
++#ifndef PROC_FS_2325
++DEBUG_NO_STATIC
++#endif /* PROC_FS_2325 */
++int
++pfkey_registered_get_info(char *buffer, char **start, off_t offset, int length
++#ifndef  PROC_NO_DUMMY
++, int dummy
++#endif /* !PROC_NO_DUMMY */
++)
++{
++      const int max_content = length > 0? length-1 : 0;       /* limit of useful snprintf output */
++      off_t begin=0;
++      int len=0;
++      int satype;
++      struct socket_list *pfkey_sockets;
++      
++      len += ipsec_snprintf(buffer, length,
++                    "satype   socket   pid       sk\n");
++      
++      for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) {
++              pfkey_sockets = pfkey_registered_sockets[satype];
++              while(pfkey_sockets) {
++                      len += ipsec_snprintf(buffer+len, length-len,
++                                   "    %2d %8p %5d %8p\n",
++                                   satype,
++                                   pfkey_sockets->socketp,
++                                   key_pid(pfkey_sockets->socketp->sk),
++                                   pfkey_sockets->socketp->sk);
++                      
++                      if (len >= max_content) {
++                              /* we've done all that can fit -- stop loop (could stop two) */
++                              len = max_content;      /* truncate crap */
++                              break;
++                      } else {
++                              const off_t pos = begin + len;  /* file position of end of what we've generated */
++
++                              if (pos <= offset) {
++                                      /* all is before first interesting character:
++                                       * discard, but note where we are.
++                                       */
++                                      len = 0;
++                                      begin = pos;
++                              }
++                      }
++
++                      pfkey_sockets = pfkey_sockets->next;
++              }
++      }
++      *start = buffer + (offset - begin);     /* Start of wanted data */
++      return len - (offset - begin);
++}
++
++#ifndef PROC_FS_2325
++struct proc_dir_entry proc_net_pfkey =
++{
++      0,
++      6, "pf_key",
++      S_IFREG | S_IRUGO, 1, 0, 0,
++      0, &proc_net_inode_operations,
++      pfkey_get_info
++};
++struct proc_dir_entry proc_net_pfkey_supported =
++{
++      0,
++      16, "pf_key_supported",
++      S_IFREG | S_IRUGO, 1, 0, 0,
++      0, &proc_net_inode_operations,
++      pfkey_supported_get_info
++};
++struct proc_dir_entry proc_net_pfkey_registered =
++{
++      0,
++      17, "pf_key_registered",
++      S_IFREG | S_IRUGO, 1, 0, 0,
++      0, &proc_net_inode_operations,
++      pfkey_registered_get_info
++};
++#endif /* !PROC_FS_2325 */
++#endif /* CONFIG_PROC_FS */
++
++DEBUG_NO_STATIC int
++supported_add_all(int satype, struct ipsec_alg_supported supported[], int size)
++{
++      int i;
++      int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:init_pfkey: "
++                  "sizeof(supported_init_<satype=%d>)[%d]/sizeof(struct ipsec_alg_supported)[%d]=%d.\n",
++                  satype,
++                  size,
++                  (int)sizeof(struct ipsec_alg_supported),
++                  (int)(size/sizeof(struct ipsec_alg_supported)));
++
++      for(i = 0; i < size / sizeof(struct ipsec_alg_supported); i++) {
++
++              unsigned char *n = supported[i].ias_name;
++              if(n == NULL) n="unknown";
++
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:init_pfkey: "
++                          "i=%d inserting satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n",
++                          i,
++                          satype,
++                          supported[i].ias_exttype,
++                          supported[i].ias_id,
++                          supported[i].ias_ivlen,
++                          supported[i].ias_keyminbits,
++                          supported[i].ias_keymaxbits,
++                          n);                     
++                          
++              error |= pfkey_list_insert_supported(&(supported[i]),
++                                          &(pfkey_supported_list[satype]));
++      }
++      return error;
++}
++
++DEBUG_NO_STATIC int
++supported_remove_all(int satype)
++{
++      int error = 0;
++      struct ipsec_alg_supported*supportedp;
++
++      while(pfkey_supported_list[satype]) {
++              unsigned char *n;
++              supportedp = pfkey_supported_list[satype]->supportedp;
++
++              n = supportedp->ias_name;
++              if(n == NULL) n="unknown";
++
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:init_pfkey: "
++                          "removing satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d name=%s.\n",
++                          satype,
++                          supportedp->ias_exttype,
++                          supportedp->ias_id,
++                          supportedp->ias_ivlen,
++                          supportedp->ias_keyminbits,
++                          supportedp->ias_keymaxbits, n);
++                          
++              error |= pfkey_list_remove_supported(supportedp,
++                                          &(pfkey_supported_list[satype]));
++      }
++      return error;
++}
++
++int
++pfkey_init(void)
++{
++      int error = 0;
++      int i;
++      
++      static struct ipsec_alg_supported supported_init_ah[] = {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128},
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160}
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++      };
++      static struct ipsec_alg_supported supported_init_esp[] = {
++#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5
++              {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_MD5HMAC, 0, 128, 128},
++#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */
++#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1
++              {SADB_EXT_SUPPORTED_AUTH, SADB_AALG_SHA1HMAC, 0, 160, 160},
++#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */
++#ifdef CONFIG_KLIPS_ENC_3DES
++              {SADB_EXT_SUPPORTED_ENCRYPT, SADB_EALG_3DESCBC, 64, 168, 168},
++#endif /* CONFIG_KLIPS_ENC_3DES */
++      };
++      static struct ipsec_alg_supported supported_init_ipip[] = {
++              {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv4, 0, 32, 32}
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++              , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv4, 0, 128, 32}
++              , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv4_in_IPv6, 0, 32, 128}
++              , {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_TALG_IPv6_in_IPv6, 0, 128, 128}
++#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
++      };
++#ifdef CONFIG_KLIPS_IPCOMP
++      static struct ipsec_alg_supported supported_init_ipcomp[] = {
++              {SADB_EXT_SUPPORTED_ENCRYPT, SADB_X_CALG_DEFLATE, 0, 1, 1}
++      };
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#if 0
++        printk(KERN_INFO
++             "klips_info:pfkey_init: "
++             "FreeS/WAN: initialising PF_KEYv2 domain sockets.\n");
++#endif
++
++      for(i = SADB_SATYPE_UNSPEC; i <= SADB_SATYPE_MAX; i++) {
++              pfkey_registered_sockets[i] = NULL;
++              pfkey_supported_list[i] = NULL;
++      }
++
++      error |= supported_add_all(SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah));
++      error |= supported_add_all(SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp));
++#ifdef CONFIG_KLIPS_IPCOMP
++      error |= supported_add_all(SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp));
++#endif /* CONFIG_KLIPS_IPCOMP */
++      error |= supported_add_all(SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip));
++
++        error |= sock_register(&pfkey_family_ops);
++
++#ifdef CONFIG_PROC_FS
++#  ifndef PROC_FS_2325
++#    ifdef PROC_FS_21
++      error |= proc_register(proc_net, &proc_net_pfkey);
++      error |= proc_register(proc_net, &proc_net_pfkey_supported);
++      error |= proc_register(proc_net, &proc_net_pfkey_registered);
++#    else /* PROC_FS_21 */
++      error |= proc_register_dynamic(&proc_net, &proc_net_pfkey);
++      error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_supported);
++      error |= proc_register_dynamic(&proc_net, &proc_net_pfkey_registered);
++#    endif /* PROC_FS_21 */
++#  else /* !PROC_FS_2325 */
++      proc_net_create ("pf_key", 0, pfkey_get_info);
++      proc_net_create ("pf_key_supported", 0, pfkey_supported_get_info);
++      proc_net_create ("pf_key_registered", 0, pfkey_registered_get_info);
++#  endif /* !PROC_FS_2325 */
++#endif /* CONFIG_PROC_FS */
++
++      return error;
++}
++
++int
++pfkey_cleanup(void)
++{
++      int error = 0;
++      
++        printk(KERN_INFO "klips_info:pfkey_cleanup: "
++             "shutting down PF_KEY domain sockets.\n");
++        sock_unregister(PF_KEY);
++
++      error |= supported_remove_all(SADB_SATYPE_AH);
++      error |= supported_remove_all(SADB_SATYPE_ESP);
++#ifdef CONFIG_KLIPS_IPCOMP
++      error |= supported_remove_all(SADB_X_SATYPE_COMP);
++#endif /* CONFIG_KLIPS_IPCOMP */
++      error |= supported_remove_all(SADB_X_SATYPE_IPIP);
++
++#ifdef CONFIG_PROC_FS
++#  ifndef PROC_FS_2325
++      if (proc_net_unregister(proc_net_pfkey.low_ino) != 0)
++              printk("klips_debug:pfkey_cleanup: "
++                     "cannot unregister /proc/net/pf_key\n");
++      if (proc_net_unregister(proc_net_pfkey_supported.low_ino) != 0)
++              printk("klips_debug:pfkey_cleanup: "
++                     "cannot unregister /proc/net/pf_key_supported\n");
++      if (proc_net_unregister(proc_net_pfkey_registered.low_ino) != 0)
++              printk("klips_debug:pfkey_cleanup: "
++                     "cannot unregister /proc/net/pf_key_registered\n");
++#  else /* !PROC_FS_2325 */
++      proc_net_remove ("pf_key");
++      proc_net_remove ("pf_key_supported");
++      proc_net_remove ("pf_key_registered");
++#  endif /* !PROC_FS_2325 */
++#endif /* CONFIG_PROC_FS */
++
++      /* other module unloading cleanup happens here */
++      return error;
++}
++
++#ifdef MODULE
++#if 0
++int
++init_module(void)
++{
++      pfkey_init();
++      return 0;
++}
++
++void
++cleanup_module(void)
++{
++      pfkey_cleanup();
++}
++#endif /* 0 */
++#else /* MODULE */
++struct net_protocol;
++void pfkey_proto_init(struct net_protocol *pro)
++{
++      pfkey_init();
++}
++#endif /* MODULE */
++
++/*
++ * $Log: pfkey_v2.c,v $
++ * Revision 1.97.2.12  2006/11/24 05:43:29  paul
++ * kernels after 2.6.18 do not return a code from unregister_socket()
++ * backport from git 41e54a2684dc809d7952e816860ea646a3194a72
++ *
++ * Revision 1.97.2.11  2006/11/15 16:05:57  paul
++ * fix for compiling on 2.4. kernels by Matthias Haas.
++ *
++ * Revision 1.97.2.10  2006/10/10 20:43:28  paul
++ * Add family/create/owner for pfkey_family_ops. This fixes bug #671
++ *
++ * Revision 1.97.2.9  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.97.2.8  2006/07/10 15:56:11  paul
++ * Fix for bug #642 by Bart.
++ *
++ * Revision 1.97.2.7  2006/04/04 11:34:19  ken
++ * Backport SMP fixes + #ifdef cleanup from #public
++ *
++ * Revision 1.97.2.6  2006/02/15 05:00:20  paul
++ * Fix for crasher on 2.6.12+ with klips (mostly seen on redhat kernels)
++ *
++ * Revision 1.97.2.5  2005/11/22 04:11:52  ken
++ * Backport fixes for 2.6.14 kernels from HEAD
++ *
++ * Revision 1.97.2.4  2005/09/14 16:40:45  mcr
++ *    pull up of compilation on 2.4
++ *
++ * Revision 1.97.2.3  2005/09/06 02:10:03  mcr
++ *    pulled up possible SMP-related compilation fix
++ *
++ * Revision 1.97.2.2  2005/08/28 01:21:12  paul
++ * Undid Ken's gcc4 fix in version 1.94 since it breaks linking KLIPS on
++ * SMP kernels.
++ *
++ * Revision 1.97.2.1  2005/08/27 23:40:00  paul
++ * recommited HAVE_SOCK_SECURITY fixes for linux 2.6.13
++ *
++ * Revision 1.102  2005/09/14 16:37:23  mcr
++ *    fix to compile on 2.4.
++ *
++ * Revision 1.101  2005/09/06 01:42:25  mcr
++ *    removed additional SOCKOPS_WRAPPED code
++ *
++ * Revision 1.100  2005/08/30 18:10:15  mcr
++ *    remove SOCKOPS_WRAPPED() code, add proper locking to the
++ *    pfkey code. (cross fingers)
++ *
++ * Revision 1.99  2005/08/28 01:53:37  paul
++ * Undid Ken's gcc4 fix in version 1.94 since it breaks linking KLIPS on SMP kernels.
++ *
++ * Revision 1.98  2005/08/27 23:07:21  paul
++ * Somewhere between 2.6.12 and 2.6.13rc7 the unused security memnber in sk_buff
++ * has been removed. This patch should fix compilation for both cases.
++ *
++ * Revision 1.97  2005/07/20 00:33:36  mcr
++ *    fixed typo in #ifdef for SKALLOC.
++ *
++ * Revision 1.96  2005/07/19 20:02:15  mcr
++ *    sk_alloc() interface change.
++ *
++ * Revision 1.95  2005/07/09 00:40:06  ken
++ * Fix for GCC4 - it doesn't like the potential for duplicate declaration
++ *
++ * Revision 1.94  2005/07/09 00:14:04  ken
++ * Casts for 64bit cleanliness
++ *
++ * Revision 1.93  2005/07/08 16:20:05  mcr
++ *    fix for 2.6.12 disapperance of sk_zapped field -> sock_flags.
++ *
++ * Revision 1.92  2005/05/21 03:29:39  mcr
++ *    fixed missing prototype definition.
++ *
++ * Revision 1.91  2005/05/11 01:43:45  mcr
++ *    removed "poor-man"s OOP in favour of proper C structures.
++ *
++ * Revision 1.90  2005/05/02 18:42:47  mcr
++ *    fix for cut&paste error with pfkey_v2.c "supported_name"
++ *
++ * Revision 1.89  2005/05/01 03:12:31  mcr
++ *    print name if it is available.
++ *
++ * Revision 1.88  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.87  2005/04/15 19:57:10  mcr
++ *    make sure that address has 0p so that it will
++ *    sanitized.
++ *
++ * Revision 1.86  2005/04/08 18:28:36  mcr
++ *    some minor #ifdef simplification in pursuit of a possible bug.
++ *
++ * Revision 1.85  2004/12/03 21:25:57  mcr
++ *    compile time fixes for running on 2.6.
++ *    still experimental.
++ *
++ * Revision 1.84  2004/08/17 03:27:23  mcr
++ *    klips 2.6 edits.
++ *
++ * Revision 1.83  2004/08/04 15:57:07  mcr
++ *    moved des .h files to include/des/ *
++ *    included 2.6 protocol specific things
++ *    started at NAT-T support, but it will require a kernel patch.
++ *
++ * Revision 1.82  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.81  2004/04/25 21:23:11  ken
++ * Pull in dhr's changes from FreeS/WAN 2.06
++ *
++ * Revision 1.80  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.79.4.1  2003/12/22 15:25:52  jjo
++ * . Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.79  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.78.4.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.78  2003/04/03 17:38:09  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ *
++ * Revision 1.77  2002/10/17 16:49:36  mcr
++ *    sock->ops should reference the unwrapped options so that
++ *    we get hacked in locking on SMP systems.
++ *
++ * Revision 1.76  2002/10/12 23:11:53  dhr
++ *
++ * [KenB + DHR] more 64-bit cleanup
++ *
++ * Revision 1.75  2002/09/20 05:01:57  rgb
++ * Added memory allocation debugging.
++ *
++ * Revision 1.74  2002/09/19 02:42:50  mcr
++ *    do not define the pfkey_ops function for now.
++ *
++ * Revision 1.73  2002/09/17 17:29:23  mcr
++ *    #if 0 out some dead code - pfkey_ops is never used as written.
++ *
++ * Revision 1.72  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.71  2002/05/23 07:14:11  rgb
++ * Cleaned up %p variants to 0p%p for test suite cleanup.
++ *
++ * Revision 1.70  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.69  2002/04/24 07:36:33  mcr
++ * Moved from ./klips/net/ipsec/pfkey_v2.c,v
++ *
++ * Revision 1.68  2002/03/08 01:15:17  mcr
++ *    put some internal structure only debug messages behind
++ *    && sysctl_ipsec_debug_verbose.
++ *
++ * Revision 1.67  2002/01/29 17:17:57  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.66  2002/01/29 04:00:54  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.65  2002/01/29 02:13:18  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.64  2001/11/26 09:23:51  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.61.2.1  2001/09/25 02:28:44  mcr
++ *    cleaned up includes.
++ *
++ * Revision 1.63  2001/11/12 19:38:00  rgb
++ * Continue trying other sockets even if one fails and return only original
++ * error.
++ *
++ * Revision 1.62  2001/10/18 04:45:22  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.61  2001/09/20 15:32:59  rgb
++ * Min/max cleanup.
++ *
++ * Revision 1.60  2001/06/14 19:35:12  rgb
++ * Update copyright date.
++ *
++ * Revision 1.59  2001/06/13 15:35:48  rgb
++ * Fixed #endif comments.
++ *
++ * Revision 1.58  2001/05/04 16:37:24  rgb
++ * Remove erroneous checking of return codes for proc_net_* in 2.4.
++ *
++ * Revision 1.57  2001/05/03 19:43:36  rgb
++ * Initialise error return variable.
++ * Check error return codes in startup and shutdown.
++ * Standardise on SENDERR() macro.
++ *
++ * Revision 1.56  2001/04/21 23:05:07  rgb
++ * Define out skb->used for 2.4 kernels.
++ *
++ * Revision 1.55  2001/02/28 05:03:28  rgb
++ * Clean up and rationalise startup messages.
++ *
++ * Revision 1.54  2001/02/27 22:24:55  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.53  2001/02/27 06:48:18  rgb
++ * Fixed pfkey socket unregister log message to reflect type and function.
++ *
++ * Revision 1.52  2001/02/26 22:34:38  rgb
++ * Fix error return code that was getting overwritten by the error return
++ * code of an upmsg.
++ *
++ * Revision 1.51  2001/01/30 23:42:47  rgb
++ * Allow pfkey msgs from pid other than user context required for ACQUIRE
++ * and subsequent ADD or UDATE.
++ *
++ * Revision 1.50  2001/01/23 20:22:59  rgb
++ * 2.4 fix to remove removed is_clone member.
++ *
++ * Revision 1.49  2000/11/06 04:33:47  rgb
++ * Changed non-exported functions to DEBUG_NO_STATIC.
++ *
++ * Revision 1.48  2000/09/29 19:47:41  rgb
++ * Update copyright.
++ *
++ * Revision 1.47  2000/09/22 04:23:04  rgb
++ * Added more debugging to pfkey_upmsg() call from pfkey_sendmsg() error.
++ *
++ * Revision 1.46  2000/09/21 04:20:44  rgb
++ * Fixed array size off-by-one error.  (Thanks Svenning!)
++ *
++ * Revision 1.45  2000/09/20 04:01:26  rgb
++ * Changed static functions to DEBUG_NO_STATIC for revealing function names
++ * in oopsen.
++ *
++ * Revision 1.44  2000/09/19 00:33:17  rgb
++ * 2.0 fixes.
++ *
++ * Revision 1.43  2000/09/16 01:28:13  rgb
++ * Fixed use of 0 in p format warning.
++ *
++ * Revision 1.42  2000/09/16 01:09:41  rgb
++ * Fixed debug format warning for pointers that was expecting ints.
++ *
++ * Revision 1.41  2000/09/13 15:54:00  rgb
++ * Rewrote pfkey_get_info(), added pfkey_{supported,registered}_get_info().
++ * Moved supported algos add and remove to functions.
++ *
++ * Revision 1.40  2000/09/12 18:49:28  rgb
++ * Added IPIP tunnel and IPCOMP register support.
++ *
++ * Revision 1.39  2000/09/12 03:23:49  rgb
++ * Converted #if0 debugs to sysctl.
++ * Removed debug_pfkey initialisations that prevented no_debug loading or
++ * linking.
++ *
++ * Revision 1.38  2000/09/09 06:38:02  rgb
++ * Return positive errno in pfkey_reply error message.
++ *
++ * Revision 1.37  2000/09/08 19:19:09  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ * Clean-up of long-unused crud...
++ * Create pfkey error message on on failure.
++ * Give pfkey_list_{insert,remove}_{socket,supported}() some error
++ * checking.
++ *
++ * Revision 1.36  2000/09/01 18:49:38  rgb
++ * Reap experimental NET_21_ bits.
++ * Turned registered sockets list into an array of one list per satype.
++ * Remove references to deprecated sklist_{insert,remove}_socket.
++ * Removed leaking socket debugging code.
++ * Removed duplicate pfkey_insert_socket in pfkey_create.
++ * Removed all references to pfkey msg->msg_name, since it is not used for
++ * pfkey.
++ * Added a supported algorithms array lists, one per satype and registered
++ * existing algorithms.
++ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to
++ * list.
++ * Only send pfkey_expire() messages to sockets registered for that satype.
++ *
++ * Revision 1.35  2000/08/24 17:03:00  rgb
++ * Corrected message size error return code for PF_KEYv2.
++ * Removed downward error prohibition.
++ *
++ * Revision 1.34  2000/08/21 16:32:26  rgb
++ * Re-formatted for cosmetic consistency and readability.
++ *
++ * Revision 1.33  2000/08/20 21:38:24  rgb
++ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil)
++ * Extended the upward message initiation of pfkey_sendmsg(). (Momchil)
++ *
++ * Revision 1.32  2000/07/28 14:58:31  rgb
++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
++ *
++ * Revision 1.31  2000/05/16 03:04:00  rgb
++ * Updates for 2.3.99pre8 from MB.
++ *
++ * Revision 1.30  2000/05/10 19:22:21  rgb
++ * Use sklist private functions for 2.3.xx compatibility.
++ *
++ * Revision 1.29  2000/03/22 16:17:03  rgb
++ * Fixed SOCKOPS_WRAPPED macro for SMP (MB).
++ *
++ * Revision 1.28  2000/02/21 19:30:45  rgb
++ * Removed references to pkt_bridged for 2.3.47 compatibility.
++ *
++ * Revision 1.27  2000/02/14 21:07:00  rgb
++ * Fixed /proc/net/pf-key legend spacing.
++ *
++ * Revision 1.26  2000/01/22 03:46:59  rgb
++ * Fixed pfkey error return mechanism so that we are able to free the
++ * local copy of the pfkey_msg, plugging a memory leak and silencing
++ * the bad object free complaints.
++ *
++ * Revision 1.25  2000/01/21 06:19:44  rgb
++ * Moved pfkey_list_remove_socket() calls to before MOD_USE_DEC_COUNT.
++ * Added debugging to pfkey_upmsg.
++ *
++ * Revision 1.24  2000/01/10 16:38:23  rgb
++ * MB fixups for 2.3.x.
++ *
++ * Revision 1.23  1999/12/09 23:22:16  rgb
++ * Added more instrumentation for debugging 2.0 socket
++ * selection/reading.
++ * Removed erroneous 2.0 wait==NULL check bug in select.
++ *
++ * Revision 1.22  1999/12/08 20:32:16  rgb
++ * Tidied up 2.0.xx support, after major pfkey work, eliminating
++ * msg->msg_name twiddling in the process, since it is not defined
++ * for PF_KEYv2.
++ *
++ * Revision 1.21  1999/12/01 22:17:19  rgb
++ * Set skb->dev to zero on new skb in case it is a reused skb.
++ * Added check for skb_put overflow and freeing to avoid upmsg on error.
++ * Added check for wrong pfkey version and freeing to avoid upmsg on
++ * error.
++ * Shut off content dumping in pfkey_destroy.
++ * Added debugging message for size of buffer allocated for upmsg.
++ *
++ * Revision 1.20  1999/11/27 12:11:00  rgb
++ * Minor clean-up, enabling quiet operation of pfkey if desired.
++ *
++ * Revision 1.19  1999/11/25 19:04:21  rgb
++ * Update proc_fs code for pfkey to use dynamic registration.
++ *
++ * Revision 1.18  1999/11/25 09:07:17  rgb
++ * Implemented SENDERR macro for propagating error codes.
++ * Fixed error return code bug.
++ *
++ * Revision 1.17  1999/11/23 23:07:20  rgb
++ * Change name of pfkey_msg_parser to pfkey_msg_interp since it no longer
++ * parses. (PJO)
++ * Sort out pfkey and freeswan headers, putting them in a library path.
++ *
++ * Revision 1.16  1999/11/20 22:00:22  rgb
++ * Moved socketlist type declarations and prototypes for shared use.
++ * Renamed reformatted and generically extended for use by other socket
++ * lists pfkey_{del,add}_open_socket to pfkey_list_{remove,insert}_socket.
++ *
++ * Revision 1.15  1999/11/18 04:15:09  rgb
++ * Make pfkey_data_ready temporarily available for 2.2.x testing.
++ * Clean up pfkey_destroy_socket() debugging statements.
++ * Add Peter Onion's code to send messages up to all listening sockets.
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ * Replaced all kernel version macros to shorter, readable form.
++ * Added CONFIG_PROC_FS compiler directives in case it is shut off.
++ *
++ * Revision 1.14  1999/11/17 16:01:00  rgb
++ * Make pfkey_data_ready temporarily available for 2.2.x testing.
++ * Clean up pfkey_destroy_socket() debugging statements.
++ * Add Peter Onion's code to send messages up to all listening sockets.
++ * Changed #include "../../../lib/freeswan.h" to #include <freeswan.h>
++ * which works due to -Ilibfreeswan in the klips/net/ipsec/Makefile.
++ *
++ * Revision 1.13  1999/10/27 19:59:51  rgb
++ * Removed af_unix comments that are no longer relevant.
++ * Added debug prink statements.
++ * Added to the /proc output in pfkey_get_info.
++ * Made most functions non-static to enable oops tracing.
++ * Re-enable skb dequeueing and freeing.
++ * Fix skb_alloc() and skb_put() size bug in pfkey_upmsg().
++ *
++ * Revision 1.12  1999/10/26 17:05:42  rgb
++ * Complete re-ordering based on proto_ops structure order.
++ * Separated out proto_ops structures for 2.0.x and 2.2.x for clarity.
++ * Simplification to use built-in socket ops where possible for 2.2.x.
++ * Add shorter macros for compiler directives to visually clean-up.
++ * Add lots of sk skb dequeueing debugging statements.
++ * Added to the /proc output in pfkey_get_info.
++ *
++ * Revision 1.11  1999/09/30 02:55:10  rgb
++ * Bogus skb detection.
++ * Fix incorrect /proc/net/ipsec-eroute printk message.
++ *
++ * Revision 1.10  1999/09/21 15:22:13  rgb
++ * Temporary fix while I figure out the right way to destroy sockets.
++ *
++ * Revision 1.9  1999/07/08 19:19:44  rgb
++ * Fix pointer format warning.
++ * Fix missing member error under 2.0.xx kernels.
++ *
++ * Revision 1.8  1999/06/13 07:24:04  rgb
++ * Add more debugging.
++ *
++ * Revision 1.7  1999/06/10 05:24:17  rgb
++ * Clarified compiler directives.
++ * Renamed variables to reduce confusion.
++ * Used sklist_*_socket() kernel functions to simplify 2.2.x socket support.
++ * Added lots of sanity checking.
++ *
++ * Revision 1.6  1999/06/03 18:59:50  rgb
++ * More updates to 2.2.x socket support.  Almost works, oops at end of call.
++ *
++ * Revision 1.5  1999/05/25 22:44:05  rgb
++ * Start fixing 2.2 sockets.
++ *
++ * Revision 1.4  1999/04/29 15:21:34  rgb
++ * Move log to the end of the file.
++ * Eliminate min/max redefinition in #include <net/tcp.h>.
++ * Correct path for pfkey #includes
++ * Standardise an error return method.
++ * Add debugging instrumentation.
++ * Move message type checking to pfkey_msg_parse().
++ * Add check for errno incorrectly set.
++ * Add check for valid PID.
++ * Add check for reserved illegally set.
++ * Add check for message out of bounds.
++ *
++ * Revision 1.3  1999/04/15 17:58:07  rgb
++ * Add RCSID labels.
++ *
++ * Revision 1.2  1999/04/15 15:37:26  rgb
++ * Forward check changes from POST1_00 branch.
++ *
++ * Revision 1.1.2.2  1999/04/13 20:37:12  rgb
++ * Header Title correction.
++ *
++ * Revision 1.1.2.1  1999/03/26 20:58:55  rgb
++ * Add pfkeyv2 support to KLIPS.
++ *
++ *
++ * RFC 2367
++ * PF_KEY_v2 Key Management API
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/pfkey_v2_build.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1581 @@
++/*
++ * RFC2367 PF_KEYv2 Key management API message parser
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey_v2_build.c,v 1.51.8.1 2006/05/01 14:36:39 mcr Exp $
++ */
++
++/*
++ *            Template from klips/net/ipsec/ipsec/ipsec_parser.c.
++ */
++
++char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.51.8.1 2006/05/01 14:36:39 mcr Exp $";
++
++/*
++ * Some ugly stuff to allow consistent debugging code for use in the
++ * kernel and in user space
++*/
++
++#ifdef __KERNEL__
++
++# include <linux/kernel.h>  /* for printk */
++
++# include "openswan/ipsec_kversion.h" /* for malloc switch */
++# ifdef MALLOC_SLAB
++#  include <linux/slab.h> /* kmalloc() */
++# else /* MALLOC_SLAB */
++#  include <linux/malloc.h> /* kmalloc() */
++# endif /* MALLOC_SLAB */
++# include <linux/errno.h>  /* error codes */
++# include <linux/types.h>  /* size_t */
++# include <linux/interrupt.h> /* mark_bh */
++
++# include <linux/netdevice.h>   /* struct device, and other headers */
++# include <linux/etherdevice.h> /* eth_type_trans */
++# include <linux/ip.h>          /* struct iphdr */ 
++# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#  include <linux/ipv6.h>        /* struct ipv6hdr */
++# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
++
++# define MALLOC(size) kmalloc(size, GFP_ATOMIC)
++# define FREE(obj) kfree(obj)
++# include <openswan.h>
++#else /* __KERNEL__ */
++
++# include <sys/types.h>
++# include <linux/types.h>
++# include <linux/errno.h>
++# include <malloc.h>
++# include <string.h> /* memset */
++
++# include <openswan.h>
++
++#endif /* __KERNEL__ */
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#ifdef __KERNEL__
++#include "openswan/radij.h"  /* rd_nodes */
++#include "openswan/ipsec_encap.h"  /* sockaddr_encap */
++#endif /* __KERNEL__ */
++
++
++#include "openswan/ipsec_sa.h"  /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */
++#include "openswan/pfkey_debug.h"
++
++
++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
++
++void
++pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
++{
++      int i;
++      
++      for (i = 0; i != SADB_EXT_MAX + 1; i++) {
++              extensions[i] = NULL;
++      }
++}
++
++void
++pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1])
++{
++      int i;
++      
++      if(!extensions) {
++              return;
++      }
++
++      if(extensions[0]) {
++              memset(extensions[0], 0, sizeof(struct sadb_msg));
++              FREE(extensions[0]);
++              extensions[0] = NULL;
++      }
++      
++      for (i = 1; i != SADB_EXT_MAX + 1; i++) {
++              if(extensions[i]) {
++                      memset(extensions[i], 0, extensions[i]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
++                      FREE(extensions[i]);
++                      extensions[i] = NULL;
++              }
++      }
++}
++
++void
++pfkey_msg_free(struct sadb_msg **pfkey_msg)
++{
++      if(*pfkey_msg) {
++              memset(*pfkey_msg, 0, (*pfkey_msg)->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
++              FREE(*pfkey_msg);
++              *pfkey_msg = NULL;
++      }
++}
++
++/* Default extension builders taken from the KLIPS code */
++
++int
++pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext,
++                  uint8_t             msg_type,
++                  uint8_t             satype,
++                  uint8_t             msg_errno,
++                  uint32_t            seq,
++                  uint32_t            pid)
++{
++      int error = 0;
++      struct sadb_msg *pfkey_msg = (struct sadb_msg *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_msg_hdr_build:\n");
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_msg_hdr_build: "
++              "on_entry &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n",
++              &pfkey_ext,
++              pfkey_ext,
++              *pfkey_ext);
++      /* sanity checks... */
++      if(pfkey_msg) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_msg_hdr_build: "
++                      "why is pfkey_msg already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      if(!msg_type) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_msg_hdr_build: "
++                      "msg type not set, must be non-zero..\n");
++              SENDERR(EINVAL);
++      }
++
++      if(msg_type > SADB_MAX) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_msg_hdr_build: "
++                      "msg type too large:%d.\n",
++                      msg_type);
++              SENDERR(EINVAL);
++      }
++
++      if(satype > SADB_SATYPE_MAX) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_msg_hdr_build: "
++                      "satype %d > max %d\n", 
++                      satype, SADB_SATYPE_MAX);
++              SENDERR(EINVAL);
++      }
++
++      pfkey_msg = (struct sadb_msg*)MALLOC(sizeof(struct sadb_msg));
++      *pfkey_ext = (struct sadb_ext*)pfkey_msg;
++      
++      if(pfkey_msg == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_msg_hdr_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_msg, 0, sizeof(struct sadb_msg));
++
++      pfkey_msg->sadb_msg_len = sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
++
++      pfkey_msg->sadb_msg_type = msg_type;
++      pfkey_msg->sadb_msg_satype = satype;
++
++      pfkey_msg->sadb_msg_version = PF_KEY_V2;
++      pfkey_msg->sadb_msg_errno = msg_errno;
++      pfkey_msg->sadb_msg_reserved = 0;
++      pfkey_msg->sadb_msg_seq = seq;
++      pfkey_msg->sadb_msg_pid = pid;
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_msg_hdr_build: "
++              "on_exit &pfkey_ext=0p%p pfkey_ext=0p%p *pfkey_ext=0p%p.\n",
++              &pfkey_ext,
++              pfkey_ext,
++              *pfkey_ext);
++errlab:
++      return error;
++}     
++
++int
++pfkey_sa_ref_build(struct sadb_ext **         pfkey_ext,
++                 uint16_t                     exttype,
++                 uint32_t                     spi,
++                 uint8_t                      replay_window,
++                 uint8_t                      sa_state,
++                 uint8_t                      auth,
++                 uint8_t                      encrypt,
++                 uint32_t                     flags,
++                 uint32_t/*IPsecSAref_t*/     ref)
++{
++      int error = 0;
++      struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++                  "pfkey_sa_build: "
++                  "spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n",
++                  ntohl(spi), /* in network order */
++                  replay_window,
++                  sa_state,
++                  auth,
++                  encrypt,
++                  flags);
++      /* sanity checks... */
++      if(pfkey_sa) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "why is pfkey_sa already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      if(exttype != SADB_EXT_SA &&
++         exttype != SADB_X_EXT_SA2) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "invalid exttype=%d.\n",
++                      exttype);
++              SENDERR(EINVAL);
++      }
++
++      if(replay_window > 64) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "replay window size: %d -- must be 0 <= size <= 64\n",
++                      replay_window);
++              SENDERR(EINVAL);
++      }
++
++      if(auth > SADB_AALG_MAX) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "auth=%d > SADB_AALG_MAX=%d.\n",
++                      auth,
++                      SADB_AALG_MAX);
++              SENDERR(EINVAL);
++      }
++
++#if SADB_EALG_MAX < 255       
++      if(encrypt > SADB_EALG_MAX) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "encrypt=%d > SADB_EALG_MAX=%d.\n",
++                      encrypt,
++                      SADB_EALG_MAX);
++              SENDERR(EINVAL);
++      }
++#endif
++
++      if(sa_state > SADB_SASTATE_MAX) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "sa_state=%d exceeds MAX=%d.\n",
++                      sa_state,
++                      SADB_SASTATE_MAX);
++              SENDERR(EINVAL);
++      }
++
++      if(sa_state == SADB_SASTATE_DEAD) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "sa_state=%d is DEAD=%d is not allowed.\n",
++                      sa_state,
++                      SADB_SASTATE_DEAD);
++              SENDERR(EINVAL);
++      }
++      
++      if((IPSEC_SAREF_NULL != ref) && (ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                        "pfkey_sa_build: "
++                        "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n",
++                        ref,
++                        IPSEC_SAREF_NULL,
++                        IPSEC_SA_REF_TABLE_NUM_ENTRIES);
++              SENDERR(EINVAL);
++      }
++      
++      pfkey_sa = (struct sadb_sa*)MALLOC(sizeof(struct sadb_sa));
++      *pfkey_ext = (struct sadb_ext*)pfkey_sa;
++
++      if(pfkey_sa == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_sa_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_sa, 0, sizeof(struct sadb_sa));
++      
++      pfkey_sa->sadb_sa_len = sizeof(*pfkey_sa) / IPSEC_PFKEYv2_ALIGN;
++      pfkey_sa->sadb_sa_exttype = exttype;
++      pfkey_sa->sadb_sa_spi = spi;
++      pfkey_sa->sadb_sa_replay = replay_window;
++      pfkey_sa->sadb_sa_state = sa_state;
++      pfkey_sa->sadb_sa_auth = auth;
++      pfkey_sa->sadb_sa_encrypt = encrypt;
++      pfkey_sa->sadb_sa_flags = flags;
++      pfkey_sa->sadb_x_sa_ref = ref;  
++
++errlab:
++      return error;
++}     
++
++int
++pfkey_sa_build(struct sadb_ext **     pfkey_ext,
++             uint16_t                 exttype,
++             uint32_t                 spi,
++             uint8_t                  replay_window,
++             uint8_t                  sa_state,
++             uint8_t                  auth,
++             uint8_t                  encrypt,
++             uint32_t                 flags)
++{
++      return pfkey_sa_ref_build(pfkey_ext,
++                         exttype,
++                         spi,
++                         replay_window,
++                         sa_state,
++                         auth,
++                         encrypt,
++                         flags,
++                         IPSEC_SAREF_NULL);
++}
++
++int
++pfkey_lifetime_build(struct sadb_ext **       pfkey_ext,
++                   uint16_t           exttype,
++                   uint32_t           allocations,
++                   uint64_t           bytes,
++                   uint64_t           addtime,
++                   uint64_t           usetime,
++                   uint32_t           packets)
++{
++      int error = 0;
++      struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_lifetime_build:\n");
++      /* sanity checks... */
++      if(pfkey_lifetime) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_lifetime_build: "
++                      "why is pfkey_lifetime already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      if(exttype != SADB_EXT_LIFETIME_CURRENT &&
++         exttype != SADB_EXT_LIFETIME_HARD &&
++         exttype != SADB_EXT_LIFETIME_SOFT) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_lifetime_build: "
++                      "invalid exttype=%d.\n",
++                      exttype);
++              SENDERR(EINVAL);
++      }
++
++      pfkey_lifetime = (struct sadb_lifetime*)MALLOC(sizeof(struct sadb_lifetime));
++      *pfkey_ext = (struct sadb_ext*) pfkey_lifetime;
++
++      if(pfkey_lifetime == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_lifetime_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime));
++
++      pfkey_lifetime->sadb_lifetime_len = sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN;
++      pfkey_lifetime->sadb_lifetime_exttype = exttype;
++      pfkey_lifetime->sadb_lifetime_allocations = allocations;
++      pfkey_lifetime->sadb_lifetime_bytes = bytes;
++      pfkey_lifetime->sadb_lifetime_addtime = addtime;
++      pfkey_lifetime->sadb_lifetime_usetime = usetime;
++      pfkey_lifetime->sadb_x_lifetime_packets = packets;
++
++errlab:
++      return error;
++}
++
++int
++pfkey_address_build(struct sadb_ext** pfkey_ext,
++                  uint16_t            exttype,
++                  uint8_t             proto,
++                  uint8_t             prefixlen,
++                  struct sockaddr*    address)
++{
++      int error = 0;
++      int saddr_len = 0;
++      char ipaddr_txt[ADDRTOT_BUF + 6/*extra for port number*/];
++      struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext;
++      
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_address_build: "
++              "exttype=%d proto=%d prefixlen=%d\n",
++              exttype,
++              proto,
++              prefixlen);
++      /* sanity checks... */
++      if(pfkey_address) {
++              ERROR("pfkey_address_build: "
++                    "why is pfkey_address already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      if (!address)  {
++                      ERROR("pfkey_address_build: " "address is NULL\n");
++                      SENDERR(EINVAL);
++      }
++      
++      switch(exttype) {       
++      case SADB_EXT_ADDRESS_SRC:
++      case SADB_EXT_ADDRESS_DST:
++      case SADB_EXT_ADDRESS_PROXY:
++      case SADB_X_EXT_ADDRESS_DST2:
++      case SADB_X_EXT_ADDRESS_SRC_FLOW:
++      case SADB_X_EXT_ADDRESS_DST_FLOW:
++      case SADB_X_EXT_ADDRESS_SRC_MASK:
++      case SADB_X_EXT_ADDRESS_DST_MASK:
++#ifdef NAT_TRAVERSAL
++      case SADB_X_EXT_NAT_T_OA:
++#endif        
++              break;
++      default:
++              ERROR("pfkey_address_build: "
++                      "unrecognised ext_type=%d.\n", 
++                      exttype); 
++              SENDERR(EINVAL); 
++      }
++
++      switch(address->sa_family) {
++      case AF_INET:
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_address_build: "
++                      "found address family AF_INET.\n");
++              saddr_len = sizeof(struct sockaddr_in);
++              sprintf(ipaddr_txt, "%d.%d.%d.%d:%d"
++                      , (((struct sockaddr_in*)address)->sin_addr.s_addr >>  0) & 0xFF
++                      , (((struct sockaddr_in*)address)->sin_addr.s_addr >>  8) & 0xFF
++                      , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 16) & 0xFF
++                      , (((struct sockaddr_in*)address)->sin_addr.s_addr >> 24) & 0xFF
++                      , ntohs(((struct sockaddr_in*)address)->sin_port));
++              break;
++      case AF_INET6:
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_address_build: "
++                      "found address family AF_INET6.\n");
++              saddr_len = sizeof(struct sockaddr_in6);
++              sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x-%x"
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[1])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[2])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[3])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[4])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[5])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[6])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[7])
++                      , ntohs(((struct sockaddr_in6*)address)->sin6_port));
++              break;
++      default:
++              ERROR("pfkey_address_build: "
++                    "address->sa_family=%d not supported.\n",
++                    address->sa_family);
++              SENDERR(EPFNOSUPPORT);
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_address_build: "
++              "found address=%s.\n",
++              ipaddr_txt);
++      if(prefixlen != 0) {
++              ERROR("pfkey_address_build: "
++                      "address prefixes not supported yet.\n");
++              SENDERR(EAFNOSUPPORT); /* not supported yet */
++      }
++
++      /* allocate some memory for the extension */
++      pfkey_address = (struct sadb_address*)
++              MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN));
++      *pfkey_ext = (struct sadb_ext*)pfkey_address;
++
++      if(pfkey_address == NULL ) {
++              ERROR("pfkey_lifetime_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_address,
++             0,
++             ALIGN_N(sizeof(struct sadb_address) + saddr_len,
++                   IPSEC_PFKEYv2_ALIGN));
++             
++      pfkey_address->sadb_address_len = DIVUP(sizeof(struct sadb_address) + saddr_len,
++                                              IPSEC_PFKEYv2_ALIGN);
++      
++      pfkey_address->sadb_address_exttype = exttype;
++      pfkey_address->sadb_address_proto = proto;
++      pfkey_address->sadb_address_prefixlen = prefixlen;
++      pfkey_address->sadb_address_reserved = 0;
++
++      memcpy((char*)pfkey_address + sizeof(struct sadb_address),
++             address,
++             saddr_len);
++
++#if 0
++      for(i = 0; i < sizeof(struct sockaddr_in) - offsetof(struct sockaddr_in, sin_zero); i++) {
++              pfkey_address_s_ska.sin_zero[i] = 0;
++      }
++#endif
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++                "pfkey_address_build: "
++                "successful created len: %d.\n", pfkey_address->sadb_address_len);
++
++ errlab:
++      return error;
++}
++
++int
++pfkey_key_build(struct sadb_ext**     pfkey_ext,
++              uint16_t                exttype,
++              uint16_t                key_bits,
++              char*                   key)
++{
++      int error = 0;
++      struct sadb_key *pfkey_key = (struct sadb_key *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_key_build:\n");
++      /* sanity checks... */
++      if(pfkey_key) {
++              ERROR("pfkey_key_build: "
++                      "why is pfkey_key already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      if(!key_bits) {
++              ERROR("pfkey_key_build: "
++                      "key_bits is zero, it must be non-zero.\n");
++              SENDERR(EINVAL);
++      }
++
++      if( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) {
++              ERROR("pfkey_key_build: "
++                      "unsupported extension type=%d.\n",
++                      exttype);
++              SENDERR(EINVAL);
++      }
++
++      pfkey_key = (struct sadb_key*)
++        MALLOC(sizeof(struct sadb_key) +
++               DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN);
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_key;
++
++      if(pfkey_key == NULL) {
++              ERROR("pfkey_key_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_key,
++             0,
++             sizeof(struct sadb_key) +
++             DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN);
++      
++      pfkey_key->sadb_key_len = DIVUP(sizeof(struct sadb_key) * IPSEC_PFKEYv2_ALIGN + key_bits,
++                                      64);
++      pfkey_key->sadb_key_exttype = exttype;
++      pfkey_key->sadb_key_bits = key_bits;
++      pfkey_key->sadb_key_reserved = 0;
++      memcpy((char*)pfkey_key + sizeof(struct sadb_key),
++             key,
++             DIVUP(key_bits, 8));
++
++errlab:
++      return error;
++}
++
++int
++pfkey_ident_build(struct sadb_ext**   pfkey_ext,
++                uint16_t              exttype,
++                uint16_t              ident_type,
++                uint64_t              ident_id,
++                uint8_t               ident_len,
++                char*                 ident_string)
++{
++      int error = 0;
++      struct sadb_ident *pfkey_ident = (struct sadb_ident *)*pfkey_ext;
++      int data_len = ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_ident_build:\n");
++      /* sanity checks... */
++      if(pfkey_ident) {
++              ERROR("pfkey_ident_build: "
++                      "why is pfkey_ident already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      if( ! ((exttype == SADB_EXT_IDENTITY_SRC) ||
++             (exttype == SADB_EXT_IDENTITY_DST))) {
++              ERROR("pfkey_ident_build: "
++                      "unsupported extension type=%d.\n",
++                      exttype);
++              SENDERR(EINVAL);
++      }
++
++      if((ident_type == SADB_IDENTTYPE_RESERVED)) {
++              ERROR("pfkey_ident_build: "
++                      "ident_type must be non-zero.\n");
++              SENDERR(EINVAL);
++      }
++
++      if(ident_type > SADB_IDENTTYPE_MAX) {
++              ERROR("pfkey_ident_build: "
++                      "identtype=%d out of range.\n",
++                      ident_type);
++              SENDERR(EINVAL);
++      }
++
++      if(((ident_type == SADB_IDENTTYPE_PREFIX) ||
++          (ident_type == SADB_IDENTTYPE_FQDN)) &&
++         !ident_string) {
++              ERROR("pfkey_ident_build: "
++                      "string required to allocate size of extension.\n");
++              SENDERR(EINVAL);
++      }
++      
++#if 0
++      if((ident_type == SADB_IDENTTYPE_USERFQDN) ) {
++      }
++#endif
++          
++      pfkey_ident = (struct sadb_ident*)
++        MALLOC(ident_len * IPSEC_PFKEYv2_ALIGN);
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_ident;
++
++      if(pfkey_ident == NULL) {
++              ERROR("pfkey_ident_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_ident, 0, ident_len * IPSEC_PFKEYv2_ALIGN);
++      
++      pfkey_ident->sadb_ident_len = ident_len;
++      pfkey_ident->sadb_ident_exttype = exttype;
++      pfkey_ident->sadb_ident_type = ident_type;
++      pfkey_ident->sadb_ident_reserved = 0;
++      pfkey_ident->sadb_ident_id = ident_id;
++      memcpy((char*)pfkey_ident + sizeof(struct sadb_ident),
++             ident_string,
++             data_len);
++
++errlab:
++      return error;
++}
++
++int
++pfkey_sens_build(struct sadb_ext**    pfkey_ext,
++               uint32_t               dpd,
++               uint8_t                sens_level,
++               uint8_t                sens_len,
++               uint64_t*              sens_bitmap,
++               uint8_t                integ_level,
++               uint8_t                integ_len,
++               uint64_t*              integ_bitmap)
++{
++      int error = 0;
++      struct sadb_sens *pfkey_sens = (struct sadb_sens *)*pfkey_ext;
++      int i;
++      uint64_t* bitmap;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_sens_build:\n");
++      /* sanity checks... */
++      if(pfkey_sens) {
++              ERROR("pfkey_sens_build: "
++                      "why is pfkey_sens already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_sens_build: "
++              "Sorry, I can't build exttype=%d yet.\n",
++              (*pfkey_ext)->sadb_ext_type);
++      SENDERR(EINVAL); /* don't process these yet */
++
++      pfkey_sens = (struct sadb_sens*)
++        MALLOC(sizeof(struct sadb_sens) +
++               (sens_len + integ_len) * sizeof(uint64_t));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_sens;
++
++      if(pfkey_sens == NULL) {
++              ERROR("pfkey_sens_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_sens,
++             0,
++             sizeof(struct sadb_sens) +
++             (sens_len + integ_len) * sizeof(uint64_t));
++      
++      pfkey_sens->sadb_sens_len = (sizeof(struct sadb_sens) +
++                  (sens_len + integ_len) * sizeof(uint64_t)) / IPSEC_PFKEYv2_ALIGN;
++      pfkey_sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY;
++      pfkey_sens->sadb_sens_dpd = dpd;
++      pfkey_sens->sadb_sens_sens_level = sens_level;
++      pfkey_sens->sadb_sens_sens_len = sens_len;
++      pfkey_sens->sadb_sens_integ_level = integ_level;
++      pfkey_sens->sadb_sens_integ_len = integ_len;
++      pfkey_sens->sadb_sens_reserved = 0;
++
++      bitmap = (uint64_t*)((char*)pfkey_ext + sizeof(struct sadb_sens));
++      for(i = 0; i < sens_len; i++) {
++              *bitmap = sens_bitmap[i];
++              bitmap++;
++      }
++      for(i = 0; i < integ_len; i++) {
++              *bitmap = integ_bitmap[i];
++              bitmap++;
++      }
++
++errlab:
++      return error;
++}
++
++int
++pfkey_prop_build(struct sadb_ext**    pfkey_ext,
++               uint8_t                replay,
++               unsigned int           comb_num,
++               struct sadb_comb*      comb)
++{
++      int error = 0;
++      int i;
++      struct sadb_prop *pfkey_prop = (struct sadb_prop *)*pfkey_ext;
++      struct sadb_comb *combp;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_prop_build:\n");
++      /* sanity checks... */
++      if(pfkey_prop) {
++              ERROR("pfkey_prop_build: "
++                      "why is pfkey_prop already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      pfkey_prop = (struct sadb_prop*)
++        MALLOC(sizeof(struct sadb_prop) +
++               comb_num * sizeof(struct sadb_comb));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_prop;
++
++      if(pfkey_prop == NULL) {
++              ERROR("pfkey_prop_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_prop,
++             0,
++             sizeof(struct sadb_prop) +
++                  comb_num * sizeof(struct sadb_comb));
++      
++      pfkey_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
++                  comb_num * sizeof(struct sadb_comb)) / IPSEC_PFKEYv2_ALIGN;
++
++      pfkey_prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
++      pfkey_prop->sadb_prop_replay = replay;
++
++      for(i=0; i<3; i++) {
++              pfkey_prop->sadb_prop_reserved[i] = 0;
++      }
++
++      combp = (struct sadb_comb*)((char*)*pfkey_ext + sizeof(struct sadb_prop));
++      for(i = 0; i < comb_num; i++) {
++              memcpy (combp, &(comb[i]), sizeof(struct sadb_comb));
++              combp++;
++      }
++
++#if 0
++  uint8_t sadb_comb_auth;
++  uint8_t sadb_comb_encrypt;
++  uint16_t sadb_comb_flags;
++  uint16_t sadb_comb_auth_minbits;
++  uint16_t sadb_comb_auth_maxbits;
++  uint16_t sadb_comb_encrypt_minbits;
++  uint16_t sadb_comb_encrypt_maxbits;
++  uint32_t sadb_comb_reserved;
++  uint32_t sadb_comb_soft_allocations;
++  uint32_t sadb_comb_hard_allocations;
++  uint64_t sadb_comb_soft_bytes;
++  uint64_t sadb_comb_hard_bytes;
++  uint64_t sadb_comb_soft_addtime;
++  uint64_t sadb_comb_hard_addtime;
++  uint64_t sadb_comb_soft_usetime;
++  uint64_t sadb_comb_hard_usetime;
++  uint32_t sadb_comb_soft_packets;
++  uint32_t sadb_comb_hard_packets;
++#endif
++errlab:
++      return error;
++}
++
++int
++pfkey_supported_build(struct sadb_ext**       pfkey_ext,
++                    uint16_t          exttype,
++                    unsigned int      alg_num,
++                    struct sadb_alg*  alg)
++{
++      int error = 0;
++      unsigned int i;
++      struct sadb_supported *pfkey_supported = (struct sadb_supported *)*pfkey_ext;
++      struct sadb_alg *pfkey_alg;
++
++      /* sanity checks... */
++      if(pfkey_supported) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_supported_build: "
++                      "why is pfkey_supported already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++
++      if( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_supported_build: "
++                      "unsupported extension type=%d.\n",
++                      exttype);
++              SENDERR(EINVAL);
++      }
++
++      pfkey_supported = (struct sadb_supported*)
++        MALLOC(sizeof(struct sadb_supported) +
++                  alg_num *
++                  sizeof(struct sadb_alg));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_supported;
++
++      if(pfkey_supported == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_supported_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_supported,
++             0,
++             sizeof(struct sadb_supported) +
++                                             alg_num *
++                                             sizeof(struct sadb_alg));
++      
++      pfkey_supported->sadb_supported_len = (sizeof(struct sadb_supported) +
++                                             alg_num *
++                                             sizeof(struct sadb_alg)) /
++                                              IPSEC_PFKEYv2_ALIGN;
++      pfkey_supported->sadb_supported_exttype = exttype;
++      pfkey_supported->sadb_supported_reserved = 0;
++
++      pfkey_alg = (struct sadb_alg*)((char*)pfkey_supported + sizeof(struct sadb_supported));
++      for(i = 0; i < alg_num; i++) {
++              memcpy (pfkey_alg, &(alg[i]), sizeof(struct sadb_alg));
++              pfkey_alg->sadb_alg_reserved = 0;
++              pfkey_alg++;
++      }
++      
++#if 0
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_supported_build: "
++              "Sorry, I can't build exttype=%d yet.\n",
++              (*pfkey_ext)->sadb_ext_type);
++      SENDERR(EINVAL); /* don't process these yet */
++
++  uint8_t sadb_alg_id;
++  uint8_t sadb_alg_ivlen;
++  uint16_t sadb_alg_minbits;
++  uint16_t sadb_alg_maxbits;
++  uint16_t sadb_alg_reserved;
++#endif
++errlab:
++      return error;
++}
++
++int
++pfkey_spirange_build(struct sadb_ext**        pfkey_ext,
++                   uint16_t           exttype,
++                   uint32_t           min, /* in network order */
++                   uint32_t           max) /* in network order */
++{
++      int error = 0;
++      struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)*pfkey_ext;
++      
++      /* sanity checks... */
++      if(pfkey_spirange) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_spirange_build: "
++                      "why is pfkey_spirange already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++      
++        if(ntohl(max) < ntohl(min)) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_spirange_build: "
++                      "minspi=%08x must be < maxspi=%08x.\n",
++                      ntohl(min),
++                      ntohl(max));
++                SENDERR(EINVAL);
++        }
++      
++      if(ntohl(min) <= 255) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_spirange_build: "
++                      "minspi=%08x must be > 255.\n",
++                      ntohl(min));
++              SENDERR(EEXIST);
++      }
++      
++      pfkey_spirange = (struct sadb_spirange*)
++        MALLOC(sizeof(struct sadb_spirange));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_spirange;
++
++      if(pfkey_spirange == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_spirange_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_spirange,
++             0,
++             sizeof(struct sadb_spirange));
++      
++        pfkey_spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN;
++
++      pfkey_spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
++      pfkey_spirange->sadb_spirange_min = min;
++      pfkey_spirange->sadb_spirange_max = max;
++      pfkey_spirange->sadb_spirange_reserved = 0;
++ errlab:
++      return error;
++}
++
++int
++pfkey_x_kmprivate_build(struct sadb_ext**     pfkey_ext)
++{
++      int error = 0;
++      struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)*pfkey_ext;
++
++      /* sanity checks... */
++      if(pfkey_x_kmprivate) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_x_kmprivate_build: "
++                      "why is pfkey_x_kmprivate already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++      
++      pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_kmprivate_build: "
++              "Sorry, I can't build exttype=%d yet.\n",
++              (*pfkey_ext)->sadb_ext_type);
++      SENDERR(EINVAL); /* don't process these yet */
++
++      pfkey_x_kmprivate = (struct sadb_x_kmprivate*)
++        MALLOC(sizeof(struct sadb_x_kmprivate));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_x_kmprivate;
++
++      if(pfkey_x_kmprivate == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_x_kmprivate_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_x_kmprivate,
++             0,
++             sizeof(struct sadb_x_kmprivate));
++      
++        pfkey_x_kmprivate->sadb_x_kmprivate_len =
++              sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN;
++
++        pfkey_x_kmprivate->sadb_x_kmprivate_exttype = SADB_X_EXT_KMPRIVATE;
++        pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
++errlab:
++      return error;
++}
++
++int
++pfkey_x_satype_build(struct sadb_ext**        pfkey_ext,
++                   uint8_t            satype)
++{
++      int error = 0;
++      int i;
++      struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_satype_build:\n");
++      /* sanity checks... */
++      if(pfkey_x_satype) {
++              ERROR("pfkey_x_satype_build: "
++                      "why is pfkey_x_satype already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++      
++      if(!satype) {
++              ERROR("pfkey_x_satype_build: "
++                      "SA type not set, must be non-zero.\n");
++              SENDERR(EINVAL);
++      }
++
++      if(satype > SADB_SATYPE_MAX) {
++              ERROR("pfkey_x_satype_build: "
++                      "satype %d > max %d\n", 
++                      satype, SADB_SATYPE_MAX);
++              SENDERR(EINVAL);
++      }
++
++      pfkey_x_satype = (struct sadb_x_satype*)
++        MALLOC(sizeof(struct sadb_x_satype));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_x_satype;
++      if(pfkey_x_satype == NULL) {
++              ERROR("pfkey_x_satype_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      memset(pfkey_x_satype,
++             0,
++             sizeof(struct sadb_x_satype));
++      
++        pfkey_x_satype->sadb_x_satype_len = sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN;
++
++      pfkey_x_satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2;
++      pfkey_x_satype->sadb_x_satype_satype = satype;
++      for(i=0; i<3; i++) {
++              pfkey_x_satype->sadb_x_satype_reserved[i] = 0;
++      }
++
++errlab:
++      return error;
++}
++
++int
++pfkey_x_debug_build(struct sadb_ext** pfkey_ext,
++                  uint32_t            tunnel,
++                  uint32_t            netlink,
++                  uint32_t            xform,
++                  uint32_t            eroute,
++                  uint32_t            spi,
++                  uint32_t            radij,
++                  uint32_t            esp,
++                  uint32_t            ah,
++                  uint32_t            rcv,
++                  uint32_t            pfkey,
++                  uint32_t            ipcomp,
++                  uint32_t            verbose)
++{
++      int error = 0;
++      int i;
++      struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_debug_build:\n");
++      /* sanity checks... */
++      if(pfkey_x_debug) {
++              ERROR("pfkey_x_debug_build: "
++                      "why is pfkey_x_debug already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++      
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_debug_build: "
++              "tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n",
++              tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose);
++
++      pfkey_x_debug = (struct sadb_x_debug*)
++        MALLOC(sizeof(struct sadb_x_debug));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_x_debug;
++
++      if(pfkey_x_debug == NULL) {
++              ERROR("pfkey_x_debug_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++#if 0
++      memset(pfkey_x_debug,
++             0,
++             sizeof(struct sadb_x_debug));
++#endif
++      
++        pfkey_x_debug->sadb_x_debug_len = sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN;
++      pfkey_x_debug->sadb_x_debug_exttype = SADB_X_EXT_DEBUG;
++
++      pfkey_x_debug->sadb_x_debug_tunnel = tunnel;
++      pfkey_x_debug->sadb_x_debug_netlink = netlink;
++      pfkey_x_debug->sadb_x_debug_xform = xform;
++      pfkey_x_debug->sadb_x_debug_eroute = eroute;
++      pfkey_x_debug->sadb_x_debug_spi = spi;
++      pfkey_x_debug->sadb_x_debug_radij = radij;
++      pfkey_x_debug->sadb_x_debug_esp = esp;
++      pfkey_x_debug->sadb_x_debug_ah = ah;
++      pfkey_x_debug->sadb_x_debug_rcv = rcv;
++      pfkey_x_debug->sadb_x_debug_pfkey = pfkey;
++      pfkey_x_debug->sadb_x_debug_ipcomp = ipcomp;
++      pfkey_x_debug->sadb_x_debug_verbose = verbose;
++
++      for(i=0; i<4; i++) {
++              pfkey_x_debug->sadb_x_debug_reserved[i] = 0;
++      }
++
++errlab:
++      return error;
++}
++
++int
++pfkey_x_nat_t_type_build(struct sadb_ext**    pfkey_ext,
++                       uint8_t         type)
++{
++      int error = 0;
++      int i;
++      struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_nat_t_type_build:\n");
++      /* sanity checks... */
++      if(pfkey_x_nat_t_type) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_x_nat_t_type_build: "
++                      "why is pfkey_x_nat_t_type already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++      
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_nat_t_type_build: "
++              "type=%d\n", type);
++
++      pfkey_x_nat_t_type = (struct sadb_x_nat_t_type*)
++        MALLOC(sizeof(struct sadb_x_nat_t_type));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_type;
++
++      if(pfkey_x_nat_t_type == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_x_nat_t_type_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      
++      pfkey_x_nat_t_type->sadb_x_nat_t_type_len = sizeof(struct sadb_x_nat_t_type) / IPSEC_PFKEYv2_ALIGN;
++      pfkey_x_nat_t_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
++      pfkey_x_nat_t_type->sadb_x_nat_t_type_type = type;
++      for(i=0; i<3; i++) {
++              pfkey_x_nat_t_type->sadb_x_nat_t_type_reserved[i] = 0;
++      }
++
++errlab:
++      return error;
++}
++int
++pfkey_x_nat_t_port_build(struct sadb_ext**    pfkey_ext,
++                  uint16_t         exttype,
++                  uint16_t         port)
++{
++      int error = 0;
++      struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)*pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_nat_t_port_build:\n");
++      /* sanity checks... */
++      if(pfkey_x_nat_t_port) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_x_nat_t_port_build: "
++                      "why is pfkey_x_nat_t_port already pointing to something?\n");
++              SENDERR(EINVAL);
++      }
++      
++      switch(exttype) {       
++      case SADB_X_EXT_NAT_T_SPORT:
++      case SADB_X_EXT_NAT_T_DPORT:
++              break;
++      default:
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_nat_t_port_build: "
++                      "unrecognised ext_type=%d.\n", 
++                      exttype); 
++              SENDERR(EINVAL); 
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_x_nat_t_port_build: "
++              "ext=%d, port=%d\n", exttype, port);
++
++      pfkey_x_nat_t_port = (struct sadb_x_nat_t_port*)
++        MALLOC(sizeof(struct sadb_x_nat_t_port));
++
++      *pfkey_ext = (struct sadb_ext*)pfkey_x_nat_t_port;
++
++      if(pfkey_x_nat_t_port == NULL) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_x_nat_t_port_build: "
++                      "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      
++      pfkey_x_nat_t_port->sadb_x_nat_t_port_len = sizeof(struct sadb_x_nat_t_port) / IPSEC_PFKEYv2_ALIGN;
++      pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype = exttype;
++      pfkey_x_nat_t_port->sadb_x_nat_t_port_port = port;
++      pfkey_x_nat_t_port->sadb_x_nat_t_port_reserved = 0;
++
++errlab:
++      return error;
++}
++
++int pfkey_x_protocol_build(struct sadb_ext **pfkey_ext,
++                         uint8_t protocol)
++{
++      int error = 0;
++      struct sadb_protocol * p = (struct sadb_protocol *)*pfkey_ext;
++      DEBUGGING(PF_KEY_DEBUG_BUILD,"pfkey_x_protocol_build: protocol=%u\n", protocol);
++      /* sanity checks... */
++      if  (p != 0) {
++              ERROR("pfkey_x_protocol_build: bogus protocol pointer\n");
++              SENDERR(EINVAL);
++      }
++      if ((p = (struct sadb_protocol*)MALLOC(sizeof(*p))) == 0) {
++              ERROR("pfkey_build: memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      *pfkey_ext = (struct sadb_ext *)p;
++      p->sadb_protocol_len = sizeof(*p) / sizeof(uint64_t);
++      p->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
++      p->sadb_protocol_proto = protocol;
++      p->sadb_protocol_flags = 0;
++      p->sadb_protocol_reserved2 = 0;
++ errlab:
++      return error;
++}
++
++int
++pfkey_msg_build(struct sadb_msg **pfkey_msg, struct sadb_ext *extensions[], int dir)
++{
++      int error = 0;
++      unsigned ext;
++      unsigned total_size;
++      struct sadb_ext *pfkey_ext;
++      int extensions_seen = 0;
++#ifndef __KERNEL__    
++      struct sadb_ext *extensions_check[SADB_EXT_MAX + 1];
++#endif
++      
++      if(!extensions[0]) {
++              ERROR("pfkey_msg_build: "
++                      "extensions[0] must be specified (struct sadb_msg).\n");
++              SENDERR(EINVAL);
++      }
++
++      /* figure out the total size for all the requested extensions */
++      total_size = IPSEC_PFKEYv2_WORDS(sizeof(struct sadb_msg));
++      for(ext = 1; ext <= SADB_EXT_MAX; ext++) {
++              if(extensions[ext]) {
++                      total_size += (extensions[ext])->sadb_ext_len;
++              }
++        }                
++
++      /* allocate that much space */
++      *pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN);
++      if(*pfkey_msg == NULL) {
++              ERROR("pfkey_msg_build: "
++                    "memory allocation failed\n");
++              SENDERR(ENOMEM);
++      }
++      
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++                "pfkey_msg_build: "
++                "pfkey_msg=0p%p allocated %lu bytes, &(extensions[0])=0p%p\n",
++                *pfkey_msg,
++                (unsigned long)(total_size * IPSEC_PFKEYv2_ALIGN),
++                &(extensions[0]));
++
++      memcpy(*pfkey_msg,
++             extensions[0],
++             sizeof(struct sadb_msg));
++      (*pfkey_msg)->sadb_msg_len = total_size;
++      (*pfkey_msg)->sadb_msg_reserved = 0;
++      extensions_seen =  1 ;
++      
++      /*
++       * point pfkey_ext to immediately after the space for the header,
++       * i.e. at the first extension location.
++       */
++      pfkey_ext = (struct sadb_ext*)(((char*)(*pfkey_msg)) + sizeof(struct sadb_msg));
++
++      for(ext = 1; ext <= SADB_EXT_MAX; ext++) {
++              /* copy from extension[ext] to buffer */
++              if(extensions[ext]) {    
++                      /* Is this type of extension permitted for this type of message? */
++                      if(!(extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type] &
++                           1<<ext)) {
++                              ERROR("pfkey_msg_build: "
++                                      "ext type %d not permitted, exts_perm=%08x, 1<<type=%08x\n", 
++                                      ext, 
++                                      extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
++                                      1<<ext);
++                              SENDERR(EINVAL);
++                      }
++
++                      DEBUGGING(PF_KEY_DEBUG_BUILD,
++                                "pfkey_msg_build: "
++                                "copying %lu bytes from extensions[%u] (type=%d)\n",
++                                (unsigned long)(extensions[ext]->sadb_ext_len * IPSEC_PFKEYv2_ALIGN),
++                                ext,
++                                extensions[ext]->sadb_ext_type);
++
++                      memcpy(pfkey_ext,
++                             extensions[ext],
++                             (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
++                      {
++                        char *pfkey_ext_c = (char *)pfkey_ext;
++
++                        pfkey_ext_c += (extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN;
++                        pfkey_ext = (struct sadb_ext *)pfkey_ext_c;
++                      }
++
++                      /* Mark that we have seen this extension and remember the header location */
++                      extensions_seen |= ( 1 << ext );
++              }
++      }
++
++      /* check required extensions */
++      DEBUGGING(PF_KEY_DEBUG_BUILD,
++              "pfkey_msg_build: "
++              "extensions permitted=%08x, seen=%08x, required=%08x.\n",
++              extensions_bitmaps[dir][EXT_BITS_PERM][(*pfkey_msg)->sadb_msg_type],
++              extensions_seen,
++              extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]);
++      
++      if((extensions_seen &
++          extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) !=
++         extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) {
++              DEBUGGING(PF_KEY_DEBUG_BUILD,
++                      "pfkey_msg_build: "
++                      "required extensions missing:%08x.\n",
++                      extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type] -
++                      (extensions_seen &
++                       extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) );
++              SENDERR(EINVAL);
++      }
++
++#ifndef __KERNEL__    
++/*
++ * this is silly, there is no need to reparse the message that we just built.
++ *
++ */
++      if((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) {
++              ERROR(
++                      "pfkey_msg_build: "
++                      "Trouble parsing newly built pfkey message, error=%d.\n",
++                      error);
++              SENDERR(-error);
++      }
++#endif
++
++errlab:
++
++      return error;
++}
++
++/*
++ * $Log: pfkey_v2_build.c,v $
++ * Revision 1.51.8.1  2006/05/01 14:36:39  mcr
++ * get rid of dead code.
++ *
++ * Revision 1.51  2004/10/03 01:26:36  mcr
++ *    fixes for gcc 3.4 compilation.
++ *
++ * Revision 1.50  2004/07/10 07:48:35  mcr
++ * Moved from linux/lib/libfreeswan/pfkey_v2_build.c,v
++ *
++ * Revision 1.49  2004/04/12 02:59:06  mcr
++ *     erroneously moved pfkey_v2_build.c
++ *
++ * Revision 1.48  2004/04/09 18:00:40  mcr
++ * Moved from linux/lib/libfreeswan/pfkey_v2_build.c,v
++ *
++ * Revision 1.47  2004/03/08 01:59:08  ken
++ * freeswan.h -> openswan.h
++ *
++ * Revision 1.46  2003/12/10 01:20:19  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.45  2003/12/04 23:01:12  mcr
++ *    removed ipsec_netlink.h
++ *
++ * Revision 1.44  2003/10/31 02:27:12  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.43.4.2  2003/10/29 01:11:32  mcr
++ *    added debugging for pfkey library.
++ *
++ * Revision 1.43.4.1  2003/09/21 13:59:44  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.43  2003/05/07 17:29:17  mcr
++ *    new function pfkey_debug_func added for us in debugging from
++ *    pfkey library.
++ *
++ * Revision 1.42  2003/01/30 02:32:09  rgb
++ *
++ * Rename SAref table macro names for clarity.
++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
++ *
++ * Revision 1.41  2002/12/13 18:16:02  mcr
++ *    restored sa_ref code
++ *
++ * Revision 1.40  2002/12/13 18:06:52  mcr
++ *    temporarily removed sadb_x_sa_ref reference for 2.xx
++ *
++ * Revision 1.39  2002/12/13 17:43:28  mcr
++ *    commented out access to sadb_x_sa_ref for 2.xx branch
++ *
++ * Revision 1.38  2002/10/09 03:12:05  dhr
++ *
++ * [kenb+dhr] 64-bit fixes
++ *
++ * Revision 1.37  2002/09/20 15:40:39  rgb
++ * Added new function pfkey_sa_ref_build() to accomodate saref parameter.
++ *
++ * Revision 1.36  2002/09/20 05:01:22  rgb
++ * Generalise for platform independance: fix (ia64) using unsigned for sizes.
++ *
++ * Revision 1.35  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.34  2002/05/23 07:14:11  rgb
++ * Cleaned up %p variants to 0p%p for test suite cleanup.
++ *
++ * Revision 1.33  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.32  2002/04/24 07:36:40  mcr
++ * Moved from ./lib/pfkey_v2_build.c,v
++ *
++ * Revision 1.31  2002/01/29 22:25:35  rgb
++ * Re-add ipsec_kversion.h to keep MALLOC happy.
++ *
++ * Revision 1.30  2002/01/29 01:59:09  mcr
++ *    removal of kversions.h - sources that needed it now use ipsec_param.h.
++ *    updating of IPv6 structures to match latest in6.h version.
++ *    removed dead code from openswan.h that also duplicated kversions.h
++ *    code.
++ *
++ * Revision 1.29  2001/12/19 21:06:09  rgb
++ * Added port numbers to pfkey_address_build() debugging.
++ *
++ * Revision 1.28  2001/11/06 19:47:47  rgb
++ * Added packet parameter to lifetime and comb structures.
++ *
++ * Revision 1.27  2001/10/18 04:45:24  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/openswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.26  2001/09/08 21:13:34  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.25  2001/06/14 19:35:16  rgb
++ * Update copyright date.
++ *
++ * Revision 1.24  2001/03/20 03:49:45  rgb
++ * Ditch superfluous debug_pfkey declaration.
++ * Move misplaced openswan.h inclusion for kernel case.
++ *
++ * Revision 1.23  2001/03/16 07:41:50  rgb
++ * Put openswan.h include before pluto includes.
++ *
++ * Revision 1.22  2001/02/27 22:24:56  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.21  2000/11/17 18:10:30  rgb
++ * Fixed bugs mostly relating to spirange, to treat all spi variables as
++ * network byte order since this is the way PF_KEYv2 stored spis.
++ *
++ * Revision 1.20  2000/10/12 00:02:39  rgb
++ * Removed 'format, ##' nonsense from debug macros for RH7.0.
++ *
++ * Revision 1.19  2000/10/10 20:10:20  rgb
++ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
++ *
++ * Revision 1.18  2000/09/12 18:59:54  rgb
++ * Added Gerhard's IPv6 support to pfkey parts of libopenswan.
++ *
++ * Revision 1.17  2000/09/12 03:27:00  rgb
++ * Moved DEBUGGING definition to compile kernel with debug off.
++ *
++ * Revision 1.16  2000/09/08 19:22:12  rgb
++ * Fixed pfkey_prop_build() parameter to be only single indirection.
++ * Fixed struct alg copy.
++ *
++ * Revision 1.15  2000/08/20 21:40:01  rgb
++ * Added an address parameter sanity check to pfkey_address_build().
++ *
++ * Revision 1.14  2000/08/15 17:29:23  rgb
++ * Fixes from SZI to untested pfkey_prop_build().
++ *
++ * Revision 1.13  2000/06/02 22:54:14  rgb
++ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
++ *
++ * Revision 1.12  2000/05/10 19:24:01  rgb
++ * Fleshed out sensitivity, proposal and supported extensions.
++ *
++ * Revision 1.11  2000/03/16 14:07:23  rgb
++ * Renamed ALIGN macro to avoid fighting with others in kernel.
++ *
++ * Revision 1.10  2000/01/24 21:14:35  rgb
++ * Added disabled pluto pfkey lib debug flag.
++ *
++ * Revision 1.9  2000/01/21 06:27:32  rgb
++ * Added address cases for eroute flows.
++ * Removed unused code.
++ * Dropped unused argument to pfkey_x_satype_build().
++ * Indented compiler directives for readability.
++ * Added klipsdebug switching capability.
++ * Fixed SADB_EXT_MAX bug not permitting last extension access.
++ *
++ * Revision 1.8  1999/12/29 21:17:41  rgb
++ * Changed pfkey_msg_build() I/F to include a struct sadb_msg**
++ * parameter for cleaner manipulation of extensions[] and to guard
++ * against potential memory leaks.
++ * Changed the I/F to pfkey_msg_free() for the same reason.
++ *
++ * Revision 1.7  1999/12/09 23:12:20  rgb
++ * Removed unused cruft.
++ * Added argument to pfkey_sa_build() to do eroutes.
++ * Fixed exttype check in as yet unused pfkey_lifetime_build().
++ *
++ * Revision 1.6  1999/12/07 19:54:29  rgb
++ * Removed static pluto debug flag.
++ * Added functions for pfkey message and extensions initialisation
++ * and cleanup.
++ *
++ * Revision 1.5  1999/12/01 22:20:06  rgb
++ * Changed pfkey_sa_build to accept an SPI in network byte order.
++ * Added <string.h> to quiet userspace compiler.
++ * Moved pfkey_lib_debug variable into the library.
++ * Removed SATYPE check from pfkey_msg_hdr_build so FLUSH will work.
++ * Added extension assembly debugging.
++ * Isolated assignment with brackets to be sure of scope.
++ *
++ * Revision 1.4  1999/11/27 11:57:35  rgb
++ * Added ipv6 headers.
++ * Remove over-zealous algorithm sanity checkers from pfkey_sa_build.
++ * Debugging error messages added.
++ * Fixed missing auth and encrypt assignment bug.
++ * Add argument to pfkey_msg_parse() for direction.
++ * Move parse-after-build check inside pfkey_msg_build().
++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
++ * Add CVS log entry to bottom of file.
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/pfkey_v2_debug.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,181 @@
++/*
++ * @(#) pfkey version 2 debugging messages
++ *
++ * Copyright (C) 2001  Richard Guy Briggs  <rgb@openswan.org>
++ *                 and Michael Richardson  <mcr@openswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey_v2_debug.c,v 1.11 2005/04/06 17:45:16 mcr Exp $
++ *
++ */
++
++#ifdef __KERNEL__
++
++# include <linux/kernel.h>  /* for printk */
++
++# include "openswan/ipsec_kversion.h" /* for malloc switch */
++# ifdef MALLOC_SLAB
++#  include <linux/slab.h> /* kmalloc() */
++# else /* MALLOC_SLAB */
++#  include <linux/malloc.h> /* kmalloc() */
++# endif /* MALLOC_SLAB */
++# include <linux/errno.h>  /* error codes */
++# include <linux/types.h>  /* size_t */
++# include <linux/interrupt.h> /* mark_bh */
++
++# include <linux/netdevice.h>   /* struct device, and other headers */
++# include <linux/etherdevice.h> /* eth_type_trans */
++extern int debug_pfkey;
++
++#else /* __KERNEL__ */
++
++# include <sys/types.h>
++# include <linux/types.h>
++# include <linux/errno.h>
++
++#endif /* __KERNEL__ */
++
++#include "openswan.h"
++#include "pfkeyv2.h"
++#include "pfkey.h"
++
++/* 
++ * This file provides ASCII translations of PF_KEY magic numbers.
++ *
++ */
++
++static char *pfkey_sadb_ext_strings[]={
++  "reserved",                     /* SADB_EXT_RESERVED             0 */
++  "security-association",         /* SADB_EXT_SA                   1 */
++  "lifetime-current",             /* SADB_EXT_LIFETIME_CURRENT     2 */
++  "lifetime-hard",                /* SADB_EXT_LIFETIME_HARD        3 */
++  "lifetime-soft",                /* SADB_EXT_LIFETIME_SOFT        4 */
++  "source-address",               /* SADB_EXT_ADDRESS_SRC          5 */
++  "destination-address",          /* SADB_EXT_ADDRESS_DST          6 */
++  "proxy-address",                /* SADB_EXT_ADDRESS_PROXY        7 */
++  "authentication-key",           /* SADB_EXT_KEY_AUTH             8 */
++  "cipher-key",                   /* SADB_EXT_KEY_ENCRYPT          9 */
++  "source-identity",              /* SADB_EXT_IDENTITY_SRC         10 */
++  "destination-identity",         /* SADB_EXT_IDENTITY_DST         11 */
++  "sensitivity-label",            /* SADB_EXT_SENSITIVITY          12 */
++  "proposal",                     /* SADB_EXT_PROPOSAL             13 */
++  "supported-auth",               /* SADB_EXT_SUPPORTED_AUTH       14 */
++  "supported-cipher",             /* SADB_EXT_SUPPORTED_ENCRYPT    15 */
++  "spi-range",                    /* SADB_EXT_SPIRANGE             16 */
++  "X-kmpprivate",                 /* SADB_X_EXT_KMPRIVATE          17 */
++  "X-satype2",                    /* SADB_X_EXT_SATYPE2            18 */
++  "X-security-association",       /* SADB_X_EXT_SA2                19 */
++  "X-destination-address2",       /* SADB_X_EXT_ADDRESS_DST2       20 */
++  "X-source-flow-address",        /* SADB_X_EXT_ADDRESS_SRC_FLOW   21 */
++  "X-dest-flow-address",          /* SADB_X_EXT_ADDRESS_DST_FLOW   22 */
++  "X-source-mask",                /* SADB_X_EXT_ADDRESS_SRC_MASK   23 */
++  "X-dest-mask",                  /* SADB_X_EXT_ADDRESS_DST_MASK   24 */
++  "X-set-debug",                  /* SADB_X_EXT_DEBUG              25 */
++  /* NAT_TRAVERSAL */
++  "X-NAT-T-type",                 /* SADB_X_EXT_NAT_T_TYPE         26 */
++  "X-NAT-T-sport",                /* SADB_X_EXT_NAT_T_SPORT        27 */
++  "X-NAT-T-dport",                /* SADB_X_EXT_NAT_T_DPORT        28 */
++  "X-NAT-T-OA",                   /* SADB_X_EXT_NAT_T_OA           29 */
++};
++
++const char *
++pfkey_v2_sadb_ext_string(int ext)
++{
++  if(ext <= SADB_EXT_MAX) {
++    return pfkey_sadb_ext_strings[ext];
++  } else {
++    return "unknown-ext";
++  }
++}
++
++
++static char *pfkey_sadb_type_strings[]={
++      "reserved",                     /* SADB_RESERVED      */
++      "getspi",                       /* SADB_GETSPI        */
++      "update",                       /* SADB_UPDATE        */
++      "add",                          /* SADB_ADD           */
++      "delete",                       /* SADB_DELETE        */
++      "get",                          /* SADB_GET           */
++      "acquire",                      /* SADB_ACQUIRE       */
++      "register",                     /* SADB_REGISTER      */
++      "expire",                       /* SADB_EXPIRE        */
++      "flush",                        /* SADB_FLUSH         */
++      "dump",                         /* SADB_DUMP          */
++      "x-promisc",                    /* SADB_X_PROMISC     */
++      "x-pchange",                    /* SADB_X_PCHANGE     */
++      "x-groupsa",                    /* SADB_X_GRPSA       */
++      "x-addflow(eroute)",            /* SADB_X_ADDFLOW     */
++      "x-delflow(eroute)",            /* SADB_X_DELFLOW     */
++      "x-debug",                      /* SADB_X_DEBUG       */
++};
++
++const char *
++pfkey_v2_sadb_type_string(int sadb_type)
++{
++  if(sadb_type <= SADB_MAX) {
++    return pfkey_sadb_type_strings[sadb_type];
++  } else {
++    return "unknown-sadb-type";
++  }
++}
++
++
++
++
++/*
++ * $Log: pfkey_v2_debug.c,v $
++ * Revision 1.11  2005/04/06 17:45:16  mcr
++ *    always include NAT-T names.
++ *
++ * Revision 1.10  2004/07/10 07:48:35  mcr
++ * Moved from linux/lib/libfreeswan/pfkey_v2_debug.c,v
++ *
++ * Revision 1.9  2004/03/08 01:59:08  ken
++ * freeswan.h -> openswan.h
++ *
++ * Revision 1.8  2003/12/10 01:20:19  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.7  2002/09/20 05:01:26  rgb
++ * Fixed limit inclusion error in both type and ext string conversion.
++ *
++ * Revision 1.6  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.5  2002/04/24 07:36:40  mcr
++ * Moved from ./lib/pfkey_v2_debug.c,v
++ *
++ * Revision 1.4  2002/01/29 22:25:36  rgb
++ * Re-add ipsec_kversion.h to keep MALLOC happy.
++ *
++ * Revision 1.3  2002/01/29 01:59:09  mcr
++ *    removal of kversions.h - sources that needed it now use ipsec_param.h.
++ *    updating of IPv6 structures to match latest in6.h version.
++ *    removed dead code from openswan.h that also duplicated kversions.h
++ *    code.
++ *
++ * Revision 1.2  2002/01/20 20:34:50  mcr
++ *    added pfkey_v2_sadb_type_string to decode sadb_type to string.
++ *
++ * Revision 1.1  2001/11/27 05:30:06  mcr
++ *    initial set of debug strings for pfkey debugging.
++ *    this will eventually only be included for debug builds.
++ *
++ * Revision 1.1  2001/09/21 04:12:03  mcr
++ *    first compilable version.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/pfkey_v2_ext_bits.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,814 @@
++/*
++ * RFC2367 PF_KEYv2 Key management API message parser
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey_v2_ext_bits.c,v 1.22 2005/05/11 01:45:31 mcr Exp $
++ */
++
++/*
++ *            Template from klips/net/ipsec/ipsec/ipsec_parse.c.
++ */
++
++char pfkey_v2_ext_bits_c_version[] = "$Id: pfkey_v2_ext_bits.c,v 1.22 2005/05/11 01:45:31 mcr Exp $";
++
++/*
++ * Some ugly stuff to allow consistent debugging code for use in the
++ * kernel and in user space
++*/
++
++#ifdef __KERNEL__
++
++# include <linux/kernel.h>  /* for printk */
++
++# include "openswan/ipsec_kversion.h" /* for malloc switch */
++# ifdef MALLOC_SLAB
++#  include <linux/slab.h> /* kmalloc() */
++# else /* MALLOC_SLAB */
++#  include <linux/malloc.h> /* kmalloc() */
++# endif /* MALLOC_SLAB */
++# include <linux/errno.h>  /* error codes */
++# include <linux/types.h>  /* size_t */
++# include <linux/interrupt.h> /* mark_bh */
++
++# include <linux/netdevice.h>   /* struct device, and other headers */
++# include <linux/etherdevice.h> /* eth_type_trans */
++# include <linux/ip.h>          /* struct iphdr */ 
++# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#  include <linux/ipv6.h>
++# endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
++
++#else /* __KERNEL__ */
++
++# include <sys/types.h>
++# include <linux/types.h>
++# include <linux/errno.h>
++#endif
++
++#include <openswan.h>
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_EXTENSIONS_MAX] = {
++
++/* INBOUND EXTENSIONS */
++{
++
++/* PERMITTED IN */
++{
++/* SADB_RESERVED */
++0
++,
++/* SADB_GETSPI */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_SPIRANGE
++,
++/* SADB_UPDATE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++,
++/* SADB_ADD */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_X_EXT_NAT_T_TYPE
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++| 1<<SADB_X_EXT_NAT_T_OA
++,
++/* SADB_DELETE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_GET */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_ACQUIRE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++,
++/* SADB_REGISTER */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_EXPIRE */
++0
++,
++/* SADB_FLUSH */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_DUMP */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_X_PROMISC */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_PCHANGE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_GRPSA */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_ADDFLOW */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_X_EXT_PROTOCOL
++,
++/* SADB_X_DELFLOW */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_X_EXT_PROTOCOL
++,
++/* SADB_X_DEBUG */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_X_EXT_DEBUG
++,
++/* SADB_X_NAT_T_NEW_MAPPING */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++},
++
++/* REQUIRED IN */
++{
++/* SADB_RESERVED */
++0
++,
++/* SADB_GETSPI */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_SPIRANGE
++,
++/* SADB_UPDATE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++/*| 1<<SADB_EXT_KEY_AUTH*/
++/*| 1<<SADB_EXT_KEY_ENCRYPT*/
++,
++/* SADB_ADD */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++/*| 1<<SADB_EXT_KEY_AUTH*/
++/*| 1<<SADB_EXT_KEY_ENCRYPT*/
++,
++/* SADB_DELETE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_GET */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_ACQUIRE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_PROPOSAL
++,
++/* SADB_REGISTER */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_EXPIRE */
++0
++,
++/* SADB_FLUSH */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_DUMP */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_X_PROMISC */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_PCHANGE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_GRPSA */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_DST
++/*| 1<<SADB_X_EXT_SATYPE2*/
++/*| 1<<SADB_X_EXT_SA2*/
++/*| 1<<SADB_X_EXT_ADDRESS_DST2*/
++,
++/* SADB_X_ADDFLOW */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++,
++/* SADB_X_DELFLOW */
++1<<SADB_EXT_RESERVED
++/*| 1<<SADB_EXT_SA*/
++#if 0 /* SADB_X_CLREROUTE doesn't need all these... */
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++#endif
++,
++/* SADB_X_DEBUG */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_X_EXT_DEBUG
++,
++/* SADB_X_NAT_T_NEW_MAPPING */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++}
++
++},
++
++/* OUTBOUND EXTENSIONS */
++{
++
++/* PERMITTED OUT */
++{
++/* SADB_RESERVED */
++0
++,
++/* SADB_GETSPI */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_UPDATE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++,
++/* SADB_ADD */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_X_EXT_NAT_T_TYPE
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++| 1<<SADB_X_EXT_NAT_T_OA
++,
++/* SADB_DELETE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_GET */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_X_EXT_NAT_T_TYPE
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++| 1<<SADB_X_EXT_NAT_T_OA
++,
++/* SADB_ACQUIRE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++,
++/* SADB_REGISTER */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++,
++/* SADB_EXPIRE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_FLUSH */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_DUMP */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_X_EXT_NAT_T_TYPE
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++| 1<<SADB_X_EXT_NAT_T_OA
++,
++/* SADB_X_PROMISC */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_PCHANGE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_GRPSA */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_ADDFLOW */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++| 1<<SADB_X_EXT_PROTOCOL
++,
++/* SADB_X_DELFLOW */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++| 1<<SADB_X_EXT_PROTOCOL
++,
++/* SADB_X_DEBUG */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_X_EXT_DEBUG
++,
++/* SADB_X_NAT_T_NEW_MAPPING */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++},
++
++/* REQUIRED OUT */
++{
++/* SADB_RESERVED */
++0
++,
++/* SADB_GETSPI */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_UPDATE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_ADD */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_DELETE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_GET */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++/* | 1<<SADB_EXT_KEY_AUTH */
++/* | 1<<SADB_EXT_KEY_ENCRYPT */
++,
++/* SADB_ACQUIRE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_PROPOSAL
++,
++/* SADB_REGISTER */
++1<<SADB_EXT_RESERVED
++/* | 1<<SADB_EXT_SUPPORTED_AUTH
++   | 1<<SADB_EXT_SUPPORTED_ENCRYPT */
++,
++/* SADB_EXPIRE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++/* | 1<<SADB_EXT_LIFETIME_HARD
++   | 1<<SADB_EXT_LIFETIME_SOFT */
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_FLUSH */
++1<<SADB_EXT_RESERVED
++,
++/* SADB_DUMP */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++,
++/* SADB_X_PROMISC */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_PCHANGE */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_LIFETIME_CURRENT
++| 1<<SADB_EXT_LIFETIME_HARD
++| 1<<SADB_EXT_LIFETIME_SOFT
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_EXT_ADDRESS_PROXY
++| 1<<SADB_EXT_KEY_AUTH
++| 1<<SADB_EXT_KEY_ENCRYPT
++| 1<<SADB_EXT_IDENTITY_SRC
++| 1<<SADB_EXT_IDENTITY_DST
++| 1<<SADB_EXT_SENSITIVITY
++| 1<<SADB_EXT_PROPOSAL
++| 1<<SADB_EXT_SUPPORTED_AUTH
++| 1<<SADB_EXT_SUPPORTED_ENCRYPT
++| 1<<SADB_EXT_SPIRANGE
++| 1<<SADB_X_EXT_KMPRIVATE
++| 1<<SADB_X_EXT_SATYPE2
++| 1<<SADB_X_EXT_SA2
++| 1<<SADB_X_EXT_ADDRESS_DST2
++,
++/* SADB_X_GRPSA */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_DST
++,
++/* SADB_X_ADDFLOW */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++,
++/* SADB_X_DELFLOW */
++1<<SADB_EXT_RESERVED
++/*| 1<<SADB_EXT_SA*/
++| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
++| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
++| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
++| 1<<SADB_X_EXT_ADDRESS_DST_MASK
++,
++/* SADB_X_DEBUG */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_X_EXT_DEBUG
++,
++/* SADB_X_NAT_T_NEW_MAPPING */
++1<<SADB_EXT_RESERVED
++| 1<<SADB_EXT_SA
++| 1<<SADB_EXT_ADDRESS_SRC
++| 1<<SADB_EXT_ADDRESS_DST
++| 1<<SADB_X_EXT_NAT_T_SPORT
++| 1<<SADB_X_EXT_NAT_T_DPORT
++}
++}
++};
++
++/*
++ * $Log: pfkey_v2_ext_bits.c,v $
++ * Revision 1.22  2005/05/11 01:45:31  mcr
++ *    make pfkey.h standalone.
++ *
++ * Revision 1.21  2004/07/10 07:48:36  mcr
++ * Moved from linux/lib/libfreeswan/pfkey_v2_ext_bits.c,v
++ *
++ * Revision 1.20  2004/03/08 01:59:08  ken
++ * freeswan.h -> openswan.h
++ *
++ * Revision 1.19  2003/12/22 21:38:13  mcr
++ *    removed extraenous #endif.
++ *
++ * Revision 1.18  2003/12/22 19:34:41  mcr
++ *    added 0.6c NAT-T patch.
++ *
++ * Revision 1.17  2003/12/10 01:20:19  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.16  2003/10/31 02:27:12  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.15.30.1  2003/09/21 13:59:44  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.15  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.14  2002/04/24 07:36:40  mcr
++ * Moved from ./lib/pfkey_v2_ext_bits.c,v
++ *
++ * Revision 1.13  2002/01/29 22:25:36  rgb
++ * Re-add ipsec_kversion.h to keep MALLOC happy.
++ *
++ * Revision 1.12  2002/01/29 01:59:10  mcr
++ *    removal of kversions.h - sources that needed it now use ipsec_param.h.
++ *    updating of IPv6 structures to match latest in6.h version.
++ *    removed dead code from openswan.h that also duplicated kversions.h
++ *    code.
++ *
++ * Revision 1.11  2001/10/18 04:45:24  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/openswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.10  2001/09/08 21:13:35  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ *
++ * Revision 1.9  2001/06/14 19:35:16  rgb
++ * Update copyright date.
++ *
++ * Revision 1.8  2001/03/26 23:07:36  rgb
++ * Remove requirement for auth and enc key from UPDATE.
++ *
++ * Revision 1.7  2000/09/12 22:35:37  rgb
++ * Restructured to remove unused extensions from CLEARFLOW messages.
++ *
++ * Revision 1.6  2000/09/09 06:39:01  rgb
++ * Added comments for clarity.
++ *
++ * Revision 1.5  2000/06/02 22:54:14  rgb
++ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
++ *
++ * Revision 1.4  2000/01/21 06:27:56  rgb
++ * Added address cases for eroute flows.
++ * Added comments for each message type.
++ * Added klipsdebug switching capability.
++ * Fixed GRPSA bitfields.
++ *
++ * Revision 1.3  1999/12/01 22:20:27  rgb
++ * Remove requirement for a proxy address in an incoming getspi message.
++ *
++ * Revision 1.2  1999/11/27 11:57:06  rgb
++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
++ * Add CVS log entry to bottom of file.
++ * Cleaned out unused bits.
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/pfkey_v2_ext_process.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,951 @@
++/*
++ * @(#) RFC2367 PF_KEYv2 Key management API message parser
++ * Copyright (C) 1998-2003   Richard Guy Briggs.
++ * Copyright (C) 2004        Michael Richardson <mcr@xelerance.com>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey_v2_ext_process.c,v 1.20.2.2 2006/10/06 21:39:26 paul Exp $
++ */
++
++/*
++ *            Template from klips/net/ipsec/ipsec/ipsec_netlink.c.
++ */
++
++char pfkey_v2_ext_process_c_version[] = "$Id: pfkey_v2_ext_process.c,v 1.20.2.2 2006/10/06 21:39:26 paul Exp $";
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++
++#include <openswan.h>
++
++#include <crypto/des.h>
++
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++#ifdef NET_21
++# include <linux/in6.h>
++# define ip_chk_addr inet_addr_type
++# define IS_MYADDR RTN_LOCAL
++#endif
++
++#include <net/ip.h>
++#ifdef NETLINK_SOCK
++# include <linux/netlink.h>
++#else
++# include <net/netlink.h>
++#endif
++
++#include <linux/random.h>     /* get_random_bytes() */
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipcomp.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_alg.h"
++
++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
++
++int
++pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;
++      int error = 0;
++      struct ipsec_sa* ipsp;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_sa_process: .\n");
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sa_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      switch(pfkey_ext->sadb_ext_type) {
++      case SADB_EXT_SA:
++              ipsp = extr->ips;
++              break;
++      case SADB_X_EXT_SA2:
++              if(extr->ips2 == NULL) {
++                      extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */
++              }
++              if(extr->ips2 == NULL) {
++                      SENDERR(-error);
++              }
++              ipsp = extr->ips2;
++              break;
++      default:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sa_process: "
++                          "invalid exttype=%d.\n",
++                          pfkey_ext->sadb_ext_type);
++              SENDERR(EINVAL);
++      }
++
++      ipsp->ips_said.spi = pfkey_sa->sadb_sa_spi;
++      ipsp->ips_replaywin = pfkey_sa->sadb_sa_replay;
++      ipsp->ips_state = pfkey_sa->sadb_sa_state;
++      ipsp->ips_flags = pfkey_sa->sadb_sa_flags;
++      ipsp->ips_replaywin_lastseq = ipsp->ips_replaywin_bitmap = 0;
++      ipsp->ips_ref_rel = pfkey_sa->sadb_x_sa_ref;
++      
++      switch(ipsp->ips_said.proto) {
++      case IPPROTO_AH:
++              ipsp->ips_authalg = pfkey_sa->sadb_sa_auth;
++              ipsp->ips_encalg = SADB_EALG_NONE;
++              break;
++      case IPPROTO_ESP:
++              ipsp->ips_authalg = pfkey_sa->sadb_sa_auth;
++              ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt;
++              ipsec_alg_sa_init(ipsp);
++              break;
++      case IPPROTO_IPIP:
++              ipsp->ips_authalg = AH_NONE;
++              ipsp->ips_encalg = ESP_NONE;
++              break;
++#ifdef CONFIG_KLIPS_IPCOMP
++      case IPPROTO_COMP:
++              ipsp->ips_authalg = AH_NONE;
++              ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt;
++              break;
++#endif /* CONFIG_KLIPS_IPCOMP */
++      case IPPROTO_INT:
++              ipsp->ips_authalg = AH_NONE;
++              ipsp->ips_encalg = ESP_NONE;
++              break;
++      case 0:
++              break;
++      default:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_sa_process: "
++                          "unknown proto=%d.\n",
++                          ipsp->ips_said.proto);
++              SENDERR(EINVAL);
++      }
++
++errlab:
++      return error;
++}
++
++int
++pfkey_lifetime_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_lifetime_process: .\n");
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_lifetime_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      switch(pfkey_lifetime->sadb_lifetime_exttype) {
++      case SADB_EXT_LIFETIME_CURRENT:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_lifetime_process: "
++                          "lifetime_current not supported yet.\n");
++              SENDERR(EINVAL);
++              break;
++      case SADB_EXT_LIFETIME_HARD:
++              ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_allocations,
++                                        pfkey_lifetime->sadb_lifetime_allocations);
++
++              ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_bytes,
++                                        pfkey_lifetime->sadb_lifetime_bytes);
++
++              ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_addtime,
++                                        pfkey_lifetime->sadb_lifetime_addtime);
++
++              ipsec_lifetime_update_hard(&extr->ips->ips_life.ipl_usetime,
++                                        pfkey_lifetime->sadb_lifetime_usetime);
++
++              break;
++
++      case SADB_EXT_LIFETIME_SOFT:
++              ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_allocations,
++                                         pfkey_lifetime->sadb_lifetime_allocations);
++
++              ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_bytes,
++                                         pfkey_lifetime->sadb_lifetime_bytes);
++
++              ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_addtime,
++                                         pfkey_lifetime->sadb_lifetime_addtime);
++
++              ipsec_lifetime_update_soft(&extr->ips->ips_life.ipl_usetime,
++                                         pfkey_lifetime->sadb_lifetime_usetime);
++
++              break;
++      default:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_lifetime_process: "
++                          "invalid exttype=%d.\n",
++                          pfkey_ext->sadb_ext_type);
++              SENDERR(EINVAL);
++      }
++
++errlab:
++      return error;
++}
++
++int
++pfkey_address_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      int saddr_len = 0;
++      char ipaddr_txt[ADDRTOA_BUF];
++      unsigned char **sap;
++      unsigned short * portp = 0;
++      struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext;
++      struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address));
++      struct ipsec_sa* ipsp;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_address_process:\n");
++      
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      switch(s->sa_family) {
++      case AF_INET:
++              saddr_len = sizeof(struct sockaddr_in);
++              addrtoa(((struct sockaddr_in*)s)->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt));
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found address family=%d, AF_INET, %s.\n",
++                          s->sa_family,
++                          ipaddr_txt);
++              break;
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      case AF_INET6:
++              saddr_len = sizeof(struct sockaddr_in6);
++              break;
++#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
++      default:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "s->sa_family=%d not supported.\n",
++                          s->sa_family);
++              SENDERR(EPFNOSUPPORT);
++      }
++      
++      switch(pfkey_address->sadb_address_exttype) {
++      case SADB_EXT_ADDRESS_SRC:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found src address.\n");
++              sap = (unsigned char **)&(extr->ips->ips_addr_s);
++              extr->ips->ips_addr_s_size = saddr_len;
++              break;
++      case SADB_EXT_ADDRESS_DST:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found dst address.\n");
++              sap = (unsigned char **)&(extr->ips->ips_addr_d);
++              extr->ips->ips_addr_d_size = saddr_len;
++              break;
++      case SADB_EXT_ADDRESS_PROXY:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found proxy address.\n");
++              sap = (unsigned char **)&(extr->ips->ips_addr_p);
++              extr->ips->ips_addr_p_size = saddr_len;
++              break;
++      case SADB_X_EXT_ADDRESS_DST2:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found 2nd dst address.\n");
++              if(extr->ips2 == NULL) {
++                      extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */
++              }
++              if(extr->ips2 == NULL) {
++                      SENDERR(-error);
++              }
++              sap = (unsigned char **)&(extr->ips2->ips_addr_d);
++              extr->ips2->ips_addr_d_size = saddr_len;
++              break;
++      case SADB_X_EXT_ADDRESS_SRC_FLOW:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found src flow address.\n");
++              if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
++                      SENDERR(ENOMEM);
++              }
++              sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_src);
++              portp = &(extr->eroute->er_eaddr.sen_sport);
++              break;
++      case SADB_X_EXT_ADDRESS_DST_FLOW:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found dst flow address.\n");
++              if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
++                      SENDERR(ENOMEM);
++              }
++              sap = (unsigned char **)&(extr->eroute->er_eaddr.sen_ip_dst);
++              portp = &(extr->eroute->er_eaddr.sen_dport);
++              break;
++      case SADB_X_EXT_ADDRESS_SRC_MASK:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found src mask address.\n");
++              if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
++                      SENDERR(ENOMEM);
++              }
++              sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_src);
++              portp = &(extr->eroute->er_emask.sen_sport);
++              break;
++      case SADB_X_EXT_ADDRESS_DST_MASK:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found dst mask address.\n");
++              if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
++                      SENDERR(ENOMEM);
++              }
++              sap = (unsigned char **)&(extr->eroute->er_emask.sen_ip_dst);
++              portp = &(extr->eroute->er_emask.sen_dport);
++              break;
++#ifdef NAT_TRAVERSAL
++      case SADB_X_EXT_NAT_T_OA:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "found NAT-OA address.\n");
++              sap = (unsigned char **)&(extr->ips->ips_natt_oa);
++              extr->ips->ips_natt_oa_size = saddr_len;
++              break;
++#endif
++      default:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "unrecognised ext_type=%d.\n",
++                          pfkey_address->sadb_address_exttype);
++              SENDERR(EINVAL);
++      }
++      
++      switch(pfkey_address->sadb_address_exttype) {
++      case SADB_EXT_ADDRESS_SRC:
++      case SADB_EXT_ADDRESS_DST:
++      case SADB_EXT_ADDRESS_PROXY:
++      case SADB_X_EXT_ADDRESS_DST2:
++#ifdef NAT_TRAVERSAL
++      case SADB_X_EXT_NAT_T_OA:
++#endif
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_address_process: "
++                          "allocating %d bytes for saddr.\n",
++                          saddr_len);
++              if(!(*sap = kmalloc(saddr_len, GFP_KERNEL))) {
++                      SENDERR(ENOMEM);
++              }
++              memcpy(*sap, s, saddr_len);
++              break;
++      default:
++              if(s->sa_family != AF_INET) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_address_process: "
++                                  "s->sa_family=%d not supported.\n",
++                                  s->sa_family);
++                      SENDERR(EPFNOSUPPORT);
++              }
++              {
++                      unsigned long *ulsap = (unsigned long *)sap;
++                      *ulsap = ((struct sockaddr_in*)s)->sin_addr.s_addr;
++              }
++
++              if (portp != 0)
++                      *portp = ((struct sockaddr_in*)s)->sin_port;
++#ifdef CONFIG_KLIPS_DEBUG
++              if(extr->eroute) {
++                      char buf1[64], buf2[64];
++                      if (debug_pfkey) {
++                              subnettoa(extr->eroute->er_eaddr.sen_ip_src,
++                                        extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
++                              subnettoa(extr->eroute->er_eaddr.sen_ip_dst,
++                                        extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
++                              KLIPS_PRINT(debug_pfkey,
++                                          "klips_debug:pfkey_address_parse: "
++                                          "extr->eroute set to %s:%d->%s:%d\n",
++                                          buf1,
++                                          ntohs(extr->eroute->er_eaddr.sen_sport),
++                                          buf2,
++                                          ntohs(extr->eroute->er_eaddr.sen_dport));
++                      }
++              }
++#endif /* CONFIG_KLIPS_DEBUG */
++      }
++
++      ipsp = extr->ips;
++      switch(pfkey_address->sadb_address_exttype) {
++      case SADB_X_EXT_ADDRESS_DST2:
++              ipsp = extr->ips2;
++      case SADB_EXT_ADDRESS_DST:
++              if(s->sa_family == AF_INET) {
++                      ipsp->ips_said.dst.u.v4.sin_addr.s_addr = ((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr.s_addr;
++                      ipsp->ips_said.dst.u.v4.sin_family      = AF_INET;
++                      addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr,
++                              0,
++                              ipaddr_txt,
++                              sizeof(ipaddr_txt));
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_address_process: "
++                                  "ips_said.dst set to %s.\n",
++                                  ipaddr_txt);
++              } else {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_address_process: "
++                                  "uh, ips_said.dst doesn't do address family=%d yet, said will be invalid.\n",
++                                  s->sa_family);
++              }
++      default:
++              break;
++      }
++      
++      /* XXX check if port!=0 */
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_address_process: successful.\n");
++ errlab:
++      return error;
++}
++
++int
++pfkey_key_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++        int error = 0;
++        struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_key_process: .\n");
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_key_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++        switch(pfkey_key->sadb_key_exttype) {
++        case SADB_EXT_KEY_AUTH:
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_key_process: "
++                          "allocating %d bytes for authkey.\n",
++                          DIVUP(pfkey_key->sadb_key_bits, 8));
++              if(!(extr->ips->ips_key_a = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_key_process: "
++                                  "memory allocation error.\n");
++                      SENDERR(ENOMEM);
++              }
++                extr->ips->ips_key_bits_a = pfkey_key->sadb_key_bits;
++                extr->ips->ips_key_a_size = DIVUP(pfkey_key->sadb_key_bits, 8);
++              memcpy(extr->ips->ips_key_a,
++                     (char*)pfkey_key + sizeof(struct sadb_key),
++                     extr->ips->ips_key_a_size);
++              break;
++      case SADB_EXT_KEY_ENCRYPT: /* Key(s) */
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_key_process: "
++                          "allocating %d bytes for enckey.\n",
++                          DIVUP(pfkey_key->sadb_key_bits, 8));
++              if(!(extr->ips->ips_key_e = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_key_process: "
++                                  "memory allocation error.\n");
++                      SENDERR(ENOMEM);
++              }
++              extr->ips->ips_key_bits_e = pfkey_key->sadb_key_bits;
++              extr->ips->ips_key_e_size = DIVUP(pfkey_key->sadb_key_bits, 8);
++              memcpy(extr->ips->ips_key_e,
++                     (char*)pfkey_key + sizeof(struct sadb_key),
++                     extr->ips->ips_key_e_size);
++              break;
++      default:
++              SENDERR(EINVAL);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_key_process: "
++                  "success.\n");
++errlab:
++      return error;
++}
++
++int
++pfkey_ident_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++        int error = 0;
++        struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext;
++      int data_len;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_ident_process: .\n");
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_ident_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      switch(pfkey_ident->sadb_ident_exttype) {
++      case SADB_EXT_IDENTITY_SRC:
++              data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
++              
++              extr->ips->ips_ident_s.type = pfkey_ident->sadb_ident_type;
++              extr->ips->ips_ident_s.id = pfkey_ident->sadb_ident_id;
++              extr->ips->ips_ident_s.len = pfkey_ident->sadb_ident_len;
++              if(data_len) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_ident_process: "
++                                  "allocating %d bytes for ident_s.\n",
++                                  data_len);
++                      if(!(extr->ips->ips_ident_s.data
++                           = kmalloc(data_len, GFP_KERNEL))) {
++                                SENDERR(ENOMEM);
++                        }
++                      memcpy(extr->ips->ips_ident_s.data,
++                               (char*)pfkey_ident + sizeof(struct sadb_ident),
++                             data_len);
++                } else {
++                      extr->ips->ips_ident_s.data = NULL;
++                }
++                break;
++      case SADB_EXT_IDENTITY_DST: /* Identity(ies) */
++              data_len = pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);
++              
++              extr->ips->ips_ident_d.type = pfkey_ident->sadb_ident_type;
++              extr->ips->ips_ident_d.id = pfkey_ident->sadb_ident_id;
++              extr->ips->ips_ident_d.len = pfkey_ident->sadb_ident_len;
++              if(data_len) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_ident_process: "
++                                  "allocating %d bytes for ident_d.\n",
++                                  data_len);
++                      if(!(extr->ips->ips_ident_d.data
++                           = kmalloc(data_len, GFP_KERNEL))) {
++                                SENDERR(ENOMEM);
++                        }
++                      memcpy(extr->ips->ips_ident_d.data,
++                               (char*)pfkey_ident + sizeof(struct sadb_ident),
++                             data_len);
++                } else {
++                      extr->ips->ips_ident_d.data = NULL;
++                }
++                break;
++      default:
++              SENDERR(EINVAL);
++      }
++errlab:
++      return error;
++}
++
++int
++pfkey_sens_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++        int error = 0;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_sens_process: "
++                  "Sorry, I can't process exttype=%d yet.\n",
++                  pfkey_ext->sadb_ext_type);
++        SENDERR(EINVAL); /* don't process these yet */
++ errlab:
++        return error;
++}
++
++int
++pfkey_prop_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++        int error = 0;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_prop_process: "
++                  "Sorry, I can't process exttype=%d yet.\n",
++                  pfkey_ext->sadb_ext_type);
++      SENDERR(EINVAL); /* don't process these yet */
++      
++ errlab:
++      return error;
++}
++
++int
++pfkey_supported_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++        int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_supported_process: "
++                  "Sorry, I can't process exttype=%d yet.\n",
++                  pfkey_ext->sadb_ext_type);
++      SENDERR(EINVAL); /* don't process these yet */
++
++errlab:
++      return error;
++}
++
++int
++pfkey_spirange_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++        int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_spirange_process: .\n");
++/* errlab: */
++      return error;
++}
++
++int
++pfkey_x_kmprivate_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_kmprivate_process: "
++                  "Sorry, I can't process exttype=%d yet.\n",
++                  pfkey_ext->sadb_ext_type);
++      SENDERR(EINVAL); /* don't process these yet */
++
++errlab:
++      return error;
++}
++
++int
++pfkey_x_satype_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_satype_process: .\n");
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_satype_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      if(extr->ips2 == NULL) {
++              extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */
++      }
++      if(extr->ips2 == NULL) {
++              SENDERR(-error);
++      }
++      if(!(extr->ips2->ips_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_satype_process: "
++                          "proto lookup from satype=%d failed.\n",
++                          pfkey_x_satype->sadb_x_satype_satype);
++              SENDERR(EINVAL);
++      }
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_satype_process: "
++                  "protocol==%d decoded from satype==%d(%s).\n",
++                  extr->ips2->ips_said.proto,
++                  pfkey_x_satype->sadb_x_satype_satype,
++                  satype2name(pfkey_x_satype->sadb_x_satype_satype));
++
++errlab:
++      return error;
++}
++
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++int
++pfkey_x_nat_t_type_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct sadb_x_nat_t_type *pfkey_x_nat_t_type = (struct sadb_x_nat_t_type *)pfkey_ext;
++
++      if(!pfkey_x_nat_t_type) {
++              printk("klips_debug:pfkey_x_nat_t_type_process: "
++                     "null pointer passed in\n");
++              SENDERR(EINVAL);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_nat_t_type_process: %d.\n",
++                      pfkey_x_nat_t_type->sadb_x_nat_t_type_type);
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_nat_t_type_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      switch(pfkey_x_nat_t_type->sadb_x_nat_t_type_type) {
++              case ESPINUDP_WITH_NON_IKE: /* with Non-IKE (older version) */
++              case ESPINUDP_WITH_NON_ESP: /* with Non-ESP */
++
++                      extr->ips->ips_natt_type = pfkey_x_nat_t_type->sadb_x_nat_t_type_type;
++                      break;
++              default:
++                      KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_nat_t_type_process: "
++                          "unknown type %d.\n",
++                          pfkey_x_nat_t_type->sadb_x_nat_t_type_type);
++                      SENDERR(EINVAL);
++                      break;
++      }
++
++errlab:
++      return error;
++}
++
++int
++pfkey_x_nat_t_port_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct sadb_x_nat_t_port *pfkey_x_nat_t_port = (struct sadb_x_nat_t_port *)pfkey_ext;
++
++      if(!pfkey_x_nat_t_port) {
++              printk("klips_debug:pfkey_x_nat_t_port_process: "
++                     "null pointer passed in\n");
++              SENDERR(EINVAL);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_nat_t_port_process: %d/%d.\n",
++                      pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype,
++                      pfkey_x_nat_t_port->sadb_x_nat_t_port_port);
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_nat_t_type_process: "
++                          "extr or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      switch(pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype) {
++              case SADB_X_EXT_NAT_T_SPORT:
++                      extr->ips->ips_natt_sport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port;
++                      break;
++              case SADB_X_EXT_NAT_T_DPORT:
++                      extr->ips->ips_natt_dport = pfkey_x_nat_t_port->sadb_x_nat_t_port_port;
++                      break;
++              default:
++                      KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_nat_t_port_process: "
++                          "unknown exttype %d.\n",
++                          pfkey_x_nat_t_port->sadb_x_nat_t_port_exttype);
++                      SENDERR(EINVAL);
++                      break;
++      }
++
++errlab:
++      return error;
++}
++#endif
++
++int
++pfkey_x_debug_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext;
++
++      if(!pfkey_x_debug) {
++              printk("klips_debug:pfkey_x_debug_process: "
++                     "null pointer passed in\n");
++              SENDERR(EINVAL);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_debug_process: .\n");
++
++#ifdef CONFIG_KLIPS_DEBUG
++              if(pfkey_x_debug->sadb_x_debug_netlink >>
++                 (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 - 1)) {
++                      pfkey_x_debug->sadb_x_debug_netlink &=
++                              ~(1 << (sizeof(pfkey_x_debug->sadb_x_debug_netlink) * 8 -1));
++                      debug_tunnel  |= pfkey_x_debug->sadb_x_debug_tunnel;
++                      debug_netlink |= pfkey_x_debug->sadb_x_debug_netlink;
++                      debug_xform   |= pfkey_x_debug->sadb_x_debug_xform;
++                      debug_eroute  |= pfkey_x_debug->sadb_x_debug_eroute;
++                      debug_spi     |= pfkey_x_debug->sadb_x_debug_spi;
++                      debug_radij   |= pfkey_x_debug->sadb_x_debug_radij;
++                      debug_esp     |= pfkey_x_debug->sadb_x_debug_esp;
++                      debug_ah      |= pfkey_x_debug->sadb_x_debug_ah;
++                      debug_rcv     |= pfkey_x_debug->sadb_x_debug_rcv;
++                      debug_pfkey   |= pfkey_x_debug->sadb_x_debug_pfkey;
++#ifdef CONFIG_KLIPS_IPCOMP
++                      sysctl_ipsec_debug_ipcomp  |= pfkey_x_debug->sadb_x_debug_ipcomp;
++#endif /* CONFIG_KLIPS_IPCOMP */
++                      sysctl_ipsec_debug_verbose |= pfkey_x_debug->sadb_x_debug_verbose;
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_debug_process: "
++                                  "set\n");
++              } else {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_debug_process: "
++                                  "unset\n");
++                      debug_tunnel  &= pfkey_x_debug->sadb_x_debug_tunnel;
++                      debug_netlink &= pfkey_x_debug->sadb_x_debug_netlink;
++                      debug_xform   &= pfkey_x_debug->sadb_x_debug_xform;
++                      debug_eroute  &= pfkey_x_debug->sadb_x_debug_eroute;
++                      debug_spi     &= pfkey_x_debug->sadb_x_debug_spi;
++                      debug_radij   &= pfkey_x_debug->sadb_x_debug_radij;
++                      debug_esp     &= pfkey_x_debug->sadb_x_debug_esp;
++                      debug_ah      &= pfkey_x_debug->sadb_x_debug_ah;
++                      debug_rcv     &= pfkey_x_debug->sadb_x_debug_rcv;
++                      debug_pfkey   &= pfkey_x_debug->sadb_x_debug_pfkey;
++#ifdef CONFIG_KLIPS_IPCOMP
++                      sysctl_ipsec_debug_ipcomp  &= pfkey_x_debug->sadb_x_debug_ipcomp;
++#endif /* CONFIG_KLIPS_IPCOMP */
++                      sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose;
++              }
++#else /* CONFIG_KLIPS_DEBUG */
++              printk("klips_debug:pfkey_x_debug_process: "
++                     "debugging not enabled\n");
++              SENDERR(EINVAL);
++#endif /* CONFIG_KLIPS_DEBUG */
++      
++errlab:
++      return error;
++}
++
++/*
++ * $Log: pfkey_v2_ext_process.c,v $
++ * Revision 1.20.2.2  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.20.2.1  2006/04/20 16:33:07  mcr
++ * remove all of CONFIG_KLIPS_ALG --- one can no longer build without it.
++ * Fix in-kernel module compilation. Sub-makefiles do not work.
++ *
++ * Revision 1.20  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.19  2004/12/04 07:14:18  mcr
++ *    resolution to gcc3-ism was wrong. fixed to assign correct
++ *    variable.
++ *
++ * Revision 1.18  2004/12/03 21:25:57  mcr
++ *    compile time fixes for running on 2.6.
++ *    still experimental.
++ *
++ * Revision 1.17  2004/08/21 00:45:04  mcr
++ *    CONFIG_KLIPS_NAT was wrong, also need to include udp.h.
++ *
++ * Revision 1.16  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.15  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.14  2004/02/03 03:13:59  mcr
++ *    no longer #ifdef out NON_ESP mode. That was a mistake.
++ *
++ * Revision 1.13  2003/12/15 18:13:12  mcr
++ *    when compiling with NAT traversal, don't assume that the
++ *    kernel has been patched, unless CONFIG_IPSEC_NAT_NON_ESP
++ *    is set.
++ *
++ * Revision 1.12.2.1  2003/12/22 15:25:52  jjo
++ *      Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.12  2003/12/10 01:14:27  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.11  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.10.4.2  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.10.4.1  2003/09/21 13:59:56  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.10  2003/02/06 01:51:41  rgb
++ * Removed no longer relevant comment
++ *
++ * Revision 1.9  2003/01/30 02:32:44  rgb
++ *
++ * Transmit error code through to caller from callee for better diagnosis of problems.
++ *
++ * Revision 1.8  2002/12/13 22:42:22  mcr
++ *    restored sa_ref code
++ *
++ * Revision 1.7  2002/12/13 22:40:48  mcr
++ *    temporarily removed sadb_x_sa_ref reference for 2.xx
++ *
++ * Revision 1.6  2002/10/05 05:02:58  dhr
++ *
++ * C labels go on statements
++ *
++ * Revision 1.5  2002/09/20 15:41:08  rgb
++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc().
++ * Added sadb_x_sa_ref to struct sadb_sa.
++ *
++ * Revision 1.4  2002/09/20 05:02:02  rgb
++ * Added memory allocation debugging.
++ *
++ * Revision 1.3  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.2  2002/05/27 18:55:03  rgb
++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT.
++ *
++ * Revision 1.1  2002/05/14 02:33:51  rgb
++ * Moved all the extension processing functions to pfkey_v2_ext_process.c.
++ *
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/pfkey_v2_parse.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1846 @@
++/*
++ * RFC2367 PF_KEYv2 Key management API message parser
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey_v2_parse.c,v 1.65 2005/04/06 17:46:05 mcr Exp $
++ */
++
++/*
++ *            Template from klips/net/ipsec/ipsec/ipsec_parser.c.
++ */
++
++char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.65 2005/04/06 17:46:05 mcr Exp $";
++
++/*
++ * Some ugly stuff to allow consistent debugging code for use in the
++ * kernel and in user space
++*/
++
++#ifdef __KERNEL__
++
++# include <linux/kernel.h>  /* for printk */
++
++#include "openswan/ipsec_kversion.h" /* for malloc switch */
++
++# ifdef MALLOC_SLAB
++#  include <linux/slab.h> /* kmalloc() */
++# else /* MALLOC_SLAB */
++#  include <linux/malloc.h> /* kmalloc() */
++# endif /* MALLOC_SLAB */
++# include <linux/errno.h>  /* error codes */
++# include <linux/types.h>  /* size_t */
++# include <linux/interrupt.h> /* mark_bh */
++
++# include <linux/netdevice.h>   /* struct device, and other headers */
++# include <linux/etherdevice.h> /* eth_type_trans */
++# include <linux/ip.h>          /* struct iphdr */ 
++# if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++#  include <linux/ipv6.h>        /* struct ipv6hdr */
++# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
++extern int debug_pfkey;
++
++# include <openswan.h>
++
++#include "openswan/ipsec_encap.h"
++
++#else /* __KERNEL__ */
++
++# include <sys/types.h>
++# include <linux/types.h>
++# include <linux/errno.h>
++
++# include <openswan.h>
++# include "constants.h" 
++# include "programs/pluto/defs.h"  /* for PRINTF_LIKE */
++
++#endif /* __KERNEL__ */
++
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_sa.h"  /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH */
++
++/* 
++ * how to handle debugging for pfkey.
++ */
++#include <openswan/pfkey_debug.h>
++
++unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE;
++void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1);
++void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1);
++
++
++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
++
++struct satype_tbl {
++      uint8_t proto;
++      uint8_t satype;
++      char* name;
++} static satype_tbl[] = {
++#ifdef __KERNEL__
++      { IPPROTO_ESP,  SADB_SATYPE_ESP,        "ESP"  },
++      { IPPROTO_AH,   SADB_SATYPE_AH,         "AH"   },
++      { IPPROTO_IPIP, SADB_X_SATYPE_IPIP,     "IPIP" },
++#ifdef CONFIG_KLIPS_IPCOMP
++      { IPPROTO_COMP, SADB_X_SATYPE_COMP,     "COMP" },
++#endif /* CONFIG_KLIPS_IPCOMP */
++      { IPPROTO_INT,  SADB_X_SATYPE_INT,      "INT" },
++#else /* __KERNEL__ */
++      { SA_ESP,       SADB_SATYPE_ESP,        "ESP"  },
++      { SA_AH,        SADB_SATYPE_AH,         "AH"   },
++      { SA_IPIP,      SADB_X_SATYPE_IPIP,     "IPIP" },
++      { SA_COMP,      SADB_X_SATYPE_COMP,     "COMP" },
++      { SA_INT,       SADB_X_SATYPE_INT,      "INT" },
++#endif /* __KERNEL__ */
++      { 0,            0,                      "UNKNOWN" }
++};
++
++uint8_t
++satype2proto(uint8_t satype)
++{
++      int i =0;
++
++      while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
++              i++;
++      }
++      return satype_tbl[i].proto;
++}
++
++uint8_t
++proto2satype(uint8_t proto)
++{
++      int i = 0;
++
++      while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
++              i++;
++      }
++      return satype_tbl[i].satype;
++}
++
++char*
++satype2name(uint8_t satype)
++{
++      int i = 0;
++
++      while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) {
++              i++;
++      }
++      return satype_tbl[i].name;
++}
++
++char*
++proto2name(uint8_t proto)
++{
++      int i = 0;
++
++      while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) {
++              i++;
++      }
++      return satype_tbl[i].name;
++}
++
++/* Default extension parsers taken from the KLIPS code */
++
++DEBUG_NO_STATIC int
++pfkey_sa_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;
++#if 0
++      struct sadb_sa sav2;
++#endif
++      
++      /* sanity checks... */
++      if(!pfkey_sa) {
++              ERROR("pfkey_sa_parse: "
++                        "NULL pointer passed in.\n");
++              SENDERR(EINVAL);
++      }
++      
++#if 0
++      /* check if this structure is short, and if so, fix it up.
++       * XXX this is NOT the way to do things.
++       */
++      if(pfkey_sa->sadb_sa_len == sizeof(struct sadb_sa_v1)/IPSEC_PFKEYv2_ALIGN) {
++
++              /* yes, so clear out a temporary structure, and copy first */
++              memset(&sav2, 0, sizeof(sav2));
++              memcpy(&sav2, pfkey_sa, sizeof(struct sadb_sa_v1));
++              sav2.sadb_x_sa_ref=-1;
++              sav2.sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN;
++              
++              pfkey_sa = &sav2;
++      }
++#endif
++
++
++      if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n",
++                        pfkey_sa->sadb_sa_len,
++                        (int)sizeof(struct sadb_sa));
++              SENDERR(EINVAL);
++      }
++
++#if SADB_EALG_MAX < 255       
++      if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n",
++                        pfkey_sa->sadb_sa_encrypt,
++                        SADB_EALG_MAX);
++              SENDERR(EINVAL);
++      }
++#endif
++      
++#if SADB_AALG_MAX < 255       
++      if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n",
++                        pfkey_sa->sadb_sa_auth,
++                        SADB_AALG_MAX);
++              SENDERR(EINVAL);
++      }
++#endif
++      
++#if SADB_SASTATE_MAX < 255    
++      if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "state=%d exceeds MAX=%d.\n",
++                        pfkey_sa->sadb_sa_state,
++                        SADB_SASTATE_MAX);
++              SENDERR(EINVAL);
++      }
++#endif
++      
++      if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "state=%d is DEAD=%d.\n",
++                        pfkey_sa->sadb_sa_state,
++                        SADB_SASTATE_DEAD);
++              SENDERR(EINVAL);
++      }
++      
++      if(pfkey_sa->sadb_sa_replay > 64) {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "replay window size: %d -- must be 0 <= size <= 64\n",
++                        pfkey_sa->sadb_sa_replay);
++              SENDERR(EINVAL);
++      }
++      
++      if(! ((pfkey_sa->sadb_sa_exttype ==  SADB_EXT_SA) ||
++            (pfkey_sa->sadb_sa_exttype ==  SADB_X_EXT_SA2)))
++      {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n",
++                        pfkey_sa->sadb_sa_exttype,
++                        SADB_EXT_SA,
++                        SADB_X_EXT_SA2);
++              SENDERR(EINVAL);
++      }
++
++      if((IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref) && (pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) {
++              ERROR(
++                        "pfkey_sa_parse: "
++                        "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n",
++                        pfkey_sa->sadb_x_sa_ref,
++                        IPSEC_SAREF_NULL,
++                        IPSEC_SA_REF_TABLE_NUM_ENTRIES);
++              SENDERR(EINVAL);
++      }
++      
++      DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                "pfkey_sa_parse: "
++                "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n",
++                pfkey_sa->sadb_sa_len,
++                pfkey_sa->sadb_sa_exttype,
++                pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype),
++                (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi),
++                pfkey_sa->sadb_sa_replay,
++                pfkey_sa->sadb_sa_state,
++                pfkey_sa->sadb_sa_auth,
++                pfkey_sa->sadb_sa_encrypt,
++                pfkey_sa->sadb_sa_flags,
++                pfkey_sa->sadb_x_sa_ref);
++      
++ errlab:
++      return error;
++}     
++
++DEBUG_NO_STATIC int
++pfkey_lifetime_parse(struct sadb_ext  *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++                "pfkey_lifetime_parse:enter\n");
++      /* sanity checks... */
++      if(!pfkey_lifetime) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_lifetime_parse: "
++                        "NULL pointer passed in.\n");
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_lifetime->sadb_lifetime_len !=
++         sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_lifetime_parse: "
++                        "length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n",
++                        pfkey_lifetime->sadb_lifetime_len,
++                        (int)sizeof(struct sadb_lifetime));
++              SENDERR(EINVAL);
++      }
++
++      if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) &&
++         (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) &&
++         (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_lifetime_parse: "
++                        "unexpected ext_type=%d.\n", 
++                        pfkey_lifetime->sadb_lifetime_exttype); 
++              SENDERR(EINVAL);
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                "pfkey_lifetime_parse: "
++                "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u pkts=%u.\n", 
++                pfkey_lifetime->sadb_lifetime_exttype,
++                pfkey_v2_sadb_ext_string(pfkey_lifetime->sadb_lifetime_exttype),
++                pfkey_lifetime->sadb_lifetime_allocations,
++                (unsigned)pfkey_lifetime->sadb_lifetime_bytes,
++                (unsigned)pfkey_lifetime->sadb_lifetime_addtime,
++                (unsigned)pfkey_lifetime->sadb_lifetime_usetime,
++                pfkey_lifetime->sadb_x_lifetime_packets); 
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_address_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      int saddr_len = 0;
++      struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext;
++      struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address));
++      char ipaddr_txt[ADDRTOT_BUF];
++      
++      /* sanity checks... */
++      if(!pfkey_address) {
++              ERROR(
++                      "pfkey_address_parse: "
++                      "NULL pointer passed in.\n");
++              SENDERR(EINVAL);
++      }
++      
++      if(pfkey_address->sadb_address_len <
++         (sizeof(struct sadb_address) + sizeof(struct sockaddr))/
++         IPSEC_PFKEYv2_ALIGN) {
++              ERROR("pfkey_address_parse: "
++                        "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
++                        pfkey_address->sadb_address_len,
++                        (int)sizeof(struct sadb_address),
++                        (int)sizeof(struct sockaddr));
++              SENDERR(EINVAL);
++      }
++      
++      if(pfkey_address->sadb_address_reserved) {
++              ERROR("pfkey_address_parse: "
++                        "res=%d, must be zero.\n",
++                        pfkey_address->sadb_address_reserved);
++              SENDERR(EINVAL);
++      }
++      
++      switch(pfkey_address->sadb_address_exttype) {   
++      case SADB_EXT_ADDRESS_SRC:
++      case SADB_EXT_ADDRESS_DST:
++      case SADB_EXT_ADDRESS_PROXY:
++      case SADB_X_EXT_ADDRESS_DST2:
++      case SADB_X_EXT_ADDRESS_SRC_FLOW:
++      case SADB_X_EXT_ADDRESS_DST_FLOW:
++      case SADB_X_EXT_ADDRESS_SRC_MASK:
++      case SADB_X_EXT_ADDRESS_DST_MASK:
++#ifdef NAT_TRAVERSAL
++      case SADB_X_EXT_NAT_T_OA:
++#endif
++              break;
++      default:
++              ERROR(
++                      "pfkey_address_parse: "
++                      "unexpected ext_type=%d.\n",
++                      pfkey_address->sadb_address_exttype);
++              SENDERR(ENOPKG);
++      }
++
++      switch(s->sa_family) {
++      case AF_INET:
++              saddr_len = sizeof(struct sockaddr_in);
++              sprintf(ipaddr_txt, "%d.%d.%d.%d"
++                      , (((struct sockaddr_in*)s)->sin_addr.s_addr >>  0) & 0xFF
++                      , (((struct sockaddr_in*)s)->sin_addr.s_addr >>  8) & 0xFF
++                      , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF
++                      , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF);
++              DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                        "pfkey_address_parse: "
++                        "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n",
++                        pfkey_address->sadb_address_exttype,
++                        pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype),
++                        s->sa_family,
++                        ipaddr_txt,
++                        pfkey_address->sadb_address_proto,
++                        ntohs(((struct sockaddr_in*)s)->sin_port));
++              break;
++      case AF_INET6:
++              saddr_len = sizeof(struct sockaddr_in6);
++              sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x"
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0])
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1])
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2])
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3])
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4])
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5])
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6])
++                      , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7]));
++              DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                        "pfkey_address_parse: "
++                        "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n",
++                        pfkey_address->sadb_address_exttype,
++                        pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype),
++                        s->sa_family,
++                        ipaddr_txt,
++                        pfkey_address->sadb_address_proto,
++                        ((struct sockaddr_in6*)s)->sin6_port);
++              break;
++      default:
++              ERROR(
++                      "pfkey_address_parse: "
++                      "s->sa_family=%d not supported.\n",
++                      s->sa_family);
++              SENDERR(EPFNOSUPPORT);
++      }
++      
++      if(pfkey_address->sadb_address_len !=
++         DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) {
++              ERROR(
++                        "pfkey_address_parse: "
++                        "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
++                        pfkey_address->sadb_address_len,
++                        (int)sizeof(struct sadb_address),
++                        saddr_len);
++              SENDERR(EINVAL);
++      }
++      
++      if(pfkey_address->sadb_address_prefixlen != 0) {
++              ERROR(
++                      "pfkey_address_parse: "
++                      "address prefixes not supported yet.\n");
++              SENDERR(EAFNOSUPPORT); /* not supported yet */
++      }
++      
++      /* XXX check if port!=0 */
++      
++      DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++              "pfkey_address_parse: successful.\n");
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_key_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_key *pfkey_key = (struct sadb_key *)pfkey_ext;
++
++      /* sanity checks... */
++
++      if(!pfkey_key) {
++              ERROR(
++                      "pfkey_key_parse: "
++                      "NULL pointer passed in.\n");
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) {
++              ERROR(
++                        "pfkey_key_parse: "
++                        "size wrong ext_len=%d, key_ext_len=%d.\n",
++                        pfkey_key->sadb_key_len,
++                        (int)sizeof(struct sadb_key));
++              SENDERR(EINVAL);
++      }
++
++      if(!pfkey_key->sadb_key_bits) {
++              ERROR(
++                      "pfkey_key_parse: "
++                      "key length set to zero, must be non-zero.\n");
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_key->sadb_key_len !=
++         DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits,
++               PFKEYBITS)) {
++              ERROR(
++                      "pfkey_key_parse: "
++                      "key length=%d does not agree with extension length=%d.\n",
++                      pfkey_key->sadb_key_bits,
++                      pfkey_key->sadb_key_len);
++              SENDERR(EINVAL);
++      }
++      
++      if(pfkey_key->sadb_key_reserved) {
++              ERROR(
++                      "pfkey_key_parse: "
++                      "res=%d, must be zero.\n",
++                      pfkey_key->sadb_key_reserved);
++              SENDERR(EINVAL);
++      }
++
++      if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ||
++             (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) {
++              ERROR(
++                      "pfkey_key_parse: "
++                      "expecting extension type AUTH or ENCRYPT, got %d.\n",
++                      pfkey_key->sadb_key_exttype);
++              SENDERR(EINVAL);
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                "pfkey_key_parse: "
++                "success, found len=%d exttype=%d(%s) bits=%d reserved=%d.\n",
++                pfkey_key->sadb_key_len,
++                pfkey_key->sadb_key_exttype,
++                pfkey_v2_sadb_ext_string(pfkey_key->sadb_key_exttype),
++                pfkey_key->sadb_key_bits,
++                pfkey_key->sadb_key_reserved);
++
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_ident_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_ident *pfkey_ident = (struct sadb_ident *)pfkey_ext;
++
++      /* sanity checks... */
++      if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
++              ERROR(
++                        "pfkey_ident_parse: "
++                        "size wrong ext_len=%d, key_ext_len=%d.\n",
++                        pfkey_ident->sadb_ident_len,
++                        (int)sizeof(struct sadb_ident));
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) {
++              ERROR(
++                      "pfkey_ident_parse: "
++                      "ident_type=%d out of range, must be less than %d.\n",
++                      pfkey_ident->sadb_ident_type,
++                      SADB_IDENTTYPE_MAX);
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_ident->sadb_ident_reserved) {
++              ERROR(
++                      "pfkey_ident_parse: "
++                      "res=%d, must be zero.\n",
++                      pfkey_ident->sadb_ident_reserved);
++              SENDERR(EINVAL);
++      }
++
++      /* string terminator/padding must be zero */
++      if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
++              if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) {
++                      ERROR(
++                              "pfkey_ident_parse: "
++                              "string padding must be zero, last is 0x%02x.\n",
++                              *((char*)pfkey_ident +
++                                pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1));
++                      SENDERR(EINVAL);
++              }
++      }
++      
++      if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ||
++             (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) {
++              ERROR(
++                      "pfkey_key_parse: "
++                      "expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n",
++                      pfkey_ident->sadb_ident_exttype);
++              SENDERR(EINVAL);
++      }
++
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_sens_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_sens *pfkey_sens = (struct sadb_sens *)pfkey_ext;
++
++      /* sanity checks... */
++      if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_sens_parse: "
++                        "size wrong ext_len=%d, key_ext_len=%d.\n",
++                        pfkey_sens->sadb_sens_len,
++                        (int)sizeof(struct sadb_sens));
++              SENDERR(EINVAL);
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++              "pfkey_sens_parse: "
++              "Sorry, I can't parse exttype=%d yet.\n",
++              pfkey_ext->sadb_ext_type);
++#if 0
++      SENDERR(EINVAL); /* don't process these yet */
++#endif
++
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_prop_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      int i, num_comb;
++      struct sadb_prop *pfkey_prop = (struct sadb_prop *)pfkey_ext;
++      struct sadb_comb *pfkey_comb = (struct sadb_comb *)((char*)pfkey_ext + sizeof(struct sadb_prop));
++
++      /* sanity checks... */
++      if((pfkey_prop->sadb_prop_len < sizeof(struct sadb_prop) / IPSEC_PFKEYv2_ALIGN) || 
++         (((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb))) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_prop_parse: "
++                        "size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n",
++                        pfkey_prop->sadb_prop_len,
++                        (int)sizeof(struct sadb_prop),
++                        (int)sizeof(struct sadb_comb));
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_prop->sadb_prop_replay > 64) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_prop_parse: "
++                      "replay window size: %d -- must be 0 <= size <= 64\n",
++                      pfkey_prop->sadb_prop_replay);
++              SENDERR(EINVAL);
++      }
++      
++      for(i=0; i<3; i++) {
++              if(pfkey_prop->sadb_prop_reserved[i]) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_prop_parse: "
++                              "res[%d]=%d, must be zero.\n",
++                              i, pfkey_prop->sadb_prop_reserved[i]);
++                      SENDERR(EINVAL);
++              }
++      }
++
++      num_comb = ((pfkey_prop->sadb_prop_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_prop)) / sizeof(struct sadb_comb);
++
++      for(i = 0; i < num_comb; i++) {
++              if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_prop_parse: "
++                              "pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n",
++                              i,
++                              pfkey_comb->sadb_comb_auth,
++                              SADB_AALG_MAX);
++                      SENDERR(EINVAL);
++              }
++
++              if(pfkey_comb->sadb_comb_auth) {
++                      if(!pfkey_comb->sadb_comb_auth_minbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n",
++                                      i);
++                              SENDERR(EINVAL);
++                      }
++                      if(!pfkey_comb->sadb_comb_auth_maxbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n",
++                                      i);
++                              SENDERR(EINVAL);
++                      }
++                      if(pfkey_comb->sadb_comb_auth_minbits > pfkey_comb->sadb_comb_auth_maxbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n",
++                                      i,
++                                      pfkey_comb->sadb_comb_auth_minbits,
++                                      pfkey_comb->sadb_comb_auth_maxbits);
++                              SENDERR(EINVAL);
++                      }
++              } else {
++                      if(pfkey_comb->sadb_comb_auth_minbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n",
++                                      i,
++                                      pfkey_comb->sadb_comb_auth_minbits);
++                              SENDERR(EINVAL);
++                      }
++                      if(pfkey_comb->sadb_comb_auth_maxbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n",
++                                      i,
++                                      pfkey_comb->sadb_comb_auth_maxbits);
++                              SENDERR(EINVAL);
++                      }
++              }
++
++#if SADB_EALG_MAX < 255       
++              if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_comb_parse: "
++                              "pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n",
++                              i,
++                              pfkey_comb->sadb_comb_encrypt,
++                              SADB_EALG_MAX);
++                      SENDERR(EINVAL);
++              }
++#endif
++
++              if(pfkey_comb->sadb_comb_encrypt) {
++                      if(!pfkey_comb->sadb_comb_encrypt_minbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n",
++                                      i);
++                              SENDERR(EINVAL);
++                      }
++                      if(!pfkey_comb->sadb_comb_encrypt_maxbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n",
++                                      i);
++                              SENDERR(EINVAL);
++                      }
++                      if(pfkey_comb->sadb_comb_encrypt_minbits > pfkey_comb->sadb_comb_encrypt_maxbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n",
++                                      i,
++                                      pfkey_comb->sadb_comb_encrypt_minbits,
++                                      pfkey_comb->sadb_comb_encrypt_maxbits);
++                              SENDERR(EINVAL);
++                      }
++              } else {
++                      if(pfkey_comb->sadb_comb_encrypt_minbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n",
++                                      i,
++                                      pfkey_comb->sadb_comb_encrypt_minbits);
++                              SENDERR(EINVAL);
++                      }
++                      if(pfkey_comb->sadb_comb_encrypt_maxbits) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_prop_parse: "
++                                      "pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n",
++                                      i,
++                                      pfkey_comb->sadb_comb_encrypt_maxbits);
++                              SENDERR(EINVAL);
++                      }
++              }
++
++              /* XXX do sanity check on flags */
++
++              if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                "pfkey_prop_parse: "
++                                "pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n",
++                                i,
++                                pfkey_comb->sadb_comb_soft_allocations,
++                                pfkey_comb->sadb_comb_hard_allocations);
++                      SENDERR(EINVAL);
++              }
++
++              if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                "pfkey_prop_parse: "
++                                "pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n",
++                                i,
++                                (unsigned long long int)pfkey_comb->sadb_comb_soft_bytes,
++                                (unsigned long long int)pfkey_comb->sadb_comb_hard_bytes);
++                      SENDERR(EINVAL);
++              }
++
++              if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                "pfkey_prop_parse: "
++                                "pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n",
++                                i,
++                                (unsigned long long int)pfkey_comb->sadb_comb_soft_addtime,
++                                (unsigned long long int)pfkey_comb->sadb_comb_hard_addtime);
++                      SENDERR(EINVAL);
++              }
++
++              if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                "pfkey_prop_parse: "
++                                "pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n",
++                                i,
++                                (unsigned long long int)pfkey_comb->sadb_comb_soft_usetime,
++                                (unsigned long long int)pfkey_comb->sadb_comb_hard_usetime);
++                      SENDERR(EINVAL);
++              }
++
++              if(pfkey_comb->sadb_x_comb_hard_packets && pfkey_comb->sadb_x_comb_soft_packets > pfkey_comb->sadb_x_comb_hard_packets) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_prop_parse: "
++                              "pfkey_comb[%d]->sadb_x_comb_soft_packets=%d > hard_packets=%d, fatal.\n",
++                              i,
++                              pfkey_comb->sadb_x_comb_soft_packets,
++                              pfkey_comb->sadb_x_comb_hard_packets);
++                      SENDERR(EINVAL);
++              }
++
++              if(pfkey_comb->sadb_comb_reserved) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_prop_parse: "
++                              "comb[%d].res=%d, must be zero.\n",
++                              i,
++                              pfkey_comb->sadb_comb_reserved);
++                      SENDERR(EINVAL);
++              }
++              pfkey_comb++;
++      }
++
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_supported_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      unsigned int i, num_alg;
++      struct sadb_supported *pfkey_supported = (struct sadb_supported *)pfkey_ext;
++      struct sadb_alg *pfkey_alg = (struct sadb_alg*)((char*)pfkey_ext + sizeof(struct sadb_supported));
++
++      /* sanity checks... */
++      if((pfkey_supported->sadb_supported_len <
++         sizeof(struct sadb_supported) / IPSEC_PFKEYv2_ALIGN) ||
++         (((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) -
++           sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) {
++
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_supported_parse: "
++                        "size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n",
++                        pfkey_supported->sadb_supported_len,
++                        (int)sizeof(struct sadb_supported),
++                        (int)sizeof(struct sadb_alg));
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_supported->sadb_supported_reserved) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_supported_parse: "
++                      "res=%d, must be zero.\n",
++                      pfkey_supported->sadb_supported_reserved);
++              SENDERR(EINVAL);
++      }
++
++      num_alg = ((pfkey_supported->sadb_supported_len * IPSEC_PFKEYv2_ALIGN) - sizeof(struct sadb_supported)) / sizeof(struct sadb_alg);
++
++      for(i = 0; i < num_alg; i++) {
++              /* process algo description */
++              if(pfkey_alg->sadb_alg_reserved) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_supported_parse: "
++                              "alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n",
++                              i,
++                              pfkey_alg->sadb_alg_id,
++                              pfkey_alg->sadb_alg_ivlen,
++                              pfkey_alg->sadb_alg_minbits,
++                              pfkey_alg->sadb_alg_maxbits,
++                              pfkey_alg->sadb_alg_reserved);
++                      SENDERR(EINVAL);
++              }
++
++              /* XXX can alg_id auth/enc be determined from info given?
++                 Yes, but OpenBSD's method does not iteroperate with rfc2367.
++                 rgb, 2000-04-06 */
++
++              switch(pfkey_supported->sadb_supported_exttype) {
++              case SADB_EXT_SUPPORTED_AUTH:
++                      if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_supported_parse: "
++                                      "alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n",
++                                      i,
++                                      pfkey_alg->sadb_alg_id,
++                                      SADB_AALG_MAX);
++                              SENDERR(EINVAL);
++                      }
++                      break;
++              case SADB_EXT_SUPPORTED_ENCRYPT:
++#if SADB_EALG_MAX < 255       
++                      if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_supported_parse: "
++                                      "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
++                                      i,
++                                      pfkey_alg->sadb_alg_id,
++                                      SADB_EALG_MAX);
++                              SENDERR(EINVAL);
++                      }
++#endif
++                      break;
++              default:
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_supported_parse: "
++                              "alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
++                              i,
++                              pfkey_alg->sadb_alg_id,
++                              SADB_EALG_MAX);
++                      SENDERR(EINVAL);
++              }
++              pfkey_alg++;
++      }
++      
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_spirange_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_spirange *pfkey_spirange = (struct sadb_spirange *)pfkey_ext;
++      
++      /* sanity checks... */
++        if(pfkey_spirange->sadb_spirange_len !=
++         sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_spirange_parse: "
++                        "size wrong ext_len=%d, key_ext_len=%d.\n",
++                        pfkey_spirange->sadb_spirange_len,
++                        (int)sizeof(struct sadb_spirange));
++                SENDERR(EINVAL);
++        }
++      
++        if(pfkey_spirange->sadb_spirange_reserved) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_spirange_parse: "
++                      "reserved=%d must be set to zero.\n",
++                      pfkey_spirange->sadb_spirange_reserved);
++                SENDERR(EINVAL);
++        }
++      
++        if(ntohl(pfkey_spirange->sadb_spirange_max) < ntohl(pfkey_spirange->sadb_spirange_min)) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_spirange_parse: "
++                      "minspi=%08x must be < maxspi=%08x.\n",
++                      ntohl(pfkey_spirange->sadb_spirange_min),
++                      ntohl(pfkey_spirange->sadb_spirange_max));
++                SENDERR(EINVAL);
++        }
++      
++      if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_spirange_parse: "
++                      "minspi=%08x must be > 255.\n",
++                      ntohl(pfkey_spirange->sadb_spirange_min));
++              SENDERR(EEXIST);
++      }
++      
++      DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                "pfkey_spirange_parse: "
++                "ext_len=%u ext_type=%u(%s) min=%u max=%u res=%u.\n",
++                pfkey_spirange->sadb_spirange_len,
++                pfkey_spirange->sadb_spirange_exttype,
++                pfkey_v2_sadb_ext_string(pfkey_spirange->sadb_spirange_exttype),
++                pfkey_spirange->sadb_spirange_min,
++                pfkey_spirange->sadb_spirange_max,
++                pfkey_spirange->sadb_spirange_reserved);
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_kmprivate_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_x_kmprivate *pfkey_x_kmprivate = (struct sadb_x_kmprivate *)pfkey_ext;
++
++      /* sanity checks... */
++      if(pfkey_x_kmprivate->sadb_x_kmprivate_len <
++         sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_x_kmprivate_parse: "
++                        "size wrong ext_len=%d, key_ext_len=%d.\n",
++                        pfkey_x_kmprivate->sadb_x_kmprivate_len,
++                        (int)sizeof(struct sadb_x_kmprivate));
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_x_kmprivate_parse: "
++                        "reserved=%d must be set to zero.\n",
++                        pfkey_x_kmprivate->sadb_x_kmprivate_reserved);
++              SENDERR(EINVAL);
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                "pfkey_x_kmprivate_parse: "
++                "Sorry, I can't parse exttype=%d yet.\n",
++                pfkey_ext->sadb_ext_type);
++      SENDERR(EINVAL); /* don't process these yet */
++
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_satype_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      int i;
++      struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++              "pfkey_x_satype_parse: enter\n");
++      /* sanity checks... */
++      if(pfkey_x_satype->sadb_x_satype_len !=
++         sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_x_satype_parse: "
++                        "size wrong ext_len=%d, key_ext_len=%d.\n",
++                        pfkey_x_satype->sadb_x_satype_len,
++                        (int)sizeof(struct sadb_x_satype));
++              SENDERR(EINVAL);
++      }
++      
++      if(!pfkey_x_satype->sadb_x_satype_satype) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_x_satype_parse: "
++                      "satype is zero, must be non-zero.\n");
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_x_satype->sadb_x_satype_satype > SADB_SATYPE_MAX) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_x_satype_parse: "
++                      "satype %d > max %d, invalid.\n", 
++                      pfkey_x_satype->sadb_x_satype_satype, SADB_SATYPE_MAX);
++              SENDERR(EINVAL);
++      }
++
++      if(!(satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_x_satype_parse: "
++                      "proto lookup from satype=%d failed.\n",
++                      pfkey_x_satype->sadb_x_satype_satype);
++              SENDERR(EINVAL);
++      }
++
++      for(i = 0; i < 3; i++) {
++              if(pfkey_x_satype->sadb_x_satype_reserved[i]) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_x_satype_parse: "
++                              "reserved[%d]=%d must be set to zero.\n",
++                              i, pfkey_x_satype->sadb_x_satype_reserved[i]);
++                      SENDERR(EINVAL);
++              }
++      }
++      
++      DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                "pfkey_x_satype_parse: "
++                "len=%u ext=%u(%s) satype=%u(%s) res=%u,%u,%u.\n",
++                pfkey_x_satype->sadb_x_satype_len,
++                pfkey_x_satype->sadb_x_satype_exttype,
++                pfkey_v2_sadb_ext_string(pfkey_x_satype->sadb_x_satype_exttype),
++                pfkey_x_satype->sadb_x_satype_satype,
++                satype2name(pfkey_x_satype->sadb_x_satype_satype),
++                pfkey_x_satype->sadb_x_satype_reserved[0],
++                pfkey_x_satype->sadb_x_satype_reserved[1],
++                pfkey_x_satype->sadb_x_satype_reserved[2]);
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_ext_debug_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      int i;
++      struct sadb_x_debug *pfkey_x_debug = (struct sadb_x_debug *)pfkey_ext;
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++              "pfkey_x_debug_parse: enter\n");
++      /* sanity checks... */
++      if(pfkey_x_debug->sadb_x_debug_len !=
++         sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_x_debug_parse: "
++                        "size wrong ext_len=%d, key_ext_len=%d.\n",
++                        pfkey_x_debug->sadb_x_debug_len,
++                        (int)sizeof(struct sadb_x_debug));
++              SENDERR(EINVAL);
++      }
++      
++      for(i = 0; i < 4; i++) {
++              if(pfkey_x_debug->sadb_x_debug_reserved[i]) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_x_debug_parse: "
++                              "reserved[%d]=%d must be set to zero.\n",
++                              i, pfkey_x_debug->sadb_x_debug_reserved[i]);
++                      SENDERR(EINVAL);
++              }
++      }
++      
++errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_ext_protocol_parse(struct sadb_ext *pfkey_ext)
++{
++      int error = 0;
++      struct sadb_protocol *p = (struct sadb_protocol *)pfkey_ext;
++      
++      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_x_protocol_parse:\n");
++      /* sanity checks... */
++      
++      if (p->sadb_protocol_len != sizeof(*p)/IPSEC_PFKEYv2_ALIGN) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_x_protocol_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
++                        p->sadb_protocol_len, (int)sizeof(*p));
++              SENDERR(EINVAL);
++      }
++      
++      if (p->sadb_protocol_reserved2 != 0) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                        "pfkey_protocol_parse: res=%d, must be zero.\n",
++                        p->sadb_protocol_reserved2);
++              SENDERR(EINVAL);
++      }
++
++ errlab:
++      return error;
++}
++
++#ifdef NAT_TRAVERSAL
++DEBUG_NO_STATIC int
++pfkey_x_ext_nat_t_type_parse(struct sadb_ext *pfkey_ext)
++{
++      return 0;
++}
++DEBUG_NO_STATIC int
++pfkey_x_ext_nat_t_port_parse(struct sadb_ext *pfkey_ext)
++{
++      return 0;
++}
++#endif
++
++#define DEFINEPARSER(NAME) static struct pf_key_ext_parsers_def NAME##_def={NAME, #NAME};
++
++DEFINEPARSER(pfkey_sa_parse);
++DEFINEPARSER(pfkey_lifetime_parse);
++DEFINEPARSER(pfkey_address_parse);
++DEFINEPARSER(pfkey_key_parse);
++DEFINEPARSER(pfkey_ident_parse);
++DEFINEPARSER(pfkey_sens_parse);
++DEFINEPARSER(pfkey_prop_parse);
++DEFINEPARSER(pfkey_supported_parse);
++DEFINEPARSER(pfkey_spirange_parse);
++DEFINEPARSER(pfkey_x_kmprivate_parse);
++DEFINEPARSER(pfkey_x_satype_parse);
++DEFINEPARSER(pfkey_x_ext_debug_parse);
++DEFINEPARSER(pfkey_x_ext_protocol_parse);
++#ifdef NAT_TRAVERSAL
++DEFINEPARSER(pfkey_x_ext_nat_t_type_parse);
++DEFINEPARSER(pfkey_x_ext_nat_t_port_parse);
++#endif
++
++struct pf_key_ext_parsers_def *ext_default_parsers[]=
++{
++      NULL,                 /* pfkey_msg_parse, */
++      &pfkey_sa_parse_def,
++      &pfkey_lifetime_parse_def,
++      &pfkey_lifetime_parse_def,
++      &pfkey_lifetime_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_key_parse_def,
++      &pfkey_key_parse_def,
++      &pfkey_ident_parse_def,
++      &pfkey_ident_parse_def,
++      &pfkey_sens_parse_def,
++      &pfkey_prop_parse_def,
++      &pfkey_supported_parse_def,
++      &pfkey_supported_parse_def,
++      &pfkey_spirange_parse_def,
++      &pfkey_x_kmprivate_parse_def,
++      &pfkey_x_satype_parse_def,
++      &pfkey_sa_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_address_parse_def,
++      &pfkey_x_ext_debug_parse_def,
++      &pfkey_x_ext_protocol_parse_def
++#ifdef NAT_TRAVERSAL
++      ,
++      &pfkey_x_ext_nat_t_type_parse_def,
++      &pfkey_x_ext_nat_t_port_parse_def,
++      &pfkey_x_ext_nat_t_port_parse_def,
++      &pfkey_address_parse_def
++#endif
++};
++
++int
++pfkey_msg_parse(struct sadb_msg *pfkey_msg,
++              struct pf_key_ext_parsers_def *ext_parsers[],
++              struct sadb_ext *extensions[],
++              int dir)
++{
++      int error = 0;
++      int remain;
++      struct sadb_ext *pfkey_ext;
++      int extensions_seen = 0;
++      
++      DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                "pfkey_msg_parse: "
++                "parsing message ver=%d, type=%d(%s), errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", 
++                pfkey_msg->sadb_msg_version,
++                pfkey_msg->sadb_msg_type,
++                pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type),
++                pfkey_msg->sadb_msg_errno,
++                pfkey_msg->sadb_msg_satype,
++                satype2name(pfkey_msg->sadb_msg_satype),
++                pfkey_msg->sadb_msg_len,
++                pfkey_msg->sadb_msg_reserved,
++                pfkey_msg->sadb_msg_seq,
++                pfkey_msg->sadb_msg_pid);
++      
++      if(ext_parsers == NULL) ext_parsers = ext_default_parsers;
++      
++      pfkey_extensions_init(extensions);
++      
++      remain = pfkey_msg->sadb_msg_len;
++      remain -= sizeof(struct sadb_msg) / IPSEC_PFKEYv2_ALIGN;
++      
++      pfkey_ext = (struct sadb_ext*)((char*)pfkey_msg +
++                                     sizeof(struct sadb_msg));
++      
++      extensions[0] = (struct sadb_ext *) pfkey_msg;
++      
++      
++      if(pfkey_msg->sadb_msg_version != PF_KEY_V2) {
++              ERROR("pfkey_msg_parse: "
++                      "not PF_KEY_V2 msg, found %d, should be %d.\n",
++                      pfkey_msg->sadb_msg_version,
++                      PF_KEY_V2);
++              SENDERR(EINVAL);
++      }
++
++      if(!pfkey_msg->sadb_msg_type) {
++              ERROR("pfkey_msg_parse: "
++                      "msg type not set, must be non-zero..\n");
++              SENDERR(EINVAL);
++      }
++
++      if(pfkey_msg->sadb_msg_type > SADB_MAX) {
++              ERROR("pfkey_msg_parse: "
++                      "msg type=%d > max=%d.\n",
++                      pfkey_msg->sadb_msg_type,
++                      SADB_MAX);
++              SENDERR(EINVAL);
++      }
++
++      switch(pfkey_msg->sadb_msg_type) {
++      case SADB_GETSPI:
++      case SADB_UPDATE:
++      case SADB_ADD:
++      case SADB_DELETE:
++      case SADB_GET:
++      case SADB_X_GRPSA:
++      case SADB_X_ADDFLOW:
++              if(!satype2proto(pfkey_msg->sadb_msg_satype)) {
++                      ERROR("pfkey_msg_parse: "
++                                "satype %d conversion to proto failed for msg_type %d (%s).\n",
++                                pfkey_msg->sadb_msg_satype,
++                                pfkey_msg->sadb_msg_type,
++                                pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
++                      SENDERR(EINVAL);
++              } else {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                "pfkey_msg_parse: "
++                                "satype %d(%s) conversion to proto gives %d for msg_type %d(%s).\n",
++                                pfkey_msg->sadb_msg_satype,
++                                satype2name(pfkey_msg->sadb_msg_satype),
++                                satype2proto(pfkey_msg->sadb_msg_satype),
++                                pfkey_msg->sadb_msg_type,
++                                pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
++              }
++      case SADB_ACQUIRE:
++      case SADB_REGISTER:
++      case SADB_EXPIRE:
++              if(!pfkey_msg->sadb_msg_satype) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                "pfkey_msg_parse: "
++                                "satype is zero, must be non-zero for msg_type %d(%s).\n",
++                                pfkey_msg->sadb_msg_type,
++                                pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type));
++                      SENDERR(EINVAL);
++              }
++      default:
++              break;
++      }
++      
++      /* errno must not be set in downward messages */
++      /* this is not entirely true... a response to an ACQUIRE could return an error */
++      if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type != SADB_ACQUIRE) && pfkey_msg->sadb_msg_errno) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                          "pfkey_msg_parse: "
++                          "errno set to %d.\n",
++                          pfkey_msg->sadb_msg_errno);
++              SENDERR(EINVAL);
++      }
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++                "pfkey_msg_parse: "
++                "remain=%d\n", 
++                remain
++                );
++
++      DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++              "pfkey_msg_parse: "
++              "extensions permitted=%08x, required=%08x.\n",
++              extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
++              extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
++      
++      extensions_seen = 1;
++      
++      while( (remain * IPSEC_PFKEYv2_ALIGN) >= sizeof(struct sadb_ext) ) {
++              /* Is there enough message left to support another extension header? */
++              if(remain < pfkey_ext->sadb_ext_len) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_msg_parse: "
++                              "remain %d less than ext len %d.\n", 
++                              remain, pfkey_ext->sadb_ext_len);
++                      SENDERR(EINVAL);
++              }
++              
++              DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++                      "pfkey_msg_parse: "
++                      "parsing ext type=%d(%s) remain=%d.\n",
++                      pfkey_ext->sadb_ext_type,
++                      pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
++                      remain);
++              
++              /* Is the extension header type valid? */
++              if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_msg_parse: "
++                              "ext type %d(%s) invalid, SADB_EXT_MAX=%d.\n", 
++                              pfkey_ext->sadb_ext_type,
++                              pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
++                              SADB_EXT_MAX);
++                      SENDERR(EINVAL);
++              }
++              
++              /* Have we already seen this type of extension? */
++              if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0)
++              {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_msg_parse: "
++                              "ext type %d(%s) already seen.\n", 
++                              pfkey_ext->sadb_ext_type,
++                              pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
++                      SENDERR(EINVAL);
++              }
++
++              /* Do I even know about this type of extension? */
++              if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) {
++                      ERROR("pfkey_msg_parse: "
++                              "ext type %d(%s) unknown, ignoring.\n", 
++                              pfkey_ext->sadb_ext_type,
++                              pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
++                      goto next_ext;
++              }
++
++              /* Is this type of extension permitted for this type of message? */
++              if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] &
++                   1<<pfkey_ext->sadb_ext_type)) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_msg_parse: "
++                              "ext type %d(%s) not permitted, exts_perm_in=%08x, 1<<type=%08x\n", 
++                              pfkey_ext->sadb_ext_type, 
++                              pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
++                              extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
++                              1<<pfkey_ext->sadb_ext_type);
++                      SENDERR(EINVAL);
++              }
++
++              DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++                        "pfkey_msg_parse: "
++                        "remain=%d ext_type=%d(%s) ext_len=%d parsing ext 0p%p with parser %s.\n",
++                        remain,
++                        pfkey_ext->sadb_ext_type,
++                        pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
++                        pfkey_ext->sadb_ext_len,
++                        pfkey_ext,
++                        ext_parsers[pfkey_ext->sadb_ext_type]->parser_name);
++              
++              /* Parse the extension */
++              if((error =
++                  (*ext_parsers[pfkey_ext->sadb_ext_type]->parser)(pfkey_ext))) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_msg_parse: "
++                              "extension parsing for type %d(%s) failed with error %d.\n",
++                              pfkey_ext->sadb_ext_type,
++                              pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type),
++                              error); 
++                      SENDERR(-error);
++              }
++              DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
++                      "pfkey_msg_parse: "
++                      "Extension %d(%s) parsed.\n",
++                      pfkey_ext->sadb_ext_type,
++                      pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));
++              
++              /* Mark that we have seen this extension and remember the header location */
++              extensions_seen |= ( 1 << pfkey_ext->sadb_ext_type );
++              extensions[pfkey_ext->sadb_ext_type] = pfkey_ext;
++
++      next_ext:               
++              /* Calculate how much message remains */
++              remain -= pfkey_ext->sadb_ext_len;
++
++              if(!remain) {
++                      break;
++              }
++              /* Find the next extension header */
++              pfkey_ext = (struct sadb_ext*)((char*)pfkey_ext +
++                      pfkey_ext->sadb_ext_len * IPSEC_PFKEYv2_ALIGN);
++      }
++
++      if(remain) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_msg_parse: "
++                      "unexpected remainder of %d.\n", 
++                      remain);
++              /* why is there still something remaining? */
++              SENDERR(EINVAL);
++      }
++
++      /* check required extensions */
++      DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT,
++              "pfkey_msg_parse: "
++              "extensions permitted=%08x, seen=%08x, required=%08x.\n",
++              extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
++              extensions_seen,
++              extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]);
++
++      /* don't check further if it is an error return message since it
++         may not have a body */
++      if(pfkey_msg->sadb_msg_errno) {
++              SENDERR(-error);
++      }
++
++      if((extensions_seen &
++          extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) !=
++         extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_msg_parse: "
++                      "required extensions missing:%08x.\n",
++                      extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type] -
++                      (extensions_seen &
++                       extensions_bitmaps[dir][EXT_BITS_REQ][pfkey_msg->sadb_msg_type]));
++              SENDERR(EINVAL);
++      }
++      
++      if((dir == EXT_BITS_IN) && (pfkey_msg->sadb_msg_type == SADB_X_DELFLOW)
++         && ((extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW)
++             != SADB_X_EXT_ADDRESS_DELFLOW)
++         && (((extensions_seen & (1<<SADB_EXT_SA)) != (1<<SADB_EXT_SA))
++         || ((((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_flags
++              & SADB_X_SAFLAGS_CLEARFLOW)
++             != SADB_X_SAFLAGS_CLEARFLOW))) {
++              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                      "pfkey_msg_parse: "
++                      "required SADB_X_DELFLOW extensions missing: either %08x must be present or %08x must be present with SADB_X_SAFLAGS_CLEARFLOW set.\n",
++                      SADB_X_EXT_ADDRESS_DELFLOW
++                      - (extensions_seen & SADB_X_EXT_ADDRESS_DELFLOW),
++                      (1<<SADB_EXT_SA) - (extensions_seen & (1<<SADB_EXT_SA)));
++              SENDERR(EINVAL);
++      }
++      
++      switch(pfkey_msg->sadb_msg_type) {
++      case SADB_ADD:
++      case SADB_UPDATE:
++              /* check maturity */
++              if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state !=
++                 SADB_SASTATE_MATURE) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_msg_parse: "
++                              "state=%d for add or update should be MATURE=%d.\n",
++                              ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
++                              SADB_SASTATE_MATURE);
++                      SENDERR(EINVAL);
++              }
++              
++              /* check AH and ESP */
++              switch(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype) {
++              case SADB_SATYPE_AH:
++                      if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
++                           ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_auth !=
++                           SADB_AALG_NONE)) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_msg_parse: "
++                                      "auth alg is zero, must be non-zero for AH SAs.\n");
++                              SENDERR(EINVAL);
++                      }
++                      if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt !=
++                         SADB_EALG_NONE) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_msg_parse: "
++                                      "AH handed encalg=%d, must be zero.\n",
++                                      ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt);
++                              SENDERR(EINVAL);
++                      }
++                      break;
++              case SADB_SATYPE_ESP:
++                      if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
++                           ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
++                           SADB_EALG_NONE)) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_msg_parse: "
++                                      "encrypt alg=%d is zero, must be non-zero for ESP=%d SAs.\n",
++                                      ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
++                                      ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
++                              SENDERR(EINVAL);
++                      }
++                      if((((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt ==
++                          SADB_EALG_NULL) &&
++                         (((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth ==
++                          SADB_AALG_NONE) ) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_msg_parse: "
++                                      "ESP handed encNULL+authNONE, illegal combination.\n");
++                              SENDERR(EINVAL);
++                      }
++                      break;
++              case SADB_X_SATYPE_COMP:
++                      if(!(((struct sadb_sa*)extensions[SADB_EXT_SA]) &&
++                           ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt !=
++                           SADB_EALG_NONE)) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_msg_parse: "
++                                      "encrypt alg=%d is zero, must be non-zero for COMP=%d SAs.\n",
++                                      ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_encrypt,
++                                      ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
++                              SENDERR(EINVAL);
++                      }
++                      if(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth !=
++                         SADB_AALG_NONE) {
++                              DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                                      "pfkey_msg_parse: "
++                                      "COMP handed auth=%d, must be zero.\n",
++                                      ((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth);
++                              SENDERR(EINVAL);
++                      }
++                      break;
++              default:
++                      break;
++              }
++              if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) {
++                      DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM,
++                              "pfkey_msg_parse: "
++                              "spi=%08x must be > 255.\n",
++                              ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi));
++                      SENDERR(EINVAL);
++              }
++      default:        
++              break;
++      }
++errlab:
++
++      return error;
++}
++
++/*
++ * $Log: pfkey_v2_parse.c,v $
++ * Revision 1.65  2005/04/06 17:46:05  mcr
++ *    failure to recognize an extension is considered an error.
++ *    This could be a problem in the future, but we need some kind
++ *    of logging. This should be rate limited, probably.
++ *
++ * Revision 1.64  2005/01/26 00:50:35  mcr
++ *    adjustment of confusion of CONFIG_IPSEC_NAT vs CONFIG_KLIPS_NAT,
++ *    and make sure that NAT_TRAVERSAL is set as well to match
++ *    userspace compiles of code.
++ *
++ * Revision 1.63  2004/10/28 22:54:10  mcr
++ *    results from valgrind, thanks to: Harald Hoyer <harald@redhat.com>
++ *
++ * Revision 1.62  2004/10/03 01:26:36  mcr
++ *    fixes for gcc 3.4 compilation.
++ *
++ * Revision 1.61  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.59  2004/04/18 03:03:49  mcr
++ *    renamed common include files from pluto directory.
++ *
++ * Revision 1.58  2004/03/08 01:59:08  ken
++ * freeswan.h -> openswan.h
++ *
++ * Revision 1.57  2003/12/10 01:20:19  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.56  2003/12/04 23:01:12  mcr
++ *    removed ipsec_netlink.h
++ *
++ * Revision 1.55  2003/11/07 01:30:37  ken
++ * Cast sizeof() to int to keep things 64bit clean
++ *
++ * Revision 1.54  2003/10/31 02:27:12  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.53.20.2  2003/10/29 01:11:32  mcr
++ *    added debugging for pfkey library.
++ *
++ * Revision 1.53.20.1  2003/09/21 13:59:44  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.53  2003/01/30 02:32:09  rgb
++ *
++ * Rename SAref table macro names for clarity.
++ * Convert IPsecSAref_t from signed to unsigned to fix apparent SAref exhaustion bug.
++ *
++ * Revision 1.52  2002/12/30 06:53:07  mcr
++ *    deal with short SA structures... #if 0 out for now. Probably
++ *    not quite the right way.
++ *
++ * Revision 1.51  2002/12/13 18:16:02  mcr
++ *    restored sa_ref code
++ *
++ * Revision 1.50  2002/12/13 18:06:52  mcr
++ *    temporarily removed sadb_x_sa_ref reference for 2.xx
++ *
++ * Revision 1.49  2002/10/05 05:02:58  dhr
++ *
++ * C labels go on statements
++ *
++ * Revision 1.48  2002/09/20 15:40:45  rgb
++ * Added sadb_x_sa_ref to struct sadb_sa.
++ *
++ * Revision 1.47  2002/09/20 05:01:31  rgb
++ * Fixed usage of pfkey_lib_debug.
++ * Format for function declaration style consistency.
++ * Added text labels to elucidate numeric values presented.
++ * Re-organised debug output to reduce noise in output.
++ *
++ * Revision 1.46  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.45  2002/05/23 07:14:11  rgb
++ * Cleaned up %p variants to 0p%p for test suite cleanup.
++ *
++ * Revision 1.44  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.43  2002/04/24 07:36:40  mcr
++ * Moved from ./lib/pfkey_v2_parse.c,v
++ *
++ * Revision 1.42  2002/01/29 22:25:36  rgb
++ * Re-add ipsec_kversion.h to keep MALLOC happy.
++ *
++ * Revision 1.41  2002/01/29 01:59:10  mcr
++ *    removal of kversions.h - sources that needed it now use ipsec_param.h.
++ *    updating of IPv6 structures to match latest in6.h version.
++ *    removed dead code from openswan.h that also duplicated kversions.h
++ *    code.
++ *
++ * Revision 1.40  2002/01/20 20:34:50  mcr
++ *    added pfkey_v2_sadb_type_string to decode sadb_type to string.
++ *
++ * Revision 1.39  2001/11/27 05:29:22  mcr
++ *    pfkey parses are now maintained by a structure
++ *    that includes their name for debug purposes.
++ *    DEBUGGING() macro changed so that it takes a debug
++ *    level so that pf_key() can use this to decode the
++ *    structures without innundanting humans.
++ *    Also uses pfkey_v2_sadb_ext_string() in messages.
++ *
++ * Revision 1.38  2001/11/06 19:47:47  rgb
++ * Added packet parameter to lifetime and comb structures.
++ *
++ * Revision 1.37  2001/10/18 04:45:24  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/openswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.36  2001/06/14 19:35:16  rgb
++ * Update copyright date.
++ *
++ * Revision 1.35  2001/05/03 19:44:51  rgb
++ * Standardise on SENDERR() macro.
++ *
++ * Revision 1.34  2001/03/16 07:41:51  rgb
++ * Put openswan.h include before pluto includes.
++ *
++ * Revision 1.33  2001/02/27 07:13:51  rgb
++ * Added satype2name() function.
++ * Added text to default satype_tbl entry.
++ * Added satype2name() conversions for most satype debug output.
++ *
++ * Revision 1.32  2001/02/26 20:01:09  rgb
++ * Added internal IP protocol 61 for magic SAs.
++ * Ditch unused sadb_satype2proto[], replaced by satype2proto().
++ * Re-formatted debug output (split lines, consistent spacing).
++ * Removed acquire, register and expire requirements for a known satype.
++ * Changed message type checking to a switch structure.
++ * Verify expected NULL auth for IPCOMP.
++ * Enforced spi > 0x100 requirement, now that pass uses a magic SA for
++ * appropriate message types.
++ *
++ * Revision 1.31  2000/12/01 07:09:00  rgb
++ * Added ipcomp sanity check to require encalgo is set.
++ *
++ * Revision 1.30  2000/11/17 18:10:30  rgb
++ * Fixed bugs mostly relating to spirange, to treat all spi variables as
++ * network byte order since this is the way PF_KEYv2 stored spis.
++ *
++ * Revision 1.29  2000/10/12 00:02:39  rgb
++ * Removed 'format, ##' nonsense from debug macros for RH7.0.
++ *
++ * Revision 1.28  2000/09/20 16:23:04  rgb
++ * Remove over-paranoid extension check in the presence of sadb_msg_errno.
++ *
++ * Revision 1.27  2000/09/20 04:04:21  rgb
++ * Changed static functions to DEBUG_NO_STATIC to reveal function names in
++ * oopsen.
++ *
++ * Revision 1.26  2000/09/15 11:37:02  rgb
++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++ * IPCOMP zlib deflate code.
++ *
++ * Revision 1.25  2000/09/12 22:35:37  rgb
++ * Restructured to remove unused extensions from CLEARFLOW messages.
++ *
++ * Revision 1.24  2000/09/12 18:59:54  rgb
++ * Added Gerhard's IPv6 support to pfkey parts of libopenswan.
++ *
++ * Revision 1.23  2000/09/12 03:27:00  rgb
++ * Moved DEBUGGING definition to compile kernel with debug off.
++ *
++ * Revision 1.22  2000/09/09 06:39:27  rgb
++ * Restrict pfkey errno check to downward messages only.
++ *
++ * Revision 1.21  2000/09/08 19:22:34  rgb
++ * Enabled pfkey_sens_parse().
++ * Added check for errno on downward acquire messages only.
++ *
++ * Revision 1.20  2000/09/01 18:48:23  rgb
++ * Fixed reserved check bug and added debug output in
++ * pfkey_supported_parse().
++ * Fixed debug output label bug in pfkey_ident_parse().
++ *
++ * Revision 1.19  2000/08/27 01:55:26  rgb
++ * Define OCTETBITS and PFKEYBITS to avoid using 'magic' numbers in code.
++ *
++ * Revision 1.18  2000/08/24 17:00:36  rgb
++ * Ignore unknown extensions instead of failing.
++ *
++ * Revision 1.17  2000/06/02 22:54:14  rgb
++ * Added Gerhard Gessler's struct sockaddr_storage mods for IPv6 support.
++ *
++ * Revision 1.16  2000/05/10 19:25:11  rgb
++ * Fleshed out proposal and supported extensions.
++ *
++ * Revision 1.15  2000/01/24 21:15:31  rgb
++ * Added disabled pluto pfkey lib debug flag.
++ * Added algo debugging reporting.
++ *
++ * Revision 1.14  2000/01/22 23:24:29  rgb
++ * Added new functions proto2satype() and satype2proto() and lookup
++ * table satype_tbl.  Also added proto2name() since it was easy.
++ *
++ * Revision 1.13  2000/01/21 09:43:59  rgb
++ * Cast ntohl(spi) as (unsigned long int) to shut up compiler.
++ *
++ * Revision 1.12  2000/01/21 06:28:19  rgb
++ * Added address cases for eroute flows.
++ * Indented compiler directives for readability.
++ * Added klipsdebug switching capability.
++ *
++ * Revision 1.11  1999/12/29 21:14:59  rgb
++ * Fixed debug text cut and paste typo.
++ *
++ * Revision 1.10  1999/12/10 17:45:24  rgb
++ * Added address debugging.
++ *
++ * Revision 1.9  1999/12/09 23:11:42  rgb
++ * Ditched <string.h> include since we no longer use memset().
++ * Use new pfkey_extensions_init() instead of memset().
++ * Added check for SATYPE in pfkey_msg_build().
++ * Tidy up comments and debugging comments.
++ *
++ * Revision 1.8  1999/12/07 19:55:26  rgb
++ * Removed unused first argument from extension parsers.
++ * Removed static pluto debug flag.
++ * Moved message type and state checking to pfkey_msg_parse().
++ * Changed print[fk] type from lx to x to quiet compiler.
++ * Removed redundant remain check.
++ * Changed __u* types to uint* to avoid use of asm/types.h and
++ * sys/types.h in userspace code.
++ *
++ * Revision 1.7  1999/12/01 22:20:51  rgb
++ * Moved pfkey_lib_debug variable into the library.
++ * Added pfkey version check into header parsing.
++ * Added check for SATYPE only for those extensions that require a
++ * non-zero value.
++ *
++ * Revision 1.6  1999/11/27 11:58:05  rgb
++ * Added ipv6 headers.
++ * Moved sadb_satype2proto protocol lookup table from
++ * klips/net/ipsec/pfkey_v2_parser.c.
++ * Enable lifetime_current checking.
++ * Debugging error messages added.
++ * Add argument to pfkey_msg_parse() for direction.
++ * Consolidated the 4 1-d extension bitmap arrays into one 4-d array.
++ * Add CVS log entry to bottom of file.
++ * Moved auth and enc alg check to pfkey_msg_parse().
++ * Enable accidentally disabled spirange parsing.
++ * Moved protocol/algorithm checks from klips/net/ipsec/pfkey_v2_parser.c
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/pfkey_v2_parser.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,3520 @@
++/*
++ * @(#) RFC2367 PF_KEYv2 Key management API message parser
++ * Copyright (C) 1999, 2000, 2001  Richard Guy Briggs <rgb@freeswan.org>
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: pfkey_v2_parser.c,v 1.134.2.2 2006/10/06 21:39:26 paul Exp $
++ */
++
++/*
++ *            Template from klips/net/ipsec/ipsec/ipsec_netlink.c.
++ */
++
++char pfkey_v2_parser_c_version[] = "$Id: pfkey_v2_parser.c,v 1.134.2.2 2006/10/06 21:39:26 paul Exp $";
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++
++#include <openswan.h>
++
++#include <crypto/des.h>
++
++#ifdef SPINLOCK
++# ifdef SPINLOCK_23
++#  include <linux/spinlock.h> /* *lock* */
++# else /* SPINLOCK_23 */
++#  include <asm/spinlock.h> /* *lock* */
++# endif /* SPINLOCK_23 */
++#endif /* SPINLOCK */
++
++#include <linux/in6.h>
++#include <net/route.h>
++
++#include <net/ip.h>
++#ifdef NETLINK_SOCK
++# include <linux/netlink.h>
++#else
++# include <net/netlink.h>
++#endif
++
++#include <linux/random.h>     /* get_random_bytes() */
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_sa.h"
++
++#include "openswan/ipsec_radij.h"
++#include "openswan/ipsec_xform.h"
++#include "openswan/ipsec_ah.h"
++#include "openswan/ipsec_esp.h"
++#include "openswan/ipsec_tunnel.h"
++#include "openswan/ipsec_rcv.h"
++#include "openswan/ipcomp.h"
++
++#include <pfkeyv2.h>
++#include <pfkey.h>
++
++#include "openswan/ipsec_proto.h"
++#include "openswan/ipsec_alg.h"
++
++#include "openswan/ipsec_kern24.h"
++
++#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
++
++struct sklist_t {
++      struct socket *sk;
++      struct sklist_t* next;
++} pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev;
++
++__u32 pfkey_msg_seq = 0;
++
++
++#if 0
++#define DUMP_SAID dump_said(&extr->ips->ips_said, __LINE__)
++#define DUMP_SAID2 dump_said(&extr.ips->ips_said, __LINE__)
++static void dump_said(ip_said *s, int line)
++{ 
++      char msa[SATOT_BUF];
++      size_t msa_len;
++      
++      msa_len = satot(s, 0, msa, sizeof(msa));
++      
++      printk("line: %d msa: %s\n", line, msa);
++}
++#endif
++
++
++int
++pfkey_alloc_eroute(struct eroute** eroute)
++{
++      int error = 0;
++      if(*eroute) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_alloc_eroute: "
++                          "eroute struct already allocated\n");
++              SENDERR(EEXIST);
++      }
++
++      if((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_alloc_eroute: "
++                          "memory allocation error\n");
++              SENDERR(ENOMEM);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_alloc_eroute: "
++                  "allocating %lu bytes for an eroute at 0p%p\n",
++                  (unsigned long) sizeof(**eroute), *eroute);
++
++      memset((caddr_t)*eroute, 0, sizeof(**eroute));
++      (*eroute)->er_eaddr.sen_len =
++              (*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap);
++      (*eroute)->er_eaddr.sen_family =
++              (*eroute)->er_emask.sen_family = AF_ENCAP;
++      (*eroute)->er_eaddr.sen_type = SENT_IP4;
++      (*eroute)->er_emask.sen_type = 255;
++      (*eroute)->er_pid = 0;
++      (*eroute)->er_count = 0;
++      (*eroute)->er_lasttime = jiffies/HZ;
++
++ errlab:
++      return(error);
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_protocol_process(struct sadb_ext *pfkey_ext,
++                       struct pfkey_extracted_data *extr)
++{
++      int error = 0;
++      struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext;
++
++      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: %p\n", extr);
++
++      if (extr == 0) {
++              KLIPS_PRINT(debug_pfkey,
++                         "klips_debug:pfkey_x_protocol_process:"
++                          "extr is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++      if (extr->eroute == 0) {
++              KLIPS_PRINT(debug_pfkey,
++                        "klips_debug:pfkey_x_protocol_process:"
++                          "extr->eroute is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto;
++      extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0:0;
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_protocol_process: protocol = %d.\n",
++                  p->sadb_protocol_proto);
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_ipsec_sa_init(struct ipsec_sa *ipsp)
++{
++
++      return ipsec_sa_init(ipsp);
++}
++
++int
++pfkey_safe_build(int error, struct sadb_ext *extensions[SADB_MAX+1])
++{
++      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: "
++                  "error=%d\n",
++                  error);
++      if (!error) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:"
++                          "success.\n");
++              return 1;
++      } else {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:"
++                          "caught error %d\n",
++                          error);
++              pfkey_extensions_free(extensions);
++              return 0;
++      }
++}
++
++
++DEBUG_NO_STATIC int
++pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L);
++      int found_avail = 0;
++      struct ipsec_sa *ipsq;
++      char sa[SATOT_BUF];
++      size_t sa_len;
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_getspi_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      if(extr == NULL || extr->ips == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_getspi_parse: "
++                          "error, extr or extr->ipsec_sa pointer NULL\n");
++              SENDERR(EINVAL);
++      }
++
++      if(extensions[SADB_EXT_SPIRANGE]) {
++              minspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_min;
++              maxspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_max;
++      }
++
++      if(maxspi == minspi) {
++              extr->ips->ips_said.spi = maxspi;
++              ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said));
++              if(ipsq != NULL) {
++                      sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa));
++                      ipsec_sa_put(ipsq);
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_getspi_parse: "
++                                  "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n",
++                                  sa_len ? sa : " (error)");
++                      SENDERR(EEXIST);
++              } else {
++                      found_avail = 1;
++              }
++      } else {
++              int i = 0;
++              __u32 rand_val;
++              __u32 spi_diff;
++              while( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) {
++                      prng_bytes(&ipsec_prng, (char *) &(rand_val),
++                                       ( (spi_diff < (2^8))  ? 1 :
++                                         ( (spi_diff < (2^16)) ? 2 :
++                                           ( (spi_diff < (2^24)) ? 3 :
++                                         4 ) ) ) );
++                      extr->ips->ips_said.spi = htonl(ntohl(minspi) +
++                                            (rand_val %
++                                            (spi_diff + 1)));
++                      i++;
++                      ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said));
++                      if(ipsq == NULL) {
++                              found_avail = 1;
++                      } else {
++                              ipsec_sa_put(ipsq);
++                      }
++              }
++      }
++
++      sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa));
++
++      if (!found_avail) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_getspi_parse: "
++                          "found an old ipsec_sa for SA: %s, delete it first.\n",
++                          sa_len ? sa : " (error)");
++              SENDERR(EEXIST);
++      }
++
++      if(inet_addr_type((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == RTN_LOCAL) {
++              extr->ips->ips_flags |= EMT_INBOUND;
++      }
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_getspi_parse: "
++                  "existing ipsec_sa not found (this is good) for SA: %s, %s-bound, allocating.\n",
++                  sa_len ? sa : " (error)",
++                  extr->ips->ips_flags & EMT_INBOUND ? "in" : "out");
++      
++      /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/
++      extr->ips->ips_rcvif = NULL;
++      extr->ips->ips_life.ipl_addtime.ipl_count = jiffies/HZ;
++
++      extr->ips->ips_state = SADB_SASTATE_LARVAL;
++
++      if(!extr->ips->ips_life.ipl_allocations.ipl_count) {
++              extr->ips->ips_life.ipl_allocations.ipl_count += 1;
++      }
++
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_GETSPI,
++                                                        satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      0,
++                                                      SADB_SASTATE_LARVAL,
++                                                      0,
++                                                      0,
++                                                      0,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
++                                                   SADB_EXT_ADDRESS_SRC,
++                                                   0, /*extr->ips->ips_said.proto,*/
++                                                   0,
++                                                   extr->ips->ips_addr_s),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
++                                                   SADB_EXT_ADDRESS_DST,
++                                                   0, /*extr->ips->ips_said.proto,*/
++                                                   0,
++                                                   extr->ips->ips_addr_d),
++                               extensions_reply) )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
++                          "failed to build the getspi reply message extensions\n");
++              goto errlab;
++      }
++      
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
++                          "failed to build the getspi reply message\n");
++              SENDERR(-error);
++      }
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
++                                  "sending up getspi reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
++                          "sending up getspi reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++      if((error = ipsec_sa_add(extr->ips))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
++                          "failed to add the larval SA=%s with error=%d.\n",
++                          sa_len ? sa : " (error)",
++                          error);
++              SENDERR(-error);
++      }
++      extr->ips = NULL;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_getspi_parse: "
++                  "successful for SA: %s\n",
++                  sa_len ? sa : " (error)");
++      
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct ipsec_sa* ipsq;
++      char sa[SATOT_BUF];
++      size_t sa_len;
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      struct ipsec_sa *nat_t_ips_saved = NULL;
++#endif
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_update_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_update_parse: "
++                          "error, sa_state=%d must be MATURE=%d\n",
++                          ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
++                          SADB_SASTATE_MATURE);
++              SENDERR(EINVAL);
++      }
++
++      if(extr == NULL || extr->ips == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_update_parse: "
++                          "error, extr or extr->ips pointer NULL\n");
++              SENDERR(EINVAL);
++      }
++
++      sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa));
++
++      spin_lock_bh(&tdb_lock);
++
++      ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said));
++      if (ipsq == NULL) {
++              spin_unlock_bh(&tdb_lock);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_update_parse: "
++                          "reserved ipsec_sa for SA: %s not found.  Call SADB_GETSPI first or call SADB_ADD instead.\n",
++                          sa_len ? sa : " (error)");
++              SENDERR(ENOENT);
++      }
++
++      if(inet_addr_type((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == RTN_LOCAL) {
++              extr->ips->ips_flags |= EMT_INBOUND;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_update_parse: "
++                  "existing ipsec_sa found (this is good) for SA: %s, %s-bound, updating.\n",
++                  sa_len ? sa : " (error)",
++                  extr->ips->ips_flags & EMT_INBOUND ? "in" : "out");
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      if (extr->ips->ips_natt_sport || extr->ips->ips_natt_dport) {
++              KLIPS_PRINT(debug_pfkey,
++                      "klips_debug:pfkey_update_parse: only updating NAT-T ports "
++                      "(%u:%u -> %u:%u)\n", 
++                      ipsq->ips_natt_sport, ipsq->ips_natt_dport,
++                      extr->ips->ips_natt_sport, extr->ips->ips_natt_dport);
++
++              if (extr->ips->ips_natt_sport) {
++                      ipsq->ips_natt_sport = extr->ips->ips_natt_sport;
++                      if (ipsq->ips_addr_s->sa_family == AF_INET) {
++                              ((struct sockaddr_in *)(ipsq->ips_addr_s))->sin_port = htons(extr->ips->ips_natt_sport);
++                      }
++              }
++
++              if (extr->ips->ips_natt_dport) {
++                      ipsq->ips_natt_dport = extr->ips->ips_natt_dport;
++                      if (ipsq->ips_addr_d->sa_family == AF_INET) {
++                              ((struct sockaddr_in *)(ipsq->ips_addr_d))->sin_port = htons(extr->ips->ips_natt_dport);
++                      }
++              }
++
++              nat_t_ips_saved = extr->ips;
++              extr->ips = ipsq;
++      }
++      else {
++#endif
++      
++      /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/
++      extr->ips->ips_rcvif = NULL;
++      if ((error = pfkey_ipsec_sa_init(extr->ips))) {
++              ipsec_sa_put(ipsq);
++              spin_unlock_bh(&tdb_lock);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_update_parse: "
++                          "not successful for SA: %s, deleting.\n",
++                          sa_len ? sa : " (error)");
++              SENDERR(-error);
++      }
++
++      extr->ips->ips_life.ipl_addtime.ipl_count = ipsq->ips_life.ipl_addtime.ipl_count;
++      ipsec_sa_put(ipsq);
++      if((error = ipsec_sa_delchain(ipsq))) {
++              spin_unlock_bh(&tdb_lock);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_update_parse: "
++                          "error=%d, trouble deleting intermediate ipsec_sa for SA=%s.\n",
++                          error,
++                          sa_len ? sa : " (error)");
++              SENDERR(-error);
++      }
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      }
++#endif
++
++      spin_unlock_bh(&tdb_lock);
++      
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_UPDATE,
++                                                        satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      extr->ips->ips_replaywin,
++                                                      extr->ips->ips_state,
++                                                      extr->ips->ips_authalg,
++                                                      extr->ips->ips_encalg,
++                                                      extr->ips->ips_flags,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           /* The 3 lifetime extentions should only be sent if non-zero. */
++           && (extensions[SADB_EXT_LIFETIME_HARD]
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD],
++                                                               SADB_EXT_LIFETIME_HARD,
++                                                               extr->ips->ips_life.ipl_allocations.ipl_hard,
++                                                               extr->ips->ips_life.ipl_bytes.ipl_hard,
++                                                               extr->ips->ips_life.ipl_addtime.ipl_hard,
++                                                               extr->ips->ips_life.ipl_usetime.ipl_hard,
++                                                               extr->ips->ips_life.ipl_packets.ipl_hard),
++                                  extensions_reply) : 1)
++           && (extensions[SADB_EXT_LIFETIME_SOFT]
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT],
++                                                               SADB_EXT_LIFETIME_SOFT,
++                                                               extr->ips->ips_life.ipl_allocations.ipl_count,
++                                                               extr->ips->ips_life.ipl_bytes.ipl_count,
++                                                               extr->ips->ips_life.ipl_addtime.ipl_count,
++                                                               extr->ips->ips_life.ipl_usetime.ipl_count,
++                                                               extr->ips->ips_life.ipl_packets.ipl_count),
++                                  extensions_reply) : 1)
++           && (extr->ips->ips_life.ipl_allocations.ipl_count
++               || extr->ips->ips_life.ipl_bytes.ipl_count
++               || extr->ips->ips_life.ipl_addtime.ipl_count
++               || extr->ips->ips_life.ipl_usetime.ipl_count
++               || extr->ips->ips_life.ipl_packets.ipl_count
++
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT],
++                                                               SADB_EXT_LIFETIME_CURRENT,
++                                                               extr->ips->ips_life.ipl_allocations.ipl_count,
++                                                               extr->ips->ips_life.ipl_bytes.ipl_count,
++                                                               extr->ips->ips_life.ipl_addtime.ipl_count,
++                                                               extr->ips->ips_life.ipl_usetime.ipl_count,
++                                                               extr->ips->ips_life.ipl_packets.ipl_count),
++                                  extensions_reply) : 1)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
++                                                           SADB_EXT_ADDRESS_SRC,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_s),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
++                                                           SADB_EXT_ADDRESS_DST,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_d),
++                               extensions_reply)
++           && (extr->ips->ips_ident_s.data
++                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC],
++                                                              SADB_EXT_IDENTITY_SRC,
++                                                            extr->ips->ips_ident_s.type,
++                                                            extr->ips->ips_ident_s.id,
++                                                              extr->ips->ips_ident_s.len,
++                                                            extr->ips->ips_ident_s.data),
++                                    extensions_reply) : 1)
++           && (extr->ips->ips_ident_d.data
++                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST],
++                                                              SADB_EXT_IDENTITY_DST,
++                                                            extr->ips->ips_ident_d.type,
++                                                            extr->ips->ips_ident_d.id,
++                                                              extr->ips->ips_ident_d.len,
++                                                            extr->ips->ips_ident_d.data),
++                                    extensions_reply) : 1)
++#if 0
++           /* FIXME: This won't work yet because I have not finished
++              it. */
++           && (extr->ips->ips_sens_
++               ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY],
++                                                           extr->ips->ips_sens_dpd,
++                                                           extr->ips->ips_sens_sens_level,
++                                                           extr->ips->ips_sens_sens_len,
++                                                           extr->ips->ips_sens_sens_bitmap,
++                                                           extr->ips->ips_sens_integ_level,
++                                                           extr->ips->ips_sens_integ_len,
++                                                           extr->ips->ips_sens_integ_bitmap),
++                                  extensions_reply) : 1)
++#endif
++              )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
++                          "failed to build the update reply message extensions\n");
++              SENDERR(-error);
++      }
++              
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
++                          "failed to build the update reply message\n");
++              SENDERR(-error);
++      }
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
++                                  "sending up update reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
++                          "sending up update reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      if (nat_t_ips_saved) {
++              /**
++               * As we _really_ update existing SA, we keep tdbq and need to delete
++               * parsed ips (nat_t_ips_saved, was extr->ips).
++               *
++               * goto errlab with extr->ips = nat_t_ips_saved will free it.
++               */
++
++              extr->ips = nat_t_ips_saved;
++
++              error = 0;
++              KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_update_parse (NAT-T ports): "
++                  "successful for SA: %s\n",
++                  sa_len ? sa : " (error)");
++
++              goto errlab;
++      }
++#endif
++
++      if((error = ipsec_sa_add(extr->ips))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
++                          "failed to update the mature SA=%s with error=%d.\n",
++                          sa_len ? sa : " (error)",
++                          error);
++              SENDERR(-error);
++      }
++      extr->ips = NULL;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_update_parse: "
++                  "successful for SA: %s\n",
++                  sa_len ? sa : " (error)");
++      
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct ipsec_sa* ipsq;
++      char sa[SATOT_BUF];
++      size_t sa_len;
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_add_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      if(((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_add_parse: "
++                          "error, sa_state=%d must be MATURE=%d\n",
++                          ((struct sadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,
++                          SADB_SASTATE_MATURE);
++              SENDERR(EINVAL);
++      }
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_add_parse: "
++                          "extr or extr->ips pointer NULL\n");
++              SENDERR(EINVAL);
++      }
++
++      sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa));
++
++      ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said));
++      if(ipsq != NULL) {
++              ipsec_sa_put(ipsq);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_add_parse: "
++                          "found an old ipsec_sa for SA%s, delete it first.\n",
++                          sa_len ? sa : " (error)");
++              SENDERR(EEXIST);
++      }
++
++      if(inet_addr_type((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == RTN_LOCAL) {
++              extr->ips->ips_flags |= EMT_INBOUND;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_add_parse: "
++                  "existing ipsec_sa not found (this is good) for SA%s, %s-bound, allocating.\n",
++                  sa_len ? sa : " (error)",
++                  extr->ips->ips_flags & EMT_INBOUND ? "in" : "out");
++      
++      /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/
++      extr->ips->ips_rcvif = NULL;
++      
++      if ((error = pfkey_ipsec_sa_init(extr->ips))) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_add_parse: "
++                          "not successful for SA: %s, deleting.\n",
++                          sa_len ? sa : " (error)");
++              SENDERR(-error);
++      }
++
++      extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ;
++      if(!extr->ips->ips_life.ipl_allocations.ipl_count) {
++              extr->ips->ips_life.ipl_allocations.ipl_count += 1;
++      }
++
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_ADD,
++                                                        satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      extr->ips->ips_replaywin,
++                                                      extr->ips->ips_state,
++                                                      extr->ips->ips_authalg,
++                                                      extr->ips->ips_encalg,
++                                                      extr->ips->ips_flags,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           /* The 3 lifetime extentions should only be sent if non-zero. */
++           && (extensions[SADB_EXT_LIFETIME_HARD]
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD],
++                                                               SADB_EXT_LIFETIME_HARD,
++                                                               extr->ips->ips_life.ipl_allocations.ipl_hard,
++                                                               extr->ips->ips_life.ipl_bytes.ipl_hard,
++                                                               extr->ips->ips_life.ipl_addtime.ipl_hard,
++                                                               extr->ips->ips_life.ipl_usetime.ipl_hard,
++                                                               extr->ips->ips_life.ipl_packets.ipl_hard),
++                                  extensions_reply) : 1)
++           && (extensions[SADB_EXT_LIFETIME_SOFT]
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT],
++                                                               SADB_EXT_LIFETIME_SOFT,
++                                                               extr->ips->ips_life.ipl_allocations.ipl_soft,
++                                                               extr->ips->ips_life.ipl_bytes.ipl_soft,
++                                                               extr->ips->ips_life.ipl_addtime.ipl_soft,
++                                                               extr->ips->ips_life.ipl_usetime.ipl_soft,
++                                                               extr->ips->ips_life.ipl_packets.ipl_soft),
++                                  extensions_reply) : 1)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
++                                                           SADB_EXT_ADDRESS_SRC,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_s),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
++                                                           SADB_EXT_ADDRESS_DST,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_d),
++                               extensions_reply)
++            && (extr->ips->ips_ident_s.data
++                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC],
++                                                              SADB_EXT_IDENTITY_SRC,
++                                                            extr->ips->ips_ident_s.type,
++                                                            extr->ips->ips_ident_s.id,
++                                                              extr->ips->ips_ident_s.len,
++                                                            extr->ips->ips_ident_s.data),
++                                    extensions_reply) : 1)
++            && (extr->ips->ips_ident_d.data
++                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST],
++                                                              SADB_EXT_IDENTITY_DST,
++                                                            extr->ips->ips_ident_d.type,
++                                                            extr->ips->ips_ident_d.id,
++                                                              extr->ips->ips_ident_d.len,
++                                                            extr->ips->ips_ident_d.data),
++                                    extensions_reply) : 1)
++#if 0
++           /* FIXME: This won't work yet because I have not finished
++              it. */
++           && (extr->ips->ips_sens_
++               ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY],
++                                                           extr->ips->ips_sens_dpd,
++                                                           extr->ips->ips_sens_sens_level,
++                                                           extr->ips->ips_sens_sens_len,
++                                                           extr->ips->ips_sens_sens_bitmap,
++                                                           extr->ips->ips_sens_integ_level,
++                                                           extr->ips->ips_sens_integ_len,
++                                                           extr->ips->ips_sens_integ_bitmap),
++                                  extensions_reply) : 1)
++#endif
++              )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
++                          "failed to build the add reply message extensions\n");
++              SENDERR(-error);
++      }
++              
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
++                          "failed to build the add reply message\n");
++              SENDERR(-error);
++      }
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
++                                  "sending up add reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
++                          "sending up add reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++
++      if((error = ipsec_sa_add(extr->ips))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
++                          "failed to add the mature SA=%s with error=%d.\n",
++                          sa_len ? sa : " (error)",
++                          error);
++              SENDERR(-error);
++      }
++      extr->ips = NULL;
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_add_parse: "
++                  "successful for SA: %s\n",
++                  sa_len ? sa : " (error)");
++      
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      struct ipsec_sa *ipsp;
++      char sa[SATOT_BUF];
++      size_t sa_len;
++      int error = 0;
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_delete_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_delete_parse: "
++                          "extr or extr->ips pointer NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa));
++
++      spin_lock_bh(&tdb_lock);
++
++      ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said));
++      if (ipsp == NULL) {
++              spin_unlock_bh(&tdb_lock);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_delete_parse: "
++                          "ipsec_sa not found for SA:%s, could not delete.\n",
++                          sa_len ? sa : " (error)");
++              SENDERR(ESRCH);
++      }
++
++      ipsec_sa_put(ipsp);
++      if((error = ipsec_sa_delchain(ipsp))) {
++              spin_unlock_bh(&tdb_lock);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_delete_parse: "
++                          "error=%d returned trying to delete ipsec_sa for SA:%s.\n",
++                          error,
++                          sa_len ? sa : " (error)");
++              SENDERR(-error);
++      }
++      spin_unlock_bh(&tdb_lock);
++
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_DELETE,
++                                                        satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      0,
++                                                      0,
++                                                      0,
++                                                      0,
++                                                      0,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
++                                                           SADB_EXT_ADDRESS_SRC,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_s),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
++                                                           SADB_EXT_ADDRESS_DST,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_d),
++                               extensions_reply)
++              )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
++                          "failed to build the delete reply message extensions\n");
++              SENDERR(-error);
++      }
++      
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
++                          "failed to build the delete reply message\n");
++              SENDERR(-error);
++      }
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
++                                  "sending up delete reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
++                          "sending up delete reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct ipsec_sa *ipsp;
++      char sa[SATOT_BUF];
++      size_t sa_len;
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_get_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      if(!extr || !extr->ips) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_get_parse: "
++                          "extr or extr->ips pointer NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa));
++
++      spin_lock_bh(&tdb_lock);
++
++      ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said));
++      if (ipsp == NULL) {
++              spin_unlock_bh(&tdb_lock);
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
++                          "ipsec_sa not found for SA=%s, could not get.\n",
++                          sa_len ? sa : " (error)");
++              SENDERR(ESRCH);
++      }
++      
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_GET,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      extr->ips->ips_replaywin,
++                                                      extr->ips->ips_state,
++                                                      extr->ips->ips_authalg,
++                                                      extr->ips->ips_encalg,
++                                                      extr->ips->ips_flags,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           /* The 3 lifetime extentions should only be sent if non-zero. */
++           && (ipsp->ips_life.ipl_allocations.ipl_count
++               || ipsp->ips_life.ipl_bytes.ipl_count
++               || ipsp->ips_life.ipl_addtime.ipl_count
++               || ipsp->ips_life.ipl_usetime.ipl_count
++               || ipsp->ips_life.ipl_packets.ipl_count
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_CURRENT],
++                                                               SADB_EXT_LIFETIME_CURRENT,
++                                                               ipsp->ips_life.ipl_allocations.ipl_count,
++                                                               ipsp->ips_life.ipl_bytes.ipl_count,
++                                                               ipsp->ips_life.ipl_addtime.ipl_count,
++                                                               ipsp->ips_life.ipl_usetime.ipl_count,
++                                                               ipsp->ips_life.ipl_packets.ipl_count),
++                                  extensions_reply) : 1)
++           && (ipsp->ips_life.ipl_allocations.ipl_hard
++               || ipsp->ips_life.ipl_bytes.ipl_hard
++               || ipsp->ips_life.ipl_addtime.ipl_hard
++               || ipsp->ips_life.ipl_usetime.ipl_hard
++               || ipsp->ips_life.ipl_packets.ipl_hard
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD],
++                                                               SADB_EXT_LIFETIME_HARD,
++                                                               ipsp->ips_life.ipl_allocations.ipl_hard,
++                                                               ipsp->ips_life.ipl_bytes.ipl_hard,
++                                                               ipsp->ips_life.ipl_addtime.ipl_hard,
++                                                               ipsp->ips_life.ipl_usetime.ipl_hard,
++                                                               ipsp->ips_life.ipl_packets.ipl_hard),
++                                  extensions_reply) : 1)
++           && (ipsp->ips_life.ipl_allocations.ipl_soft
++               || ipsp->ips_life.ipl_bytes.ipl_soft
++               || ipsp->ips_life.ipl_addtime.ipl_soft
++               || ipsp->ips_life.ipl_usetime.ipl_soft
++               || ipsp->ips_life.ipl_packets.ipl_soft
++               ? pfkey_safe_build(error = pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT],
++                                                               SADB_EXT_LIFETIME_SOFT,
++                                                               ipsp->ips_life.ipl_allocations.ipl_soft,
++                                                               ipsp->ips_life.ipl_bytes.ipl_soft,
++                                                               ipsp->ips_life.ipl_addtime.ipl_soft,
++                                                               ipsp->ips_life.ipl_usetime.ipl_soft,
++                                                               ipsp->ips_life.ipl_packets.ipl_soft),
++                                  extensions_reply) : 1)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
++                                                           SADB_EXT_ADDRESS_SRC,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_s),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
++                                                           SADB_EXT_ADDRESS_DST,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_d),
++                               extensions_reply)
++           && (extr->ips->ips_addr_p
++               ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_PROXY],
++                                                              SADB_EXT_ADDRESS_PROXY,
++                                                              0, /*extr->ips->ips_said.proto,*/
++                                                              0,
++                                                              extr->ips->ips_addr_p),
++                                  extensions_reply) : 1)
++#if 0
++           /* FIXME: This won't work yet because the keys are not
++              stored directly in the ipsec_sa.  They are stored as
++              contexts. */
++           && (extr->ips->ips_key_a_size
++               ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_AUTH],
++                                                          SADB_EXT_KEY_AUTH,
++                                                          extr->ips->ips_key_a_size * 8,
++                                                          extr->ips->ips_key_a),
++                                  extensions_reply) : 1)
++           /* FIXME: This won't work yet because the keys are not
++              stored directly in the ipsec_sa.  They are stored as
++              key schedules. */
++           && (extr->ips->ips_key_e_size
++               ? pfkey_safe_build(error = pfkey_key_build(&extensions_reply[SADB_EXT_KEY_ENCRYPT],
++                                                          SADB_EXT_KEY_ENCRYPT,
++                                                          extr->ips->ips_key_e_size * 8,
++                                                          extr->ips->ips_key_e),
++                                  extensions_reply) : 1)
++#endif
++           && (extr->ips->ips_ident_s.data
++                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC],
++                                                              SADB_EXT_IDENTITY_SRC,
++                                                            extr->ips->ips_ident_s.type,
++                                                            extr->ips->ips_ident_s.id,
++                                                              extr->ips->ips_ident_s.len,
++                                                            extr->ips->ips_ident_s.data),
++                                    extensions_reply) : 1)
++           && (extr->ips->ips_ident_d.data
++                 ? pfkey_safe_build(error = pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST],
++                                                              SADB_EXT_IDENTITY_DST,
++                                                            extr->ips->ips_ident_d.type,
++                                                            extr->ips->ips_ident_d.id,
++                                                              extr->ips->ips_ident_d.len,
++                                                            extr->ips->ips_ident_d.data),
++                                    extensions_reply) : 1)
++#if 0
++           /* FIXME: This won't work yet because I have not finished
++              it. */
++           && (extr->ips->ips_sens_
++               ? pfkey_safe_build(error = pfkey_sens_build(&extensions_reply[SADB_EXT_SENSITIVITY],
++                                                           extr->ips->ips_sens_dpd,
++                                                           extr->ips->ips_sens_sens_level,
++                                                           extr->ips->ips_sens_sens_len,
++                                                           extr->ips->ips_sens_sens_bitmap,
++                                                           extr->ips->ips_sens_integ_level,
++                                                           extr->ips->ips_sens_integ_len,
++                                                           extr->ips->ips_sens_integ_bitmap),
++                                  extensions_reply) : 1)
++#endif
++                   )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
++                          "failed to build the get reply message extensions\n");
++              ipsec_sa_put(ipsp);
++              spin_unlock_bh(&tdb_lock);
++              SENDERR(-error);
++      }
++              
++      ipsec_sa_put(ipsp);
++      spin_unlock_bh(&tdb_lock);
++      
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
++                          "failed to build the get reply message\n");
++              SENDERR(-error);
++      }
++      
++      if((error = pfkey_upmsg(sk->sk_socket, pfkey_reply))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
++                          "failed to send the get reply message\n");
++              SENDERR(-error);
++      }
++      
++      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
++                  "succeeded in sending get reply message.\n");
++      
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_acquire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_acquire_parse: .\n");
++
++      /* XXX I don't know if we want an upper bound, since userspace may
++         want to register itself for an satype > SADB_SATYPE_MAX. */
++      if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_acquire_parse: "
++                          "SATYPE=%d invalid.\n",
++                          satype);
++              SENDERR(EINVAL);
++      }
++
++      if(!(pfkey_registered_sockets[satype])) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
++                          "no sockets registered for SAtype=%d(%s).\n",
++                          satype,
++                          satype2name(satype));
++              SENDERR(EPROTONOSUPPORT);
++      }
++
++      for(pfkey_socketsp = pfkey_registered_sockets[satype];
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp,
++                                      ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
++                                  "sending up acquire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
++                          "sending up acquire reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_register_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_register_parse: .\n");
++
++      /* XXX I don't know if we want an upper bound, since userspace may
++         want to register itself for an satype > SADB_SATYPE_MAX. */
++      if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_register_parse: "
++                          "SATYPE=%d invalid.\n",
++                          satype);
++              SENDERR(EINVAL);
++      }
++
++      if(!pfkey_list_insert_socket(sk->sk_socket,
++                               &(pfkey_registered_sockets[satype]))) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_register_parse: "
++                          "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n",
++                          satype,
++                          satype2name(satype),
++                          key_pid(sk));
++      };
++      
++      /* send up register msg with supported SATYPE algos */
++
++      error=pfkey_register_reply(satype, (struct sadb_msg*)extensions[SADB_EXT_RESERVED]);
++ errlab:
++      return error;
++}
++
++int
++pfkey_register_reply(int satype, struct sadb_msg *sadb_msg)
++{
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      struct supported_list *pfkey_supported_listp;
++      unsigned int alg_num_a = 0, alg_num_e = 0;
++      struct sadb_alg *alg_a = NULL, *alg_e = NULL, *alg_ap = NULL, *alg_ep = NULL;
++      int error = 0;
++
++      pfkey_extensions_init(extensions_reply);
++
++      if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
++                          "SAtype=%d unspecified or unknown.\n",
++                          satype);
++              SENDERR(EINVAL);
++      }
++      if(!(pfkey_registered_sockets[satype])) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
++                          "no sockets registered for SAtype=%d(%s).\n",
++                          satype,
++                          satype2name(satype));
++              SENDERR(EPROTONOSUPPORT);
++      }
++      /* send up register msg with supported SATYPE algos */
++      pfkey_supported_listp = pfkey_supported_list[satype];
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_register_reply: "
++                  "pfkey_supported_list[%d]=0p%p\n",
++                  satype,
++                  pfkey_supported_list[satype]);
++      while(pfkey_supported_listp) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_register_reply: "
++                          "checking supported=0p%p\n",
++                          pfkey_supported_listp);
++              if(pfkey_supported_listp->supportedp->ias_exttype == SADB_EXT_SUPPORTED_AUTH) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_register_reply: "
++                                  "adding auth alg.\n");
++                      alg_num_a++;
++              }
++              if(pfkey_supported_listp->supportedp->ias_exttype == SADB_EXT_SUPPORTED_ENCRYPT) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_register_reply: "
++                                  "adding encrypt alg.\n");
++                      alg_num_e++;
++              }
++              pfkey_supported_listp = pfkey_supported_listp->next;
++      }
++      
++      if(alg_num_a) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_register_reply: "
++                          "allocating %lu bytes for auth algs.\n",
++                          (unsigned long) (alg_num_a * sizeof(struct sadb_alg)));
++              if((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_register_reply: "
++                                  "auth alg memory allocation error\n");
++                      SENDERR(ENOMEM);
++              }
++              alg_ap = alg_a;
++      }
++      
++      if(alg_num_e) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_register_reply: "
++                          "allocating %lu bytes for enc algs.\n",
++                          (unsigned long) (alg_num_e * sizeof(struct sadb_alg)));
++              if((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_register_reply: "
++                                  "enc alg memory allocation error\n");
++                      SENDERR(ENOMEM);
++              }
++              alg_ep = alg_e;
++      }
++      
++      pfkey_supported_listp = pfkey_supported_list[satype];
++      while(pfkey_supported_listp) {
++              if(alg_num_a) {
++                      if(pfkey_supported_listp->supportedp->ias_exttype == SADB_EXT_SUPPORTED_AUTH) {
++                              alg_ap->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id;
++                              alg_ap->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen;
++                              alg_ap->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits;
++                              alg_ap->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits;
++                              alg_ap->sadb_alg_reserved = 0;
++                              KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                          "klips_debug:pfkey_register_reply: "
++                                          "adding auth=0p%p\n",
++                                          alg_ap);
++                              alg_ap++;
++                      }
++              }
++              if(alg_num_e) {
++                      if(pfkey_supported_listp->supportedp->ias_exttype == SADB_EXT_SUPPORTED_ENCRYPT) {
++                              alg_ep->sadb_alg_id = pfkey_supported_listp->supportedp->ias_id;
++                              alg_ep->sadb_alg_ivlen = pfkey_supported_listp->supportedp->ias_ivlen;
++                              alg_ep->sadb_alg_minbits = pfkey_supported_listp->supportedp->ias_keyminbits;
++                              alg_ep->sadb_alg_maxbits = pfkey_supported_listp->supportedp->ias_keymaxbits;
++                              alg_ep->sadb_alg_reserved = 0;
++                              KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
++                                          "klips_debug:pfkey_register_reply: "
++                                          "adding encrypt=0p%p\n",
++                                          alg_ep);
++                              alg_ep++;
++                      }
++              }
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_register_reply: "
++                          "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_supported_listp->supportedp->ias_exttype,
++                          pfkey_supported_listp->supportedp->ias_id,
++                          pfkey_supported_listp->supportedp->ias_ivlen,
++                          pfkey_supported_listp->supportedp->ias_keyminbits,
++                          pfkey_supported_listp->supportedp->ias_keymaxbits);
++              pfkey_supported_listp = pfkey_supported_listp->next;
++      }
++      
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_REGISTER,
++                                                        satype,
++                                                        0,
++                                                        sadb_msg? sadb_msg->sadb_msg_seq : ++pfkey_msg_seq,
++                                                        sadb_msg? sadb_msg->sadb_msg_pid: current->pid),
++                            extensions_reply) &&
++           (alg_num_a ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_AUTH],
++                                                                      SADB_EXT_SUPPORTED_AUTH,
++                                                                      alg_num_a,
++                                                                      alg_a),
++                                        extensions_reply) : 1) &&
++           (alg_num_e ? pfkey_safe_build(error = pfkey_supported_build(&extensions_reply[SADB_EXT_SUPPORTED_ENCRYPT],
++                                                                      SADB_EXT_SUPPORTED_ENCRYPT,
++                                                                      alg_num_e,
++                                                                      alg_e),
++                                        extensions_reply) : 1))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
++                          "failed to build the register message extensions_reply\n");
++              SENDERR(-error);
++      }
++      
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
++                          "failed to build the register message\n");
++              SENDERR(-error);
++      }
++      /* this should go to all registered sockets for that satype only */
++      for(pfkey_socketsp = pfkey_registered_sockets[satype];
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
++                                  "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_reply: "
++                          "sending up register message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++ errlab:
++      if(alg_a) {
++              kfree(alg_a);
++      }
++      if(alg_e) {
++              kfree(alg_e);
++      }
++
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_expire_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct socket_list *pfkey_socketsp;
++#ifdef CONFIG_KLIPS_DEBUG
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_expire_parse: .\n");
++
++      if(pfkey_open_sockets) {
++              for(pfkey_socketsp = pfkey_open_sockets;
++                  pfkey_socketsp;
++                  pfkey_socketsp = pfkey_socketsp->next) {
++                      if((error = pfkey_upmsg(pfkey_socketsp->socketp,
++                                              ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) {
++                              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: "
++                                          "sending up expire reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                          satype,
++                                          satype2name(satype),
++                                          pfkey_socketsp->socketp,
++                                          error);
++                              SENDERR(-error);
++                      }
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: "
++                                  "sending up expire reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp);
++              }
++      }
++
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_flush_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++      uint8_t proto = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_flush_parse: "
++                  "flushing type %d SAs\n",
++                  satype);
++
++      if(satype && !(proto = satype2proto(satype))) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_flush_parse: "
++                          "satype %d lookup failed.\n", 
++                          ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype);
++              SENDERR(EINVAL);
++      }
++
++      if ((error = ipsec_sadb_cleanup(proto))) {
++              SENDERR(-error);
++      }
++
++      if(pfkey_open_sockets) {
++              for(pfkey_socketsp = pfkey_open_sockets;
++                  pfkey_socketsp;
++                  pfkey_socketsp = pfkey_socketsp->next) {
++                      if((error = pfkey_upmsg(pfkey_socketsp->socketp,
++                                              ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])))) {
++                              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: "
++                                          "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=0p%p failed with error=%d.\n",
++                                          satype,
++                                          satype2name(satype),
++                                          proto,
++                                          pfkey_socketsp->socketp,
++                                          error);
++                              SENDERR(-error);
++                      }
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: "
++                                  "sending up flush reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp);
++              }
++      }
++
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_dump_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_dump_parse: .\n");
++
++      SENDERR(ENOSYS);
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_promisc_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_promisc_parse: .\n");
++
++      SENDERR(ENOSYS);
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_pchange_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_pchange_parse: .\n");
++
++      SENDERR(ENOSYS);
++ errlab:
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      struct ipsec_sa *ips1p, *ips2p, *ipsp;
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++      char sa1[SATOT_BUF], sa2[SATOT_BUF];
++      size_t sa_len1, sa_len2 = 0;
++      int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_grpsa_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      if(extr == NULL || extr->ips == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_grpsa_parse: "
++                          "extr or extr->ips is NULL, fatal.\n");
++              SENDERR(EINVAL);
++      }
++
++      sa_len1 = satot(&extr->ips->ips_said, 0, sa1, sizeof(sa1));
++      if(extr->ips2 != NULL) {
++              sa_len2 = satot(&extr->ips2->ips_said, 0, sa2, sizeof(sa2));
++      }
++
++      spin_lock_bh(&tdb_lock);
++
++      ips1p = ipsec_sa_getbyid(&(extr->ips->ips_said));
++      if(ips1p == NULL) {
++              spin_unlock_bh(&tdb_lock);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_grpsa_parse: "
++                          "reserved ipsec_sa for SA1: %s not found.  Call SADB_ADD/UPDATE first.\n",
++                          sa_len1 ? sa1 : " (error)");
++              SENDERR(ENOENT);
++      }
++      if(extr->ips2) { /* GRPSA */
++              ips2p = ipsec_sa_getbyid(&(extr->ips2->ips_said));
++              if(ips2p == NULL) {
++                      ipsec_sa_put(ips1p);
++                      spin_unlock_bh(&tdb_lock);
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_grpsa_parse: "
++                                  "reserved ipsec_sa for SA2: %s not found.  Call SADB_ADD/UPDATE first.\n",
++                                  sa_len2 ? sa2 : " (error)");
++                      SENDERR(ENOENT);
++              }
++
++              /* Is either one already linked? */
++              if(ips1p->ips_onext) {
++                      ipsec_sa_put(ips1p);
++                      ipsec_sa_put(ips2p);
++                      spin_unlock_bh(&tdb_lock);
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_grpsa_parse: "
++                                  "ipsec_sa for SA: %s is already linked.\n",
++                                  sa_len1 ? sa1 : " (error)");
++                      SENDERR(EEXIST);
++              }
++              if(ips2p->ips_inext) {
++                      ipsec_sa_put(ips1p);
++                      ipsec_sa_put(ips2p);
++                      spin_unlock_bh(&tdb_lock);
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_grpsa_parse: "
++                                  "ipsec_sa for SA: %s is already linked.\n",
++                                  sa_len2 ? sa2 : " (error)");
++                      SENDERR(EEXIST);
++              }
++              
++              /* Is extr->ips already linked to extr->ips2? */
++              ipsp = ips2p;
++              while(ipsp) {
++                      if(ipsp == ips1p) {
++                              ipsec_sa_put(ips1p);
++                              ipsec_sa_put(ips2p);
++                              spin_unlock_bh(&tdb_lock);
++                              KLIPS_PRINT(debug_pfkey,
++                                          "klips_debug:pfkey_x_grpsa_parse: "
++                                          "ipsec_sa for SA: %s is already linked to %s.\n",
++                                          sa_len1 ? sa1 : " (error)",
++                                          sa_len2 ? sa2 : " (error)");
++                              SENDERR(EEXIST);
++                      }
++                      ipsp = ipsp->ips_onext;
++              }
++              
++              /* link 'em */
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_grpsa_parse: "
++                          "linking ipsec_sa SA: %s with %s.\n",
++                          sa_len1 ? sa1 : " (error)",
++                          sa_len2 ? sa2 : " (error)");
++              ips1p->ips_onext = ips2p;
++              ips2p->ips_inext = ips1p;
++      } else { /* UNGRPSA */
++              ipsec_sa_put(ips1p);
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_grpsa_parse: "
++                          "unlinking ipsec_sa SA: %s.\n",
++                          sa_len1 ? sa1 : " (error)");
++              while(ips1p->ips_onext) {
++                      ips1p = ips1p->ips_onext;
++              }
++              while(ips1p->ips_inext) {
++                      ipsp = ips1p;
++                      ips1p = ips1p->ips_inext;
++                      ipsec_sa_put(ips1p);
++                      ipsp->ips_inext = NULL;
++                      ipsec_sa_put(ipsp);
++                      ips1p->ips_onext = NULL;
++              }
++      }
++
++      spin_unlock_bh(&tdb_lock);
++
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_X_GRPSA,
++                                                        satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      extr->ips->ips_replaywin,
++                                                      extr->ips->ips_state,
++                                                      extr->ips->ips_authalg,
++                                                      extr->ips->ips_encalg,
++                                                      extr->ips->ips_flags,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
++                                                           SADB_EXT_ADDRESS_DST,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           extr->ips->ips_addr_d),
++                               extensions_reply)
++           && (extr->ips2
++               ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2],
++                                                                ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype
++                                                                /* proto2satype(extr->ips2->ips_said.proto) */),
++                                                                extensions_reply)
++                                   && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_X_EXT_SA2],
++                                                                              SADB_X_EXT_SA2,
++                                                                              extr->ips2->ips_said.spi,
++                                                                              extr->ips2->ips_replaywin,
++                                                                              extr->ips2->ips_state,
++                                                                              extr->ips2->ips_authalg,
++                                                                              extr->ips2->ips_encalg,
++                                                                              extr->ips2->ips_flags,
++                                                                              extr->ips2->ips_ref),
++                                                       extensions_reply)
++                                   && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2],
++                                                                                   SADB_X_EXT_ADDRESS_DST2,
++                                                                                   0, /*extr->ips->ips_said.proto,*/
++                                                                                   0,
++                                                                                   extr->ips2->ips_addr_d),
++                                                       extensions_reply) ) : 1 )
++                   )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
++                          "failed to build the x_grpsa reply message extensions\n");
++              SENDERR(-error);
++      }
++         
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
++                          "failed to build the x_grpsa reply message\n");
++              SENDERR(-error);
++      }
++      
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
++                                  "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
++                          "sending up x_grpsa reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
++                  "succeeded in sending x_grpsa reply message.\n");
++      
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++#ifdef CONFIG_KLIPS_DEBUG
++      char buf1[64], buf2[64];
++#endif /* CONFIG_KLIPS_DEBUG */
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++      ip_address srcflow, dstflow, srcmask, dstmask;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_addflow_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      memset((caddr_t)&srcflow, 0, sizeof(srcflow));
++      memset((caddr_t)&dstflow, 0, sizeof(dstflow));
++      memset((caddr_t)&srcmask, 0, sizeof(srcmask));
++      memset((caddr_t)&dstmask, 0, sizeof(dstmask));
++
++      if(!extr || !(extr->ips) || !(extr->eroute)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_addflow_parse: "
++                          "missing extr, ipsec_sa or eroute data.\n");
++              SENDERR(EINVAL);
++      }
++
++      srcflow.u.v4.sin_family = AF_INET;
++      dstflow.u.v4.sin_family = AF_INET;
++      srcmask.u.v4.sin_family = AF_INET;
++      dstmask.u.v4.sin_family = AF_INET;
++      srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src;
++      dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst;
++      srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src;
++      dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst;
++
++#ifdef CONFIG_KLIPS_DEBUG
++      if (debug_pfkey) {
++              subnettoa(extr->eroute->er_eaddr.sen_ip_src,
++                        extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
++              subnettoa(extr->eroute->er_eaddr.sen_ip_dst,
++                        extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_addflow_parse: "
++                          "calling breakeroute and/or makeroute for %s->%s\n",
++                          buf1, buf2);
++      }
++#endif /* CONFIG_KLIPS_DEBUG */
++
++      if(extr->ips->ips_flags & SADB_X_SAFLAGS_INFLOW) {
++              struct ipsec_sa *ipsp, *ipsq;
++              char sa[SATOT_BUF];
++              size_t sa_len;
++
++              ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said));
++              if(ipsq == NULL) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_addflow_parse: "
++                                  "ipsec_sa not found, cannot set incoming policy.\n");
++                      SENDERR(ENOENT);
++              }
++
++              ipsp = ipsq;
++              while(ipsp && ipsp->ips_said.proto != IPPROTO_IPIP) {
++                      ipsp = ipsp->ips_inext;
++              }
++
++              if(ipsp == NULL) {
++                      ipsec_sa_put(ipsq);
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_addflow_parse: "
++                                  "SA chain does not have an IPIP SA, cannot set incoming policy.\n");
++                      SENDERR(ENOENT);
++              }
++              
++              sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa));
++
++              ipsp->ips_flags |= SADB_X_SAFLAGS_INFLOW;
++              ipsp->ips_flow_s = srcflow;
++              ipsp->ips_flow_d = dstflow;
++              ipsp->ips_mask_s = srcmask;
++              ipsp->ips_mask_d = dstmask;
++
++              ipsec_sa_put(ipsq);
++
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_addflow_parse: "
++                          "inbound eroute, setting incoming policy information in IPIP ipsec_sa for SA: %s.\n",
++                          sa_len ? sa : " (error)");
++      } else {
++              struct sk_buff *first = NULL, *last = NULL;
++
++              if(extr->ips->ips_flags & SADB_X_SAFLAGS_REPLACEFLOW) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_addflow_parse: "
++                                  "REPLACEFLOW flag set, calling breakeroute.\n");
++                      if ((error = ipsec_breakroute(&(extr->eroute->er_eaddr),
++                                                    &(extr->eroute->er_emask),
++                                                    &first, &last))) {
++                              KLIPS_PRINT(debug_pfkey,
++                                          "klips_debug:pfkey_x_addflow_parse: "
++                                          "breakeroute returned %d.  first=0p%p, last=0p%p\n",
++                                          error,
++                                          first,
++                                          last);
++                              if(first != NULL) {
++                                      ipsec_kfree_skb(first);
++                              }
++                              if(last != NULL) {
++                                      ipsec_kfree_skb(last);
++                              }
++                              SENDERR(-error);
++                      }
++              }
++              
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_addflow_parse: "
++                          "calling makeroute.\n");
++              
++              if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr),
++                                           &(extr->eroute->er_emask),
++                                           extr->ips->ips_said,
++                                           ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid,
++                                           NULL,
++                                           &(extr->ips->ips_ident_s),
++                                           &(extr->ips->ips_ident_d)))) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_addflow_parse: "
++                                  "makeroute returned %d.\n", error);
++                      SENDERR(-error);
++              }
++              if(first != NULL) {
++                      KLIPS_PRINT(debug_eroute,
++                                  "klips_debug:pfkey_x_addflow_parse: "
++                                  "first=0p%p HOLD packet re-injected.\n",
++                                  first);
++                      DEV_QUEUE_XMIT(first, first->dev, SOPRI_NORMAL);
++              }
++              if(last != NULL) {
++                      KLIPS_PRINT(debug_eroute,
++                                  "klips_debug:pfkey_x_addflow_parse: "
++                                  "last=0p%p HOLD packet re-injected.\n",
++                                  last);
++                      DEV_QUEUE_XMIT(last, last->dev, SOPRI_NORMAL);
++              }
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_addflow_parse: "
++                  "makeroute call successful.\n");
++
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_X_ADDFLOW,
++                                                        satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      extr->ips->ips_replaywin,
++                                                      extr->ips->ips_state,
++                                                      extr->ips->ips_authalg,
++                                                      extr->ips->ips_encalg,
++                                                      extr->ips->ips_flags,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           && (extensions[SADB_EXT_ADDRESS_SRC]
++               ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
++                                                              SADB_EXT_ADDRESS_SRC,
++                                                              0, /*extr->ips->ips_said.proto,*/
++                                                              0,
++                                                              extr->ips->ips_addr_s),
++                                  extensions_reply) : 1)
++           && (extensions[SADB_EXT_ADDRESS_DST]
++               ? pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
++                                                              SADB_EXT_ADDRESS_DST,
++                                                              0, /*extr->ips->ips_said.proto,*/
++                                                              0,
++                                                              extr->ips->ips_addr_d),
++                                  extensions_reply) : 1)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW],
++                                                           SADB_X_EXT_ADDRESS_SRC_FLOW,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&srcflow),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW],
++                                                           SADB_X_EXT_ADDRESS_DST_FLOW,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&dstflow),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK],
++                                                           SADB_X_EXT_ADDRESS_SRC_MASK,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&srcmask),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK],
++                                                           SADB_X_EXT_ADDRESS_DST_MASK,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&dstmask),
++                               extensions_reply)
++              )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
++                          "failed to build the x_addflow reply message extensions\n");
++              SENDERR(-error);
++      }
++              
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
++                          "failed to build the x_addflow reply message\n");
++              SENDERR(-error);
++      }
++      
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
++                                  "sending up x_addflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
++                          "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          extr->ips->ips_said.proto,
++                          pfkey_socketsp->socketp);
++      }
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_addflow_parse: "
++                  "extr->ips cleaned up and freed.\n");
++
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_delflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++#ifdef CONFIG_KLIPS_DEBUG
++      char buf1[64], buf2[64];
++#endif /* CONFIG_KLIPS_DEBUG */
++      struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_reply = NULL;
++      struct socket_list *pfkey_socketsp;
++      uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
++      ip_address srcflow, dstflow, srcmask, dstmask;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_delflow_parse: .\n");
++
++      pfkey_extensions_init(extensions_reply);
++
++      memset((caddr_t)&srcflow, 0, sizeof(srcflow));
++      memset((caddr_t)&dstflow, 0, sizeof(dstflow));
++      memset((caddr_t)&srcmask, 0, sizeof(srcmask));
++      memset((caddr_t)&dstmask, 0, sizeof(dstmask));
++
++      if(!extr || !(extr->ips)) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_delflow_parse: "
++                          "extr, or extr->ips is NULL, fatal\n");
++              SENDERR(EINVAL);
++      }
++
++      if(extr->ips->ips_flags & SADB_X_SAFLAGS_CLEARFLOW) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_x_delflow_parse: "
++                          "CLEARFLOW flag set, calling cleareroutes.\n");
++              if ((error = ipsec_cleareroutes()))
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_delflow_parse: "
++                                  "cleareroutes returned %d.\n", error);
++                      SENDERR(-error);
++      } else {
++              struct sk_buff *first = NULL, *last = NULL;
++
++              if(!(extr->eroute)) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_delflow_parse: "
++                                  "extr->eroute is NULL, fatal.\n");
++                      SENDERR(EINVAL);
++              }
++              
++              srcflow.u.v4.sin_family = AF_INET;
++              dstflow.u.v4.sin_family = AF_INET;
++              srcmask.u.v4.sin_family = AF_INET;
++              dstmask.u.v4.sin_family = AF_INET;
++              srcflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_src;
++              dstflow.u.v4.sin_addr = extr->eroute->er_eaddr.sen_ip_dst;
++              srcmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_src;
++              dstmask.u.v4.sin_addr = extr->eroute->er_emask.sen_ip_dst;
++
++#ifdef CONFIG_KLIPS_DEBUG
++              if (debug_pfkey) {
++                      subnettoa(extr->eroute->er_eaddr.sen_ip_src,
++                                extr->eroute->er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
++                      subnettoa(extr->eroute->er_eaddr.sen_ip_dst,
++                                extr->eroute->er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_delflow_parse: "
++                                  "calling breakeroute for %s->%s\n",
++                                  buf1, buf2);
++              }
++#endif /* CONFIG_KLIPS_DEBUG */
++              error = ipsec_breakroute(&(extr->eroute->er_eaddr),
++                                           &(extr->eroute->er_emask),
++                                           &first, &last);
++              if(error) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_x_delflow_parse: "
++                                  "breakeroute returned %d.  first=0p%p, last=0p%p\n",
++                                  error,
++                                  first,
++                                  last);
++              }
++              if(first != NULL) {
++                      ipsec_kfree_skb(first);
++              }
++              if(last != NULL) {
++                      ipsec_kfree_skb(last);
++              }
++              if(error) {
++                      SENDERR(-error);
++              }
++      }
++      
++      if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
++                                                        SADB_X_DELFLOW,
++                                                        satype,
++                                                        0,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
++                                                        ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
++                            extensions_reply)
++           && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],
++                                                      SADB_EXT_SA,
++                                                      extr->ips->ips_said.spi,
++                                                      extr->ips->ips_replaywin,
++                                                      extr->ips->ips_state,
++                                                      extr->ips->ips_authalg,
++                                                      extr->ips->ips_encalg,
++                                                      extr->ips->ips_flags,
++                                                      extr->ips->ips_ref),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_FLOW],
++                                                           SADB_X_EXT_ADDRESS_SRC_FLOW,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&srcflow),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_FLOW],
++                                                           SADB_X_EXT_ADDRESS_DST_FLOW,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&dstflow),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_SRC_MASK],
++                                                           SADB_X_EXT_ADDRESS_SRC_MASK,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&srcmask),
++                               extensions_reply)
++           && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST_MASK],
++                                                           SADB_X_EXT_ADDRESS_DST_MASK,
++                                                           0, /*extr->ips->ips_said.proto,*/
++                                                           0,
++                                                           (struct sockaddr*)&dstmask),
++                               extensions_reply)
++              )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
++                          "failed to build the x_delflow reply message extensions\n");
++              SENDERR(-error);
++      }
++              
++      if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
++                          "failed to build the x_delflow reply message\n");
++              SENDERR(-error);
++      }
++      
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
++                                  "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
++                          "sending up x_delflow reply message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_delflow_parse: "
++                  "extr->ips cleaned up and freed.\n");
++
++ errlab:
++      if (pfkey_reply) {
++              pfkey_msg_free(&pfkey_reply);
++      }
++      pfkey_extensions_free(extensions_reply);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_msg_debug_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      int error = 0;
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_x_msg_debug_parse: .\n");
++
++/* errlab:*/
++      return error;
++}
++
++/* pfkey_expire expects the ipsec_sa table to be locked before being called. */
++int
++pfkey_expire(struct ipsec_sa *ipsp, int hard)
++{
++      struct sadb_ext *extensions[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_msg = NULL;
++      struct socket_list *pfkey_socketsp;
++      int error = 0;
++      uint8_t satype;
++
++      pfkey_extensions_init(extensions);
++
++      if(!(satype = proto2satype(ipsp->ips_said.proto))) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_expire: "
++                          "satype lookup for protocol %d lookup failed.\n", 
++                          ipsp->ips_said.proto);
++              SENDERR(EINVAL);
++      }
++      
++      if(!pfkey_open_sockets) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
++                          "no sockets listening.\n");
++              SENDERR(EPROTONOSUPPORT);
++      }
++
++      if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0],
++                                                         SADB_EXPIRE,
++                                                         satype,
++                                                         0,
++                                                         ++pfkey_msg_seq,
++                                                         0),
++                             extensions)
++            && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions[SADB_EXT_SA],
++                                                       SADB_EXT_SA,
++                                                       ipsp->ips_said.spi,
++                                                       ipsp->ips_replaywin,
++                                                       ipsp->ips_state,
++                                                       ipsp->ips_authalg,
++                                                       ipsp->ips_encalg,
++                                                       ipsp->ips_flags,
++                                                       ipsp->ips_ref),
++                                extensions)
++            && pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_CURRENT],
++                                                             SADB_EXT_LIFETIME_CURRENT,
++                                                             ipsp->ips_life.ipl_allocations.ipl_count,
++                                                             ipsp->ips_life.ipl_bytes.ipl_count,
++                                                             ipsp->ips_life.ipl_addtime.ipl_count,
++                                                             ipsp->ips_life.ipl_usetime.ipl_count,
++                                                             ipsp->ips_life.ipl_packets.ipl_count),
++                                extensions)
++            && (hard ? 
++                pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD],
++                                                              SADB_EXT_LIFETIME_HARD,
++                                                              ipsp->ips_life.ipl_allocations.ipl_hard,
++                                                              ipsp->ips_life.ipl_bytes.ipl_hard,
++                                                              ipsp->ips_life.ipl_addtime.ipl_hard,
++                                                              ipsp->ips_life.ipl_usetime.ipl_hard,
++                                                              ipsp->ips_life.ipl_packets.ipl_hard),
++                                 extensions)
++                : pfkey_safe_build(error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT],
++                                                                SADB_EXT_LIFETIME_SOFT,
++                                                                ipsp->ips_life.ipl_allocations.ipl_soft,
++                                                                ipsp->ips_life.ipl_bytes.ipl_soft,
++                                                                ipsp->ips_life.ipl_addtime.ipl_soft,
++                                                                ipsp->ips_life.ipl_usetime.ipl_soft,
++                                                                ipsp->ips_life.ipl_packets.ipl_soft),
++                                   extensions))
++            && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
++                                                            SADB_EXT_ADDRESS_SRC,
++                                                            0, /* ipsp->ips_said.proto, */
++                                                            0,
++                                                            ipsp->ips_addr_s),
++                                extensions)
++            && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
++                                                            SADB_EXT_ADDRESS_DST,
++                                                            0, /* ipsp->ips_said.proto, */
++                                                            0,
++                                                            ipsp->ips_addr_d),
++                                extensions))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
++                          "failed to build the expire message extensions\n");
++              spin_unlock(&tdb_lock);
++              goto errlab;
++      }
++      
++      if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
++                          "failed to build the expire message\n");
++              SENDERR(-error);
++      }
++      
++      for(pfkey_socketsp = pfkey_open_sockets;
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
++                                  "sending up expire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
++                          "sending up expire message for satype=%d(%s) (proto=%d) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          ipsp->ips_said.proto,
++                          pfkey_socketsp->socketp);
++      }
++      
++ errlab:
++      if (pfkey_msg) {
++              pfkey_msg_free(&pfkey_msg);
++      }
++      pfkey_extensions_free(extensions);
++      return error;
++}
++
++int
++pfkey_acquire(struct ipsec_sa *ipsp)
++{
++      struct sadb_ext *extensions[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_msg = NULL;
++      struct socket_list *pfkey_socketsp;
++      int error = 0;
++      struct sadb_comb comb[] = {
++              /* auth; encrypt; flags; */
++              /* auth_minbits; auth_maxbits; encrypt_minbits; encrypt_maxbits; */
++              /* reserved; soft_allocations; hard_allocations; soft_bytes; hard_bytes; */
++              /* soft_addtime; hard_addtime; soft_usetime; hard_usetime; */
++              /* soft_packets; hard_packets; */
++              { SADB_AALG_MD5HMAC,  SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS,
++                128, 128, 168, 168,
++                0, 0, 0, 0, 0,
++                57600, 86400, 57600, 86400,
++                0, 0 },
++              { SADB_AALG_SHA1HMAC, SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS,
++                160, 160, 168, 168,
++                0, 0, 0, 0, 0,
++                57600, 86400, 57600, 86400,
++                0, 0 }
++      };
++       
++      /* XXX This should not be hard-coded.  It should be taken from the spdb */
++      uint8_t satype = SADB_SATYPE_ESP;
++
++      pfkey_extensions_init(extensions);
++
++      if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
++                          "SAtype=%d unspecified or unknown.\n",
++                          satype);
++              SENDERR(EINVAL);
++      }
++
++      if(!(pfkey_registered_sockets[satype])) {
++              KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: "
++                          "no sockets registered for SAtype=%d(%s).\n",
++                          satype,
++                          satype2name(satype));
++              SENDERR(EPROTONOSUPPORT);
++      }
++      
++      if (!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions[0],
++                                                        SADB_ACQUIRE,
++                                                        satype,
++                                                        0,
++                                                        ++pfkey_msg_seq,
++                                                        0),
++                            extensions)
++            && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
++                                                            SADB_EXT_ADDRESS_SRC,
++                                                            ipsp->ips_transport_protocol,
++                                                            0,
++                                                            ipsp->ips_addr_s),
++                                extensions)
++            && pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
++                                                            SADB_EXT_ADDRESS_DST,
++                                                            ipsp->ips_transport_protocol,
++                                                            0,
++                                                            ipsp->ips_addr_d),
++                                extensions)
++#if 0
++            && (ipsp->ips_addr_p
++                ? pfkey_safe_build(error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY],
++                                                               SADB_EXT_ADDRESS_PROXY,
++                                                               ipsp->ips_transport_protocol,
++                                                               0,
++                                                               ipsp->ips_addr_p),
++                                   extensions) : 1)
++#endif
++            && (ipsp->ips_ident_s.type != SADB_IDENTTYPE_RESERVED
++                ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC],
++                                                             SADB_EXT_IDENTITY_SRC,
++                                                             ipsp->ips_ident_s.type,
++                                                             ipsp->ips_ident_s.id,
++                                                             ipsp->ips_ident_s.len,
++                                                             ipsp->ips_ident_s.data),
++                                   extensions) : 1)
++
++            && (ipsp->ips_ident_d.type != SADB_IDENTTYPE_RESERVED
++                ? pfkey_safe_build(error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST],
++                                                             SADB_EXT_IDENTITY_DST,
++                                                             ipsp->ips_ident_d.type,
++                                                             ipsp->ips_ident_d.id,
++                                                             ipsp->ips_ident_d.len,
++                                                             ipsp->ips_ident_d.data),
++                                   extensions) : 1)
++#if 0
++            /* FIXME: This won't work yet because I have not finished
++               it. */
++            && (ipsp->ips_sens_
++                ? pfkey_safe_build(error = pfkey_sens_build(&extensions[SADB_EXT_SENSITIVITY],
++                                                            ipsp->ips_sens_dpd,
++                                                            ipsp->ips_sens_sens_level,
++                                                            ipsp->ips_sens_sens_len,
++                                                            ipsp->ips_sens_sens_bitmap,
++                                                            ipsp->ips_sens_integ_level,
++                                                            ipsp->ips_sens_integ_len,
++                                                            ipsp->ips_sens_integ_bitmap),
++                                   extensions) : 1)
++#endif
++            && pfkey_safe_build(error = pfkey_prop_build(&extensions[SADB_EXT_PROPOSAL],
++                                                         64, /* replay */
++                                                         sizeof(comb)/sizeof(struct sadb_comb),
++                                                         &(comb[0])),
++                                extensions)
++              )) {
++              KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: "
++                          "failed to build the acquire message extensions\n");
++              SENDERR(-error);
++      }
++      
++      if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) {
++              KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: "
++                          "failed to build the acquire message\n");
++              SENDERR(-error);
++      }
++
++#if KLIPS_PFKEY_ACQUIRE_LOSSAGE > 0
++      if(sysctl_ipsec_regress_pfkey_lossage) {
++              return(0);
++      }
++#endif        
++      
++      /* this should go to all registered sockets for that satype only */
++      for(pfkey_socketsp = pfkey_registered_sockets[satype];
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) {
++                      KLIPS_PRINT(1|debug_pfkey, "klips_debug:pfkey_acquire: "
++                                  "sending up acquire message for satype=%d(%s) to socket=0p%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
++                          "sending up acquire message for satype=%d(%s) to socket=0p%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++ errlab:
++      if (pfkey_msg) {
++              pfkey_msg_free(&pfkey_msg);
++      }
++      pfkey_extensions_free(extensions);
++      return error;
++}
++
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++int
++pfkey_nat_t_new_mapping(struct ipsec_sa *ipsp, struct sockaddr *ipaddr,
++      __u16 sport)
++{
++      struct sadb_ext *extensions[SADB_EXT_MAX+1];
++      struct sadb_msg *pfkey_msg = NULL;
++      struct socket_list *pfkey_socketsp;
++      int error = 0;
++      uint8_t satype = (ipsp->ips_said.proto==IPPROTO_ESP) ? SADB_SATYPE_ESP : 0;
++
++      /* Construct SADB_X_NAT_T_NEW_MAPPING message */
++
++      pfkey_extensions_init(extensions);
++
++      if((satype == 0) || (satype > SADB_SATYPE_MAX)) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
++                          "SAtype=%d unspecified or unknown.\n",
++                          satype);
++              SENDERR(EINVAL);
++      }
++
++      if(!(pfkey_registered_sockets[satype])) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
++                          "no sockets registered for SAtype=%d(%s).\n",
++                          satype,
++                          satype2name(satype));
++              SENDERR(EPROTONOSUPPORT);
++      }
++
++      if (!(pfkey_safe_build
++              (error = pfkey_msg_hdr_build(&extensions[0], SADB_X_NAT_T_NEW_MAPPING,
++                      satype, 0, ++pfkey_msg_seq, 0), extensions)
++              /* SA */
++              && pfkey_safe_build
++              (error = pfkey_sa_build(&extensions[SADB_EXT_SA],
++                      SADB_EXT_SA, ipsp->ips_said.spi, 0, 0, 0, 0, 0), extensions)
++              /* ADDRESS_SRC = old addr */
++              && pfkey_safe_build
++              (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
++                      SADB_EXT_ADDRESS_SRC, ipsp->ips_said.proto, 0, ipsp->ips_addr_s),
++                      extensions)
++              /* NAT_T_SPORT = old port */
++          && pfkey_safe_build
++              (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_SPORT],
++                      SADB_X_EXT_NAT_T_SPORT, ipsp->ips_natt_sport), extensions)
++              /* ADDRESS_DST = new addr */
++              && pfkey_safe_build
++              (error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
++                      SADB_EXT_ADDRESS_DST, ipsp->ips_said.proto, 0, ipaddr), extensions)
++              /* NAT_T_DPORT = new port */
++          && pfkey_safe_build
++              (error = pfkey_x_nat_t_port_build(&extensions[SADB_X_EXT_NAT_T_DPORT],
++                      SADB_X_EXT_NAT_T_DPORT, sport), extensions)
++              )) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
++                          "failed to build the nat_t_new_mapping message extensions\n");
++              SENDERR(-error);
++      }
++      
++      if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
++                          "failed to build the nat_t_new_mapping message\n");
++              SENDERR(-error);
++      }
++
++      /* this should go to all registered sockets for that satype only */
++      for(pfkey_socketsp = pfkey_registered_sockets[satype];
++          pfkey_socketsp;
++          pfkey_socketsp = pfkey_socketsp->next) {
++              if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
++                                  "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p failed with error=%d.\n",
++                                  satype,
++                                  satype2name(satype),
++                                  pfkey_socketsp->socketp,
++                                  error);
++                      SENDERR(-error);
++              }
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_nat_t_new_mapping: "
++                          "sending up nat_t_new_mapping message for satype=%d(%s) to socket=%p succeeded.\n",
++                          satype,
++                          satype2name(satype),
++                          pfkey_socketsp->socketp);
++      }
++      
++ errlab:
++      if (pfkey_msg) {
++              pfkey_msg_free(&pfkey_msg);
++      }
++      pfkey_extensions_free(extensions);
++      return error;
++}
++
++DEBUG_NO_STATIC int
++pfkey_x_nat_t_new_mapping_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr)
++{
++      /* SADB_X_NAT_T_NEW_MAPPING not used in kernel */
++      return -EINVAL;
++}
++#endif
++
++DEBUG_NO_STATIC int (*ext_processors[SADB_EXT_MAX+1])(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) =
++{
++  NULL, /* pfkey_msg_process, */
++        pfkey_sa_process,
++        pfkey_lifetime_process,
++        pfkey_lifetime_process,
++        pfkey_lifetime_process,
++        pfkey_address_process,
++        pfkey_address_process,
++        pfkey_address_process,
++        pfkey_key_process,
++        pfkey_key_process,
++        pfkey_ident_process,
++        pfkey_ident_process,
++        pfkey_sens_process,
++        pfkey_prop_process,
++        pfkey_supported_process,
++        pfkey_supported_process,
++        pfkey_spirange_process,
++        pfkey_x_kmprivate_process,
++        pfkey_x_satype_process,
++        pfkey_sa_process,
++        pfkey_address_process,
++        pfkey_address_process,
++        pfkey_address_process,
++        pfkey_address_process,
++        pfkey_address_process,
++      pfkey_x_debug_process,
++      pfkey_x_protocol_process
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      ,
++      pfkey_x_nat_t_type_process,
++      pfkey_x_nat_t_port_process,
++      pfkey_x_nat_t_port_process,
++      pfkey_address_process
++#endif        
++};
++
++
++DEBUG_NO_STATIC int (*msg_parsers[SADB_MAX +1])(struct sock *sk, struct sadb_ext *extensions[], struct pfkey_extracted_data* extr)
++ =
++{
++      NULL, /* RESERVED */
++      pfkey_getspi_parse,
++      pfkey_update_parse,
++      pfkey_add_parse,
++      pfkey_delete_parse,
++      pfkey_get_parse,
++      pfkey_acquire_parse,
++      pfkey_register_parse,
++      pfkey_expire_parse,
++      pfkey_flush_parse,
++      pfkey_dump_parse,
++      pfkey_x_promisc_parse,
++      pfkey_x_pchange_parse,
++      pfkey_x_grpsa_parse,
++      pfkey_x_addflow_parse,
++      pfkey_x_delflow_parse,
++      pfkey_x_msg_debug_parse
++#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
++      , pfkey_x_nat_t_new_mapping_parse
++#endif        
++};
++
++int
++pfkey_build_reply(struct sadb_msg *pfkey_msg,
++                struct pfkey_extracted_data *extr,
++                struct sadb_msg **pfkey_reply)
++{
++      struct sadb_ext *extensions[SADB_EXT_MAX+1];
++      int error = 0;
++      int msg_type = pfkey_msg->sadb_msg_type;
++      int seq = pfkey_msg->sadb_msg_seq;
++
++      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
++                  "building reply with type: %d\n",
++                  msg_type);
++      pfkey_extensions_init(extensions);
++      if (!extr || !extr->ips) {
++                      KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
++                                  "bad ipsec_sa passed\n");
++                      return EINVAL;
++      }
++      error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0],
++                                                   msg_type,
++                                                   proto2satype(extr->ips->ips_said.proto),
++                                                   0,
++                                                   seq,
++                                                   pfkey_msg->sadb_msg_pid),
++                               extensions) &&
++              (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
++                 1 << SADB_EXT_SA)
++               || pfkey_safe_build(pfkey_sa_ref_build(&extensions[SADB_EXT_SA],
++                                                  SADB_EXT_SA,
++                                                  extr->ips->ips_said.spi,
++                                                  extr->ips->ips_replaywin,
++                                                  extr->ips->ips_state,
++                                                  extr->ips->ips_authalg,
++                                                  extr->ips->ips_encalg,
++                                                  extr->ips->ips_flags,
++                                                  extr->ips->ips_ref),
++                                   extensions)) &&
++              (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
++                 1 << SADB_EXT_LIFETIME_CURRENT)
++               || pfkey_safe_build(pfkey_lifetime_build(&extensions
++                                                        [SADB_EXT_LIFETIME_CURRENT],
++                                                        SADB_EXT_LIFETIME_CURRENT,
++                                                        extr->ips->ips_life.ipl_allocations.ipl_count,
++                                                        extr->ips->ips_life.ipl_bytes.ipl_count,
++                                                        extr->ips->ips_life.ipl_addtime.ipl_count,
++                                                        extr->ips->ips_life.ipl_usetime.ipl_count,
++                                                        extr->ips->ips_life.ipl_packets.ipl_count),
++                                   extensions)) &&
++              (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
++                 1 << SADB_EXT_ADDRESS_SRC)
++               || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
++                                                       SADB_EXT_ADDRESS_SRC,
++                                                       extr->ips->ips_said.proto,
++                                                       0,
++                                                       extr->ips->ips_addr_s),
++                                   extensions)) &&
++              (!(extensions_bitmaps[EXT_BITS_OUT][EXT_BITS_REQ][msg_type] &
++                 1 << SADB_EXT_ADDRESS_DST)
++               || pfkey_safe_build(pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
++                                                       SADB_EXT_ADDRESS_DST,
++                                                       extr->ips->ips_said.proto,
++                                                       0,
++                                                       extr->ips->ips_addr_d),
++                                   extensions));
++
++      if (error == 0) {
++              KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
++                          "building extensions failed\n");
++              return EINVAL;
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_build_reply: "
++                  "built extensions, proceed to build the message\n");
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_build_reply: "
++                  "extensions[1]=0p%p\n",
++                  extensions[1]);
++      error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT);
++      pfkey_extensions_free(extensions);
++
++      return error;
++}
++
++int
++pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg,
++                              struct sadb_msg **pfkey_reply)
++{
++      int error = 0;
++      int i;
++      struct sadb_ext *extensions[SADB_EXT_MAX+1];
++      struct pfkey_extracted_data extr = {NULL, NULL, NULL};
++      
++      pfkey_extensions_init(extensions);
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_msg_interp: "
++                  "parsing message ver=%d, type=%d, errno=%d, satype=%d(%s), len=%d, res=%d, seq=%d, pid=%d.\n", 
++                  pfkey_msg->sadb_msg_version,
++                  pfkey_msg->sadb_msg_type,
++                  pfkey_msg->sadb_msg_errno,
++                  pfkey_msg->sadb_msg_satype,
++                  satype2name(pfkey_msg->sadb_msg_satype),
++                  pfkey_msg->sadb_msg_len,
++                  pfkey_msg->sadb_msg_reserved,
++                  pfkey_msg->sadb_msg_seq,
++                  pfkey_msg->sadb_msg_pid);
++      
++      extr.ips = ipsec_sa_alloc(&error); /* pass in error var by pointer */
++      if(extr.ips == NULL) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_msg_interp: "
++                          "memory allocation error.\n");
++              SENDERR(-error);
++      }
++
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_msg_interp: "
++                  "allocated extr->ips=0p%p.\n",
++                  extr.ips);
++      
++      if(pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_msg_interp: "
++                          "satype %d > max %d\n", 
++                          pfkey_msg->sadb_msg_satype,
++                          SADB_SATYPE_MAX);
++              SENDERR(EINVAL);
++      }
++      
++      switch(pfkey_msg->sadb_msg_type) {
++      case SADB_GETSPI:
++      case SADB_UPDATE:
++      case SADB_ADD:
++      case SADB_DELETE:
++      case SADB_X_GRPSA:
++      case SADB_X_ADDFLOW:
++              if(!(extr.ips->ips_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_msg_interp: "
++                                  "satype %d lookup failed.\n", 
++                                  pfkey_msg->sadb_msg_satype);
++                      SENDERR(EINVAL);
++              } else {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_msg_interp: "
++                                  "satype %d lookups to proto=%d.\n", 
++                                  pfkey_msg->sadb_msg_satype,
++                                  extr.ips->ips_said.proto);
++              }
++              break;
++      default:
++              break;
++      }
++      
++      /* The NULL below causes the default extension parsers to be used */
++      /* Parse the extensions */
++      if((error = pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN)))
++      {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_msg_interp: "
++                          "message parsing failed with error %d.\n",
++                          error); 
++              SENDERR(-error);
++      }
++      
++      /* Process the extensions */
++      for(i=1; i <= SADB_EXT_MAX;i++) {
++              if(extensions[i] != NULL) {
++                      KLIPS_PRINT(debug_pfkey,
++                                  "klips_debug:pfkey_msg_interp: "
++                                  "processing ext %d 0p%p with processor 0p%p.\n", 
++                                  i, extensions[i], ext_processors[i]);
++                      if((error = ext_processors[i](extensions[i], &extr))) {
++                              KLIPS_PRINT(debug_pfkey,
++                                          "klips_debug:pfkey_msg_interp: "
++                                          "extension processing for type %d failed with error %d.\n",
++                                          i,
++                                          error); 
++                              SENDERR(-error);
++                      }
++                      
++              }
++              
++      }
++      
++      /* Parse the message types */
++      KLIPS_PRINT(debug_pfkey,
++                  "klips_debug:pfkey_msg_interp: "
++                  "parsing message type %d(%s) with msg_parser 0p%p.\n",
++                  pfkey_msg->sadb_msg_type,
++                  pfkey_v2_sadb_type_string(pfkey_msg->sadb_msg_type),
++                  msg_parsers[pfkey_msg->sadb_msg_type]); 
++      if((error = msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) {
++              KLIPS_PRINT(debug_pfkey,
++                          "klips_debug:pfkey_msg_interp: "
++                          "message parsing failed with error %d.\n",
++                          error); 
++              SENDERR(-error);
++      }
++
++#if 0
++      error = pfkey_build_reply(pfkey_msg, &extr, pfkey_reply);
++      if (error) {
++              *pfkey_reply = NULL;
++      }
++#endif        
++ errlab:
++      if(extr.ips != NULL) {
++              ipsec_sa_wipe(extr.ips);
++      }
++      if(extr.ips2 != NULL) {
++              ipsec_sa_wipe(extr.ips2);
++      }
++      if (extr.eroute != NULL) {
++              kfree(extr.eroute);
++      }
++      return(error);
++}
++
++/*
++ * $Log: pfkey_v2_parser.c,v $
++ * Revision 1.134.2.2  2006/10/06 21:39:26  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.134.2.1  2006/05/01 14:37:25  mcr
++ * ip_chk_addr -> inet_addr_type for more direct 2.4/2.6 support.
++ *
++ * Revision 1.134  2005/05/11 01:48:20  mcr
++ *    removed "poor-man"s OOP in favour of proper C structures.
++ *
++ * Revision 1.133  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.132  2005/04/14 20:56:24  mcr
++ *    moved (pfkey_)ipsec_sa_init to ipsec_sa.c.
++ *
++ * Revision 1.131  2005/01/26 00:50:35  mcr
++ *    adjustment of confusion of CONFIG_IPSEC_NAT vs CONFIG_KLIPS_NAT,
++ *    and make sure that NAT_TRAVERSAL is set as well to match
++ *    userspace compiles of code.
++ *
++ * Revision 1.130  2004/09/08 17:21:36  ken
++ * Rename MD5* -> osMD5 functions to prevent clashes with other symbols exported by kernel modules (CIFS in 2.6 initiated this)
++ *
++ * Revision 1.129  2004/09/06 18:36:30  mcr
++ *    if a protocol can not be found, then log it. This is not
++ *    debugging.
++ *
++ * Revision 1.128  2004/08/21 00:45:19  mcr
++ *    CONFIG_KLIPS_NAT was wrong, also need to include udp.h.
++ *
++ * Revision 1.127  2004/08/20 21:45:45  mcr
++ *    CONFIG_KLIPS_NAT_TRAVERSAL is not used in an attempt to
++ *    be 26sec compatible. But, some defines where changed.
++ *
++ * Revision 1.126  2004/08/17 03:27:23  mcr
++ *    klips 2.6 edits.
++ *
++ * Revision 1.125  2004/08/04 15:57:07  mcr
++ *    moved des .h files to include/des/ *
++ *    included 2.6 protocol specific things
++ *    started at NAT-T support, but it will require a kernel patch.
++ *
++ * Revision 1.124  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.123  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.122.2.2  2004/04/05 04:30:46  mcr
++ *    patches for alg-branch to compile/work with 2.x openswan
++ *
++ * Revision 1.122.2.1  2003/12/22 15:25:52  jjo
++ * . Merged algo-0.8.1-rc11-test1 into alg-branch
++ *
++ * Revision 1.122  2003/12/10 01:14:27  mcr
++ *    NAT-traversal patches to KLIPS.
++ *
++ * Revision 1.121  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.120.4.2  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.120.4.1  2003/09/21 13:59:56  mcr
++ *    pre-liminary X.509 patch - does not yet pass tests.
++ *
++ * Revision 1.120  2003/04/03 17:38:09  rgb
++ * Centralised ipsec_kfree_skb and ipsec_dev_{get,put}.
++ *
++ * Revision 1.119  2003/02/06 01:52:37  rgb
++ * Removed no longer relevant comment
++ *
++ * Revision 1.118  2003/01/30 02:32:44  rgb
++ *
++ * Transmit error code through to caller from callee for better diagnosis of problems.
++ *
++ * Revision 1.117  2003/01/16 18:48:13  rgb
++ *
++ * Fixed sign bug in error return from an sa allocation call in
++ * pfkey_msg_interp.
++ *
++ * Revision 1.116  2002/10/17 16:38:01  rgb
++ * Change pfkey_alloc_eroute() to never static since its consumers
++ * have been moved outside the file.
++ *
++ * Revision 1.115  2002/10/12 23:11:53  dhr
++ *
++ * [KenB + DHR] more 64-bit cleanup
++ *
++ * Revision 1.114  2002/10/05 05:02:58  dhr
++ *
++ * C labels go on statements
++ *
++ * Revision 1.113  2002/09/30 19:11:22  rgb
++ *    Turn on debugging for upgoing acquire messages to test for reliability.
++ *
++ * Revision 1.112  2002/09/20 15:41:16  rgb
++ * Switch from pfkey_alloc_ipsec_sa() to ipsec_sa_alloc().
++ * Added sadb_x_sa_ref to struct sadb_sa.
++ * Added ref parameter to pfkey_sa_build().
++ *
++ * Revision 1.111  2002/09/20 05:02:08  rgb
++ * Added memory allocation debugging.
++ * Convert to switch to divulge hmac keys for debugging.
++ * Added text labels to elucidate numeric values presented.
++ *
++ * Revision 1.110  2002/08/03 18:03:05  mcr
++ *    loop that checks for SPI's to have been already linked
++ *    fails to actually step to next pointer, but continuously
++ *    resets to head of list. Wrong pointer used.
++ *    test east-icmp-02 revealed this.
++ *
++ * Revision 1.109  2002/07/26 08:48:31  rgb
++ * Added SA ref table code.
++ *
++ * Revision 1.108  2002/05/27 18:55:03  rgb
++ * Remove final vistiges of tdb references via IPSEC_KLIPS1_COMPAT.
++ *
++ * Revision 1.107  2002/05/23 07:16:08  rgb
++ * Added ipsec_sa_put() for releasing an ipsec_sa refcount.
++ * Pointer clean-up.
++ * Added refcount code.
++ *
++ * Revision 1.106  2002/05/14 02:34:13  rgb
++ * Converted reference from ipsec_sa_put to ipsec_sa_add to avoid confusion
++ * with "put" usage in the kernel.
++ * Change all references to tdb, TDB or Tunnel Descriptor Block to ips,
++ * ipsec_sa or ipsec_sa.
++ * Moved all the extension parsing functions to pfkey_v2_ext_process.c.
++ *
++ * Revision 1.105  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.104  2002/04/24 07:36:34  mcr
++ * Moved from ./klips/net/ipsec/pfkey_v2_parser.c,v
++ *
++ * Revision 1.103  2002/04/20 00:12:25  rgb
++ * Added esp IV CBC attack fix, disabled.
++ *
++ * Revision 1.102  2002/03/08 01:15:17  mcr
++ *    put some internal structure only debug messages behind
++ *    && sysctl_ipsec_debug_verbose.
++ *
++ * Revision 1.101  2002/01/29 17:17:57  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.100  2002/01/29 04:00:54  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.99  2002/01/29 02:13:19  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.98  2002/01/12 02:57:57  mcr
++ *    first regression test causes acquire messages to be lost
++ *    100% of the time. This is to help testing of pluto.
++ *
++ * Revision 1.97  2001/11/26 09:23:52  rgb
++ * Merge MCR's ipsec_sa, eroute, proc and struct lifetime changes.
++ *
++ * Revision 1.93.2.4  2001/10/23 04:20:27  mcr
++ *    parity was forced on wrong structure! prototypes help here.
++ *
++ * Revision 1.93.2.3  2001/10/22 21:14:59  mcr
++ *    include des.h, removed phony prototypes and fixed calling
++ *    conventions to match real prototypes.
++ *
++ * Revision 1.93.2.2  2001/10/15 05:39:03  mcr
++ *    %08lx is not the right format for u32. Use %08x. 64-bit safe? ha.
++ *
++ * Revision 1.93.2.1  2001/09/25 02:30:14  mcr
++ *    struct tdb -> struct ipsec_sa.
++ *    use new lifetime structure. common format routines for debug.
++ *
++ * Revision 1.96  2001/11/06 20:47:54  rgb
++ * Fixed user context call to ipsec_dev_start_xmit() bug.  Call
++ * dev_queue_xmit() instead.
++ *
++ * Revision 1.95  2001/11/06 19:47:46  rgb
++ * Added packet parameter to lifetime and comb structures.
++ *
++ * Revision 1.94  2001/10/18 04:45:23  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.93  2001/09/20 15:32:59  rgb
++ * Min/max cleanup.
++ *
++ * Revision 1.92  2001/09/19 16:35:48  rgb
++ * PF_KEY ident fix for getspi from NetCelo (puttdb duplication).
++ *
++ * Revision 1.91  2001/09/15 16:24:06  rgb
++ * Re-inject first and last HOLD packet when an eroute REPLACE is done.
++ *
++ * Revision 1.90  2001/09/14 16:58:38  rgb
++ * Added support for storing the first and last packets through a HOLD.
++ *
++ * Revision 1.89  2001/09/08 21:14:07  rgb
++ * Added pfkey ident extension support for ISAKMPd. (NetCelo)
++ * Better state coherency (error management) between pf_key and IKE daemon.
++ * (NetCelo)
++ *
++ * Revision 1.88  2001/08/27 19:42:44  rgb
++ * Fix memory leak of encrypt and auth structs in pfkey register.
++ *
++ * Revision 1.87  2001/07/06 19:50:46  rgb
++ * Removed unused debugging code.
++ * Added inbound policy checking code for IPIP SAs.
++ *
++ * Revision 1.86  2001/06/20 06:26:04  rgb
++ * Changed missing SA errors from EEXIST to ENOENT and added debug output
++ * for already linked SAs.
++ *
++ * Revision 1.85  2001/06/15 04:57:02  rgb
++ * Remove single error return condition check and check for all errors in
++ * the case of a replace eroute delete operation.  This means that
++ * applications must expect to be deleting something before replacing it
++ * and if nothing is found, complain.
++ *
++ * Revision 1.84  2001/06/14 19:35:12  rgb
++ * Update copyright date.
++ *
++ * Revision 1.83  2001/06/12 00:03:19  rgb
++ * Silence debug set/unset under normal conditions.
++ *
++ * Revision 1.82  2001/05/30 08:14:04  rgb
++ * Removed vestiges of esp-null transforms.
++ *
++ * Revision 1.81  2001/05/27 06:12:12  rgb
++ * Added structures for pid, packet count and last access time to eroute.
++ * Added packet count to beginning of /proc/net/ipsec_eroute.
++ *
++ * Revision 1.80  2001/05/03 19:43:59  rgb
++ * Check error return codes for all build function calls.
++ * Standardise on SENDERR() macro.
++ *
++ * Revision 1.79  2001/04/20 21:09:16  rgb
++ * Cleaned up fixed tdbwipes.
++ * Free pfkey_reply and clean up extensions_reply for grpsa, addflow and
++ * delflow (Per Cederqvist) plugging memleaks.
++ *
++ * Revision 1.78  2001/04/19 19:02:39  rgb
++ * Fixed extr.tdb freeing, stealing it for getspi, update and add.
++ * Refined a couple of spinlocks, fixed the one in update.
++ *
++ * Revision 1.77  2001/04/18 20:26:16  rgb
++ * Wipe/free eroute and both tdbs from extr at end of pfkey_msg_interp()
++ * instead of inside each message type parser.  This fixes two memleaks.
++ *
++ * Revision 1.76  2001/04/17 23:51:18  rgb
++ * Quiet down pfkey_x_debug_process().
++ *
++ * Revision 1.75  2001/03/29 01:55:05  rgb
++ * Fixed pfkey key init memleak.
++ * Fixed pfkey encryption key debug output.
++ *
++ * Revision 1.74  2001/03/27 05:29:14  rgb
++ * Debug output cleanup/silencing.
++ *
++ * Revision 1.73  2001/02/28 05:03:28  rgb
++ * Clean up and rationalise startup messages.
++ *
++ * Revision 1.72  2001/02/27 22:24:56  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.71  2001/02/27 06:59:30  rgb
++ * Added satype2name() conversions most places satype is debug printed.
++ *
++ * Revision 1.70  2001/02/26 22:37:08  rgb
++ * Fixed 'unknown proto' INT bug in new code.
++ * Added satype to protocol debugging instrumentation.
++ *
++ * Revision 1.69  2001/02/26 19:57:51  rgb
++ * Re-formatted debug output (split lines, consistent spacing).
++ * Fixed as yet undetected FLUSH bug which called ipsec_tdbcleanup()
++ * with an satype instead of proto.
++ * Checked for satype consistency and fixed minor bugs.
++ * Fixed undetected ungrpspi bug that tried to upmsg a second tdb.
++ * Check for satype sanity in pfkey_expire().
++ * Added satype sanity check to addflow.
++ *
++ * Revision 1.68  2001/02/12 23:14:40  rgb
++ * Remove double spin lock in pfkey_expire().
++ *
++ * Revision 1.67  2001/01/31 19:23:40  rgb
++ * Fixed double-unlock bug introduced by grpsa upmsg (found by Lars Heete).
++ *
++ * Revision 1.66  2001/01/29 22:20:04  rgb
++ * Fix minor add upmsg lifetime bug.
++ *
++ * Revision 1.65  2001/01/24 06:12:33  rgb
++ * Fixed address extension compile bugs just introduced.
++ *
++ * Revision 1.64  2001/01/24 00:31:15  rgb
++ * Added upmsg for addflow/delflow.
++ *
++ * Revision 1.63  2001/01/23 22:02:55  rgb
++ * Added upmsg to x_grpsa.
++ * Fixed lifetimes extentions to add/update/get upmsg.
++ *
++ * Revision 1.62  2000/11/30 21:47:51  rgb
++ * Fix error return bug after returning from pfkey_tdb_init().
++ *
++ * Revision 1.61  2000/11/17 18:10:29  rgb
++ * Fixed bugs mostly relating to spirange, to treat all spi variables as
++ * network byte order since this is the way PF_KEYv2 stored spis.
++ *
++ * Revision 1.60  2000/11/06 04:34:53  rgb
++ * Changed non-exported functions to DEBUG_NO_STATIC.
++ * Add Svenning's adaptive content compression.
++ * Ditched spin_lock_irqsave in favour of spin_lock/_bh.
++ * Fixed double unlock bug (Svenning).
++ * Fixed pfkey_msg uninitialized bug in pfkey_{expire,acquire}().
++ * Fixed incorrect extension type (prop) in pfkey)acquire().
++ *
++ * Revision 1.59  2000/10/11 15:25:12  rgb
++ * Fixed IPCOMP disabled compile bug.
++ *
++ * Revision 1.58  2000/10/11 14:54:03  rgb
++ * Fixed pfkey_acquire() satype to SADB_SATYPE_ESP and removed pfkey
++ * protocol violations of setting pfkey_address_build() protocol parameter
++ * to non-zero except in the case of pfkey_acquire().
++ *
++ * Revision 1.57  2000/10/10 20:10:18  rgb
++ * Added support for debug_ipcomp and debug_verbose to klipsdebug.
++ *
++ * Revision 1.56  2000/10/06 20:24:36  rgb
++ * Fixes to pfkey_acquire to initialize extensions[] and use correct
++ * ipproto.
++ *
++ * Revision 1.55  2000/10/03 03:20:57  rgb
++ * Added brackets to get a?b:c scope right for pfkey_register reply.
++ *
++ * Revision 1.54  2000/09/29 19:49:30  rgb
++ * As-yet-unused-bits cleanup.
++ *
++ * Revision 1.53  2000/09/28 00:35:45  rgb
++ * Padded SATYPE printout in pfkey_register for vertical alignment.
++ *
++ * Revision 1.52  2000/09/20 16:21:58  rgb
++ * Cleaned up ident string alloc/free.
++ *
++ * Revision 1.51  2000/09/20 04:04:20  rgb
++ * Changed static functions to DEBUG_NO_STATIC to reveal function names in
++ * oopsen.
++ *
++ * Revision 1.50  2000/09/16 01:10:53  rgb
++ * Fixed unused var warning with debug off.
++ *
++ * Revision 1.49  2000/09/15 11:37:02  rgb
++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++ * IPCOMP zlib deflate code.
++ *
++ * Revision 1.48  2000/09/15 04:57:57  rgb
++ * Cleaned up existing IPCOMP code before svenning addition.
++ * Initialize pfkey_reply and extensions_reply in case of early error in
++ * message parsing functions (thanks Kai!).
++ *
++ * Revision 1.47  2000/09/13 08:02:56  rgb
++ * Added KMd registration notification.
++ *
++ * Revision 1.46  2000/09/12 22:35:36  rgb
++ * Restructured to remove unused extensions from CLEARFLOW messages.
++ *
++ * Revision 1.45  2000/09/12 03:24:23  rgb
++ * Converted #if0 debugs to sysctl.
++ *
++ * Revision 1.44  2000/09/09 06:38:39  rgb
++ * Correct SADB message type for update, add and delete.
++ *
++ * Revision 1.43  2000/09/08 19:19:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ * Removed all references to CONFIG_IPSEC_PFKEYv2.
++ * Put in sanity checks in most msg type parsers to catch invalid satypes
++ * and empty socket lists.
++ * Moved spin-locks in pfkey_get_parse() to simplify.
++ * Added pfkey_acquire().
++ * Added upwards messages to update, add, delete, acquire_parse,
++ * expire_parse and flush.
++ * Fix pfkey_prop_build() parameter to be only single indirection.
++ * Changed all replies to use pfkey_reply.
++ * Check return code on puttdb() and deltdbchain() in getspi, update,
++ * add, delete.
++ * Fixed up all pfkey replies to open and registered sockets.
++ *
++ * Revision 1.42  2000/09/01 18:50:26  rgb
++ * Added a supported algorithms array lists, one per satype and registered
++ * existing algorithms.
++ * Fixed pfkey_list_{insert,remove}_{socket,support}() to allow change to
++ * list.
++ * Only send pfkey_expire() messages to sockets registered for that satype.
++ * Added reply to pfkey_getspi_parse().
++ * Added reply to pfkey_get_parse().
++ * Fixed debug output label bug in pfkey_lifetime_process().
++ * Cleaned up pfkey_sa_process a little.
++ * Moved pfkey_safe_build() above message type parsers to make it available
++ * for creating replies.
++ * Added comments for future work in pfkey_acquire_parse().
++ * Fleshed out guts of pfkey_register_parse().
++ *
++ * Revision 1.41  2000/08/24 16:58:11  rgb
++ * Fixed key debugging variables.
++ * Fixed error return code for a failed search.
++ * Changed order of pfkey_get operations.
++ *
++ * Revision 1.40  2000/08/21 16:32:27  rgb
++ * Re-formatted for cosmetic consistency and readability.
++ *
++ * Revision 1.39  2000/08/20 21:38:57  rgb
++ * Bugfixes to as-yet-unused pfkey_update_parse() and
++ * pfkey_register_parse(). (Momchil)
++ * Added functions pfkey_safe_build(), pfkey_expire() and
++ * pfkey_build_reply(). (Momchil)
++ * Added a pfkey_reply parameter to pfkey_msg_interp(). (Momchil)
++ *
++ * Revision 1.38  2000/08/18 21:30:41  rgb
++ * Purged all tdb_spi, tdb_proto and tdb_dst macros.  They are unclear.
++ *
++ * Revision 1.37  2000/08/18 18:18:02  rgb
++ * Cosmetic and descriptive changes made to debug test.
++ * getspi and update fixes from Momchil.
++ *
++ * Revision 1.36  2000/08/15 15:41:55  rgb
++ * Fixed the (as yet unused and untested) pfkey_getspi() routine.
++ *
++ * Revision 1.35  2000/08/01 14:51:52  rgb
++ * Removed _all_ remaining traces of DES.
++ *
++ * Revision 1.34  2000/07/28 14:58:32  rgb
++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
++ *
++ * Revision 1.33  2000/06/28 05:50:11  rgb
++ * Actually set iv_bits.
++ *
++ * Revision 1.32  2000/05/30 18:36:56  rgb
++ * Fix AH auth hash setup bug.  This breaks interop with previous PF_KEY
++ * FreeS/WAN, but fixes interop with other implementations.
++ *
++ * Revision 1.31  2000/03/16 14:05:48  rgb
++ * Fixed brace scope preventing non-debug compile.
++ * Added null parameter check for pfkey_x_debug().
++ *
++ * Revision 1.30  2000/01/22 23:21:13  rgb
++ * Use new function satype2proto().
++ *
++ * Revision 1.29  2000/01/22 08:40:21  rgb
++ * Invert condition to known value to avoid AF_INET6 in 2.0.36.
++ *
++ * Revision 1.28  2000/01/22 07:58:57  rgb
++ * Fixed REPLACEFLOW bug, missing braces around KLIPS_PRINT *and* SENDERR.
++ *
++ * Revision 1.27  2000/01/22 03:48:01  rgb
++ * Added extr pointer component debugging.
++ *
++ * Revision 1.26  2000/01/21 09:41:25  rgb
++ * Changed a (void*) to (char*) cast to do proper pointer math.
++ * Don't call tdbwipe if tdb2 is NULL.
++ *
++ * Revision 1.25  2000/01/21 06:21:01  rgb
++ * Added address cases for eroute flows.
++ * Tidied up compiler directive indentation for readability.
++ * Added ictx,octx vars for simplification.
++ * Added macros for HMAC padding magic numbers.
++ * Converted from double tdb arguments to one structure (extr)
++ * containing pointers to all temporary information structures
++ * and checking for valid arguments to all ext processors and
++ * msg type parsers.
++ * Added spiungrp'ing.
++ * Added klipsdebug switching capability.
++ * Removed sa_process() check for zero protocol.
++ * Added address case for DST2 for grouping.
++ * Added/changed minor debugging instrumentation.
++ * Fixed spigrp for single said, ungrouping case.
++ * Added code to parse addflow and delflow messages.
++ * Removed redundant statements duplicating tdbwipe() functionality
++ * and causing double kfrees.
++ * Permit addflow to have a protocol of 0.
++ *
++ * Revision 1.24  1999/12/09 23:23:00  rgb
++ * Added check to pfkey_sa_process() to do eroutes.
++ * Converted to DIVUP() macro.
++ * Converted if() to switch() in pfkey_register_parse().
++ * Use new pfkey_extensions_init() instead of memset().
++ *
++ * Revision 1.23  1999/12/01 22:18:13  rgb
++ * Preset minspi and maxspi values in case and spirange extension is not
++ * included and check for the presence of an spirange extension before
++ * using it.  Initialise tdb_sastate to LARVAL.
++ * Fixed debugging output typo.
++ * Fixed authentication context initialisation bugs (4 places).
++ *
++ * Revision 1.22  1999/11/27 11:53:08  rgb
++ * Moved pfkey_msg_parse prototype to pfkey.h
++ * Moved exts_permitted/required prototype to pfkey.h.
++ * Moved sadb_satype2proto protocol lookup table to lib/pfkey_v2_parse.c.
++ * Deleted SADB_X_EXT_SA2 code from pfkey_sa_process() since it will never
++ * be called.
++ * Moved protocol/algorithm checks to lib/pfkey_v2_parse.c
++ * Debugging error messages added.
++ * Enable lifetime_current checking.
++ * Remove illegal requirement for SA extension to be present in an
++ * originating GETSPI call.
++ * Re-instate requirement for UPDATE or ADD message to be MATURE.
++ * Add argument to pfkey_msg_parse() for direction.
++ * Fixed IPIP dst address bug and purged redundant, leaky code.
++ *
++ * Revision 1.21  1999/11/24 05:24:20  rgb
++ * hanged 'void*extensions' to 'struct sadb_ext*extensions'.
++ * Fixed indention.
++ * Ditched redundant replay check.
++ * Fixed debug message text from 'parse' to 'process'.
++ * Added more debug output.
++ * Forgot to zero extensions array causing bug, fixed.
++ *
++ * Revision 1.20  1999/11/23 23:08:13  rgb
++ * Move all common parsing code to lib/pfkey_v2_parse.c and rename
++ * remaining bits to *_process. (PJO)
++ * Add macros for dealing with alignment and rounding up more opaquely.
++ * Use provided macro ADDRTOA_BUF instead of hardcoded value.
++ * Sort out pfkey and freeswan headers, putting them in a library path.
++ * Corrected a couple of bugs in as-yet-inactive code.
++ *
++ * Revision 1.19  1999/11/20 22:01:10  rgb
++ * Add more descriptive error messages for non-zero reserved fields.
++ * Add more descriptive error message for spirange parsing.
++ * Start on supported extension parsing.
++ * Start on register and get message parsing.
++ *
++ * Revision 1.18  1999/11/18 04:09:20  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ *
++ * Revision 1.17  1999/11/17 15:53:41  rgb
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ *
++ * Revision 1.16  1999/10/26 16:57:43  rgb
++ * Add shorter macros for compiler directives to visually clean-up.
++ * Give ipv6 code meaningful compiler directive.
++ * Add comments to other #if 0 debug code.
++ * Remove unused *_bh_atomic() calls.
++ * Fix mis-placed spinlock.
++ *
++ * Revision 1.15  1999/10/16 18:27:10  rgb
++ * Clean-up unused cruft.
++ * Fix-up lifetime_allocations_c and lifetime_addtime_c initialisations.
++ *
++ * Revision 1.14  1999/10/08 18:37:34  rgb
++ * Fix end-of-line spacing to sate whining PHMs.
++ *
++ * Revision 1.13  1999/10/03 18:49:12  rgb
++ * Spinlock fixes for 2.0.xx and 2.3.xx.
++ *
++ * Revision 1.12  1999/10/01 15:44:54  rgb
++ * Move spinlock header include to 2.1> scope.
++ *
++ * Revision 1.11  1999/10/01 00:05:45  rgb
++ * Added tdb structure locking.
++ * Use 'jiffies' instead of do_get_timeofday().
++ * Fix lifetime assignments.
++ *
++ * Revision 1.10  1999/09/21 15:24:45  rgb
++ * Rework spirange code to save entropy and prevent endless loops.
++ *
++ * Revision 1.9  1999/09/16 12:10:21  rgb
++ * Minor fixes to random spi selection for correctness and entropy conservation.
++ *
++ * Revision 1.8  1999/05/25 22:54:46  rgb
++ * Fix comparison that should be an assignment in an if.
++ *
++ * Revision 1.7  1999/05/09 03:25:37  rgb
++ * Fix bug introduced by 2.2 quick-and-dirty patch.
++ *
++ * Revision 1.6  1999/05/08 21:32:30  rgb
++ * Fix error return reporting.
++ *
++ * Revision 1.5  1999/05/05 22:02:33  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.4  1999/04/29 15:22:40  rgb
++ * Standardise an error return method.
++ * Add debugging instrumentation.
++ * Add check for existence of macros min/max.
++ * Add extensions permitted/required in/out filters.
++ * Add satype-to-protocol table.
++ * Add a second tdb pointer to each parser to accomodate GRPSA.
++ * Move AH & no_algo_set to GETSPI, UPDATE and ADD.
++ * Add OOO window check.
++ * Add support for IPPROTO_IPIP and hooks for IPPROTO_COMP.
++ * Add timestamp to lifetime parse.
++ * Fix address structure length checking bug.
++ * Fix address structure allocation bug (forgot to kmalloc!).
++ * Add checks for extension lengths.
++ * Add checks for extension reserved illegal values.
++ * Add check for spirange legal values.
++ * Add an extension type for parsing a second satype, SA and
++ * DST_ADDRESS.
++ * Make changes to tdb_init() template to get pfkey_tdb_init(),
++ * eliminating any mention of xformsw.
++ * Implement getspi, update and grpsa (not tested).
++ * Add stubs for as yet unimplemented message types.
++ * Add table of message parsers to substitute for msg_parse switch.
++ *
++ * Revision 1.3  1999/04/15 17:58:07  rgb
++ * Add RCSID labels.
++ *
++ * Revision 1.2  1999/04/15 15:37:26  rgb
++ * Forward check changes from POST1_00 branch.
++ *
++ * Revision 1.1.2.1  1999/03/26 20:58:56  rgb
++ * Add pfkeyv2 support to KLIPS.
++ *
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/prng.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,201 @@
++/*
++ * crypto-class pseudorandom number generator
++ * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397
++ * Copyright (C) 2002  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: prng.c,v 1.7 2004/07/10 07:48:36 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - prng_init - initialize PRNG from a key
++ */
++void
++prng_init(prng, key, keylen)
++struct prng *prng;
++const unsigned char *key;
++size_t keylen;
++{
++      unsigned char k[256];
++      int i, j;
++      unsigned const char *p;
++      unsigned const char *keyend = key + keylen;
++      unsigned char t;
++
++      for (i = 0; i <= 255; i++)
++              prng->sbox[i] = i;
++      p = key;
++      for (i = 0; i <= 255; i++) {
++              k[i] = *p++;
++              if (p >= keyend)
++                      p = key;
++      }
++      j = 0;
++      for (i = 0; i <= 255; i++) {
++              j = (j + prng->sbox[i] + k[i]) & 0xff;
++              t = prng->sbox[i];
++              prng->sbox[i] = prng->sbox[j];
++              prng->sbox[j] = t;
++              k[i] = 0;       /* clear out key memory */
++      }
++      prng->i = 0;
++      prng->j = 0;
++      prng->count = 0;
++}
++
++/*
++ - prng_bytes - get some pseudorandom bytes from PRNG
++ */
++void
++prng_bytes(prng, dst, dstlen)
++struct prng *prng;
++unsigned char *dst;
++size_t dstlen;
++{
++      int i, j, t;
++      unsigned char *p = dst;
++      size_t remain = dstlen;
++#     define  MAX     4000000000ul
++
++      while (remain > 0) {
++              i = (prng->i + 1) & 0xff;
++              prng->i = i;
++              j = (prng->j + prng->sbox[i]) & 0xff;
++              prng->j = j;
++              t = prng->sbox[i];
++              prng->sbox[i] = prng->sbox[j];
++              prng->sbox[j] = t;
++              t = (t + prng->sbox[i]) & 0xff;
++              *p++ = prng->sbox[t];
++              remain--;
++      }
++      if (prng->count < MAX - dstlen)
++              prng->count += dstlen;
++      else
++              prng->count = MAX;
++}
++
++/*
++ - prnt_count - how many bytes have been extracted from PRNG so far?
++ */
++unsigned long
++prng_count(prng)
++struct prng *prng;
++{
++      return prng->count;
++}
++
++/*
++ - prng_final - clear out PRNG to ensure nothing left in memory
++ */
++void
++prng_final(prng)
++struct prng *prng;
++{
++      int i;
++
++      for (i = 0; i <= 255; i++)
++              prng->sbox[i] = 0;
++      prng->i = 0;
++      prng->j = 0;
++      prng->count = 0;        /* just for good measure */
++}
++
++
++
++#ifdef PRNG_MAIN
++
++#include <stdio.h>
++
++void regress();
++
++int
++main(argc, argv)
++int argc;
++char *argv[];
++{
++      struct prng pr;
++      unsigned char buf[100];
++      unsigned char *p;
++      size_t n;
++
++      if (argc < 2) {
++              fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]);
++              exit(2);
++      }
++
++      if (strcmp(argv[1], "-r") == 0) {
++              regress();
++              fprintf(stderr, "regress() returned?!?\n");
++              exit(1);
++      }
++
++      prng_init(&pr, argv[1], strlen(argv[1]));
++      prng_bytes(&pr, buf, 32);
++      printf("0x");
++      for (p = buf, n = 32; n > 0; p++, n--)
++              printf("%02x", *p);
++      printf("\n%lu bytes\n", prng_count(&pr));
++      prng_final(&pr);
++      exit(0);
++}
++
++void
++regress()
++{
++      struct prng pr;
++      unsigned char buf[100];
++      unsigned char *p;
++      size_t n;
++      /* somewhat non-random sample key */
++      unsigned char key[] = "here we go gathering nuts in May";
++      /* first thirty bytes of output from that key */
++      unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c"
++                              "\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71"
++                              "\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28";
++      int nzero, none;
++      int show = 0;
++
++      prng_init(&pr, key, strlen(key));
++      prng_bytes(&pr, buf, sizeof(buf));
++      for (p = buf, n = sizeof(buf); n > 0; p++, n--) {
++              if (*p == 0)
++                      nzero++;
++              if (*p == 255)
++                      none++;
++      }
++      if (nzero > 3 || none > 3) {
++              fprintf(stderr, "suspiciously non-random output!\n");
++              show = 1;
++      }
++      if (memcmp(buf, good, strlen(good)) != 0) {
++              fprintf(stderr, "incorrect output!\n");
++              show = 1;
++      }
++      if (show) {
++              fprintf(stderr, "0x");
++              for (p = buf, n = sizeof(buf); n > 0; p++, n--)
++                      fprintf(stderr, "%02x", *p);
++              fprintf(stderr, "\n");
++              exit(1);
++      }
++      if (prng_count(&pr) != sizeof(buf)) {
++              fprintf(stderr, "got %u bytes, but count is %lu\n",
++                                      sizeof(buf), prng_count(&pr));
++              exit(1);
++      }
++      prng_final(&pr);
++      exit(0);
++}
++
++#endif /* PRNG_MAIN */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/radij.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1237 @@
++char radij_c_version[] = "RCSID $Id: radij.c,v 1.48.2.1 2006/10/06 21:39:27 paul Exp $";
++
++/*
++ * This file is defived from ${SRC}/sys/net/radix.c of BSD 4.4lite
++ *
++ * Variable and procedure names have been modified so that they don't
++ * conflict with the original BSD code, as a small number of modifications
++ * have been introduced and we may want to reuse this code in BSD.
++ * 
++ * The `j' in `radij' is pronounced as a voiceless guttural (like a Greek
++ * chi or a German ch sound (as `doch', not as in `milch'), or even a 
++ * spanish j as in Juan.  It is not as far back in the throat like
++ * the corresponding Hebrew sound, nor is it a soft breath like the English h.
++ * It has nothing to do with the Dutch ij sound.
++ * 
++ * Here is the appropriate copyright notice:
++ */
++
++/*
++ * Copyright (c) 1988, 1989, 1993
++ *    The Regents of the University of California.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ *    must display the following acknowledgement:
++ *    This product includes software developed by the University of
++ *    California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ *    @(#)radix.c     8.2 (Berkeley) 1/4/94
++ */
++
++/*
++ * Routines to build and maintain radix trees for routing lookups.
++ */
++
++#ifndef AUTOCONF_INCLUDED
++#include <linux/config.h>
++#endif
++#include <linux/version.h>
++#include <linux/kernel.h> /* printk() */
++
++#include "openswan/ipsec_param.h"
++
++#ifdef MALLOC_SLAB
++# include <linux/slab.h> /* kmalloc() */
++#else /* MALLOC_SLAB */
++# include <linux/malloc.h> /* kmalloc() */
++#endif /* MALLOC_SLAB */
++#include <linux/errno.h>  /* error codes */
++#include <linux/types.h>  /* size_t */
++#include <linux/interrupt.h> /* mark_bh */
++
++#include <linux/netdevice.h>   /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h>          /* struct iphdr */
++#include <linux/skbuff.h>
++#ifdef NET_21
++# include <linux/in6.h>
++#endif /* NET_21 */
++
++#include <net/ip.h>
++
++#include <openswan.h>
++
++#include "openswan/radij.h"
++#include "openswan/ipsec_encap.h"
++#include "openswan/ipsec_radij.h"
++
++int   maj_keylen;
++struct radij_mask *rj_mkfreelist;
++struct radij_node_head *mask_rjhead;
++static int gotOddMasks;
++static char *maskedKey;
++static char *rj_zeroes, *rj_ones;
++
++#define rj_masktop (mask_rjhead->rnh_treetop)
++#ifdef Bcmp
++# undef Bcmp
++#endif /* Bcmp */
++#define Bcmp(a, b, l) (l == 0 ? 0 : memcmp((caddr_t)(b), (caddr_t)(a), (size_t)l))
++/*
++ * The data structure for the keys is a radix tree with one way
++ * branching removed.  The index rj_b at an internal node n represents a bit
++ * position to be tested.  The tree is arranged so that all descendants
++ * of a node n have keys whose bits all agree up to position rj_b - 1.
++ * (We say the index of n is rj_b.)
++ *
++ * There is at least one descendant which has a one bit at position rj_b,
++ * and at least one with a zero there.
++ *
++ * A route is determined by a pair of key and mask.  We require that the
++ * bit-wise logical and of the key and mask to be the key.
++ * We define the index of a route to associated with the mask to be
++ * the first bit number in the mask where 0 occurs (with bit number 0
++ * representing the highest order bit).
++ * 
++ * We say a mask is normal if every bit is 0, past the index of the mask.
++ * If a node n has a descendant (k, m) with index(m) == index(n) == rj_b,
++ * and m is a normal mask, then the route applies to every descendant of n.
++ * If the index(m) < rj_b, this implies the trailing last few bits of k
++ * before bit b are all 0, (and hence consequently true of every descendant
++ * of n), so the route applies to all descendants of the node as well.
++ *
++ * The present version of the code makes no use of normal routes,
++ * but similar logic shows that a non-normal mask m such that
++ * index(m) <= index(n) could potentially apply to many children of n.
++ * Thus, for each non-host route, we attach its mask to a list at an internal
++ * node as high in the tree as we can go. 
++ */
++
++struct radij_node *
++rj_search(v_arg, head)
++      void *v_arg;
++      struct radij_node *head;
++{
++      register struct radij_node *x;
++      register caddr_t v;
++
++      for (x = head, v = v_arg; x->rj_b >= 0;) {
++              if (x->rj_bmask & v[x->rj_off])
++                      x = x->rj_r;
++              else
++                      x = x->rj_l;
++      }
++      return (x);
++};
++
++struct radij_node *
++rj_search_m(v_arg, head, m_arg)
++      struct radij_node *head;
++      void *v_arg, *m_arg;
++{
++      register struct radij_node *x;
++      register caddr_t v = v_arg, m = m_arg;
++
++      for (x = head; x->rj_b >= 0;) {
++              if ((x->rj_bmask & m[x->rj_off]) &&
++                  (x->rj_bmask & v[x->rj_off]))
++                      x = x->rj_r;
++              else
++                      x = x->rj_l;
++      }
++      return x;
++};
++
++int
++rj_refines(m_arg, n_arg)
++      void *m_arg, *n_arg;
++{
++      register caddr_t m = m_arg, n = n_arg;
++      register caddr_t lim, lim2 = lim = n + *(u_char *)n;
++      int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
++      int masks_are_equal = 1;
++
++      if (longer > 0)
++              lim -= longer;
++      while (n < lim) {
++              if (*n & ~(*m))
++                      return 0;
++              if (*n++ != *m++)
++                      masks_are_equal = 0;
++                      
++      }
++      while (n < lim2)
++              if (*n++)
++                      return 0;
++      if (masks_are_equal && (longer < 0))
++              for (lim2 = m - longer; m < lim2; )
++                      if (*m++)
++                              return 1;
++      return (!masks_are_equal);
++}
++
++
++struct radij_node *
++rj_match(v_arg, head)
++      void *v_arg;
++      struct radij_node_head *head;
++{
++      caddr_t v = v_arg;
++      register struct radij_node *t = head->rnh_treetop, *x;
++      register caddr_t cp = v, cp2, cp3;
++      caddr_t cplim, mstart;
++      struct radij_node *saved_t, *top = t;
++      int off = t->rj_off, vlen = *(u_char *)cp, matched_off;
++
++      /*
++       * Open code rj_search(v, top) to avoid overhead of extra
++       * subroutine call.
++       */
++      for (; t->rj_b >= 0; ) {
++              if (t->rj_bmask & cp[t->rj_off])
++                      t = t->rj_r;
++              else
++                      t = t->rj_l;
++      }
++      /*
++       * See if we match exactly as a host destination
++       */
++      KLIPS_PRINT(debug_radij,
++                  "klips_debug:rj_match: "
++                  "* See if we match exactly as a host destination\n");
++      
++      cp += off; cp2 = t->rj_key + off; cplim = v + vlen;
++      for (; cp < cplim; cp++, cp2++)
++              if (*cp != *cp2)
++                      goto on1;
++      /*
++       * This extra grot is in case we are explicitly asked
++       * to look up the default.  Ugh!
++       */
++      if ((t->rj_flags & RJF_ROOT) && t->rj_dupedkey)
++              t = t->rj_dupedkey;
++      return t;
++on1:
++      matched_off = cp - v;
++      saved_t = t;
++      KLIPS_PRINT(debug_radij,
++                  "klips_debug:rj_match: "
++                  "** try to match a leaf, t=0p%p\n", t);
++      do {
++          if (t->rj_mask) {
++              /*
++               * Even if we don't match exactly as a hosts;
++               * we may match if the leaf we wound up at is
++               * a route to a net.
++               */
++              cp3 = matched_off + t->rj_mask;
++              cp2 = matched_off + t->rj_key;
++              for (; cp < cplim; cp++)
++                      if ((*cp2++ ^ *cp) & *cp3++)
++                              break;
++              if (cp == cplim)
++                      return t;
++              cp = matched_off + v;
++          }
++      } while ((t = t->rj_dupedkey));
++      t = saved_t;
++      /* start searching up the tree */
++      KLIPS_PRINT(debug_radij,
++                  "klips_debug:rj_match: "
++                  "*** start searching up the tree, t=0p%p\n",
++                  t);
++      do {
++              register struct radij_mask *m;
++              
++              t = t->rj_p;
++              KLIPS_PRINT(debug_radij,
++                          "klips_debug:rj_match: "
++                          "**** t=0p%p\n",
++                          t);
++              if ((m = t->rj_mklist)) {
++                      /*
++                       * After doing measurements here, it may
++                       * turn out to be faster to open code
++                       * rj_search_m here instead of always
++                       * copying and masking.
++                       */
++                      /* off = min(t->rj_off, matched_off); */
++                      off = t->rj_off;
++                      if (matched_off < off)
++                              off = matched_off;
++                      mstart = maskedKey + off;
++                      do {
++                              cp2 = mstart;
++                              cp3 = m->rm_mask + off;
++                              KLIPS_PRINT(debug_radij,
++                                          "klips_debug:rj_match: "
++                                          "***** cp2=0p%p cp3=0p%p\n",
++                                          cp2, cp3);
++                              for (cp = v + off; cp < cplim;)
++                                      *cp2++ =  *cp++ & *cp3++;
++                              x = rj_search(maskedKey, t);
++                              while (x && x->rj_mask != m->rm_mask)
++                                      x = x->rj_dupedkey;
++                              if (x &&
++                                  (Bcmp(mstart, x->rj_key + off,
++                                      vlen - off) == 0))
++                                          return x;
++                      } while ((m = m->rm_mklist));
++              }
++      } while (t != top);
++      KLIPS_PRINT(debug_radij,
++                  "klips_debug:rj_match: "
++                  "***** not found.\n");
++      return 0;
++};
++              
++#ifdef RJ_DEBUG
++int   rj_nodenum;
++struct        radij_node *rj_clist;
++int   rj_saveinfo;
++DEBUG_NO_STATIC void traverse(struct radij_node *);
++#ifdef RJ_DEBUG2
++int   rj_debug =  1;
++#else
++int   rj_debug =  0;
++#endif /* RJ_DEBUG2 */
++#endif /* RJ_DEBUG */
++
++struct radij_node *
++rj_newpair(v, b, nodes)
++      void *v;
++      int b;
++      struct radij_node nodes[2];
++{
++      register struct radij_node *tt = nodes, *t = tt + 1;
++      t->rj_b = b; t->rj_bmask = 0x80 >> (b & 7);
++      t->rj_l = tt; t->rj_off = b >> 3;
++      tt->rj_b = -1; tt->rj_key = (caddr_t)v; tt->rj_p = t;
++      tt->rj_flags = t->rj_flags = RJF_ACTIVE;
++#ifdef RJ_DEBUG
++      tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++;
++      tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt;
++#endif /* RJ_DEBUG */
++      return t;
++}
++
++struct radij_node *
++rj_insert(v_arg, head, dupentry, nodes)
++      void *v_arg;
++      struct radij_node_head *head;
++      int *dupentry;
++      struct radij_node nodes[2];
++{
++      caddr_t v = v_arg;
++      struct radij_node *top = head->rnh_treetop;
++      int head_off = top->rj_off, vlen = (int)*((u_char *)v);
++      register struct radij_node *t = rj_search(v_arg, top);
++      register caddr_t cp = v + head_off;
++      register int b;
++      struct radij_node *tt;
++      /*
++       *find first bit at which v and t->rj_key differ
++       */
++    {
++      register caddr_t cp2 = t->rj_key + head_off;
++      register int cmp_res;
++      caddr_t cplim = v + vlen;
++
++      while (cp < cplim)
++              if (*cp2++ != *cp++)
++                      goto on1;
++      *dupentry = 1;
++      return t;
++on1:
++      *dupentry = 0;
++      cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
++      for (b = (cp - v) << 3; cmp_res; b--)
++              cmp_res >>= 1;
++    }
++    {
++      register struct radij_node *p, *x = top;
++      cp = v;
++      do {
++              p = x;
++              if (cp[x->rj_off] & x->rj_bmask) 
++                      x = x->rj_r;
++              else x = x->rj_l;
++      } while (b > (unsigned) x->rj_b); /* x->rj_b < b && x->rj_b >= 0 */
++#ifdef RJ_DEBUG
++      if (rj_debug)
++              printk("klips_debug:rj_insert: Going In:\n"), traverse(p);
++#endif /* RJ_DEBUG */
++      t = rj_newpair(v_arg, b, nodes); tt = t->rj_l;
++      if ((cp[p->rj_off] & p->rj_bmask) == 0)
++              p->rj_l = t;
++      else
++              p->rj_r = t;
++      x->rj_p = t; t->rj_p = p; /* frees x, p as temp vars below */
++      if ((cp[t->rj_off] & t->rj_bmask) == 0) {
++              t->rj_r = x;
++      } else {
++              t->rj_r = tt; t->rj_l = x;
++      }
++#ifdef RJ_DEBUG
++      if (rj_debug)
++              printk("klips_debug:rj_insert: Coming out:\n"), traverse(p);
++#endif /* RJ_DEBUG */
++    }
++      return (tt);
++}
++
++struct radij_node *
++rj_addmask(n_arg, search, skip)
++      int search, skip;
++      void *n_arg;
++{
++      caddr_t netmask = (caddr_t)n_arg;
++      register struct radij_node *x;
++      register caddr_t cp, cplim;
++      register int b, mlen, j;
++      int maskduplicated;
++
++      mlen = *(u_char *)netmask;
++      if (search) {
++              x = rj_search(netmask, rj_masktop);
++              mlen = *(u_char *)netmask;
++              if (Bcmp(netmask, x->rj_key, mlen) == 0)
++                      return (x);
++      }
++      R_Malloc(x, struct radij_node *, maj_keylen + 2 * sizeof (*x));
++      if (x == 0)
++              return (0);
++      Bzero(x, maj_keylen + 2 * sizeof (*x));
++      cp = (caddr_t)(x + 2);
++      Bcopy(netmask, cp, mlen);
++      netmask = cp;
++      x = rj_insert(netmask, mask_rjhead, &maskduplicated, x);
++      /*
++       * Calculate index of mask.
++       */
++      cplim = netmask + mlen;
++      for (cp = netmask + skip; cp < cplim; cp++)
++              if (*(u_char *)cp != 0xff)
++                      break;
++      b = (cp - netmask) << 3;
++      if (cp != cplim) {
++              if (*cp != 0) {
++                      gotOddMasks = 1;
++                      for (j = 0x80; j; b++, j >>= 1)  
++                              if ((j & *cp) == 0)
++                                      break;
++              }
++      }
++      x->rj_b = -1 - b;
++      return (x);
++}
++
++#if 0
++struct radij_node *
++#endif
++int
++rj_addroute(v_arg, n_arg, head, treenodes)
++      void *v_arg, *n_arg;
++      struct radij_node_head *head;
++      struct radij_node treenodes[2];
++{
++      caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
++      register struct radij_node *t, *x=NULL, *tt;
++      struct radij_node *saved_tt, *top = head->rnh_treetop;
++      short b = 0, b_leaf;
++      int mlen, keyduplicated;
++      caddr_t cplim;
++      struct radij_mask *m, **mp;
++
++      /*
++       * In dealing with non-contiguous masks, there may be
++       * many different routes which have the same mask.
++       * We will find it useful to have a unique pointer to
++       * the mask to speed avoiding duplicate references at
++       * nodes and possibly save time in calculating indices.
++       */
++      if (netmask)  {
++              x = rj_search(netmask, rj_masktop);
++              mlen = *(u_char *)netmask;
++              if (Bcmp(netmask, x->rj_key, mlen) != 0) {
++                      x = rj_addmask(netmask, 0, top->rj_off);
++                      if (x == 0)
++                              return -ENOMEM; /* (0) rgb */
++              }
++              netmask = x->rj_key;
++              b = -1 - x->rj_b;
++      }
++      /*
++       * Deal with duplicated keys: attach node to previous instance
++       */
++      saved_tt = tt = rj_insert(v, head, &keyduplicated, treenodes);
++#ifdef RJ_DEBUG
++      printk("addkey: duplicated: %d\n", keyduplicated);
++#endif
++      if (keyduplicated) {
++              do {
++                      if (tt->rj_mask == netmask)
++                              return -EEXIST; /* -ENXIO; (0) rgb */
++                      t = tt;
++                      if (netmask == 0 ||
++                          (tt->rj_mask && rj_refines(netmask, tt->rj_mask)))
++                              break;
++              } while ((tt = tt->rj_dupedkey));
++              /*
++               * If the mask is not duplicated, we wouldn't
++               * find it among possible duplicate key entries
++               * anyway, so the above test doesn't hurt.
++               *
++               * We sort the masks for a duplicated key the same way as
++               * in a masklist -- most specific to least specific.
++               * This may require the unfortunate nuisance of relocating
++               * the head of the list.
++               */
++              if (tt && t == saved_tt) {
++                      struct  radij_node *xx = x;
++                      /* link in at head of list */
++                      (tt = treenodes)->rj_dupedkey = t;
++                      tt->rj_flags = t->rj_flags;
++                      tt->rj_p = x = t->rj_p;
++                      if (x->rj_l == t) x->rj_l = tt; else x->rj_r = tt;
++                      saved_tt = tt; x = xx;
++              } else {
++                      (tt = treenodes)->rj_dupedkey = t->rj_dupedkey;
++                      t->rj_dupedkey = tt;
++              }
++#ifdef RJ_DEBUG
++              t=tt+1; tt->rj_info = rj_nodenum++; t->rj_info = rj_nodenum++;
++              tt->rj_twin = t; tt->rj_ybro = rj_clist; rj_clist = tt;
++#endif /* RJ_DEBUG */
++              t = saved_tt;
++              tt->rj_key = (caddr_t) v;
++              tt->rj_b = -1;
++              tt->rj_flags = t->rj_flags & ~RJF_ROOT;
++      }
++      /*
++       * Put mask in tree.
++       */
++      if (netmask) {
++              tt->rj_mask = netmask;
++              tt->rj_b = x->rj_b;
++      }
++      t = saved_tt->rj_p;
++      b_leaf = -1 - t->rj_b;
++      if (t->rj_r == saved_tt) x = t->rj_l; else x = t->rj_r;
++      /* Promote general routes from below */
++      if (x->rj_b < 0) { 
++              if (x->rj_mask && (x->rj_b >= b_leaf) && x->rj_mklist == 0) {
++                      MKGet(m);
++                      if (m) {
++                              Bzero(m, sizeof *m);
++                              m->rm_b = x->rj_b;
++                              m->rm_mask = x->rj_mask;
++                              x->rj_mklist = t->rj_mklist = m;
++                      }
++              }
++      } else if (x->rj_mklist) {
++              /*
++               * Skip over masks whose index is > that of new node
++               */
++              for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist)
++                      if (m->rm_b >= b_leaf)
++                              break;
++              t->rj_mklist = m; *mp = 0;
++      }
++      /* Add new route to highest possible ancestor's list */
++      if ((netmask == 0) || (b > t->rj_b )) {
++#ifdef RJ_DEBUG
++              printk("klips:radij.c: netmask = %p or b(%d)>t->rjb(%d)\n", netmask, b, t->rj_b);
++#endif
++              return 0; /* tt rgb */ /* can't lift at all */
++      }
++      b_leaf = tt->rj_b;
++      do {
++              x = t;
++              t = t->rj_p;
++      } while (b <= t->rj_b && x != top);
++      /*
++       * Search through routes associated with node to
++       * insert new route according to index.
++       * For nodes of equal index, place more specific
++       * masks first.
++       */
++      cplim = netmask + mlen;
++      for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist) {
++              if (m->rm_b < b_leaf)
++                      continue;
++              if (m->rm_b > b_leaf)
++                      break;
++              if (m->rm_mask == netmask) {
++                      m->rm_refs++;
++                      tt->rj_mklist = m;
++#ifdef RJ_DEBUG
++                      printk("klips:radij.c: m->rm_mask %p == netmask\n", netmask);
++#endif
++                      return 0; /* tt rgb */
++              }
++              if (rj_refines(netmask, m->rm_mask))
++                      break;
++      }
++      MKGet(m);
++      if (m == 0) {
++              printk("klips_debug:rj_addroute: "
++                     "Mask for route not entered\n");
++              return 0; /* (tt) rgb */
++      }
++      Bzero(m, sizeof *m);
++      m->rm_b = b_leaf;
++      m->rm_mask = netmask;
++      m->rm_mklist = *mp;
++      *mp = m;
++      tt->rj_mklist = m;
++#ifdef RJ_DEBUG
++      printk("klips:radij.c: addroute done\n");
++#endif
++      return 0; /* tt rgb */
++}
++
++int
++rj_delete(v_arg, netmask_arg, head, node)
++      void *v_arg, *netmask_arg;
++      struct radij_node_head *head;
++      struct radij_node **node;
++{
++      register struct radij_node *t, *p, *x, *tt;
++      struct radij_mask *m, *saved_m, **mp;
++      struct radij_node *dupedkey, *saved_tt, *top;
++      caddr_t v, netmask;
++      int b, head_off, vlen;
++
++      v = v_arg;
++      netmask = netmask_arg;
++      x = head->rnh_treetop;
++      tt = rj_search(v, x);
++      head_off = x->rj_off;
++      vlen =  *(u_char *)v;
++      saved_tt = tt;
++      top = x;
++      if (tt == 0 ||
++          Bcmp(v + head_off, tt->rj_key + head_off, vlen - head_off))
++              return -EFAULT; /* (0) rgb */
++      /*
++       * Delete our route from mask lists.
++       */
++      if ((dupedkey = tt->rj_dupedkey)) {
++              if (netmask) 
++                      netmask = rj_search(netmask, rj_masktop)->rj_key;
++              while (tt->rj_mask != netmask)
++                      if ((tt = tt->rj_dupedkey) == 0)
++                              return -ENOENT; /* -ENXIO; (0) rgb */
++      }
++      if (tt->rj_mask == 0 || (saved_m = m = tt->rj_mklist) == 0)
++              goto on1;
++      if (m->rm_mask != tt->rj_mask) {
++              printk("klips_debug:rj_delete: "
++                     "inconsistent annotation\n");
++              goto on1;
++      }
++      if (--m->rm_refs >= 0)
++              goto on1;
++      b = -1 - tt->rj_b;
++      t = saved_tt->rj_p;
++      if (b > t->rj_b)
++              goto on1; /* Wasn't lifted at all */
++      do {
++              x = t;
++              t = t->rj_p;
++      } while (b <= t->rj_b && x != top);
++      for (mp = &x->rj_mklist; (m = *mp); mp = &m->rm_mklist)
++              if (m == saved_m) {
++                      *mp = m->rm_mklist;
++                      MKFree(m);
++                      break;
++              }
++      if (m == 0)
++              printk("klips_debug:rj_delete: "
++                     "couldn't find our annotation\n");
++on1:
++      /*
++       * Eliminate us from tree
++       */
++      if (tt->rj_flags & RJF_ROOT)
++              return -EFAULT; /* (0) rgb */
++#ifdef RJ_DEBUG
++      /* Get us out of the creation list */
++      for (t = rj_clist; t && t->rj_ybro != tt; t = t->rj_ybro) {}
++      if (t) t->rj_ybro = tt->rj_ybro;
++#endif /* RJ_DEBUG */
++      t = tt->rj_p;
++      if (dupedkey) {
++              if (tt == saved_tt) {
++                      x = dupedkey; x->rj_p = t;
++                      if (t->rj_l == tt) t->rj_l = x; else t->rj_r = x;
++              } else {
++                      for (x = p = saved_tt; p && p->rj_dupedkey != tt;)
++                              p = p->rj_dupedkey;
++                      if (p) p->rj_dupedkey = tt->rj_dupedkey;
++                      else printk("klips_debug:rj_delete: "
++                                     "couldn't find node that we started with\n");
++              }
++              t = tt + 1;
++              if  (t->rj_flags & RJF_ACTIVE) {
++#ifndef RJ_DEBUG
++                      *++x = *t; p = t->rj_p;
++#else
++                      b = t->rj_info; *++x = *t; t->rj_info = b; p = t->rj_p;
++#endif /* RJ_DEBUG */
++                      if (p->rj_l == t) p->rj_l = x; else p->rj_r = x;
++                      x->rj_l->rj_p = x; x->rj_r->rj_p = x;
++              }
++              goto out;
++      }
++      if (t->rj_l == tt) x = t->rj_r; else x = t->rj_l;
++      p = t->rj_p;
++      if (p->rj_r == t) p->rj_r = x; else p->rj_l = x;
++      x->rj_p = p;
++      /*
++       * Demote routes attached to us.
++       */
++      if (t->rj_mklist) {
++              if (x->rj_b >= 0) {
++                      for (mp = &x->rj_mklist; (m = *mp);)
++                              mp = &m->rm_mklist;
++                      *mp = t->rj_mklist;
++              } else {
++                      for (m = t->rj_mklist; m;) {
++                              struct radij_mask *mm = m->rm_mklist;
++                              if (m == x->rj_mklist && (--(m->rm_refs) < 0)) {
++                                      x->rj_mklist = 0;
++                                      MKFree(m);
++                              } else 
++                                      printk("klips_debug:rj_delete: "
++                                          "Orphaned Mask 0p%p at 0p%p\n", m, x);
++                              m = mm;
++                      }
++              }
++      }
++      /*
++       * We may be holding an active internal node in the tree.
++       */
++      x = tt + 1;
++      if (t != x) {
++#ifndef RJ_DEBUG
++              *t = *x;
++#else
++              b = t->rj_info; *t = *x; t->rj_info = b;
++#endif /* RJ_DEBUG */
++              t->rj_l->rj_p = t; t->rj_r->rj_p = t;
++              p = x->rj_p;
++              if (p->rj_l == x) p->rj_l = t; else p->rj_r = t;
++      }
++out:
++      tt->rj_flags &= ~RJF_ACTIVE;
++      tt[1].rj_flags &= ~RJF_ACTIVE;
++      *node = tt;
++      return 0; /* (tt) rgb */
++}
++
++int
++rj_walktree(h, f, w)
++      struct radij_node_head *h;
++      register int (*f)(struct radij_node *,void *);
++      void *w;
++{
++      int error;
++      struct radij_node *base, *next;
++      register struct radij_node *rn;
++
++      if(!h || !f /* || !w */) {
++              return -ENODATA;
++      }
++
++      rn = h->rnh_treetop;
++      /*
++       * This gets complicated because we may delete the node
++       * while applying the function f to it, so we need to calculate
++       * the successor node in advance.
++       */
++      /* First time through node, go left */
++      while (rn->rj_b >= 0)
++              rn = rn->rj_l;
++      for (;;) {
++#ifdef CONFIG_KLIPS_DEBUG
++              if(debug_radij) {
++                      printk("klips_debug:rj_walktree: "
++                             "for: rn=0p%p rj_b=%d rj_flags=%x",
++                             rn,
++                             rn->rj_b,
++                             rn->rj_flags);
++                      rn->rj_b >= 0 ?
++                              printk(" node off=%x\n",
++                                     rn->rj_off) :
++                              printk(" leaf key = %08x->%08x\n",
++                                     (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
++                                     (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr))
++                              ;
++              }
++#endif /* CONFIG_KLIPS_DEBUG */
++              base = rn;
++              /* If at right child go back up, otherwise, go right */
++              while (rn->rj_p->rj_r == rn && (rn->rj_flags & RJF_ROOT) == 0)
++                      rn = rn->rj_p;
++              /* Find the next *leaf* since next node might vanish, too */
++              for (rn = rn->rj_p->rj_r; rn->rj_b >= 0;)
++                      rn = rn->rj_l;
++              next = rn;
++#ifdef CONFIG_KLIPS_DEBUG
++              if(debug_radij) {
++                      printk("klips_debug:rj_walktree: "
++                             "processing leaves, rn=0p%p rj_b=%d rj_flags=%x",
++                             rn,
++                             rn->rj_b,
++                             rn->rj_flags);
++                      rn->rj_b >= 0 ?
++                              printk(" node off=%x\n",
++                                     rn->rj_off) :
++                              printk(" leaf key = %08x->%08x\n",
++                                     (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
++                                     (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr))
++                              ;
++              }
++#endif /* CONFIG_KLIPS_DEBUG */
++              /* Process leaves */
++              while ((rn = base)) {
++                      base = rn->rj_dupedkey;
++#ifdef CONFIG_KLIPS_DEBUG
++                      if(debug_radij) {
++                              printk("klips_debug:rj_walktree: "
++                                     "while: base=0p%p rn=0p%p rj_b=%d rj_flags=%x",
++                                     base,
++                                     rn,
++                                     rn->rj_b,
++                                     rn->rj_flags);
++                              rn->rj_b >= 0 ?
++                                      printk(" node off=%x\n",
++                                             rn->rj_off) :
++                                      printk(" leaf key = %08x->%08x\n",
++                                             (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
++                                             (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr))
++                                      ;
++                      }
++#endif /* CONFIG_KLIPS_DEBUG */
++                      if (!(rn->rj_flags & RJF_ROOT) && (error = (*f)(rn, w)))
++                              return (-error);
++              }
++              rn = next;
++              if (rn->rj_flags & RJF_ROOT)
++                      return (0);
++      }
++      /* NOTREACHED */
++}
++
++int
++rj_inithead(head, off)
++      void **head;
++      int off;
++{
++      register struct radij_node_head *rnh;
++      register struct radij_node *t, *tt, *ttt;
++      if (*head)
++              return (1);
++      R_Malloc(rnh, struct radij_node_head *, sizeof (*rnh));
++      if (rnh == NULL)
++              return (0);
++      Bzero(rnh, sizeof (*rnh));
++      *head = rnh;
++      t = rj_newpair(rj_zeroes, off, rnh->rnh_nodes);
++      ttt = rnh->rnh_nodes + 2;
++      t->rj_r = ttt;
++      t->rj_p = t;
++      tt = t->rj_l;
++      tt->rj_flags = t->rj_flags = RJF_ROOT | RJF_ACTIVE;
++      tt->rj_b = -1 - off;
++      *ttt = *tt;
++      ttt->rj_key = rj_ones;
++      rnh->rnh_addaddr = rj_addroute;
++      rnh->rnh_deladdr = rj_delete;
++      rnh->rnh_matchaddr = rj_match;
++      rnh->rnh_walktree = rj_walktree;
++      rnh->rnh_treetop = t;
++      return (1);
++}
++
++void
++rj_init()
++{
++      char *cp, *cplim;
++
++      if (maj_keylen == 0) {
++              printk("klips_debug:rj_init: "
++                     "radij functions require maj_keylen be set\n");
++              return;
++      }
++      R_Malloc(rj_zeroes, char *, 3 * maj_keylen);
++      if (rj_zeroes == NULL)
++              panic("rj_init");
++      Bzero(rj_zeroes, 3 * maj_keylen);
++      rj_ones = cp = rj_zeroes + maj_keylen;
++      maskedKey = cplim = rj_ones + maj_keylen;
++      while (cp < cplim)
++              *cp++ = -1;
++      if (rj_inithead((void **)&mask_rjhead, 0) == 0)
++              panic("rj_init 2");
++}
++
++void
++rj_preorder(struct radij_node *rn, int l)
++{
++      int i;
++      
++      if (rn == NULL){
++              printk("klips_debug:rj_preorder: "
++                     "NULL pointer\n");
++              return;
++      }
++      
++      if (rn->rj_b >= 0){
++              rj_preorder(rn->rj_l, l+1);
++              rj_preorder(rn->rj_r, l+1);
++              printk("klips_debug:");
++              for (i=0; i<l; i++)
++                      printk("*");
++              printk(" off = %d\n",
++                     rn->rj_off);
++      } else {
++              printk("klips_debug:");
++              for (i=0; i<l; i++)
++                      printk("@");
++              printk(" flags = %x",
++                     (u_int)rn->rj_flags);
++              if (rn->rj_flags & RJF_ACTIVE) {
++                      printk(" @key=0p%p",
++                             rn->rj_key);
++                      printk(" key = %08x->%08x",
++                             (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
++                             (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr));
++                      printk(" @mask=0p%p",
++                             rn->rj_mask);
++                      if (rn->rj_mask)
++                              printk(" mask = %08x->%08x",
++                                     (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_src.s_addr),
++                                     (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_dst.s_addr));
++                      if (rn->rj_dupedkey)
++                              printk(" dupedkey = 0p%p",
++                                     rn->rj_dupedkey);
++              }
++              printk("\n");
++      }
++}
++
++#ifdef RJ_DEBUG
++DEBUG_NO_STATIC void traverse(struct radij_node *p)
++{
++  rj_preorder(p, 0);
++}
++#endif /* RJ_DEBUG */
++
++void
++rj_dumptrees(void)
++{
++      rj_preorder(rnh->rnh_treetop, 0);
++}
++
++void
++rj_free_mkfreelist(void)
++{
++      struct radij_mask *mknp, *mknp2;
++
++      mknp = rj_mkfreelist;
++      while(mknp)
++      {
++              mknp2 = mknp;
++              mknp = mknp->rm_mklist;
++              kfree(mknp2);
++      }
++}
++
++int
++radijcleartree(void)
++{
++      return rj_walktree(rnh, ipsec_rj_walker_delete, NULL);
++}
++
++int
++radijcleanup(void)
++{
++      int error = 0;
++
++      error = radijcleartree();
++
++      rj_free_mkfreelist();
++
++/*    rj_walktree(mask_rjhead, ipsec_rj_walker_delete, NULL); */
++      if(mask_rjhead) {
++              kfree(mask_rjhead);
++      }
++
++      if(rj_zeroes) {
++              kfree(rj_zeroes);
++      }
++
++      if(rnh) {
++              kfree(rnh);
++      }
++
++      return error;
++}
++
++/*
++ * $Log: radij.c,v $
++ * Revision 1.48.2.1  2006/10/06 21:39:27  paul
++ * Fix for 2.6.18+ only include linux/config.h if AUTOCONF_INCLUDED is not
++ * set. This is defined through autoconf.h which is included through the
++ * linux kernel build macros.
++ *
++ * Revision 1.48  2005/04/29 05:10:22  mcr
++ *    removed from extraenous includes to make unit testing easier.
++ *
++ * Revision 1.47  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.46  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.45  2003/10/31 02:27:55  mcr
++ *    pulled up port-selector patches and sa_id elimination.
++ *
++ * Revision 1.44.30.1  2003/10/29 01:30:41  mcr
++ *    elimited "struct sa_id".
++ *
++ * Revision 1.44  2002/07/24 18:44:54  rgb
++ * Type fiddling to tame ia64 compiler.
++ *
++ * Revision 1.43  2002/05/23 07:14:11  rgb
++ * Cleaned up %p variants to 0p%p for test suite cleanup.
++ *
++ * Revision 1.42  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.41  2002/04/24 07:36:35  mcr
++ * Moved from ./klips/net/ipsec/radij.c,v
++ *
++ * Revision 1.40  2002/01/29 17:17:58  mcr
++ *    moved include of ipsec_param.h to after include of linux/kernel.h
++ *    otherwise, it seems that some option that is set in ipsec_param.h
++ *    screws up something subtle in the include path to kernel.h, and
++ *    it complains on the snprintf() prototype.
++ *
++ * Revision 1.39  2002/01/29 04:00:55  mcr
++ *    more excise of kversions.h header.
++ *
++ * Revision 1.38  2002/01/29 02:13:19  mcr
++ *    introduction of ipsec_kversion.h means that include of
++ *    ipsec_param.h must preceed any decisions about what files to
++ *    include to deal with differences in kernel source.
++ *
++ * Revision 1.37  2001/10/18 04:45:23  rgb
++ * 2.4.9 kernel deprecates linux/malloc.h in favour of linux/slab.h,
++ * lib/freeswan.h version macros moved to lib/kversions.h.
++ * Other compiler directive cleanups.
++ *
++ * Revision 1.36  2001/08/22 13:43:51  henry
++ * eliminate the single use of min() to avoid problems with Linus changing it
++ *
++ * Revision 1.35  2001/06/15 04:57:29  rgb
++ * Clarified error return codes.
++ * Changed mask add already exists to EEXIST.
++ * Changed mask delete did not exist to ENOENT.
++ *
++ * Revision 1.34  2001/05/03 19:44:26  rgb
++ * Fix sign of error return codes for rj_addroute().
++ *
++ * Revision 1.33  2001/02/27 22:24:56  rgb
++ * Re-formatting debug output (line-splitting, joining, 1arg/line).
++ * Check for satoa() return codes.
++ *
++ * Revision 1.32  2001/02/27 06:23:15  rgb
++ * Debug line splitting.
++ *
++ * Revision 1.31  2000/11/06 04:35:21  rgb
++ * Clear table *before* releasing other items in radijcleanup.
++ *
++ * Revision 1.30  2000/09/20 04:07:40  rgb
++ * Changed static functions to DEBUG_NO_STATIC to reveal function names in
++ * oopsen.
++ *
++ * Revision 1.29  2000/09/12 03:25:02  rgb
++ * Moved radij_c_version printing to ipsec_version_get_info().
++ *
++ * Revision 1.28  2000/09/08 19:12:56  rgb
++ * Change references from DEBUG_IPSEC to CONFIG_IPSEC_DEBUG.
++ *
++ * Revision 1.27  2000/07/28 14:58:32  rgb
++ * Changed kfree_s to kfree, eliminating extra arg to fix 2.4.0-test5.
++ *
++ * Revision 1.26  2000/05/10 23:11:37  rgb
++ * Comment out most of the startup version information.
++ *
++ * Revision 1.25  2000/01/21 06:21:47  rgb
++ * Change return codes to negative on error.
++ *
++ * Revision 1.24  1999/11/18 04:09:20  rgb
++ * Replaced all kernel version macros to shorter, readable form.
++ *
++ * Revision 1.23  1999/11/17 15:53:41  rgb
++ * Changed all occurrences of #include "../../../lib/freeswan.h"
++ * to #include <freeswan.h> which works due to -Ilibfreeswan in the
++ * klips/net/ipsec/Makefile.
++ *
++ * Revision 1.22  1999/10/15 22:17:28  rgb
++ * Modify radijcleanup() to call radijcleartree().
++ *
++ * Revision 1.21  1999/10/08 18:37:34  rgb
++ * Fix end-of-line spacing to sate whining PHMs.
++ *
++ * Revision 1.20  1999/10/01 15:44:54  rgb
++ * Move spinlock header include to 2.1> scope.
++ *
++ * Revision 1.19  1999/10/01 08:35:52  rgb
++ * Add spinlock include to shut up compiler for 2.0.38.
++ *
++ * Revision 1.18  1999/09/23 18:02:52  rgb
++ * De-alarm the search failure message so it doesn't sound so grave.
++ *
++ * Revision 1.17  1999/05/25 21:26:01  rgb
++ * Fix rj_walktree() sanity checking bug.
++ *
++ * Revision 1.16  1999/05/09 03:25:38  rgb
++ * Fix bug introduced by 2.2 quick-and-dirty patch.
++ *
++ * Revision 1.15  1999/05/05 22:02:33  rgb
++ * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
++ *
++ * Revision 1.14  1999/04/29 15:24:15  rgb
++ * Add sanity checking for null pointer arguments.
++ * Standardise an error return method.
++ *
++ * Revision 1.13  1999/04/11 00:29:02  henry
++ * GPL boilerplate
++ *
++ * Revision 1.12  1999/04/06 04:54:28  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ * Revision 1.11  1999/02/17 16:52:53  rgb
++ * Convert DEBUG_IPSEC to KLIPS_PRINT
++ * Clean out unused cruft.
++ *
++ * Revision 1.10  1999/01/22 06:30:05  rgb
++ * Cruft clean-out.
++ * 64-bit clean-up.
++ *
++ * Revision 1.9  1998/12/01 13:22:04  rgb
++ * Added support for debug printing of version info.
++ *
++ * Revision 1.8  1998/11/30 13:22:55  rgb
++ * Rationalised all the klips kernel file headers.  They are much shorter
++ * now and won't conflict under RH5.2.
++ *
++ * Revision 1.7  1998/10/25 02:43:26  rgb
++ * Change return type on rj_addroute and rj_delete and add and argument
++ * to the latter to be able to transmit more infomation about errors.
++ *
++ * Revision 1.6  1998/10/19 14:30:06  rgb
++ * Added inclusion of freeswan.h.
++ *
++ * Revision 1.5  1998/10/09 04:33:27  rgb
++ * Added 'klips_debug' prefix to all klips printk debug statements.
++ * Fixed output formatting slightly.
++ *
++ * Revision 1.4  1998/07/28 00:06:59  rgb
++ * Add debug detail to tree traversing.
++ *
++ * Revision 1.3  1998/07/14 18:07:58  rgb
++ * Add a routine to clear the eroute tree.
++ *
++ * Revision 1.2  1998/06/25 20:03:22  rgb
++ * Cleanup #endif comments.  Debug output for rj_init.
++ *
++ * Revision 1.1  1998/06/18 21:30:22  henry
++ * move sources from klips/src to klips/net/ipsec to keep stupid kernel
++ * build scripts happier about symlinks
++ *
++ * Revision 1.8  1998/05/25 20:34:15  rgb
++ * Remove temporary ipsec_walk, rj_deltree and rj_delnodes functions.
++ *
++ * Rename ipsec_rj_walker (ipsec_walk) to ipsec_rj_walker_procprint and
++ * add ipsec_rj_walker_delete.
++ *
++ * Recover memory for eroute table on unload of module.
++ *
++ * Revision 1.7  1998/05/21 12:58:58  rgb
++ * Moved 'extern' definitions to ipsec_radij.h to support /proc 3k limit fix.
++ *
++ * Revision 1.6  1998/04/23 20:57:29  rgb
++ * Cleaned up compiler warnings for unused debugging functions.
++ *
++ * Revision 1.5  1998/04/22 16:51:38  rgb
++ * Tidy up radij debug code from recent rash of modifications to debug code.
++ *
++ * Revision 1.4  1998/04/21 21:28:56  rgb
++ * Rearrange debug switches to change on the fly debug output from user
++ * space.  Only kernel changes checked in at this time.  radij.c was also
++ * changed to temporarily remove buggy debugging code in rj_delete causing
++ * an OOPS and hence, netlink device open errors.
++ *
++ * Revision 1.3  1998/04/14 17:30:37  rgb
++ * Fix up compiling errors for radij tree memory reclamation.
++ *
++ * Revision 1.2  1998/04/12 22:03:25  rgb
++ * Updated ESP-3DES-HMAC-MD5-96,
++ *    ESP-DES-HMAC-MD5-96,
++ *    AH-HMAC-MD5-96,
++ *    AH-HMAC-SHA1-96 since Henry started freeswan cvs repository
++ * from old standards (RFC182[5-9] to new (as of March 1998) drafts.
++ *
++ * Fixed eroute references in /proc/net/ipsec*.
++ *
++ * Started to patch module unloading memory leaks in ipsec_netlink and
++ * radij tree unloading.
++ *
++ * Revision 1.1  1998/04/09 03:06:15  henry
++ * sources moved up from linux/net/ipsec
++ *
++ * Revision 1.1.1.1  1998/04/08 05:35:03  henry
++ * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
++ *
++ * Revision 0.4  1997/01/15 01:28:15  ji
++ * No changes.
++ *
++ * Revision 0.3  1996/11/20 14:39:04  ji
++ * Minor cleanups.
++ * Rationalized debugging code.
++ *
++ * Revision 0.2  1996/11/02 00:18:33  ji
++ * First limited release.
++ *
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/rangetoa.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,60 @@
++/*
++ * convert binary form of address range to ASCII
++ * Copyright (C) 1998, 1999  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: rangetoa.c,v 1.9 2004/07/10 07:48:37 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - rangetoa - convert address range to ASCII
++ */
++size_t                                /* space needed for full conversion */
++rangetoa(addrs, format, dst, dstlen)
++struct in_addr addrs[2];
++int format;                   /* character */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      size_t len;
++      size_t rest;
++      int n;
++      char *p;
++
++      switch (format) {
++      case 0:
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      len = addrtoa(addrs[0], 0, dst, dstlen);
++      if (len < dstlen)
++              for (p = dst + len - 1, n = 3; len < dstlen && n > 0;
++                                                              p++, len++, n--)
++                      *p = '.';
++      else
++              p = NULL;
++      if (len < dstlen)
++              rest = dstlen - len;
++      else {
++              if (dstlen > 0)
++                      *(dst + dstlen - 1) = '\0';
++              rest = 0;
++      }
++
++      len += addrtoa(addrs[1], 0, p, rest);
++
++      return len;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/satot.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,133 @@
++/*
++ * convert from binary form of SA ID to text
++ * Copyright (C) 2000, 2001  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: satot.c,v 1.13 2004/07/10 07:48:37 mcr Exp $
++ */
++#include "openswan.h"
++
++static struct typename {
++      char type;
++      char *name;
++} typenames[] = {
++      { SA_AH,        "ah" },
++      { SA_ESP,       "esp" },
++      { SA_IPIP,      "tun" },
++      { SA_COMP,      "comp" },
++      { SA_INT,       "int" },
++      { 0,            NULL }
++};
++
++/*
++ - satot - convert SA to text "ah507@1.2.3.4"
++ */
++size_t                                /* space needed for full conversion */
++satot(sa, format, dst, dstlen)
++const ip_said *sa;
++int format;                   /* character */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      size_t len = 0;         /* 0 means "not recognized yet" */
++      int base;
++      int showversion;        /* use delimiter to show IP version? */
++      struct typename *tn;
++      char *p;
++      char *pre;
++      char buf[10+1+ULTOT_BUF+ADDRTOT_BUF];
++      char unk[10];
++
++      switch (format) {
++      case 0:
++              base = 16;
++              showversion = 1;
++              break;
++      case 'f':
++              base = 17;
++              showversion = 1;
++              break;
++      case 'x':
++              base = 'x';
++              showversion = 0;
++              break;
++      case 'd':
++              base = 10;
++              showversion = 0;
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      memset(buf, 0, sizeof(buf));
++
++      pre = NULL;
++      for (tn = typenames; tn->name != NULL; tn++)
++              if (sa->proto == tn->type) {
++                      pre = tn->name;
++                      break;                  /* NOTE BREAK OUT */
++              }
++      if (pre == NULL) {              /* unknown protocol */
++              strcpy(unk, "unk");
++              (void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk),
++                                              sizeof(unk)-strlen(unk));
++              pre = unk;
++      }
++
++      if (strcmp(pre, PASSTHROUGHTYPE) == 0 &&
++                                      sa->spi == PASSTHROUGHSPI &&
++                                      isunspecaddr(&sa->dst)) {
++              strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ?
++                                                      PASSTHROUGH4NAME :
++                                                      PASSTHROUGH6NAME);
++              len = strlen(buf);
++      }
++
++      if (sa->proto == SA_INT) {
++              switch (ntohl(sa->spi)) {
++              case SPI_PASS:  p = "%pass";    break;
++              case SPI_DROP:  p = "%drop";    break;
++              case SPI_REJECT:        p = "%reject";  break;
++              case SPI_HOLD:  p = "%hold";    break;
++              case SPI_TRAP:  p = "%trap";    break;
++              case SPI_TRAPSUBNET:    p = "%trapsubnet";      break;
++              default:        p = NULL;       break;
++              }
++              if (p != NULL) {
++                      strcpy(buf, p);
++                      len = strlen(buf);
++              }
++      }
++
++      if (len == 0) {                 /* general case needed */
++              strcpy(buf, pre);
++              len = strlen(buf);
++              if (showversion) {
++                      *(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' :
++                                                                      ':';
++                      len++;
++                      *(buf+len) = '\0';
++              }
++              len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len);
++              *(buf+len-1) = '@';
++              len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len);
++              *(buf+len) = '\0';
++      }
++
++      if (dst != NULL) {
++              if (len > dstlen)
++                      *(buf+dstlen-1) = '\0';
++              strcpy(dst, buf);
++      }
++      return len;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/subnetof.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,59 @@
++/*
++ * minor network-address manipulation utilities
++ * Copyright (C) 1998, 1999  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: subnetof.c,v 1.8 2004/07/10 07:48:37 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - subnetof - given address and mask, return subnet part
++ */
++struct in_addr
++subnetof(addr, mask)
++struct in_addr addr;
++struct in_addr mask;
++{
++      struct in_addr result;
++
++      result.s_addr = addr.s_addr & mask.s_addr;
++      return result;
++}
++
++/*
++ - hostof - given address and mask, return host part
++ */
++struct in_addr
++hostof(addr, mask)
++struct in_addr addr;
++struct in_addr mask;
++{
++      struct in_addr result;
++
++      result.s_addr = addr.s_addr & ~mask.s_addr;
++      return result;
++}
++
++/*
++ - broadcastof - given (network) address and mask, return broadcast address
++ */
++struct in_addr
++broadcastof(addr, mask)
++struct in_addr addr;
++struct in_addr mask;
++{
++      struct in_addr result;
++
++      result.s_addr = addr.s_addr | ~mask.s_addr;
++      return result;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/subnettoa.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,61 @@
++/*
++ * convert binary form of subnet description to ASCII
++ * Copyright (C) 1998, 1999  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: subnettoa.c,v 1.11 2004/07/10 07:48:37 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - subnettoa - convert address and mask to ASCII "addr/mask"
++ * Output expresses the mask as a bit count if possible, else dotted decimal.
++ */
++size_t                                /* space needed for full conversion */
++subnettoa(addr, mask, format, dst, dstlen)
++struct in_addr addr;
++struct in_addr mask;
++int format;                   /* character */
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      size_t len;
++      size_t rest;
++      int n;
++      char *p;
++
++      switch (format) {
++      case 0:
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      len = addrtoa(addr, 0, dst, dstlen);
++      if (len < dstlen) {
++              dst[len - 1] = '/';
++              p = dst + len;
++              rest = dstlen - len;
++      } else {
++              p = NULL;
++              rest = 0;
++      }
++
++      n = masktobits(mask);
++      if (n >= 0)
++              len += ultoa((unsigned long)n, 10, p, rest);
++      else
++              len += addrtoa(mask, 0, p, rest);
++
++      return len;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/sysctl_net_ipsec.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,199 @@
++/*
++ * sysctl interface to net IPSEC subsystem.
++ * Copyright (C) 1998, 1999, 2000, 2001         Richard Guy Briggs.
++ * 
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
++ * 
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * RCSID $Id: sysctl_net_ipsec.c,v 1.17 2004/07/10 19:11:18 mcr Exp $
++ */
++
++/* -*- linux-c -*-
++ *
++ * Initiated April 3, 1998, Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
++ */
++
++#include <linux/mm.h>
++#include <linux/sysctl.h>
++
++#include "openswan/ipsec_param.h"
++
++#ifdef CONFIG_SYSCTL
++
++#define NET_IPSEC 2112 /* Random number */                                        
++#ifdef CONFIG_KLIPS_DEBUG
++extern int       debug_ah;
++extern int       debug_esp;
++extern int       debug_tunnel;
++extern int       debug_eroute;
++extern int       debug_spi;
++extern int       debug_radij;
++extern int       debug_netlink;
++extern int       debug_xform;
++extern int       debug_rcv;
++extern int       debug_pfkey;
++extern int sysctl_ipsec_debug_verbose;
++#ifdef CONFIG_KLIPS_IPCOMP
++extern int sysctl_ipsec_debug_ipcomp;
++#endif /* CONFIG_KLIPS_IPCOMP */
++#endif /* CONFIG_KLIPS_DEBUG */
++
++extern int sysctl_ipsec_icmp;
++extern int sysctl_ipsec_inbound_policy_check;
++extern int sysctl_ipsec_tos;
++int sysctl_ipsec_regress_pfkey_lossage;
++
++enum {
++#ifdef CONFIG_KLIPS_DEBUG
++      NET_IPSEC_DEBUG_AH=1,
++      NET_IPSEC_DEBUG_ESP=2,
++      NET_IPSEC_DEBUG_TUNNEL=3,
++      NET_IPSEC_DEBUG_EROUTE=4,
++      NET_IPSEC_DEBUG_SPI=5,
++      NET_IPSEC_DEBUG_RADIJ=6,
++      NET_IPSEC_DEBUG_NETLINK=7,
++      NET_IPSEC_DEBUG_XFORM=8,
++      NET_IPSEC_DEBUG_RCV=9,
++      NET_IPSEC_DEBUG_PFKEY=10,
++      NET_IPSEC_DEBUG_VERBOSE=11,
++      NET_IPSEC_DEBUG_IPCOMP=12,
++#endif /* CONFIG_KLIPS_DEBUG */
++      NET_IPSEC_ICMP=13,
++      NET_IPSEC_INBOUND_POLICY_CHECK=14,
++      NET_IPSEC_TOS=15,
++      NET_IPSEC_REGRESS_PFKEY_LOSSAGE=16,
++};
++
++static ctl_table ipsec_table[] = {
++#ifdef CONFIG_KLIPS_DEBUG
++      { NET_IPSEC_DEBUG_AH, "debug_ah", &debug_ah,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_ESP, "debug_esp", &debug_esp,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_TUNNEL, "debug_tunnel", &debug_tunnel,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_EROUTE, "debug_eroute", &debug_eroute,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_SPI, "debug_spi", &debug_spi,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_RADIJ, "debug_radij", &debug_radij,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_NETLINK, "debug_netlink", &debug_netlink,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_XFORM, "debug_xform", &debug_xform,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_RCV, "debug_rcv", &debug_rcv,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_PFKEY, "debug_pfkey", &debug_pfkey,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_DEBUG_VERBOSE, "debug_verbose",&sysctl_ipsec_debug_verbose,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++#ifdef CONFIG_KLIPS_IPCOMP
++      { NET_IPSEC_DEBUG_IPCOMP, "debug_ipcomp", &sysctl_ipsec_debug_ipcomp,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++#endif /* CONFIG_KLIPS_IPCOMP */
++
++#ifdef CONFIG_KLIPS_REGRESS
++      { NET_IPSEC_REGRESS_PFKEY_LOSSAGE, "pfkey_lossage",
++        &sysctl_ipsec_regress_pfkey_lossage,
++        sizeof(int), 0644, NULL, &proc_dointvec},
++#endif /* CONFIG_KLIPS_REGRESS */
++
++#endif /* CONFIG_KLIPS_DEBUG */
++      { NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_INBOUND_POLICY_CHECK, "inbound_policy_check", &sysctl_ipsec_inbound_policy_check,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      { NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos,
++        sizeof(int), 0644, NULL, &proc_dointvec},    
++      {0}
++};
++
++static ctl_table ipsec_net_table[] = {
++        { NET_IPSEC, "ipsec", NULL, 0, 0555, ipsec_table },
++        { 0 }
++};
++ 
++static ctl_table ipsec_root_table[] = {
++        { CTL_NET, "net", NULL, 0, 0555, ipsec_net_table },
++        { 0 }
++};
++ 
++static struct ctl_table_header *ipsec_table_header;
++
++int ipsec_sysctl_register(void)
++{
++        ipsec_table_header = register_sysctl_table(ipsec_root_table, 0);
++        if (!ipsec_table_header) {
++                return -ENOMEM;
++      }
++        return 0;
++}
++ 
++void ipsec_sysctl_unregister(void)
++{
++        unregister_sysctl_table(ipsec_table_header);
++}
++
++#endif /* CONFIG_SYSCTL */
++
++/*
++ * $Log: sysctl_net_ipsec.c,v $
++ * Revision 1.17  2004/07/10 19:11:18  mcr
++ *    CONFIG_IPSEC -> CONFIG_KLIPS.
++ *
++ * Revision 1.16  2004/04/06 02:49:26  mcr
++ *    pullup of algo code from alg-branch.
++ *
++ * Revision 1.15  2002/04/24 07:55:32  mcr
++ *    #include patches and Makefiles for post-reorg compilation.
++ *
++ * Revision 1.14  2002/04/24 07:36:35  mcr
++ * Moved from ./klips/net/ipsec/sysctl_net_ipsec.c,v
++ *
++ * Revision 1.13  2002/01/12 02:58:32  mcr
++ *    first regression test causes acquire messages to be lost
++ *    100% of the time. This is to help testing of pluto.
++ *
++ * Revision 1.12  2001/06/14 19:35:13  rgb
++ * Update copyright date.
++ *
++ * Revision 1.11  2001/02/26 19:58:13  rgb
++ * Drop sysctl_ipsec_{no_eroute_pass,opportunistic}, replaced by magic SAs.
++ *
++ * Revision 1.10  2000/09/16 01:50:15  rgb
++ * Protect sysctl_ipsec_debug_ipcomp with compiler defines too so that the
++ * linker won't blame rj_delete() for missing symbols.  ;->  Damn statics...
++ *
++ * Revision 1.9  2000/09/15 23:17:51  rgb
++ * Moved stuff around to compile with debug off.
++ *
++ * Revision 1.8  2000/09/15 11:37:02  rgb
++ * Merge in heavily modified Svenning Soerensen's <svenning@post5.tele.dk>
++ * IPCOMP zlib deflate code.
++ *
++ * Revision 1.7  2000/09/15 07:37:15  rgb
++ * Munged silly log comment that was causing a warning.
++ *
++ * Revision 1.6  2000/09/15 04:58:23  rgb
++ * Added tos runtime switch.
++ * Removed 'sysctl_ipsec_' prefix from /proc/sys/net/ipsec/ filenames.
++ *
++ * Revision 1.5  2000/09/12 03:25:28  rgb
++ * Filled in and implemented sysctl.
++ *
++ * Revision 1.4  1999/04/11 00:29:03  henry
++ * GPL boilerplate
++ *
++ * Revision 1.3  1999/04/06 04:54:29  rgb
++ * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
++ * patch shell fixes.
++ *
++ */
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/trees.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,1214 @@
++/* trees.c -- output deflated data using Huffman coding
++ * Copyright (C) 1995-2002 Jean-loup Gailly
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/*
++ *  ALGORITHM
++ *
++ *      The "deflation" process uses several Huffman trees. The more
++ *      common source values are represented by shorter bit sequences.
++ *
++ *      Each code tree is stored in a compressed form which is itself
++ * a Huffman encoding of the lengths of all the code strings (in
++ * ascending order by source values).  The actual code strings are
++ * reconstructed from the lengths in the inflate process, as described
++ * in the deflate specification.
++ *
++ *  REFERENCES
++ *
++ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
++ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
++ *
++ *      Storer, James A.
++ *          Data Compression:  Methods and Theory, pp. 49-50.
++ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
++ *
++ *      Sedgewick, R.
++ *          Algorithms, p290.
++ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
++ */
++
++/* @(#) $Id: trees.c,v 1.4 2004/07/10 07:48:39 mcr Exp $ */
++
++/* #define GEN_TREES_H */
++
++#include "deflate.h"
++
++#ifdef DEBUG
++#  include <ctype.h>
++#endif
++
++/* ===========================================================================
++ * Constants
++ */
++
++#define MAX_BL_BITS 7
++/* Bit length codes must not exceed MAX_BL_BITS bits */
++
++#define END_BLOCK 256
++/* end of block literal code */
++
++#define REP_3_6      16
++/* repeat previous bit length 3-6 times (2 bits of repeat count) */
++
++#define REPZ_3_10    17
++/* repeat a zero length 3-10 times  (3 bits of repeat count) */
++
++#define REPZ_11_138  18
++/* repeat a zero length 11-138 times  (7 bits of repeat count) */
++
++local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
++   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
++
++local const int extra_dbits[D_CODES] /* extra bits for each distance code */
++   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
++
++local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
++   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
++
++local const uch bl_order[BL_CODES]
++   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
++/* The lengths of the bit length codes are sent in order of decreasing
++ * probability, to avoid transmitting the lengths for unused bit length codes.
++ */
++
++#define Buf_size (8 * 2*sizeof(char))
++/* Number of bits used within bi_buf. (bi_buf might be implemented on
++ * more than 16 bits on some systems.)
++ */
++
++/* ===========================================================================
++ * Local data. These are initialized only once.
++ */
++
++#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
++
++#if defined(GEN_TREES_H) || !defined(STDC)
++/* non ANSI compilers may not accept trees.h */
++
++local ct_data static_ltree[L_CODES+2];
++/* The static literal tree. Since the bit lengths are imposed, there is no
++ * need for the L_CODES extra codes used during heap construction. However
++ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
++ * below).
++ */
++
++local ct_data static_dtree[D_CODES];
++/* The static distance tree. (Actually a trivial tree since all codes use
++ * 5 bits.)
++ */
++
++uch _dist_code[DIST_CODE_LEN];
++/* Distance codes. The first 256 values correspond to the distances
++ * 3 .. 258, the last 256 values correspond to the top 8 bits of
++ * the 15 bit distances.
++ */
++
++uch _length_code[MAX_MATCH-MIN_MATCH+1];
++/* length code for each normalized match length (0 == MIN_MATCH) */
++
++local int base_length[LENGTH_CODES];
++/* First normalized length for each code (0 = MIN_MATCH) */
++
++local int base_dist[D_CODES];
++/* First normalized distance for each code (0 = distance of 1) */
++
++#else
++#  include "trees.h"
++#endif /* GEN_TREES_H */
++
++struct static_tree_desc_s {
++    const ct_data *static_tree;  /* static tree or NULL */
++    const intf *extra_bits;      /* extra bits for each code or NULL */
++    int     extra_base;          /* base index for extra_bits */
++    int     elems;               /* max number of elements in the tree */
++    int     max_length;          /* max bit length for the codes */
++};
++
++local static_tree_desc  static_l_desc =
++{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
++
++local static_tree_desc  static_d_desc =
++{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
++
++local static_tree_desc  static_bl_desc =
++{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
++
++/* ===========================================================================
++ * Local (static) routines in this file.
++ */
++
++local void tr_static_init OF((void));
++local void init_block     OF((deflate_state *s));
++local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
++local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
++local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
++local void build_tree     OF((deflate_state *s, tree_desc *desc));
++local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
++local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
++local int  build_bl_tree  OF((deflate_state *s));
++local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
++                              int blcodes));
++local void compress_block OF((deflate_state *s, const ct_data *ltree,
++                              const ct_data *dtree));
++local void set_data_type  OF((deflate_state *s));
++local unsigned bi_reverse OF((unsigned value, int length));
++local void bi_windup      OF((deflate_state *s));
++local void bi_flush       OF((deflate_state *s));
++local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
++                              int header));
++
++#ifdef GEN_TREES_H
++local void gen_trees_header OF((void));
++#endif
++
++#ifndef DEBUG
++#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
++   /* Send a code of the given tree. c and tree must not have side effects */
++
++#else /* DEBUG */
++#  define send_code(s, c, tree) \
++     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
++       send_bits(s, tree[c].Code, tree[c].Len); }
++#endif
++
++/* ===========================================================================
++ * Output a short LSB first on the stream.
++ * IN assertion: there is enough room in pendingBuf.
++ */
++#define put_short(s, w) { \
++    put_byte(s, (uch)((w) & 0xff)); \
++    put_byte(s, (uch)((ush)(w) >> 8)); \
++}
++
++/* ===========================================================================
++ * Send a value on a given number of bits.
++ * IN assertion: length <= 16 and value fits in length bits.
++ */
++#ifdef DEBUG
++local void send_bits      OF((deflate_state *s, int value, int length));
++
++local void send_bits(s, value, length)
++    deflate_state *s;
++    int value;  /* value to send */
++    int length; /* number of bits */
++{
++    Tracevv((stderr," l %2d v %4x ", length, value));
++    Assert(length > 0 && length <= 15, "invalid length");
++    s->bits_sent += (ulg)length;
++
++    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
++     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
++     * unused bits in value.
++     */
++    if (s->bi_valid > (int)Buf_size - length) {
++        s->bi_buf |= (value << s->bi_valid);
++        put_short(s, s->bi_buf);
++        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
++        s->bi_valid += length - Buf_size;
++    } else {
++        s->bi_buf |= value << s->bi_valid;
++        s->bi_valid += length;
++    }
++}
++#else /* !DEBUG */
++
++#define send_bits(s, value, length) \
++{ int len = length;\
++  if (s->bi_valid > (int)Buf_size - len) {\
++    int val = value;\
++    s->bi_buf |= (val << s->bi_valid);\
++    put_short(s, s->bi_buf);\
++    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
++    s->bi_valid += len - Buf_size;\
++  } else {\
++    s->bi_buf |= (value) << s->bi_valid;\
++    s->bi_valid += len;\
++  }\
++}
++#endif /* DEBUG */
++
++
++#define MAX(a,b) (a >= b ? a : b)
++/* the arguments must not have side effects */
++
++/* ===========================================================================
++ * Initialize the various 'constant' tables.
++ */
++local void tr_static_init()
++{
++#if defined(GEN_TREES_H) || !defined(STDC)
++    static int static_init_done = 0;
++    int n;        /* iterates over tree elements */
++    int bits;     /* bit counter */
++    int length;   /* length value */
++    int code;     /* code value */
++    int dist;     /* distance index */
++    ush bl_count[MAX_BITS+1];
++    /* number of codes at each bit length for an optimal tree */
++
++    if (static_init_done) return;
++
++    /* For some embedded targets, global variables are not initialized: */
++    static_l_desc.static_tree = static_ltree;
++    static_l_desc.extra_bits = extra_lbits;
++    static_d_desc.static_tree = static_dtree;
++    static_d_desc.extra_bits = extra_dbits;
++    static_bl_desc.extra_bits = extra_blbits;
++
++    /* Initialize the mapping length (0..255) -> length code (0..28) */
++    length = 0;
++    for (code = 0; code < LENGTH_CODES-1; code++) {
++        base_length[code] = length;
++        for (n = 0; n < (1<<extra_lbits[code]); n++) {
++            _length_code[length++] = (uch)code;
++        }
++    }
++    Assert (length == 256, "tr_static_init: length != 256");
++    /* Note that the length 255 (match length 258) can be represented
++     * in two different ways: code 284 + 5 bits or code 285, so we
++     * overwrite length_code[255] to use the best encoding:
++     */
++    _length_code[length-1] = (uch)code;
++
++    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
++    dist = 0;
++    for (code = 0 ; code < 16; code++) {
++        base_dist[code] = dist;
++        for (n = 0; n < (1<<extra_dbits[code]); n++) {
++            _dist_code[dist++] = (uch)code;
++        }
++    }
++    Assert (dist == 256, "tr_static_init: dist != 256");
++    dist >>= 7; /* from now on, all distances are divided by 128 */
++    for ( ; code < D_CODES; code++) {
++        base_dist[code] = dist << 7;
++        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
++            _dist_code[256 + dist++] = (uch)code;
++        }
++    }
++    Assert (dist == 256, "tr_static_init: 256+dist != 512");
++
++    /* Construct the codes of the static literal tree */
++    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
++    n = 0;
++    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
++    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
++    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
++    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
++    /* Codes 286 and 287 do not exist, but we must include them in the
++     * tree construction to get a canonical Huffman tree (longest code
++     * all ones)
++     */
++    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
++
++    /* The static distance tree is trivial: */
++    for (n = 0; n < D_CODES; n++) {
++        static_dtree[n].Len = 5;
++        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
++    }
++    static_init_done = 1;
++
++#  ifdef GEN_TREES_H
++    gen_trees_header();
++#  endif
++#endif /* defined(GEN_TREES_H) || !defined(STDC) */
++}
++
++/* ===========================================================================
++ * Genererate the file trees.h describing the static trees.
++ */
++#ifdef GEN_TREES_H
++#  ifndef DEBUG
++#    include <stdio.h>
++#  endif
++
++#  define SEPARATOR(i, last, width) \
++      ((i) == (last)? "\n};\n\n" :    \
++       ((i) % (width) == (width)-1 ? ",\n" : ", "))
++
++void gen_trees_header()
++{
++    FILE *header = fopen("trees.h", "w");
++    int i;
++
++    Assert (header != NULL, "Can't open trees.h");
++    fprintf(header,
++          "/* header created automatically with -DGEN_TREES_H */\n\n");
++
++    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
++    for (i = 0; i < L_CODES+2; i++) {
++      fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
++              static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
++    }
++
++    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
++    for (i = 0; i < D_CODES; i++) {
++      fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
++              static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
++    }
++
++    fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
++    for (i = 0; i < DIST_CODE_LEN; i++) {
++      fprintf(header, "%2u%s", _dist_code[i],
++              SEPARATOR(i, DIST_CODE_LEN-1, 20));
++    }
++
++    fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
++    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
++      fprintf(header, "%2u%s", _length_code[i],
++              SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
++    }
++
++    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
++    for (i = 0; i < LENGTH_CODES; i++) {
++      fprintf(header, "%1u%s", base_length[i],
++              SEPARATOR(i, LENGTH_CODES-1, 20));
++    }
++
++    fprintf(header, "local const int base_dist[D_CODES] = {\n");
++    for (i = 0; i < D_CODES; i++) {
++      fprintf(header, "%5u%s", base_dist[i],
++              SEPARATOR(i, D_CODES-1, 10));
++    }
++
++    fclose(header);
++}
++#endif /* GEN_TREES_H */
++
++/* ===========================================================================
++ * Initialize the tree data structures for a new zlib stream.
++ */
++void _tr_init(s)
++    deflate_state *s;
++{
++    tr_static_init();
++
++    s->l_desc.dyn_tree = s->dyn_ltree;
++    s->l_desc.stat_desc = &static_l_desc;
++
++    s->d_desc.dyn_tree = s->dyn_dtree;
++    s->d_desc.stat_desc = &static_d_desc;
++
++    s->bl_desc.dyn_tree = s->bl_tree;
++    s->bl_desc.stat_desc = &static_bl_desc;
++
++    s->bi_buf = 0;
++    s->bi_valid = 0;
++    s->last_eob_len = 8; /* enough lookahead for inflate */
++#ifdef DEBUG
++    s->compressed_len = 0L;
++    s->bits_sent = 0L;
++#endif
++
++    /* Initialize the first block of the first file: */
++    init_block(s);
++}
++
++/* ===========================================================================
++ * Initialize a new block.
++ */
++local void init_block(s)
++    deflate_state *s;
++{
++    int n; /* iterates over tree elements */
++
++    /* Initialize the trees. */
++    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
++    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
++    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
++
++    s->dyn_ltree[END_BLOCK].Freq = 1;
++    s->opt_len = s->static_len = 0L;
++    s->last_lit = s->matches = 0;
++}
++
++#define SMALLEST 1
++/* Index within the heap array of least frequent node in the Huffman tree */
++
++
++/* ===========================================================================
++ * Remove the smallest element from the heap and recreate the heap with
++ * one less element. Updates heap and heap_len.
++ */
++#define pqremove(s, tree, top) \
++{\
++    top = s->heap[SMALLEST]; \
++    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
++    pqdownheap(s, tree, SMALLEST); \
++}
++
++/* ===========================================================================
++ * Compares to subtrees, using the tree depth as tie breaker when
++ * the subtrees have equal frequency. This minimizes the worst case length.
++ */
++#define smaller(tree, n, m, depth) \
++   (tree[n].Freq < tree[m].Freq || \
++   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
++
++/* ===========================================================================
++ * Restore the heap property by moving down the tree starting at node k,
++ * exchanging a node with the smallest of its two sons if necessary, stopping
++ * when the heap property is re-established (each father smaller than its
++ * two sons).
++ */
++local void pqdownheap(s, tree, k)
++    deflate_state *s;
++    ct_data *tree;  /* the tree to restore */
++    int k;               /* node to move down */
++{
++    int v = s->heap[k];
++    int j = k << 1;  /* left son of k */
++    while (j <= s->heap_len) {
++        /* Set j to the smallest of the two sons: */
++        if (j < s->heap_len &&
++            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
++            j++;
++        }
++        /* Exit if v is smaller than both sons */
++        if (smaller(tree, v, s->heap[j], s->depth)) break;
++
++        /* Exchange v with the smallest son */
++        s->heap[k] = s->heap[j];  k = j;
++
++        /* And continue down the tree, setting j to the left son of k */
++        j <<= 1;
++    }
++    s->heap[k] = v;
++}
++
++/* ===========================================================================
++ * Compute the optimal bit lengths for a tree and update the total bit length
++ * for the current block.
++ * IN assertion: the fields freq and dad are set, heap[heap_max] and
++ *    above are the tree nodes sorted by increasing frequency.
++ * OUT assertions: the field len is set to the optimal bit length, the
++ *     array bl_count contains the frequencies for each bit length.
++ *     The length opt_len is updated; static_len is also updated if stree is
++ *     not null.
++ */
++local void gen_bitlen(s, desc)
++    deflate_state *s;
++    tree_desc *desc;    /* the tree descriptor */
++{
++    ct_data *tree        = desc->dyn_tree;
++    int max_code         = desc->max_code;
++    const ct_data *stree = desc->stat_desc->static_tree;
++    const intf *extra    = desc->stat_desc->extra_bits;
++    int base             = desc->stat_desc->extra_base;
++    int max_length       = desc->stat_desc->max_length;
++    int h;              /* heap index */
++    int n, m;           /* iterate over the tree elements */
++    int bits;           /* bit length */
++    int xbits;          /* extra bits */
++    ush f;              /* frequency */
++    int overflow = 0;   /* number of elements with bit length too large */
++
++    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
++
++    /* In a first pass, compute the optimal bit lengths (which may
++     * overflow in the case of the bit length tree).
++     */
++    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
++
++    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
++        n = s->heap[h];
++        bits = tree[tree[n].Dad].Len + 1;
++        if (bits > max_length) bits = max_length, overflow++;
++        tree[n].Len = (ush)bits;
++        /* We overwrite tree[n].Dad which is no longer needed */
++
++        if (n > max_code) continue; /* not a leaf node */
++
++        s->bl_count[bits]++;
++        xbits = 0;
++        if (n >= base) xbits = extra[n-base];
++        f = tree[n].Freq;
++        s->opt_len += (ulg)f * (bits + xbits);
++        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
++    }
++    if (overflow == 0) return;
++
++    Trace((stderr,"\nbit length overflow\n"));
++    /* This happens for example on obj2 and pic of the Calgary corpus */
++
++    /* Find the first bit length which could increase: */
++    do {
++        bits = max_length-1;
++        while (s->bl_count[bits] == 0) bits--;
++        s->bl_count[bits]--;      /* move one leaf down the tree */
++        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
++        s->bl_count[max_length]--;
++        /* The brother of the overflow item also moves one step up,
++         * but this does not affect bl_count[max_length]
++         */
++        overflow -= 2;
++    } while (overflow > 0);
++
++    /* Now recompute all bit lengths, scanning in increasing frequency.
++     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
++     * lengths instead of fixing only the wrong ones. This idea is taken
++     * from 'ar' written by Haruhiko Okumura.)
++     */
++    for (bits = max_length; bits != 0; bits--) {
++        n = s->bl_count[bits];
++        while (n != 0) {
++            m = s->heap[--h];
++            if (m > max_code) continue;
++            if (tree[m].Len != (unsigned) bits) {
++                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
++                s->opt_len += ((long)bits - (long)tree[m].Len)
++                              *(long)tree[m].Freq;
++                tree[m].Len = (ush)bits;
++            }
++            n--;
++        }
++    }
++}
++
++/* ===========================================================================
++ * Generate the codes for a given tree and bit counts (which need not be
++ * optimal).
++ * IN assertion: the array bl_count contains the bit length statistics for
++ * the given tree and the field len is set for all tree elements.
++ * OUT assertion: the field code is set for all tree elements of non
++ *     zero code length.
++ */
++local void gen_codes (tree, max_code, bl_count)
++    ct_data *tree;             /* the tree to decorate */
++    int max_code;              /* largest code with non zero frequency */
++    ushf *bl_count;            /* number of codes at each bit length */
++{
++    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
++    ush code = 0;              /* running code value */
++    int bits;                  /* bit index */
++    int n;                     /* code index */
++
++    /* The distribution counts are first used to generate the code values
++     * without bit reversal.
++     */
++    for (bits = 1; bits <= MAX_BITS; bits++) {
++        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
++    }
++    /* Check that the bit counts in bl_count are consistent. The last code
++     * must be all ones.
++     */
++    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
++            "inconsistent bit counts");
++    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
++
++    for (n = 0;  n <= max_code; n++) {
++        int len = tree[n].Len;
++        if (len == 0) continue;
++        /* Now reverse the bits */
++        tree[n].Code = bi_reverse(next_code[len]++, len);
++
++        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
++             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
++    }
++}
++
++/* ===========================================================================
++ * Construct one Huffman tree and assigns the code bit strings and lengths.
++ * Update the total bit length for the current block.
++ * IN assertion: the field freq is set for all tree elements.
++ * OUT assertions: the fields len and code are set to the optimal bit length
++ *     and corresponding code. The length opt_len is updated; static_len is
++ *     also updated if stree is not null. The field max_code is set.
++ */
++local void build_tree(s, desc)
++    deflate_state *s;
++    tree_desc *desc; /* the tree descriptor */
++{
++    ct_data *tree         = desc->dyn_tree;
++    const ct_data *stree  = desc->stat_desc->static_tree;
++    int elems             = desc->stat_desc->elems;
++    int n, m;          /* iterate over heap elements */
++    int max_code = -1; /* largest code with non zero frequency */
++    int node;          /* new node being created */
++
++    /* Construct the initial heap, with least frequent element in
++     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
++     * heap[0] is not used.
++     */
++    s->heap_len = 0, s->heap_max = HEAP_SIZE;
++
++    for (n = 0; n < elems; n++) {
++        if (tree[n].Freq != 0) {
++            s->heap[++(s->heap_len)] = max_code = n;
++            s->depth[n] = 0;
++        } else {
++            tree[n].Len = 0;
++        }
++    }
++
++    /* The pkzip format requires that at least one distance code exists,
++     * and that at least one bit should be sent even if there is only one
++     * possible code. So to avoid special checks later on we force at least
++     * two codes of non zero frequency.
++     */
++    while (s->heap_len < 2) {
++        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
++        tree[node].Freq = 1;
++        s->depth[node] = 0;
++        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
++        /* node is 0 or 1 so it does not have extra bits */
++    }
++    desc->max_code = max_code;
++
++    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
++     * establish sub-heaps of increasing lengths:
++     */
++    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
++
++    /* Construct the Huffman tree by repeatedly combining the least two
++     * frequent nodes.
++     */
++    node = elems;              /* next internal node of the tree */
++    do {
++        pqremove(s, tree, n);  /* n = node of least frequency */
++        m = s->heap[SMALLEST]; /* m = node of next least frequency */
++
++        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
++        s->heap[--(s->heap_max)] = m;
++
++        /* Create a new node father of n and m */
++        tree[node].Freq = tree[n].Freq + tree[m].Freq;
++        s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
++        tree[n].Dad = tree[m].Dad = (ush)node;
++#ifdef DUMP_BL_TREE
++        if (tree == s->bl_tree) {
++            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
++                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
++        }
++#endif
++        /* and insert the new node in the heap */
++        s->heap[SMALLEST] = node++;
++        pqdownheap(s, tree, SMALLEST);
++
++    } while (s->heap_len >= 2);
++
++    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
++
++    /* At this point, the fields freq and dad are set. We can now
++     * generate the bit lengths.
++     */
++    gen_bitlen(s, (tree_desc *)desc);
++
++    /* The field len is now set, we can generate the bit codes */
++    gen_codes ((ct_data *)tree, max_code, s->bl_count);
++}
++
++/* ===========================================================================
++ * Scan a literal or distance tree to determine the frequencies of the codes
++ * in the bit length tree.
++ */
++local void scan_tree (s, tree, max_code)
++    deflate_state *s;
++    ct_data *tree;   /* the tree to be scanned */
++    int max_code;    /* and its largest code of non zero frequency */
++{
++    int n;                     /* iterates over all tree elements */
++    int prevlen = -1;          /* last emitted length */
++    int curlen;                /* length of current code */
++    int nextlen = tree[0].Len; /* length of next code */
++    int count = 0;             /* repeat count of the current code */
++    int max_count = 7;         /* max repeat count */
++    int min_count = 4;         /* min repeat count */
++
++    if (nextlen == 0) max_count = 138, min_count = 3;
++    tree[max_code+1].Len = (ush)0xffff; /* guard */
++
++    for (n = 0; n <= max_code; n++) {
++        curlen = nextlen; nextlen = tree[n+1].Len;
++        if (++count < max_count && curlen == nextlen) {
++            continue;
++        } else if (count < min_count) {
++            s->bl_tree[curlen].Freq += count;
++        } else if (curlen != 0) {
++            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
++            s->bl_tree[REP_3_6].Freq++;
++        } else if (count <= 10) {
++            s->bl_tree[REPZ_3_10].Freq++;
++        } else {
++            s->bl_tree[REPZ_11_138].Freq++;
++        }
++        count = 0; prevlen = curlen;
++        if (nextlen == 0) {
++            max_count = 138, min_count = 3;
++        } else if (curlen == nextlen) {
++            max_count = 6, min_count = 3;
++        } else {
++            max_count = 7, min_count = 4;
++        }
++    }
++}
++
++/* ===========================================================================
++ * Send a literal or distance tree in compressed form, using the codes in
++ * bl_tree.
++ */
++local void send_tree (s, tree, max_code)
++    deflate_state *s;
++    ct_data *tree; /* the tree to be scanned */
++    int max_code;       /* and its largest code of non zero frequency */
++{
++    int n;                     /* iterates over all tree elements */
++    int prevlen = -1;          /* last emitted length */
++    int curlen;                /* length of current code */
++    int nextlen = tree[0].Len; /* length of next code */
++    int count = 0;             /* repeat count of the current code */
++    int max_count = 7;         /* max repeat count */
++    int min_count = 4;         /* min repeat count */
++
++    /* tree[max_code+1].Len = -1; */  /* guard already set */
++    if (nextlen == 0) max_count = 138, min_count = 3;
++
++    for (n = 0; n <= max_code; n++) {
++        curlen = nextlen; nextlen = tree[n+1].Len;
++        if (++count < max_count && curlen == nextlen) {
++            continue;
++        } else if (count < min_count) {
++            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
++
++        } else if (curlen != 0) {
++            if (curlen != prevlen) {
++                send_code(s, curlen, s->bl_tree); count--;
++            }
++            Assert(count >= 3 && count <= 6, " 3_6?");
++            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
++
++        } else if (count <= 10) {
++            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
++
++        } else {
++            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
++        }
++        count = 0; prevlen = curlen;
++        if (nextlen == 0) {
++            max_count = 138, min_count = 3;
++        } else if (curlen == nextlen) {
++            max_count = 6, min_count = 3;
++        } else {
++            max_count = 7, min_count = 4;
++        }
++    }
++}
++
++/* ===========================================================================
++ * Construct the Huffman tree for the bit lengths and return the index in
++ * bl_order of the last bit length code to send.
++ */
++local int build_bl_tree(s)
++    deflate_state *s;
++{
++    int max_blindex;  /* index of last bit length code of non zero freq */
++
++    /* Determine the bit length frequencies for literal and distance trees */
++    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
++    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
++
++    /* Build the bit length tree: */
++    build_tree(s, (tree_desc *)(&(s->bl_desc)));
++    /* opt_len now includes the length of the tree representations, except
++     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
++     */
++
++    /* Determine the number of bit length codes to send. The pkzip format
++     * requires that at least 4 bit length codes be sent. (appnote.txt says
++     * 3 but the actual value used is 4.)
++     */
++    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
++        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
++    }
++    /* Update opt_len to include the bit length tree and counts */
++    s->opt_len += 3*(max_blindex+1) + 5+5+4;
++    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
++            s->opt_len, s->static_len));
++
++    return max_blindex;
++}
++
++/* ===========================================================================
++ * Send the header for a block using dynamic Huffman trees: the counts, the
++ * lengths of the bit length codes, the literal tree and the distance tree.
++ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
++ */
++local void send_all_trees(s, lcodes, dcodes, blcodes)
++    deflate_state *s;
++    int lcodes, dcodes, blcodes; /* number of codes for each tree */
++{
++    int rank;                    /* index in bl_order */
++
++    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
++    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
++            "too many codes");
++    Tracev((stderr, "\nbl counts: "));
++    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
++    send_bits(s, dcodes-1,   5);
++    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
++    for (rank = 0; rank < blcodes; rank++) {
++        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
++        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
++    }
++    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
++
++    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
++    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
++
++    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
++    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
++}
++
++/* ===========================================================================
++ * Send a stored block
++ */
++void _tr_stored_block(s, buf, stored_len, eof)
++    deflate_state *s;
++    charf *buf;       /* input block */
++    ulg stored_len;   /* length of input block */
++    int eof;          /* true if this is the last block for a file */
++{
++    send_bits(s, (STORED_BLOCK<<1)+eof, 3);  /* send block type */
++#ifdef DEBUG
++    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
++    s->compressed_len += (stored_len + 4) << 3;
++#endif
++    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
++}
++
++/* ===========================================================================
++ * Send one empty static block to give enough lookahead for inflate.
++ * This takes 10 bits, of which 7 may remain in the bit buffer.
++ * The current inflate code requires 9 bits of lookahead. If the
++ * last two codes for the previous block (real code plus EOB) were coded
++ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
++ * the last real code. In this case we send two empty static blocks instead
++ * of one. (There are no problems if the previous block is stored or fixed.)
++ * To simplify the code, we assume the worst case of last real code encoded
++ * on one bit only.
++ */
++void _tr_align(s)
++    deflate_state *s;
++{
++    send_bits(s, STATIC_TREES<<1, 3);
++    send_code(s, END_BLOCK, static_ltree);
++#ifdef DEBUG
++    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
++#endif
++    bi_flush(s);
++    /* Of the 10 bits for the empty block, we have already sent
++     * (10 - bi_valid) bits. The lookahead for the last real code (before
++     * the EOB of the previous block) was thus at least one plus the length
++     * of the EOB plus what we have just sent of the empty static block.
++     */
++    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
++        send_bits(s, STATIC_TREES<<1, 3);
++        send_code(s, END_BLOCK, static_ltree);
++#ifdef DEBUG
++        s->compressed_len += 10L;
++#endif
++        bi_flush(s);
++    }
++    s->last_eob_len = 7;
++}
++
++/* ===========================================================================
++ * Determine the best encoding for the current block: dynamic trees, static
++ * trees or store, and output the encoded block to the zip file.
++ */
++void _tr_flush_block(s, buf, stored_len, eof)
++    deflate_state *s;
++    charf *buf;       /* input block, or NULL if too old */
++    ulg stored_len;   /* length of input block */
++    int eof;          /* true if this is the last block for a file */
++{
++    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
++    int max_blindex = 0;  /* index of last bit length code of non zero freq */
++
++    /* Build the Huffman trees unless a stored block is forced */
++    if (s->level > 0) {
++
++       /* Check if the file is ascii or binary */
++      if (s->data_type == Z_UNKNOWN) set_data_type(s);
++
++      /* Construct the literal and distance trees */
++      build_tree(s, (tree_desc *)(&(s->l_desc)));
++      Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
++              s->static_len));
++
++      build_tree(s, (tree_desc *)(&(s->d_desc)));
++      Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
++              s->static_len));
++      /* At this point, opt_len and static_len are the total bit lengths of
++       * the compressed block data, excluding the tree representations.
++       */
++
++      /* Build the bit length tree for the above two trees, and get the index
++       * in bl_order of the last bit length code to send.
++       */
++      max_blindex = build_bl_tree(s);
++
++      /* Determine the best encoding. Compute first the block length in bytes*/
++      opt_lenb = (s->opt_len+3+7)>>3;
++      static_lenb = (s->static_len+3+7)>>3;
++
++      Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
++              opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
++              s->last_lit));
++
++      if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
++
++    } else {
++        Assert(buf != (char*)0, "lost buf");
++      opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
++    }
++
++#ifdef FORCE_STORED
++    if (buf != (char*)0) { /* force stored block */
++#else
++    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
++                       /* 4: two words for the lengths */
++#endif
++        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
++         * Otherwise we can't have processed more than WSIZE input bytes since
++         * the last block flush, because compression would have been
++         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
++         * transform a block into a stored block.
++         */
++        _tr_stored_block(s, buf, stored_len, eof);
++
++#ifdef FORCE_STATIC
++    } else if (static_lenb >= 0) { /* force static trees */
++#else
++    } else if (static_lenb == opt_lenb) {
++#endif
++        send_bits(s, (STATIC_TREES<<1)+eof, 3);
++        compress_block(s, static_ltree, static_dtree);
++#ifdef DEBUG
++        s->compressed_len += 3 + s->static_len;
++#endif
++    } else {
++        send_bits(s, (DYN_TREES<<1)+eof, 3);
++        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
++                       max_blindex+1);
++        compress_block(s, s->dyn_ltree, s->dyn_dtree);
++#ifdef DEBUG
++        s->compressed_len += 3 + s->opt_len;
++#endif
++    }
++    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
++    /* The above check is made mod 2^32, for files larger than 512 MB
++     * and uLong implemented on 32 bits.
++     */
++    init_block(s);
++
++    if (eof) {
++        bi_windup(s);
++#ifdef DEBUG
++        s->compressed_len += 7;  /* align on byte boundary */
++#endif
++    }
++    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
++           s->compressed_len-7*eof));
++}
++
++/* ===========================================================================
++ * Save the match info and tally the frequency counts. Return true if
++ * the current block must be flushed.
++ */
++int _tr_tally (s, dist, lc)
++    deflate_state *s;
++    unsigned dist;  /* distance of matched string */
++    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
++{
++    s->d_buf[s->last_lit] = (ush)dist;
++    s->l_buf[s->last_lit++] = (uch)lc;
++    if (dist == 0) {
++        /* lc is the unmatched char */
++        s->dyn_ltree[lc].Freq++;
++    } else {
++        s->matches++;
++        /* Here, lc is the match length - MIN_MATCH */
++        dist--;             /* dist = match distance - 1 */
++        Assert((ush)dist < (ush)MAX_DIST(s) &&
++               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
++               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
++
++        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
++        s->dyn_dtree[d_code(dist)].Freq++;
++    }
++
++#ifdef TRUNCATE_BLOCK
++    /* Try to guess if it is profitable to stop the current block here */
++    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
++        /* Compute an upper bound for the compressed length */
++        ulg out_length = (ulg)s->last_lit*8L;
++        ulg in_length = (ulg)((long)s->strstart - s->block_start);
++        int dcode;
++        for (dcode = 0; dcode < D_CODES; dcode++) {
++            out_length += (ulg)s->dyn_dtree[dcode].Freq *
++                (5L+extra_dbits[dcode]);
++        }
++        out_length >>= 3;
++        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
++               s->last_lit, in_length, out_length,
++               100L - out_length*100L/in_length));
++        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
++    }
++#endif
++    return (s->last_lit == s->lit_bufsize-1);
++    /* We avoid equality with lit_bufsize because of wraparound at 64K
++     * on 16 bit machines and because stored blocks are restricted to
++     * 64K-1 bytes.
++     */
++}
++
++/* ===========================================================================
++ * Send the block data compressed using the given Huffman trees
++ */
++local void compress_block(s, ltree, dtree)
++    deflate_state *s;
++    const ct_data *ltree; /* literal tree */
++    const ct_data *dtree; /* distance tree */
++{
++    unsigned dist;      /* distance of matched string */
++    int lc;             /* match length or unmatched char (if dist == 0) */
++    unsigned lx = 0;    /* running index in l_buf */
++    unsigned code;      /* the code to send */
++    int extra;          /* number of extra bits to send */
++
++    if (s->last_lit != 0) do {
++        dist = s->d_buf[lx];
++        lc = s->l_buf[lx++];
++        if (dist == 0) {
++            send_code(s, lc, ltree); /* send a literal byte */
++            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
++        } else {
++            /* Here, lc is the match length - MIN_MATCH */
++            code = _length_code[lc];
++            send_code(s, code+LITERALS+1, ltree); /* send the length code */
++            extra = extra_lbits[code];
++            if (extra != 0) {
++                lc -= base_length[code];
++                send_bits(s, lc, extra);       /* send the extra length bits */
++            }
++            dist--; /* dist is now the match distance - 1 */
++            code = d_code(dist);
++            Assert (code < D_CODES, "bad d_code");
++
++            send_code(s, code, dtree);       /* send the distance code */
++            extra = extra_dbits[code];
++            if (extra != 0) {
++                dist -= base_dist[code];
++                send_bits(s, dist, extra);   /* send the extra distance bits */
++            }
++        } /* literal or match pair ? */
++
++        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
++        Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
++
++    } while (lx < s->last_lit);
++
++    send_code(s, END_BLOCK, ltree);
++    s->last_eob_len = ltree[END_BLOCK].Len;
++}
++
++/* ===========================================================================
++ * Set the data type to ASCII or BINARY, using a crude approximation:
++ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
++ * IN assertion: the fields freq of dyn_ltree are set and the total of all
++ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
++ */
++local void set_data_type(s)
++    deflate_state *s;
++{
++    int n = 0;
++    unsigned ascii_freq = 0;
++    unsigned bin_freq = 0;
++    while (n < 7)        bin_freq += s->dyn_ltree[n++].Freq;
++    while (n < 128)    ascii_freq += s->dyn_ltree[n++].Freq;
++    while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
++    s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
++}
++
++/* ===========================================================================
++ * Reverse the first len bits of a code, using straightforward code (a faster
++ * method would use a table)
++ * IN assertion: 1 <= len <= 15
++ */
++local unsigned bi_reverse(code, len)
++    unsigned code; /* the value to invert */
++    int len;       /* its bit length */
++{
++    register unsigned res = 0;
++    do {
++        res |= code & 1;
++        code >>= 1, res <<= 1;
++    } while (--len > 0);
++    return res >> 1;
++}
++
++/* ===========================================================================
++ * Flush the bit buffer, keeping at most 7 bits in it.
++ */
++local void bi_flush(s)
++    deflate_state *s;
++{
++    if (s->bi_valid == 16) {
++        put_short(s, s->bi_buf);
++        s->bi_buf = 0;
++        s->bi_valid = 0;
++    } else if (s->bi_valid >= 8) {
++        put_byte(s, (Byte)s->bi_buf);
++        s->bi_buf >>= 8;
++        s->bi_valid -= 8;
++    }
++}
++
++/* ===========================================================================
++ * Flush the bit buffer and align the output on a byte boundary
++ */
++local void bi_windup(s)
++    deflate_state *s;
++{
++    if (s->bi_valid > 8) {
++        put_short(s, s->bi_buf);
++    } else if (s->bi_valid > 0) {
++        put_byte(s, (Byte)s->bi_buf);
++    }
++    s->bi_buf = 0;
++    s->bi_valid = 0;
++#ifdef DEBUG
++    s->bits_sent = (s->bits_sent+7) & ~7;
++#endif
++}
++
++/* ===========================================================================
++ * Copy a stored block, storing first the length and its
++ * one's complement if requested.
++ */
++local void copy_block(s, buf, len, header)
++    deflate_state *s;
++    charf    *buf;    /* the input data */
++    unsigned len;     /* its length */
++    int      header;  /* true if block header must be written */
++{
++    bi_windup(s);        /* align on byte boundary */
++    s->last_eob_len = 8; /* enough lookahead for inflate */
++
++    if (header) {
++        put_short(s, (ush)len);   
++        put_short(s, (ush)~len);
++#ifdef DEBUG
++        s->bits_sent += 2*16;
++#endif
++    }
++#ifdef DEBUG
++    s->bits_sent += (ulg)len<<3;
++#endif
++    while (len--) {
++        put_byte(s, *buf++);
++    }
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/trees.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,128 @@
++/* header created automatically with -DGEN_TREES_H */
++
++local const ct_data static_ltree[L_CODES+2] = {
++{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
++{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
++{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
++{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
++{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
++{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
++{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
++{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
++{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
++{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
++{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
++{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
++{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
++{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
++{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
++{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
++{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
++{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
++{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
++{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
++{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
++{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
++{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
++{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
++{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
++{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
++{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
++{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
++{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
++{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
++{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
++{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
++{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
++{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
++{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
++{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
++{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
++{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
++{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
++{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
++{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
++{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
++{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
++{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
++{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
++{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
++{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
++{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
++{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
++{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
++{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
++{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
++{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
++{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
++{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
++{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
++{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
++{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
++};
++
++local const ct_data static_dtree[D_CODES] = {
++{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
++{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
++{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
++{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
++{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
++{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
++};
++
++const uch _dist_code[DIST_CODE_LEN] = {
++ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
++ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
++10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
++11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
++12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
++13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
++13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
++14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
++14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
++14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
++15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
++18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
++23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
++24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
++26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
++26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
++27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
++27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
++28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
++28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
++28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
++29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
++29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
++29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
++};
++
++const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
++ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
++13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
++17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
++19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
++22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
++23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
++24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
++25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
++25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
++26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
++26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
++27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
++};
++
++local const int base_length[LENGTH_CODES] = {
++0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
++64, 80, 96, 112, 128, 160, 192, 224, 0
++};
++
++local const int base_dist[D_CODES] = {
++    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
++   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
++ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
++};
++
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ultoa.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,66 @@
++/*
++ * convert unsigned long to ASCII
++ * Copyright (C) 1998, 1999  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: ultoa.c,v 1.10 2004/07/10 07:48:37 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - ultoa - convert unsigned long to decimal ASCII
++ */
++size_t                                /* length required for full conversion */
++ultoa(n, base, dst, dstlen)
++unsigned long n;
++int base;
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      char buf[3*sizeof(unsigned long) + 1];
++      char *bufend = buf + sizeof(buf);
++      size_t len;
++      char *p;
++      static char hex[] = "0123456789abcdef";
++
++      p = bufend;
++      *--p = '\0';
++      if (base == 10) {
++              do {
++                      *--p = n%10 + '0';
++                      n /= 10;
++              } while (n != 0);
++      } else if (base == 16) {
++              do {
++                      *--p = hex[n&0xf];
++                      n >>= 4;
++              } while (n != 0);
++              *--p = 'x';
++              *--p = '0';
++      } else if (base == 8) {
++              do {
++                      *--p = (n&07) + '0';
++                      n >>= 3;
++              } while (n != 0);
++              *--p = '0';
++      } else
++              *--p = '?';
++
++      len = bufend - p;
++
++      if (dstlen > 0) {
++              if (len > dstlen)
++                      *(p + dstlen - 1) = '\0';
++              strcpy(dst, p);
++      }
++      return len;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/ultot.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,82 @@
++/*
++ * convert unsigned long to text
++ * Copyright (C) 2000  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: ultot.c,v 1.5 2004/07/10 07:48:37 mcr Exp $
++ */
++#include "openswan.h"
++
++/*
++ - ultot - convert unsigned long to text
++ */
++size_t                                /* length required for full conversion */
++ultot(n, base, dst, dstlen)
++unsigned long n;
++int base;
++char *dst;                    /* need not be valid if dstlen is 0 */
++size_t dstlen;
++{
++      char buf[3*sizeof(unsigned long) + 1];
++      char *bufend = buf + sizeof(buf);
++      size_t len;
++      char *p;
++      static char hex[] = "0123456789abcdef";
++#     define  HEX32   (32/4)
++
++      p = bufend;
++      *--p = '\0';
++      switch (base) {
++      case 10:
++      case 'd':
++              do {
++                      *--p = n%10 + '0';
++                      n /= 10;
++              } while (n != 0);
++              break;
++      case 16:
++      case 17:
++      case 'x':
++              do {
++                      *--p = hex[n&0xf];
++                      n >>= 4;
++              } while (n != 0);
++              if (base == 17)
++                      while (bufend - p < HEX32 + 1)
++                              *--p = '0';
++              if (base == 'x') {
++                      *--p = 'x';
++                      *--p = '0';
++              }
++              break;
++      case 8:
++      case 'o':
++              do {
++                      *--p = (n&07) + '0';
++                      n >>= 3;
++              } while (n != 0);
++              if (base == 'o')
++                      *--p = '0';
++              break;
++      default:
++              return 0;
++              break;
++      }
++
++      len = bufend - p;
++      if (dstlen > 0) {
++              if (len > dstlen)
++                      *(p + dstlen - 1) = '\0';
++              strcpy(dst, p);
++      }
++      return len;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/version.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,44 @@
++/*
++ * return IPsec version information
++ * Copyright (C) 2001  Henry Spencer.
++ * 
++ * This library is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
++ * 
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
++ * License for more details.
++ *
++ * RCSID $Id: version.in.c,v 1.2 2004/04/14 05:09:46 ken Exp $
++ */
++
++#ifdef __KERNEL__
++#include <linux/netdevice.h>
++#endif
++
++#include "openswan.h"
++
++#define       V       "2.4.8"         /* substituted in by Makefile */
++static const char openswan_number[] = V;
++static const char openswan_string[] = "Openswan " V;
++
++/*
++ - ipsec_version_code - return IPsec version number/code, as string
++ */
++const char *
++ipsec_version_code()
++{
++      return openswan_number;
++}
++
++/*
++ - ipsec_version_string - return full version string
++ */
++const char *
++ipsec_version_string()
++{
++      return openswan_string;
++}
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ linux/net/ipsec/zutil.c     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,227 @@
++/* zutil.c -- target dependent utility functions for the compression library
++ * Copyright (C) 1995-2002 Jean-loup Gailly.
++ * For conditions of distribution and use, see copyright notice in zlib.h 
++ */
++
++/* @(#) $Id: zutil.c,v 1.5 2004/07/10 07:48:40 mcr Exp $ */
++
++#include <zlib/zutil.h>
++
++#define MY_ZCALLOC
++
++struct internal_state      {int dummy;}; /* for buggy compilers */
++
++#ifndef STDC
++extern void exit OF((int));
++#endif
++
++const char *z_errmsg[10] = {
++"need dictionary",     /* Z_NEED_DICT       2  */
++"stream end",          /* Z_STREAM_END      1  */
++"",                    /* Z_OK              0  */
++"file error",          /* Z_ERRNO         (-1) */
++"stream error",        /* Z_STREAM_ERROR  (-2) */
++"data error",          /* Z_DATA_ERROR    (-3) */
++"insufficient memory", /* Z_MEM_ERROR     (-4) */
++"buffer error",        /* Z_BUF_ERROR     (-5) */
++"incompatible version",/* Z_VERSION_ERROR (-6) */
++""};
++
++
++const char * ZEXPORT zlibVersion()
++{
++    return ZLIB_VERSION;
++}
++
++#ifdef DEBUG
++
++#  ifndef verbose
++#    define verbose 0
++#  endif
++int z_verbose = verbose;
++
++void z_error (m)
++    char *m;
++{
++    fprintf(stderr, "%s\n", m);
++    exit(1);
++}
++#endif
++
++/* exported to allow conversion of error code to string for compress() and
++ * uncompress()
++ */
++const char * ZEXPORT zError(err)
++    int err;
++{
++    return ERR_MSG(err);
++}
++
++
++#ifndef HAVE_MEMCPY
++
++void zmemcpy(dest, source, len)
++    Bytef* dest;
++    const Bytef* source;
++    uInt  len;
++{
++    if (len == 0) return;
++    do {
++        *dest++ = *source++; /* ??? to be unrolled */
++    } while (--len != 0);
++}
++
++int zmemcmp(s1, s2, len)
++    const Bytef* s1;
++    const Bytef* s2;
++    uInt  len;
++{
++    uInt j;
++
++    for (j = 0; j < len; j++) {
++        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
++    }
++    return 0;
++}
++
++void zmemzero(dest, len)
++    Bytef* dest;
++    uInt  len;
++{
++    if (len == 0) return;
++    do {
++        *dest++ = 0;  /* ??? to be unrolled */
++    } while (--len != 0);
++}
++#endif
++
++#ifdef __TURBOC__
++#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
++/* Small and medium model in Turbo C are for now limited to near allocation
++ * with reduced MAX_WBITS and MAX_MEM_LEVEL
++ */
++#  define MY_ZCALLOC
++
++/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
++ * and farmalloc(64K) returns a pointer with an offset of 8, so we
++ * must fix the pointer. Warning: the pointer must be put back to its
++ * original form in order to free it, use zcfree().
++ */
++
++#define MAX_PTR 10
++/* 10*64K = 640K */
++
++local int next_ptr = 0;
++
++typedef struct ptr_table_s {
++    voidpf org_ptr;
++    voidpf new_ptr;
++} ptr_table;
++
++local ptr_table table[MAX_PTR];
++/* This table is used to remember the original form of pointers
++ * to large buffers (64K). Such pointers are normalized with a zero offset.
++ * Since MSDOS is not a preemptive multitasking OS, this table is not
++ * protected from concurrent access. This hack doesn't work anyway on
++ * a protected system like OS/2. Use Microsoft C instead.
++ */
++
++voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
++{
++    voidpf buf = opaque; /* just to make some compilers happy */
++    ulg bsize = (ulg)items*size;
++
++    /* If we allocate less than 65520 bytes, we assume that farmalloc
++     * will return a usable pointer which doesn't have to be normalized.
++     */
++    if (bsize < 65520L) {
++        buf = farmalloc(bsize);
++        if (*(ush*)&buf != 0) return buf;
++    } else {
++        buf = farmalloc(bsize + 16L);
++    }
++    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
++    table[next_ptr].org_ptr = buf;
++
++    /* Normalize the pointer to seg:0 */
++    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
++    *(ush*)&buf = 0;
++    table[next_ptr++].new_ptr = buf;
++    return buf;
++}
++
++void  zcfree (voidpf opaque, voidpf ptr)
++{
++    int n;
++    if (*(ush*)&ptr != 0) { /* object < 64K */
++        farfree(ptr);
++        return;
++    }
++    /* Find the original pointer */
++    for (n = 0; n < next_ptr; n++) {
++        if (ptr != table[n].new_ptr) continue;
++
++        farfree(table[n].org_ptr);
++        while (++n < next_ptr) {
++            table[n-1] = table[n];
++        }
++        next_ptr--;
++        return;
++    }
++    ptr = opaque; /* just to make some compilers happy */
++    Assert(0, "zcfree: ptr not found");
++}
++#endif
++#endif /* __TURBOC__ */
++
++
++#if defined(M_I86) && !defined(__32BIT__)
++/* Microsoft C in 16-bit mode */
++
++#  define MY_ZCALLOC
++
++#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
++#  define _halloc  halloc
++#  define _hfree   hfree
++#endif
++
++voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
++{
++    if (opaque) opaque = 0; /* to make compiler happy */
++    return _halloc((long)items, size);
++}
++
++void  zcfree (voidpf opaque, voidpf ptr)
++{
++    if (opaque) opaque = 0; /* to make compiler happy */
++    _hfree(ptr);
++}
++
++#endif /* MSC */
++
++
++#ifndef MY_ZCALLOC /* Any system without a special alloc function */
++
++#ifndef STDC
++extern voidp  calloc OF((uInt items, uInt size));
++extern void   free   OF((voidpf ptr));
++#endif
++
++voidpf zcalloc (opaque, items, size)
++    voidpf opaque;
++    unsigned items;
++    unsigned size;
++{
++    if (opaque) items += size - size; /* make compiler happy */
++    return (voidpf)calloc(items, size);
++}
++
++void  zcfree (opaque, ptr)
++    voidpf opaque;
++    voidpf ptr;
++{
++    free(ptr);
++    if (opaque) return; /* make compiler happy */
++}
++
++#endif /* MY_ZCALLOC */
+--- swan26/net/ipv4/af_inet.c.orig     Wed Jun 16 01:18:58 2004
++++ swan26/net/ipv4/af_inet.c  Fri Aug 13 23:09:27 2004
+@@ -1169,6 +1169,18 @@
+ #if defined(CONFIG_IP_MROUTE)
+       ip_mr_init();
+ #endif
++
++#if defined(CONFIG_KLIPS)
++      {
++               extern int ipsec_klips_init(void);
++              /*
++               *  Initialise AF_INET ESP and AH protocol support including 
++               *  e-routing and SA tables
++               */
++              ipsec_klips_init();
++      }
++#endif /* CONFIG_IPSEC */
++
+       /*
+        *      Initialise per-cpu ipv4 mibs
+        */ 
+--- /dev/null   Fri May 10 13:59:54 2002
++++ linux/net/ipsec/Makefile.ver  Sun Jul 28 22:10:40 2002
+@@ -0,0 +1 @@
++IPSECVERSION=2.4.8
diff --git a/src/patches/openswan-2.4.8.kernel-2.6-natt.patch b/src/patches/openswan-2.4.8.kernel-2.6-natt.patch
new file mode 100644 (file)
index 0000000..9fdab41
--- /dev/null
@@ -0,0 +1,125 @@
+packaging/utils/nattpatch 2.6
+--- /dev/null   Tue Mar 11 13:02:56 2003
++++ nat-t/include/net/xfrmudp.h     Mon Feb  9 13:51:03 2004
+@@ -0,0 +1,10 @@
++/*
++ * pointer to function for type that xfrm4_input wants, to permit
++ * decoupling of XFRM from udp.c
++ */
++#define HAVE_XFRM4_UDP_REGISTER
++
++typedef int (*xfrm4_rcv_encap_t)(struct sk_buff *skb, __u16 encap_type);
++extern int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
++                                    , xfrm4_rcv_encap_t *oldfunc);
++extern int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func);
+--- /distros/kernel/linux-2.6.11.2/net/ipv4/Kconfig    2005-03-09 03:12:33.000000000 -0500
++++ swan26/net/ipv4/Kconfig    2005-04-04 18:46:13.000000000 -0400
+@@ -351,2 +351,8 @@
++config IPSEC_NAT_TRAVERSAL
++      bool "IPSEC NAT-Traversal (KLIPS compatible)"
++      depends on INET
++      ---help---
++          Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP.
++
+ config IP_TCPDIAG
+--- plain26/net/ipv4/udp.c.orig        2006-01-02 22:21:10.000000000 -0500
++++ plain26/net/ipv4/udp.c     2006-01-12 20:18:57.000000000 -0500
+@@ -110,2 +110,3 @@
+ #include <net/xfrm.h>
++#include <net/xfrmudp.h>
+@@ -894,6 +897,44 @@
+       sk_common_release(sk);
+ }
++#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++
++/* if XFRM isn't a module, then register it directly. */
++#if !defined(CONFIG_XFRM_MODULE) 
++static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = xfrm4_rcv_encap;
++#else
++static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL;
++#endif
++
++static xfrm4_rcv_encap_t xfrm4_rcv_encap_func;
++
++int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
++                             , xfrm4_rcv_encap_t *oldfunc)
++{
++  if(oldfunc != NULL) {
++    *oldfunc = xfrm4_rcv_encap_func;
++  }
++
++#if 0
++  if(xfrm4_rcv_encap_func != NULL)
++    return -1;
++#endif
++
++  xfrm4_rcv_encap_func = func;
++  return 0;
++}
++
++int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func)
++{
++  if(xfrm4_rcv_encap_func != func)
++    return -1;
++
++  xfrm4_rcv_encap_func = NULL;
++  return 0;
++}
++#endif /* CONFIG_XFRM || defined(CONFIG_IPSEC_NAT_TRAVERSAL)*/
++
++
+ /* return:
+  *    1  if the the UDP system should process it
+  *    0  if we should drop this packet
+@@ -901,9 +940,9 @@
+  */
+ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
+ {
+-#ifndef CONFIG_XFRM
++#if !defined(CONFIG_XFRM) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+       return 1; 
+-#else
++#else /* either CONFIG_XFRM or CONFIG_IPSEC_NAT_TRAVERSAL */
+       struct udp_sock *up = udp_sk(sk);
+       struct udphdr *uh = skb->h.uh;
+       struct iphdr *iph;
+@@ -1021,10 +1060,14 @@
+                       return 0;
+               }
+               if (ret < 0) {
+-                      /* process the ESP packet */
+-                      ret = xfrm4_rcv_encap(skb, up->encap_type);
+-                      UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
+-                      return -ret;
++                      if(xfrm4_rcv_encap_func != NULL) {
++                        ret = (*xfrm4_rcv_encap_func)(skb, up->encap_type);
++                        UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
++                      } else {
++                        UDP_INC_STATS_BH(UDP_MIB_INERRORS);
++                        ret = 1;
++                      }
++                      return ret;
+               }
+               /* FALLTHROUGH -- it's a UDP Packet */
+       }
+@@ -1114,7 +1157,6 @@
+ /*
+  *    All we need to do is get the socket, and then do a checksum. 
+  */
+- 
+ int udp_rcv(struct sk_buff *skb)
+ {
+       struct sock *sk;
+@@ -1571,3 +1613,9 @@
+ EXPORT_SYMBOL(udp_proc_register);
+ EXPORT_SYMBOL(udp_proc_unregister);
+ #endif
++
++#if defined(CONFIG_IPSEC_NAT_TRAVERSAL)
++EXPORT_SYMBOL(udp4_register_esp_rcvencap);
++EXPORT_SYMBOL(udp4_unregister_esp_rcvencap);
++#endif
++